public IEnumerable <Transaction> GetTransactions(BlockHeader parent, long gasLimit)
        {
            _nonces.Clear();

            try
            {
                return(_innerSource.GetTransactions(parent, gasLimit).Select(tx =>
                {
                    if (tx is GeneratedTransaction)
                    {
                        tx.Nonce = CalculateNonce(tx.SenderAddress, parent.StateRoot, _nonces);
                        _txSealer.Seal(tx, TxHandlingOptions.None);
                        Metrics.SealedTransactions++;
                        if (_logger.IsDebug)
                        {
                            _logger.Debug($"Sealed node generated transaction {tx.Hash} from {tx.SenderAddress} to {tx.To} with nonce {tx.Nonce}.");
                        }
                    }

                    return tx;
                }));
            }
            finally
            {
                _nonces.Clear();
            }
        }
Пример #2
0
        public IEnumerable <Transaction> GetTransactions(BlockHeader parent, long gasLimit)
        {
            _nonces.Clear();

            try
            {
                return(_innerSource.GetTransactions(parent, gasLimit).Select(tx =>
                {
                    if (tx is GeneratedTransaction)
                    {
                        tx.Nonce = CalculateNonce(tx.SenderAddress, parent.StateRoot, _nonces);
                        _txSealer.Seal(tx, TxHandlingOptions.ManagedNonce | TxHandlingOptions.AllowReplacingSignature);
                        Metrics.SealedTransactions++;
                        if (_logger.IsDebug)
                        {
                            _logger.Debug($"Sealed node generated transaction {tx.ToShortString()}");
                        }
                    }

                    return tx;
                }));
            }
            finally
            {
                _nonces.Clear();
            }
        }
Пример #3
0
 public IEnumerable <Transaction> GetTransactions(BlockHeader parent, long gasLimit)
 {
     foreach (Transaction tx in _innerSource.GetTransactions(parent, gasLimit))
     {
         if (tx is T)
         {
             (bool allowed, string reason) = _txFilter.IsAllowed(tx, parent);
             if (allowed)
             {
                 if (_logger.IsTrace)
                 {
                     _logger.Trace($"Selected {tx.ToShortString()} to be included in block.");
                 }
                 yield return(tx);
             }
             else
             {
                 if (_logger.IsDebug)
                 {
                     _logger.Debug($"Rejecting ({reason}) {tx.ToShortString()}");
                 }
             }
         }
         else
         {
             if (_logger.IsTrace)
             {
                 _logger.Trace($"Selected {tx.ToShortString()} to be included in block, skipped validation for {tx.GetType()}.");
             }
             yield return(tx);
         }
     }
 }
Пример #4
0
        protected virtual Block PrepareBlock(BlockHeader parent)
        {
            UInt256     timestamp  = UInt256.Max(parent.Timestamp + 1, _timestamper.UnixTime.Seconds);
            UInt256     difficulty = CalculateDifficulty(parent, timestamp);
            BlockHeader header     = new BlockHeader(
                parent.Hash,
                Keccak.OfAnEmptySequenceRlp,
                _sealer.Address,
                difficulty,
                parent.Number + 1,
                _gasLimitCalculator.GetGasLimit(parent),
                timestamp,
                Encoding.UTF8.GetBytes("Nethermind"))
            {
                TotalDifficulty = parent.TotalDifficulty + difficulty,
                Author          = _sealer.Address
            };

            if (Logger.IsDebug)
            {
                Logger.Debug($"Setting total difficulty to {parent.TotalDifficulty} + {difficulty}.");
            }

            var   transactions = _txSource.GetTransactions(parent, header.GasLimit);
            Block block        = new Block(header, transactions, Array.Empty <BlockHeader>());

            header.TxRoot = new TxTrie(block.Transactions).RootHash;
            return(block);
        }
Пример #5
0
        protected virtual Block PrepareBlock(BlockHeader parent)
        {
            UInt256     timestamp  = _timestamper.EpochSeconds;
            UInt256     difficulty = CalculateDifficulty(parent, timestamp);
            BlockHeader header     = new BlockHeader(
                parent.Hash,
                Keccak.OfAnEmptySequenceRlp,
                Address.Zero,
                difficulty,
                parent.Number + 1,
                GetGasLimit(parent),
                UInt256.Max(parent.Timestamp + 1, _timestamper.EpochSeconds),
                Encoding.UTF8.GetBytes("Nethermind"))
            {
                TotalDifficulty = parent.TotalDifficulty + difficulty
            };

            if (Logger.IsDebug)
            {
                Logger.Debug($"Setting total difficulty to {parent.TotalDifficulty} + {difficulty}.");
            }

            var   transactions = _txSource.GetTransactions(parent, header.GasLimit);
            Block block        = new Block(header, transactions, new BlockHeader[0]);

            header.TxRoot = new TxTrie(block.Transactions).RootHash;
            return(block);
        }
Пример #6
0
        public IEnumerable <Transaction> GetTransactions(BlockHeader parent, long gasLimit)
        {
            foreach (Transaction transaction in _txSource.GetTransactions(parent, gasLimit))
            {
                yield return(transaction);

                break;
            }
        }
Пример #7
0
 public IEnumerable<Transaction> GetTransactions(BlockHeader parent, long gasLimit)
 {
     foreach (Transaction transaction in _innerSource.GetTransactions(parent, gasLimit))
     {
         if (!(transaction is T) || _txFilter.IsAllowed(transaction, parent).Allowed)
         {
             yield return transaction;
         }
     }
 }
Пример #8
0
        public void Can_serve_one_by_one()
        {
            ITxSource source = Substitute.For <ITxSource>();

            source.GetTransactions(null, 0).Returns(new Transaction[5]);

            ITxSource oneByOne = source.ServeTxsOneByOne();

            oneByOne.GetTransactions(null, 0).Count().Should().Be(1);
        }
        public IEnumerable <Transaction> GetTransactions(BlockHeader parent, long gasLimit) =>
        _innerSource.GetTransactions(parent, gasLimit).Select(tx =>
        {
            if (tx is GeneratedTransaction)
            {
                ApproveTx(parent, tx);
            }

            return(tx);
        });
Пример #10
0
        public void Bundle(Block head)
        {
            // turn ops into txs
            var transactions =
                _txSource.GetTransactions(head.Header, head.GasLimit)
                .Select(tx => new BundleTransaction
            {
                ChainId = tx.ChainId,
                Type    = tx.Type,

                Nonce               = tx.Nonce,
                GasPrice            = tx.GasPrice,
                GasBottleneck       = tx.GasBottleneck,
                DecodedMaxFeePerGas = tx.DecodedMaxFeePerGas,
                GasLimit            = tx.GasLimit,
                To            = tx.To,
                Value         = tx.Value,
                Data          = tx.Data,
                SenderAddress = tx.SenderAddress,
                Signature     = tx.Signature,
                Hash          = tx.Hash,
                DeliveredBy   = tx.DeliveredBy,
                Timestamp     = tx.Timestamp,
                AccessList    = tx.AccessList,
            })
                .ToArray();

            if (transactions.Length == 0)
            {
                return;
            }

            // turn txs into MevBundle
            MevBundle bundle = new(head.Header.Number + 1, transactions);

            if (_logger.IsDebug)
            {
                _logger.Debug($"Trying to add bundle {bundle.Hash} from AA to MEV bundle pool");
            }
            // add MevBundle to MevPlugin bundle pool
            bool result = _bundlePool.AddBundle(bundle);

            if (result)
            {
                if (_logger.IsDebug)
                {
                    _logger.Debug($"Bundle {bundle.Hash} from AA successfuly added to MEV bundle pool");
                }
            }
            else if (_logger.IsDebug)
            {
                _logger.Debug("Bundle from AA failed to be added to MEV bundle pool");
            }
        }
        public IEnumerable <Transaction> GetTransactions(BlockHeader parent, long gasLimit)
        {
            foreach (var tx in _innerSource.GetTransactions(parent, gasLimit))
            {
                if (tx is GeneratedTransaction)
                {
                    ApproveTx(parent, tx);
                }

                yield return(tx);
            }
        }
        public IEnumerable <Transaction> GetTransactions(BlockHeader parent, long gasLimit)
        {
            IDictionary <Address, UInt256> nonces = new Dictionary <Address, UInt256>();

            return(_innerSource.GetTransactions(parent, gasLimit).Select(tx =>
            {
                if (tx is GeneratedTransaction)
                {
                    tx.Nonce = CalculateNonce(tx.SenderAddress, parent.StateRoot, nonces);
                    _txSealer.Seal(tx);
                }

                return tx;
            }));
        }
Пример #13
0
        public void When_many_transactions_returns_one_with_lowest_nonce_and_highest_timestamp()
        {
            ITxSource txSource = Substitute.For <ITxSource>();

            txSource.GetTransactions(_anyParent, 1000000).ReturnsForAnyArgs(new []
            {
                Build.A.Transaction.WithNonce(6).TestObject,
                Build.A.Transaction.WithNonce(1).WithTimestamp(7).TestObject,
                Build.A.Transaction.WithNonce(9).TestObject,
                Build.A.Transaction.WithNonce(1).WithTimestamp(8).TestObject,
            });

            SinglePendingTxSelector selector = new SinglePendingTxSelector(txSource);
            var result = selector.GetTransactions(_anyParent, 1000000).ToArray();

            result.Should().HaveCount(1);
            result[0].Timestamp.Should().Be(8);
            result[0].Nonce.Should().Be(1);
        }
Пример #14
0
        public IEnumerable <Transaction> GetTransactions(BlockHeader parent, long gasLimit)
        {
            IDictionary <Address, UInt256> nonces = new Dictionary <Address, UInt256>();

            return(_innerSource.GetTransactions(parent, gasLimit).Select(tx =>
            {
                if (tx is GeneratedTransaction)
                {
                    tx.Nonce = CalculateNonce(tx.SenderAddress, parent.StateRoot, nonces);
                    _txSealer.Seal(tx);
                    if (_logger.IsDebug)
                    {
                        _logger.Debug($"Sealed node generated transaction {tx.Hash} from {tx.SenderAddress} to {tx.To} with nonce {tx.Nonce}.");
                    }
                }

                return tx;
            }));
        }
Пример #15
0
        public void Reseal_generated_transactions()
        {
            ITxSource    innerSource = Substitute.For <ITxSource>();
            ITxSealer    txSealer    = Substitute.For <ITxSealer>();
            IStateReader stateReader = Substitute.For <IStateReader>();

            BlockHeader          parent      = Build.A.BlockHeader.TestObject;
            long                 gasLimit    = long.MaxValue;
            Transaction          poolTx      = Build.A.Transaction.WithSenderAddress(TestItem.AddressA).TestObject;
            GeneratedTransaction generatedTx = Build.A.GeneratedTransaction.WithSenderAddress(TestItem.AddressB).TestObject;

            innerSource.GetTransactions(parent, gasLimit).Returns(new[] { poolTx, generatedTx });

            var txSource = new GeneratedTxSource(innerSource, txSealer, stateReader, LimboLogs.Instance);

            txSource.GetTransactions(parent, gasLimit).ToArray();

            txSealer.Received().Seal(generatedTx, TxHandlingOptions.ManagedNonce | TxHandlingOptions.AllowReplacingSignature);
            txSealer.DidNotReceive().Seal(poolTx, Arg.Any <TxHandlingOptions>());
        }
        public void transactions_are_addable_to_block_after_sealing()
        {
            int                  chainId     = 5;
            BlockHeader          blockHeader = Build.A.BlockHeader.TestObject;
            GeneratedTransaction tx1         = Build.A.GeneratedTransaction.WithSenderAddress(TestItem.AddressA).TestObject;
            GeneratedTransaction tx2         = Build.A.GeneratedTransaction.WithSenderAddress(TestItem.AddressA).TestObject;
            ITimestamper         timestamper = Substitute.For <ITimestamper>();
            IStateReader         stateReader = Substitute.For <IStateReader>();
            Address              nodeAddress = TestItem.AddressA;

            UInt256 expectedNonce = 10;

            stateReader.GetAccount(blockHeader.StateRoot, nodeAddress).Returns(Account.TotallyEmpty.WithChangedNonce(expectedNonce));

            ulong expectedTimeStamp = 100;

            timestamper.UnixTime.Returns(UnixTime.FromSeconds(expectedTimeStamp));

            int       gasLimit      = 200;
            ITxSource innerTxSource = Substitute.For <ITxSource>();

            innerTxSource.GetTransactions(blockHeader, gasLimit).Returns(new[] { tx1, tx2 });

            TxSealer          txSealer          = new(new Signer((ulong)chainId, Build.A.PrivateKey.TestObject, LimboLogs.Instance), timestamper);
            GeneratedTxSource transactionFiller = new(innerTxSource, txSealer, stateReader, LimboLogs.Instance);

            Transaction[] sealedTxs = transactionFiller.GetTransactions(blockHeader, gasLimit).ToArray();
            Transaction   sealedTx1 = sealedTxs.First();
            Transaction   sealedTx2 = sealedTxs.Skip(1).First();

            sealedTx1.IsSigned.Should().BeTrue();
            sealedTx1.Nonce.Should().Be(expectedNonce);
            sealedTx1.Hash.Should().Be(tx1.CalculateHash());
            sealedTx1.Timestamp.Should().Be(expectedTimeStamp);

            sealedTx2.IsSigned.Should().BeTrue();
            sealedTx2.Nonce.Should().Be(expectedNonce + 1);
            sealedTx2.Hash.Should().NotBe(tx1.CalculateHash());
            sealedTx2.Timestamp.Should().Be(expectedTimeStamp);
        }
Пример #17
0
 public IEnumerable <Transaction> GetTransactions(BlockHeader parent, long gasLimit) =>
 _innerSource.GetTransactions(parent, gasLimit).Where(tx => _txPermissionFilter.IsAllowed(tx, parent));
 public IEnumerable <Transaction> GetTransactions(BlockHeader parent, long gasLimit) =>
 _innerSource.GetTransactions(parent, gasLimit)
 .OrderBy(t => t.Nonce)
 .ThenByDescending(t => t.Timestamp)
 .Take(1);
Пример #19
0
        private Block?PrepareBlock(Block parentBlock)
        {
            BlockHeader parentHeader = parentBlock.Header;

            if (parentHeader == null)
            {
                if (_logger.IsError)
                {
                    _logger.Error(
                        $"Preparing new block on top of {parentBlock.ToString(Block.Format.Short)} - parent header is null");
                }
                return(null);
            }

            if (_recentNotAllowedParent == parentBlock.Hash)
            {
                return(null);
            }

            if (!_sealer.CanSeal(parentHeader.Number + 1, parentHeader.Hash))
            {
                if (_logger.IsTrace)
                {
                    _logger.Trace($"Not allowed to sign block ({parentBlock.Number + 1})");
                }
                _recentNotAllowedParent = parentHeader.Hash;
                return(null);
            }

            if (_logger.IsInfo)
            {
                _logger.Info($"Preparing new block on top of {parentBlock.ToString(Block.Format.Short)}");
            }

            UInt256 timestamp = _timestamper.UnixTime.Seconds;

            BlockHeader header = new BlockHeader(
                parentBlock.Hash,
                Keccak.OfAnEmptySequenceRlp,
                Address.Zero,
                1,
                parentBlock.Number + 1,
                _gasLimitCalculator.GetGasLimit(parentBlock.Header),
                timestamp > parentBlock.Timestamp ? timestamp : parentBlock.Timestamp + 1,
                Array.Empty <byte>());

            // If the block isn't a checkpoint, cast a random vote (good enough for now)
            long number = header.Number;
            // Assemble the voting snapshot to check which votes make sense
            Snapshot snapshot     = _snapshotManager.GetOrCreateSnapshot(number - 1, header.ParentHash);
            bool     isEpochBlock = (ulong)number % 30000 == 0;

            if (!isEpochBlock && _proposals.Any())
            {
                // Gather all the proposals that make sense voting on
                List <Address> addresses = new List <Address>();
                foreach (var proposal in _proposals)
                {
                    Address address   = proposal.Key;
                    bool    authorize = proposal.Value;
                    if (_snapshotManager.IsValidVote(snapshot, address, authorize))
                    {
                        addresses.Add(address);
                    }
                }

                // If there's pending proposals, cast a vote on them
                if (addresses.Count > 0)
                {
                    header.Beneficiary = addresses[_cryptoRandom.NextInt(addresses.Count)];
                    if (_proposals.TryGetValue(header.Beneficiary !, out bool proposal))
                    {
                        header.Nonce = proposal ? Clique.NonceAuthVote : Clique.NonceDropVote;
                    }
                }
            }

            // Set the correct difficulty
            header.BaseFee         = BlockHeader.CalculateBaseFee(parentHeader, _specProvider.GetSpec(header.Number));
            header.Difficulty      = CalculateDifficulty(snapshot, _sealer.Address);
            header.TotalDifficulty = parentBlock.TotalDifficulty + header.Difficulty;
            if (_logger.IsDebug)
            {
                _logger.Debug($"Setting total difficulty to {parentBlock.TotalDifficulty} + {header.Difficulty}.");
            }

            // Set extra data
            int mainBytesLength   = Clique.ExtraVanityLength + Clique.ExtraSealLength;
            int signerBytesLength = isEpochBlock ? 20 * snapshot.Signers.Count : 0;
            int extraDataLength   = mainBytesLength + signerBytesLength;

            header.ExtraData = new byte[extraDataLength];

            byte[] clientName = Encoding.UTF8.GetBytes("Nethermind " + ClientVersion.Version);
            Array.Copy(clientName, header.ExtraData, clientName.Length);

            if (isEpochBlock)
            {
                for (int i = 0; i < snapshot.Signers.Keys.Count; i++)
                {
                    Address signer = snapshot.Signers.Keys[i];
                    int     index  = Clique.ExtraVanityLength + 20 * i;
                    Array.Copy(signer.Bytes, 0, header.ExtraData, index, signer.Bytes.Length);
                }
            }

            // Mix digest is reserved for now, set to empty
            header.MixHash = Keccak.Zero;
            // Ensure the timestamp has the correct delay
            header.Timestamp = parentBlock.Timestamp + _config.BlockPeriod;
            if (header.Timestamp < _timestamper.UnixTime.Seconds)
            {
                header.Timestamp = new UInt256(_timestamper.UnixTime.Seconds);
            }

            _stateProvider.StateRoot = parentHeader.StateRoot;

            var   selectedTxs = _txSource.GetTransactions(parentBlock.Header, header.GasLimit);
            Block block       = new Block(header, selectedTxs, Array.Empty <BlockHeader>());

            header.TxRoot       = new TxTrie(block.Transactions).RootHash;
            block.Header.Author = _sealer.Address;
            return(block);
        }