public void TestDuplicateOracle()
        {
            // Fake balance
            var snapshot = Blockchain.Singleton.GetSnapshot();

            ApplicationEngine engine  = ApplicationEngine.Create(TriggerType.Application, null, snapshot, null, long.MaxValue);
            BigInteger        balance = NativeContract.GAS.BalanceOf(snapshot, UInt160.Zero);

            NativeContract.GAS.Burn(engine, UInt160.Zero, balance);
            NativeContract.GAS.Mint(engine, UInt160.Zero, 8, false);

            // Test
            TransactionVerificationContext verificationContext = new TransactionVerificationContext();
            var tx = CreateTransactionWithFee(1, 2);

            tx.Attributes = new TransactionAttribute[] { new OracleResponse()
                                                         {
                                                             Code = OracleResponseCode.ConsensusUnreachable, Id = 1, Result = new byte[0]
                                                         } };
            verificationContext.CheckTransaction(tx, snapshot).Should().BeTrue();
            verificationContext.AddTransaction(tx);

            tx            = CreateTransactionWithFee(2, 1);
            tx.Attributes = new TransactionAttribute[] { new OracleResponse()
                                                         {
                                                             Code = OracleResponseCode.ConsensusUnreachable, Id = 1, Result = new byte[0]
                                                         } };
            verificationContext.CheckTransaction(tx, snapshot).Should().BeFalse();
        }
Пример #2
0
        async Task <UInt256> SubmitTransactionAsync(Transaction tx)
        {
            if (disposedValue)
            {
                throw new ObjectDisposedException(nameof(OfflineNode));
            }

            var transactions = new[] { tx };

            // 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++)
            {
                if (transactions[i].Verify(neoSystem.Settings, neoSystem.StoreView, verificationContext) != VerifyResult.Succeed)
                {
                    throw new Exception("Verification failed");
                }
            }

            var prevHash   = NativeContract.Ledger.CurrentHash(neoSystem.StoreView);
            var prevHeader = NativeContract.Ledger.GetHeader(neoSystem.StoreView, prevHash);
            var block      = ExpressOracle.CreateSignedBlock(prevHeader,
                                                             consensusNodesKeys.Value,
                                                             neoSystem.Settings.Network,
                                                             transactions);

            await RelayBlockAsync(block).ConfigureAwait(false);

            return(block.Hash);
        }
Пример #3
0
        /// <summary>
        /// Prevent that block exceed the max size
        /// </summary>
        /// <param name="txs">Ordered transactions</param>
        internal void EnsureMaxBlockLimitation(IEnumerable <Transaction> txs)
        {
            uint maxBlockSize            = NativeContract.Policy.GetMaxBlockSize(Snapshot);
            long maxBlockSystemFee       = NativeContract.Policy.GetMaxBlockSystemFee(Snapshot);
            uint maxTransactionsPerBlock = NativeContract.Policy.GetMaxTransactionsPerBlock(Snapshot);

            // Limit Speaker proposal to the limit `MaxTransactionsPerBlock` or all available transactions of the mempool
            txs = txs.Take((int)maxTransactionsPerBlock);
            List <UInt256> hashes = new List <UInt256>();

            Transactions        = new Dictionary <UInt256, Transaction>();
            VerificationContext = new TransactionVerificationContext();

            // Expected block size
            var blockSize      = GetExpectedBlockSizeWithoutTransactions(txs.Count());
            var blockSystemFee = 0L;

            // Iterate transaction until reach the size or maximum system fee
            foreach (Transaction tx in txs)
            {
                // Check if maximum block size has been already exceeded with the current selected set
                blockSize += tx.Size;
                if (blockSize > maxBlockSize)
                {
                    break;
                }

                // Check if maximum block system fee has been already exceeded with the current selected set
                blockSystemFee += tx.SystemFee;
                if (blockSystemFee > maxBlockSystemFee)
                {
                    break;
                }

                hashes.Add(tx.Hash);
                Transactions.Add(tx.Hash, tx);
                VerificationContext.AddTransaction(tx);
            }

            TransactionHashes = hashes.ToArray();
        }
Пример #4
0
 public void Deserialize(BinaryReader reader)
 {
     Reset(0);
     if (reader.ReadUInt32() != Block.Version)
     {
         throw new FormatException();
     }
     if (reader.ReadUInt32() != Block.Index)
     {
         throw new InvalidOperationException();
     }
     Block.Timestamp     = reader.ReadUInt64();
     Block.NextConsensus = reader.ReadSerializable <UInt160>();
     if (Block.NextConsensus.Equals(UInt160.Zero))
     {
         Block.NextConsensus = null;
     }
     Block.ConsensusData = reader.ReadSerializable <ConsensusData>();
     ViewNumber          = reader.ReadByte();
     TransactionHashes   = reader.ReadSerializableArray <UInt256>();
     Transaction[] transactions = reader.ReadSerializableArray <Transaction>(Block.MaxTransactionsPerBlock);
     PreparationPayloads    = reader.ReadNullableArray <ExtensiblePayload>(ProtocolSettings.Default.ValidatorsCount);
     CommitPayloads         = reader.ReadNullableArray <ExtensiblePayload>(ProtocolSettings.Default.ValidatorsCount);
     ChangeViewPayloads     = reader.ReadNullableArray <ExtensiblePayload>(ProtocolSettings.Default.ValidatorsCount);
     LastChangeViewPayloads = reader.ReadNullableArray <ExtensiblePayload>(ProtocolSettings.Default.ValidatorsCount);
     if (TransactionHashes.Length == 0 && !RequestSentOrReceived)
     {
         TransactionHashes = null;
     }
     Transactions        = transactions.Length == 0 && !RequestSentOrReceived ? null : transactions.ToDictionary(p => p.Hash);
     VerificationContext = new TransactionVerificationContext();
     if (Transactions != null)
     {
         foreach (Transaction tx in Transactions.Values)
         {
             VerificationContext.AddTransaction(tx);
         }
     }
 }
        public void TestTransactionSenderFee()
        {
            var snapshot              = Blockchain.Singleton.GetSnapshot();
            ApplicationEngine engine  = ApplicationEngine.Create(TriggerType.Application, null, snapshot, null, long.MaxValue);
            BigInteger        balance = NativeContract.GAS.BalanceOf(snapshot, UInt160.Zero);

            NativeContract.GAS.Burn(engine, UInt160.Zero, balance);
            NativeContract.GAS.Mint(engine, UInt160.Zero, 8, true);

            TransactionVerificationContext verificationContext = new TransactionVerificationContext();
            var tx = CreateTransactionWithFee(1, 2);

            verificationContext.CheckTransaction(tx, snapshot).Should().BeTrue();
            verificationContext.AddTransaction(tx);
            verificationContext.CheckTransaction(tx, snapshot).Should().BeTrue();
            verificationContext.AddTransaction(tx);
            verificationContext.CheckTransaction(tx, snapshot).Should().BeFalse();
            verificationContext.RemoveTransaction(tx);
            verificationContext.CheckTransaction(tx, snapshot).Should().BeTrue();
            verificationContext.AddTransaction(tx);
            verificationContext.CheckTransaction(tx, snapshot).Should().BeFalse();
        }
Пример #6
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);
        }