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(); } }
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(); } }
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); } } }
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); }
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); }
public IEnumerable <Transaction> GetTransactions(BlockHeader parent, long gasLimit) { foreach (Transaction transaction in _txSource.GetTransactions(parent, gasLimit)) { yield return(transaction); break; } }
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; } } }
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); });
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; })); }
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); }
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; })); }
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); }
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);
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); }