Beispiel #1
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,
                parent.GasLimit,
                UInt256.Max(parent.Timestamp + 1, Timestamper.Default.EpochSeconds),
                Encoding.UTF8.GetBytes("Nethermind"))
            {
                TotalDifficulty = parent.TotalDifficulty + difficulty
            };

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

            Block block = new Block(header, _pendingTxSelector.SelectTransactions(header.GasLimit), new BlockHeader[0]);

            header.TxRoot = new TxTrie(block.Transactions).RootHash;
            return(block);
        }
Beispiel #2
0
        public void SetUp()
        {
            _stepDelay = TimeSpan.FromMilliseconds(20);

            _pendingTxSelector   = Substitute.For <IPendingTxSelector>();
            _blockchainProcessor = Substitute.For <IBlockchainProcessor>();
            _sealer               = Substitute.For <ISealer>();
            _blockTree            = Substitute.For <IBlockTree>();
            _blockProcessingQueue = Substitute.For <IBlockProcessingQueue>();
            _stateProvider        = Substitute.For <IStateProvider>();
            _timestamper          = Substitute.For <ITimestamper>();
            _auRaStepCalculator   = Substitute.For <IAuRaStepCalculator>();
            _auraConfig           = Substitute.For <IAuraConfig>();
            _nodeAddress          = TestItem.AddressA;
            _auRaBlockProducer    = new AuRaBlockProducer(
                _pendingTxSelector,
                _blockchainProcessor,
                _stateProvider,
                _sealer,
                _blockTree,
                _blockProcessingQueue,
                _timestamper,
                LimboLogs.Instance, _auRaStepCalculator, _auraConfig, _nodeAddress);

            _auraConfig.ForceSealing.Returns(true);
            _pendingTxSelector.SelectTransactions(Arg.Any <long>()).Returns(Array.Empty <Transaction>());
            _sealer.CanSeal(Arg.Any <long>(), Arg.Any <Keccak>()).Returns(true);
            _sealer.SealBlock(Arg.Any <Block>(), Arg.Any <CancellationToken>()).Returns(c => Task.FromResult(c.Arg <Block>()));
            _blockProcessingQueue.IsEmpty.Returns(true);
            _auRaStepCalculator.TimeToNextStep.Returns(_stepDelay);
            _blockTree.BestKnownNumber.Returns(1);
            _blockTree.Head.Returns(Build.A.BlockHeader.WithAura(10, Bytes.Empty).TestObject);
            _blockchainProcessor.Process(Arg.Any <Block>(), ProcessingOptions.ProducingBlock, Arg.Any <IBlockTracer>()).Returns(c => c.Arg <Block>());
        }
        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.EpochSeconds;

            BlockHeader header = new BlockHeader(
                parentBlock.Hash,
                Keccak.OfAnEmptySequenceRlp,
                Address.Zero,
                1,
                parentBlock.Number + 1,
                parentBlock.GasLimit,
                timestamp > parentBlock.Timestamp ? timestamp : parentBlock.Timestamp + 1,
                new byte[0]);

            // 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)];
                    header.Nonce       = _proposals[header.Beneficiary] ? Clique.NonceAuthVote : Clique.NonceDropVote;
                }
            }

            // Set the correct difficulty
            header.Difficulty      = CalculateDifficulty(snapshot, _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.EpochSeconds)
            {
                header.Timestamp = new UInt256(_timestamper.EpochSeconds);
            }

            _stateProvider.StateRoot = parentHeader.StateRoot;

            var   selectedTxs = _pendingTxSelector.SelectTransactions(header.GasLimit);
            Block block       = new Block(header, selectedTxs, new BlockHeader[0]);

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