Exemplo n.º 1
0
 public void Reset(byte viewNumber)
 {
     if (viewNumber == 0)
     {
         Snapshot?.Dispose();
         Snapshot = DBFTPlugin.System.GetSnapshot();
         uint height = NativeContract.Ledger.CurrentIndex(Snapshot);
         Block = new Block
         {
             Header = new Header
             {
                 PrevHash      = NativeContract.Ledger.CurrentHash(Snapshot),
                 Index         = height + 1,
                 NextConsensus = Contract.GetBFTAddress(
                     NeoToken.ShouldRefreshCommittee(height + 1, DBFTPlugin.System.Settings.CommitteeMembersCount) ?
                     NativeContract.NEO.ComputeNextBlockValidators(Snapshot, DBFTPlugin.System.Settings) :
                     NativeContract.NEO.GetNextBlockValidators(Snapshot, DBFTPlugin.System.Settings.ValidatorsCount))
             }
         };
         var pv = Validators;
         Validators = NativeContract.NEO.GetNextBlockValidators(Snapshot, DBFTPlugin.System.Settings.ValidatorsCount);
         if (_witnessSize == 0 || (pv != null && pv.Length != Validators.Length))
         {
             // Compute the expected size of the witness
             using (ScriptBuilder sb = new ScriptBuilder())
             {
                 for (int x = 0; x < M; x++)
                 {
                     sb.EmitPush(new byte[64]);
                 }
                 _witnessSize = new Witness
                 {
                     InvocationScript   = sb.ToArray(),
                     VerificationScript = Contract.CreateMultiSigRedeemScript(M, Validators)
                 }.Size;
             }
         }
         MyIndex                = -1;
         ChangeViewPayloads     = new ExtensiblePayload[Validators.Length];
         LastChangeViewPayloads = new ExtensiblePayload[Validators.Length];
         CommitPayloads         = new ExtensiblePayload[Validators.Length];
         if (ValidatorsChanged || LastSeenMessage is null)
         {
             var previous_last_seen_message = LastSeenMessage;
             LastSeenMessage = new Dictionary <ECPoint, uint>();
             foreach (var validator in Validators)
             {
                 if (previous_last_seen_message != null && previous_last_seen_message.TryGetValue(validator, out var value))
                 {
                     LastSeenMessage[validator] = value;
                 }
                 else
                 {
                     LastSeenMessage[validator] = height;
                 }
             }
         }
         keyPair = null;
         for (int i = 0; i < Validators.Length; i++)
         {
             WalletAccount account = wallet?.GetAccount(Validators[i]);
             if (account?.HasKey != true)
             {
                 continue;
             }
             MyIndex = i;
             keyPair = account.GetKey();
             break;
         }
         cachedMessages = new Dictionary <UInt256, ConsensusMessage>();
     }
     else
     {
         for (int i = 0; i < LastChangeViewPayloads.Length; i++)
         {
             if (GetMessage <ChangeView>(ChangeViewPayloads[i])?.NewViewNumber >= viewNumber)
             {
                 LastChangeViewPayloads[i] = ChangeViewPayloads[i];
             }
             else
             {
                 LastChangeViewPayloads[i] = null;
             }
         }
     }
     ViewNumber = viewNumber;
     Block.Header.PrimaryIndex = GetPrimaryIndex(viewNumber);
     Block.Header.MerkleRoot   = null;
     Block.Header.Timestamp    = 0;
     Block.Transactions        = null;
     TransactionHashes         = null;
     PreparationPayloads       = new ExtensiblePayload[Validators.Length];
     if (MyIndex >= 0)
     {
         LastSeenMessage[Validators[MyIndex]] = Block.Index;
     }
 }
Exemplo n.º 2
0
        Block CreateSignedBlock(Transaction[] transactions)
        {
            // The logic in this method is distilled from ConsensusService/ConsensusContext + MemPool tx verification logic

            var snapshot = neoSystem.StoreView;

            // Verify the provided transactions. When running, Blockchain class does verification in two steps: VerifyStateIndependent and VerifyStateDependent.
            // However, Verify does both parts and there's no point in verifying dependent/independent in separate steps here
            var verificationContext = new TransactionVerificationContext();

            for (int i = 0; i < transactions.Length; i++)
            {
                var q = transactions[i].Size * NativeContract.Policy.GetFeePerByte(snapshot);
                if (transactions[i].Verify(ProtocolSettings, snapshot, verificationContext) != VerifyResult.Succeed)
                {
                    throw new Exception("Verification failed");
                }
            }

            // create the block instance
            var prevHash    = NativeContract.Ledger.CurrentHash(snapshot);
            var prevBlock   = NativeContract.Ledger.GetHeader(snapshot, prevHash);
            var blockHeight = prevBlock.Index + 1;
            var block       = new Block
            {
                Header = new Header
                {
                    Version       = 0,
                    PrevHash      = prevHash,
                    MerkleRoot    = MerkleTree.ComputeRoot(transactions.Select(t => t.Hash).ToArray()),
                    Timestamp     = Math.Max(Neo.Helper.ToTimestampMS(DateTime.UtcNow), prevBlock.Timestamp + 1),
                    Index         = blockHeight,
                    PrimaryIndex  = 0,
                    NextConsensus = Contract.GetBFTAddress(
                        NeoToken.ShouldRefreshCommittee(blockHeight, ProtocolSettings.CommitteeMembersCount)
                            ? NativeContract.NEO.ComputeNextBlockValidators(snapshot, ProtocolSettings)
                            : NativeContract.NEO.GetNextBlockValidators(snapshot, ProtocolSettings.ValidatorsCount)),
                },
                Transactions = transactions
            };

            // retrieve the validators for the next block. Logic lifted from ConensusContext.Reset
            var validators = NativeContract.NEO.GetNextBlockValidators(snapshot, ProtocolSettings.ValidatorsCount);
            var m          = validators.Length - (validators.Length - 1) / 3;

            // generate the block header witness. Logic lifted from ConsensusContext.CreateBlock
            var contract       = Contract.CreateMultiSigContract(m, validators);
            var signingContext = new ContractParametersContext(snapshot, block.Header, ProtocolSettings.Network);

            for (int i = 0, j = 0; i < validators.Length && j < m; i++)
            {
                var key = consensusNodesKeys.Value.SingleOrDefault(k => k.PublicKey.Equals(validators[i]));
                if (key == null)
                {
                    continue;
                }

                var signature = block.Header.Sign(key, ProtocolSettings.Network);
                signingContext.AddSignature(contract, validators[i], signature);
                j++;
            }
            if (!signingContext.Completed)
            {
                throw new Exception("block signing incomplete");
            }
            block.Header.Witness = signingContext.GetWitnesses()[0];

            return(block);
        }