public void Best_suggested_block_gets_updated() { BlockTree blockTree = BuildBlockTree(); Block block0 = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject; Block block1 = Build.A.Block.WithNumber(1).WithDifficulty(2).WithParent(block0).TestObject; AddToMain(blockTree, block0); blockTree.SuggestBlock(block1); Assert.AreEqual(block0.Hash, BlockHeader.CalculateHash(blockTree.Head), "head block"); Assert.AreEqual(block1.Hash, BlockHeader.CalculateHash(blockTree.BestSuggested), "best suggested"); }
public async Task <Block> SealBlock(Block processed, CancellationToken cancellationToken) { Block sealedBlock = Seal(processed); if (sealedBlock == null) { return(null); } sealedBlock.Hash = BlockHeader.CalculateHash(sealedBlock.Header); return(await Task.FromResult(sealedBlock)); }
private Block CreateBlock(int splitVariant, int splitFrom, int blockIndex, Block parent, Address beneficiary) { Block current; if (_receiptStorage != null && blockIndex % 3 == 0) { Transaction[] transactions = new[] { Build.A.Transaction.WithValue(1).WithData(Rlp.Encode(blockIndex).Bytes).Signed(_ecdsa, TestItem.PrivateKeyA, blockIndex + 1).TestObject, Build.A.Transaction.WithValue(2).WithData(Rlp.Encode(blockIndex + 1).Bytes).Signed(_ecdsa, TestItem.PrivateKeyA, blockIndex + 1).TestObject }; current = Build.A.Block .WithNumber(blockIndex + 1) .WithParent(parent) .WithDifficulty(BlockHeaderBuilder.DefaultDifficulty - (splitFrom > parent.Number ? 0 : (ulong)splitVariant)) .WithTransactions(transactions) .WithBloom(new Bloom()) .WithBeneficiary(beneficiary) .TestObject; List <TxReceipt> receipts = new List <TxReceipt>(); foreach (var transaction in current.Transactions) { var logEntries = _logCreationFunction?.Invoke(current, transaction)?.ToArray() ?? Array.Empty <LogEntry>(); TxReceipt receipt = new TxReceipt { Logs = logEntries, TxHash = transaction.Hash, Bloom = new Bloom(logEntries) }; _receiptStorage.Add(receipt, false); receipts.Add(receipt); current.Bloom.Add(receipt.Logs); } current.Header.TxRoot = current.CalculateTxRoot(); current.Header.ReceiptsRoot = current.CalculateReceiptRoot(_specProvider, receipts.ToArray()); current.Hash = BlockHeader.CalculateHash(current); } else { current = Build.A.Block.WithNumber(blockIndex + 1) .WithParent(parent) .WithDifficulty(BlockHeaderBuilder.DefaultDifficulty - (splitFrom > parent.Number ? 0 : (ulong)splitVariant)) .WithBeneficiary(beneficiary) .TestObject; } current.Header.AuRaStep = blockIndex; return(current); }
public ResultWrapper <CallResultWithProof> proof_call(TransactionForRpc tx, BlockParameter blockParameter) { SearchResult <BlockHeader> searchResult = _blockFinder.SearchForHeader(blockParameter); if (searchResult.IsError) { return(ResultWrapper <CallResultWithProof> .Fail(searchResult)); } BlockHeader sourceHeader = searchResult.Object; BlockHeader callHeader = new BlockHeader( sourceHeader.Hash, Keccak.OfAnEmptySequenceRlp, Address.Zero, 0, sourceHeader.Number + 1, sourceHeader.GasLimit, sourceHeader.Timestamp, Array.Empty <byte>()); callHeader.TxRoot = Keccak.EmptyTreeHash; callHeader.ReceiptsRoot = Keccak.EmptyTreeHash; callHeader.Author = Address.SystemUser; callHeader.TotalDifficulty = sourceHeader.TotalDifficulty + callHeader.Difficulty; callHeader.Hash = callHeader.CalculateHash(); Transaction transaction = tx.ToTransaction(); transaction.SenderAddress ??= Address.SystemUser; if (transaction.GasLimit == 0) { transaction.GasLimit = callHeader.GasLimit; } Block block = new Block(callHeader, new[] { transaction }, Enumerable.Empty <BlockHeader>()); ProofBlockTracer proofBlockTracer = new ProofBlockTracer(null, transaction.SenderAddress == Address.SystemUser); _tracer.Trace(block, proofBlockTracer); CallResultWithProof callResultWithProof = new CallResultWithProof(); ProofTxTracer proofTxTracer = proofBlockTracer.BuildResult().Single(); callResultWithProof.BlockHeaders = CollectHeaderBytes(proofTxTracer, sourceHeader); callResultWithProof.Result = proofTxTracer.Output; // we collect proofs from before execution (after learning which addresses will be touched) // if we wanted to collect post execution proofs then we would need to use BeforeRestore on the tracer callResultWithProof.Accounts = CollectAccountProofs(sourceHeader.StateRoot, proofTxTracer); return(ResultWrapper <CallResultWithProof> .Success(callResultWithProof)); }
public void Best_suggested_block_gets_updated() { BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), OlympicSpecProvider.Instance, NullLogManager.Instance); Block block0 = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject; Block block1 = Build.A.Block.WithNumber(1).WithDifficulty(2).WithParent(block0).TestObject; AddToMain(blockTree, block0); blockTree.SuggestBlock(block1); Assert.AreEqual(block0.Hash, BlockHeader.CalculateHash(blockTree.Head), "head block"); Assert.AreEqual(block1.Hash, BlockHeader.CalculateHash(blockTree.BestSuggested), "best suggested"); }
public static Keccak CalculateCliqueHeaderHash(BlockHeader blockHeader) { int extraSeal = 65; int shortExtraLength = blockHeader.ExtraData.Length - extraSeal; byte[] fullExtraData = blockHeader.ExtraData; byte[] shortExtraData = blockHeader.ExtraData.Slice(0, shortExtraLength); blockHeader.ExtraData = shortExtraData; Keccak sigHash = BlockHeader.CalculateHash(blockHeader); blockHeader.ExtraData = fullExtraData; return(sigHash); }
public bool ValidateHash(BlockHeader header) { bool hashAsExpected = header.Hash == BlockHeader.CalculateHash(header); if (!hashAsExpected) { if (_logger.IsWarn) { _logger.Warn($"Invalid block header ({header.Hash}) - invalid block hash"); } } return(hashAsExpected); }
private static void LoadGenesisBlock( ChainSpec chainSpec, Keccak expectedGenesisHash, IBlockTree blockTree, IStateProvider stateProvider, ISpecProvider specProvider) { // if we already have a database with blocks then we do not need to load genesis from spec if (blockTree.Genesis != null) { return; } foreach (KeyValuePair <Address, UInt256> allocation in chainSpec.Allocations) { stateProvider.CreateAccount(allocation.Key, allocation.Value); } stateProvider.Commit(specProvider.GenesisSpec); Block genesis = chainSpec.Genesis; genesis.StateRoot = stateProvider.StateRoot; genesis.Hash = BlockHeader.CalculateHash(genesis.Header); ManualResetEventSlim genesisProcessedEvent = new ManualResetEventSlim(false); bool genesisLoaded = false; void GenesisProcessed(object sender, BlockEventArgs args) { genesisLoaded = true; blockTree.NewHeadBlock -= GenesisProcessed; genesisProcessedEvent.Set(); } blockTree.NewHeadBlock += GenesisProcessed; blockTree.SuggestBlock(genesis); genesisProcessedEvent.Wait(TimeSpan.FromSeconds(5)); if (!genesisLoaded) { throw new BlockchainException("Genesis block processing failure"); } // if expectedGenesisHash is null here then it means that we do not care about the exact value in advance (e.g. in test scenarios) if (expectedGenesisHash != null && blockTree.Genesis.Hash != expectedGenesisHash) { throw new Exception($"Unexpected genesis hash, expected {expectedGenesisHash}, but was {blockTree.Genesis.Hash}"); } }
public void Stores_multiple_blocks_per_level() { BlockTree blockTree = BuildBlockTree(); Block block0 = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject; Block block1 = Build.A.Block.WithNumber(1).WithDifficulty(2).WithParent(block0).TestObject; Block block1B = Build.A.Block.WithNumber(1).WithDifficulty(3).WithParent(block0).TestObject; AddToMain(blockTree, block0); AddToMain(blockTree, block1); blockTree.SuggestBlock(block1B); Block found = blockTree.FindBlock(block1B.Hash, false); Assert.AreEqual(block1B.Hash, BlockHeader.CalculateHash(found.Header)); }
public void Find_by_number_basic() { BlockTree blockTree = BuildBlockTree(); Block block0 = Build.A.Block.WithNumber(0).TestObject; Block block1 = Build.A.Block.WithNumber(1).WithParent(block0).TestObject; Block block2 = Build.A.Block.WithNumber(2).WithParent(block1).TestObject; AddToMain(blockTree, block0); AddToMain(blockTree, block1); AddToMain(blockTree, block2); Block found = blockTree.FindBlock(2); Assert.AreEqual(block2.Hash, BlockHeader.CalculateHash(found.Header)); }
public void Can_decode() { BlockHeader header = Build.A.BlockHeader .WithMixHash(Keccak.Compute("mix_hash")) .WithNonce(1000) .TestObject; HeaderDecoder decoder = new HeaderDecoder(); Rlp rlp = decoder.Encode(header); BlockHeader decoded = decoder.Decode(new Rlp.ValueDecoderContext(rlp.Bytes)); decoded.Hash = BlockHeader.CalculateHash(decoded); Assert.AreEqual(header.Hash, decoded.Hash, "hash"); }
public void Stores_multiple_blocks_per_level() { BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), OlympicSpecProvider.Instance, NullLogManager.Instance); Block block0 = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject; Block block1 = Build.A.Block.WithNumber(1).WithDifficulty(2).WithParent(block0).TestObject; Block block1B = Build.A.Block.WithNumber(1).WithDifficulty(3).WithParent(block0).TestObject; AddToMain(blockTree, block0); AddToMain(blockTree, block1); blockTree.SuggestBlock(block1B); Block found = blockTree.FindBlock(block1B.Hash, false); Assert.AreEqual(block1B.Hash, BlockHeader.CalculateHash(found.Header)); }
public void Find_by_number_basic() { BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), OlympicSpecProvider.Instance, NullLogManager.Instance); Block block0 = Build.A.Block.WithNumber(0).TestObject; Block block1 = Build.A.Block.WithNumber(1).WithParent(block0).TestObject; Block block2 = Build.A.Block.WithNumber(2).WithParent(block1).TestObject; AddToMain(blockTree, block0); AddToMain(blockTree, block1); AddToMain(blockTree, block2); Block found = blockTree.FindBlock(2); Assert.AreEqual(block2.Hash, BlockHeader.CalculateHash(found.Header)); }
private Block ProcessOne(Block suggestedBlock, ProcessingOptions options, IBlockTracer blockTracer) { if (suggestedBlock.IsGenesis) { return(suggestedBlock); } if (_specProvider.DaoBlockNumber.HasValue && _specProvider.DaoBlockNumber.Value == suggestedBlock.Header.Number) { if (_logger.IsInfo) { _logger.Info("Applying DAO transition"); } ApplyDaoTransition(); } Block block = PrepareBlockForProcessing(suggestedBlock); var receipts = ProcessTransactions(block, options, blockTracer); SetReceiptsRootAndBloom(block, receipts); ApplyMinerRewards(block, blockTracer); _stateProvider.Commit(_specProvider.GetSpec(block.Number)); block.Header.StateRoot = _stateProvider.StateRoot; block.Header.Hash = BlockHeader.CalculateHash(block.Header); if ((options & ProcessingOptions.NoValidation) == 0 && !_blockValidator.ValidateProcessedBlock(block, receipts, suggestedBlock)) { if (_logger.IsError) { _logger.Error($"Processed block is not valid {suggestedBlock.ToString(Block.Format.FullHashAndNumber)}"); } throw new InvalidBlockException(suggestedBlock.Hash); } if ((options & ProcessingOptions.StoreReceipts) != 0) { StoreTxReceipts(block, receipts); } if ((options & ProcessingOptions.StoreTraces) != 0) { StoreTraces(blockTracer as ParityLikeBlockTracer); } BlockProcessed?.Invoke(this, new BlockProcessedEventArgs(block)); return(block); }
public void Find_sequence_basic_skip() { BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), OlympicSpecProvider.Instance, NullLogManager.Instance); Block block0 = Build.A.Block.WithNumber(0).TestObject; Block block1 = Build.A.Block.WithNumber(1).WithParent(block0).TestObject; Block block2 = Build.A.Block.WithNumber(2).WithParent(block1).TestObject; AddToMain(blockTree, block0); AddToMain(blockTree, block1); AddToMain(blockTree, block2); Block[] blocks = blockTree.FindBlocks(block0.Hash, 2, 1, false); Assert.AreEqual(2, blocks.Length, "length"); Assert.AreEqual(block0.Hash, BlockHeader.CalculateHash(blocks[0].Header)); Assert.AreEqual(block2.Hash, BlockHeader.CalculateHash(blocks[1].Header)); }
public void Find_sequence_basic_skip() { BlockTree blockTree = BuildBlockTree(); Block block0 = Build.A.Block.WithNumber(0).TestObject; Block block1 = Build.A.Block.WithNumber(1).WithParent(block0).TestObject; Block block2 = Build.A.Block.WithNumber(2).WithParent(block1).TestObject; AddToMain(blockTree, block0); AddToMain(blockTree, block1); AddToMain(blockTree, block2); Block[] blocks = blockTree.FindBlocks(block0.Hash, 2, 1, false); Assert.AreEqual(2, blocks.Length, "length"); Assert.AreEqual(block0.Hash, BlockHeader.CalculateHash(blocks[0].Header)); Assert.AreEqual(block2.Hash, BlockHeader.CalculateHash(blocks[1].Header)); }
public async Task seal_can_recover_address() { _auRaStepCalculator.CurrentStep.Returns(11); _auRaValidator.IsValidSealer(_address, 11).Returns(true); var block = Build.A.Block.WithHeader(Build.A.BlockHeader.WithBeneficiary(_address).WithAura(11, null).TestObject).TestObject; block = await _auRaSealer.SealBlock(block, CancellationToken.None); var ecdsa = new EthereumEcdsa(new MordenSpecProvider(), NullLogManager.Instance); var signature = new Signature(block.Header.AuRaSignature); signature.V += Signature.VOffset; var recoveredAddress = ecdsa.RecoverAddress(signature, BlockHeader.CalculateHash(block.Header, RlpBehaviors.ForSealing)); recoveredAddress.Should().Be(_address); }
public void Can_decode_aura() { var auRaSignature = new byte[64]; new Random().NextBytes(auRaSignature); BlockHeader header = Build.A.BlockHeader .WithAura(100000000, auRaSignature) .TestObject; HeaderDecoder decoder = new HeaderDecoder(); Rlp rlp = decoder.Encode(header); BlockHeader decoded = decoder.Decode(new Rlp.ValueDecoderContext(rlp.Bytes)); decoded.Hash = BlockHeader.CalculateHash(decoded); Assert.AreEqual(header.Hash, decoded.Hash, "hash"); }
public void Find_sequence_reverse() { BlockTree blockTree = BuildBlockTree(); Block block0 = Build.A.Block.WithNumber(0).TestObject; Block block1 = Build.A.Block.WithNumber(1).WithParent(block0).TestObject; Block block2 = Build.A.Block.WithNumber(2).WithParent(block1).TestObject; AddToMain(blockTree, block0); AddToMain(blockTree, block1); AddToMain(blockTree, block2); Block[] blocks = blockTree.FindBlocks(block2.Hash, 3, 0, true); Assert.AreEqual(3, blocks.Length); Assert.AreEqual(block2.Hash, BlockHeader.CalculateHash(blocks[0].Header)); Assert.AreEqual(block0.Hash, BlockHeader.CalculateHash(blocks[2].Header)); }
public bool validate_seal(long blockNumber, Address signedAddress, Address recoveredAddress) { signedAddress ??= _address; recoveredAddress ??= _address; var block = Build.A.BlockHeader .WithAura(10, Bytes.Empty) .WithBeneficiary(_address) .WithNumber(blockNumber) .TestObject; var hash = BlockHeader.CalculateHash(block, RlpBehaviors.ForSealing); block.AuRaSignature = _wallet.Sign(hash, signedAddress).BytesWithRecovery; _ethereumEcdsa.RecoverAddress(Arg.Any <Signature>(), hash).Returns(recoveredAddress); return(_sealValidator.ValidateSeal(block)); }
private Block Seal(Block block) { // Bail out if we're unauthorized to sign a block if (!CanSeal(block.Number, block.ParentHash)) { if (_logger.IsInfo) { _logger.Info($"Not authorized to seal the block {block.ToString(Block.Format.Short)}"); } return(null); } var headerHash = BlockHeader.CalculateHash(block.Header, RlpBehaviors.ForSealing); var signature = _wallet.Sign(headerHash, _nodeAddress); block.Header.AuRaSignature = signature.BytesWithRecovery; return(block); }
private Block CreateBlock(int blockDifficulty, int blockNumber, Block lastBlock) { Keccak parentHash = lastBlock.Hash; Keccak ommersHash = Keccak.OfAnEmptySequenceRlp; Address beneficiary = Address.Zero; UInt256 difficulty = new UInt256(blockDifficulty); long number = blockNumber; int gasLimit = 4700000; UInt256 timestamp = new UInt256(DateTimeOffset.UtcNow.ToUnixTimeSeconds()); byte[] extraData = Bytes.FromHexString("d883010812846765746888676f312e31312e31856c696e75780000000000000028eb026ab5355b45499053382886754f1db544618d45edc979de1864d83a626b77513bd34d7f21059e79e303c3ab210e1424e71bcb8347835cbd378a785a06f800"); BlockHeader header = new BlockHeader(parentHash, ommersHash, beneficiary, difficulty, number, gasLimit, timestamp, extraData); header.MixHash = Keccak.Zero; Block block = new Block(header, new BlockHeader[0]); block.Hash = BlockHeader.CalculateHash(block); block.Header.Hash = BlockHeader.CalculateHash(block.Header); return(block); }
private Block GetRinkebyGenesis() { Keccak parentHash = Keccak.Zero; Keccak ommersHash = Keccak.OfAnEmptySequenceRlp; Address beneficiary = Address.Zero; UInt256 difficulty = new UInt256(1); long number = 0L; int gasLimit = 4700000; UInt256 timestamp = new UInt256(1492009146); byte[] extraData = Bytes.FromHexString(GetGenesisExtraData()); BlockHeader header = new BlockHeader(parentHash, ommersHash, beneficiary, difficulty, number, gasLimit, timestamp, extraData); Block genesis = new Block(header, new BlockHeader[0]); genesis.Hash = BlockHeader.CalculateHash(genesis); // this would need to be loaded from rinkeby chainspec to include allocations // Assert.AreEqual(new Keccak("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177"), genesis.Hash); genesis.Header.Hash = BlockHeader.CalculateHash(genesis.Header); return(genesis); }
public async Task Find_nonce() { BlockHeader parentHeader = new BlockHeader(Keccak.Zero, Keccak.OfAnEmptySequenceRlp, Address.Zero, 131072, 0, 21000, 0, new byte[] { }); parentHeader.Hash = parentHeader.CalculateHash(); BlockHeader blockHeader = new BlockHeader(parentHeader.Hash, Keccak.OfAnEmptySequenceRlp, Address.Zero, 131136, 1, 21000, 1, new byte[] { }); blockHeader.Nonce = 7217048144105167954; blockHeader.MixHash = new Keccak("0x37d9fb46a55e9dbbffc428f3a1be6f191b3f8eaf52f2b6f53c4b9bae62937105"); blockHeader.Hash = blockHeader.CalculateHash(); Block block = new Block(blockHeader); IEthash ethash = new Ethash(LimboLogs.Instance); EthashSealer ethashSealer = new EthashSealer(ethash, LimboLogs.Instance); await ethashSealer.MineAsync(CancellationToken.None, block, 7217048144105167954); Assert.True(ethash.Validate(block.Header)); Console.WriteLine(block.Header.Nonce); Console.WriteLine(block.Header.MixHash); }
internal async Task <Block> MineAsync(CancellationToken cancellationToken, Block processed, ulong?startNonce) { if (processed.Header.TransactionsRoot == null || processed.Header.StateRoot == null || processed.Header.ReceiptsRoot == null || processed.Header.OmmersHash == null || processed.Header.Bloom == null || processed.Header.ExtraData == null) { throw new InvalidOperationException($"Requested to mine an invalid block {processed.Header}"); } Task <Block> miningTask = Task.Factory.StartNew(() => Mine(processed, startNonce), cancellationToken); await miningTask.ContinueWith( t => { if (t.IsCompleted) { t.Result.Header.Hash = BlockHeader.CalculateHash(t.Result.Header); } }, cancellationToken, TaskContinuationOptions.NotOnFaulted, TaskScheduler.Default); return(await miningTask); }
public void Hash_as_expected_2() { BlockHeader header = new BlockHeader(); header.Bloom = new Bloom( Bytes.FromHexString("0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")); header.Beneficiary = new Address("0x8888f1f195afa192cfee860698584c030f4c9db1"); header.Difficulty = Bytes.FromHexString("0x020080").ToUInt256(); header.ExtraData = Bytes.Empty; header.GasLimit = (long)Bytes.FromHexString("0x2fefba").ToUnsignedBigInteger(); header.GasUsed = (long)Bytes.FromHexString("0x5208").ToUnsignedBigInteger(); header.MixHash = new Keccak(Bytes.FromHexString("0x615bbf44eb133eab3cb24d5766ae9617d9e45ee00e7a5667db30672b47d22149")); header.Nonce = (ulong)Bytes.FromHexString("0x4c4f3d3e055cb264").ToUnsignedBigInteger(); header.Number = (long)Bytes.FromHexString("0x03").ToUInt256(); header.ParentHash = new Keccak(Bytes.FromHexString("0xde1457da701ef916533750d46c124e9ae50b974410bd590fbcf4c935a4d19465")); header.ReceiptsRoot = new Keccak(Bytes.FromHexString("0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2")); header.StateRoot = new Keccak(Bytes.FromHexString("0xfb4084a7f8b57e370fefe24a3da3aaea6c4dd8b6f6251916c32440336035160b")); header.Timestamp = Bytes.FromHexString("0x59d79f1c").ToUInt256(); header.TxRoot = new Keccak(Bytes.FromHexString("0x1722b8a91bfc4f5614ce36ee77c7cce6620ab4af36d3c54baa66d7dbeb7bce1a")); header.OmmersHash = new Keccak(Bytes.FromHexString("0xe676a42c388d2d24bb2927605d5d5d82fba50fb60d74d44b1cd7d1c4e4eee3c0")); header.Hash = header.CalculateHash(); Assert.AreEqual(new Keccak(Bytes.FromHexString("0x1423c2875714c31049cacfea8450f66a73ecbd61d7a6ab13089406a491aa9fc2")), header.Hash); }
public void Hash_as_expected() { BlockHeader header = new BlockHeader(); header.Bloom = new Bloom( Bytes.FromHexString("0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") .AsSpan().ToBigEndianBitArray2048()); header.Beneficiary = new Address("0x8888f1f195afa192cfee860698584c030f4c9db1"); header.Difficulty = Bytes.FromHexString("0x020000").ToUInt256(); header.ExtraData = Bytes.Empty; header.GasLimit = (long)Bytes.FromHexString("0x2fefba").ToUnsignedBigInteger(); header.GasUsed = (long)Bytes.FromHexString("0x5208").ToUnsignedBigInteger(); header.MixHash = new Keccak(Bytes.FromHexString("0x00be1f287e0911ea2f070b3650a1a0346535895b6c919d7e992a0c255a83fc8b")); header.Nonce = (ulong)Bytes.FromHexString("0xa0ddc06c6d7b9f48").ToUnsignedBigInteger(); header.Number = (long)Bytes.FromHexString("0x01").ToUInt256(); header.ParentHash = new Keccak(Bytes.FromHexString("0x5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae")); header.ReceiptsRoot = new Keccak(Bytes.FromHexString("0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2")); header.StateRoot = new Keccak(Bytes.FromHexString("0x5c2e5a51a79da58791cdfe572bcfa3dfe9c860bf7fad7d9738a1aace56ef9332")); header.Timestamp = Bytes.FromHexString("0x59d79f18").ToUInt256(); header.TxRoot = new Keccak(Bytes.FromHexString("0x5c9151c2413d1cd25c51ffb4ac38948acc1359bf08c6b49f283660e9bcf0f516")); header.OmmersHash = new Keccak(Bytes.FromHexString("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")); Assert.AreEqual(new Keccak(Bytes.FromHexString("0x19a24085f6b1fb174aee0463264cc7163a7ffa165af04d3f40431ab3c3b08b98")), BlockHeader.CalculateHash(header)); }
private Block ProcessNonGenesis(Block suggestedBlock, bool tryOnly) { if (_specProvider.DaoBlockNumber.HasValue && _specProvider.DaoBlockNumber.Value == suggestedBlock.Header.Number) { if (_logger.IsInfoEnabled) { _logger.Info($"Applying DAO transition"); } ApplyDaoTransition(); } // TODO: should be precalculated Keccak transactionsRoot = GetTransactionsRoot(suggestedBlock.Transactions); if (transactionsRoot != suggestedBlock.Header.TransactionsRoot) { if (_logger.IsDebugEnabled) { _logger.Debug($"TRANSACTIONS_ROOT {transactionsRoot} != TRANSACTIONS_ROOT {transactionsRoot}"); } } if (_logger.IsDebugEnabled) { _logger.Debug($"Block beneficiary {suggestedBlock.Header.Beneficiary}"); _logger.Debug($"Block gas limit {suggestedBlock.Header.GasLimit}"); _logger.Debug($"Block gas used {suggestedBlock.Header.GasUsed}"); _logger.Debug($"Block difficulty {suggestedBlock.Header.Difficulty}"); } Block processedBlock = ProcessBlock( suggestedBlock.Header.ParentHash, suggestedBlock.Header.Difficulty, suggestedBlock.Header.Number, suggestedBlock.Header.Timestamp, suggestedBlock.Header.Beneficiary, suggestedBlock.Header.GasLimit, suggestedBlock.Header.ExtraData, suggestedBlock.Transactions, suggestedBlock.Header.MixHash, suggestedBlock.Header.Nonce, suggestedBlock.Header.OmmersHash, suggestedBlock.Ommers); processedBlock.Transactions = suggestedBlock.Transactions; processedBlock.Header.TransactionsRoot = transactionsRoot; processedBlock.Header.Hash = BlockHeader.CalculateHash(processedBlock.Header); if (!tryOnly && !_blockValidator.ValidateProcessedBlock(processedBlock, suggestedBlock)) { if (_logger.IsErrorEnabled) { _logger.Error($"Processed block is not valid {processedBlock.ToString(Block.Format.Short)}"); } throw new InvalidBlockException($"{processedBlock}"); } if (_logger.IsDebugEnabled) { _logger.Debug($"Committing block - state root {_stateProvider.StateRoot}"); } return(processedBlock); }
public On CreateNode(PrivateKey privateKey, bool withGenesisAlreadyProcessed = false) { if (_logger.IsInfo) { _logger.Info($"CREATING NODE {privateKey.Address}"); } _logManagers[privateKey] = LimboLogs.Instance; // _logManagers[privateKey] = new OneLoggerLogManager(new ConsoleAsyncLogger(LogLevel.Debug, $"{privateKey.Address} ")); var nodeLogManager = _logManagers[privateKey]; AutoResetEvent newHeadBlockEvent = new AutoResetEvent(false); _blockEvents.Add(privateKey, newHeadBlockEvent); MemDb blocksDb = new MemDb(); MemDb headersDb = new MemDb(); MemDb blockInfoDb = new MemDb(); TxPool txPool = new TxPool(new InMemoryTransactionStorage(), new PendingTransactionThresholdValidator(), _timestamp, _ethereumEcdsa, GoerliSpecProvider.Instance, _logManager); _pools[privateKey] = txPool; BlockTree blockTree = new BlockTree(blocksDb, headersDb, blockInfoDb, GoerliSpecProvider.Instance, txPool, nodeLogManager); blockTree.NewHeadBlock += (sender, args) => { _blockEvents[privateKey].Set(); }; BlockhashProvider blockhashProvider = new BlockhashProvider(blockTree); _blockTrees.Add(privateKey, blockTree); IBasicWallet wallet = new BasicWallet(privateKey); SnapshotManager snapshotManager = new SnapshotManager(_cliqueConfig, blocksDb, blockTree, _ethereumEcdsa, nodeLogManager); _snapshotManager[privateKey] = snapshotManager; CliqueSealer cliqueSealer = new CliqueSealer(wallet, _cliqueConfig, snapshotManager, privateKey.Address, nodeLogManager); ISnapshotableDb stateDb = new StateDb(); ISnapshotableDb codeDb = new StateDb(); IDb traceDb = new MemDb(); StateProvider stateProvider = new StateProvider(stateDb, codeDb, nodeLogManager); stateProvider.CreateAccount(TestItem.PrivateKeyD.Address, 100.Ether()); stateProvider.Commit(GoerliSpecProvider.Instance.GenesisSpec); _genesis.StateRoot = _genesis3Validators.StateRoot = stateProvider.StateRoot; _genesis.Hash = BlockHeader.CalculateHash(_genesis.Header); _genesis3Validators.Hash = BlockHeader.CalculateHash(_genesis3Validators.Header); StorageProvider storageProvider = new StorageProvider(stateDb, stateProvider, nodeLogManager); TransactionProcessor transactionProcessor = new TransactionProcessor(GoerliSpecProvider.Instance, stateProvider, storageProvider, new VirtualMachine(stateProvider, storageProvider, blockhashProvider, nodeLogManager), nodeLogManager); BlockProcessor blockProcessor = new BlockProcessor(GoerliSpecProvider.Instance, TestBlockValidator.AlwaysValid, NoBlockRewards.Instance, transactionProcessor, stateDb, codeDb, traceDb, stateProvider, storageProvider, txPool, NullReceiptStorage.Instance, new SyncConfig(), nodeLogManager); BlockchainProcessor processor = new BlockchainProcessor(blockTree, blockProcessor, new AuthorRecoveryStep(snapshotManager), nodeLogManager, false, false); processor.Start(); StateProvider minerStateProvider = new StateProvider(stateDb, codeDb, nodeLogManager); StorageProvider minerStorageProvider = new StorageProvider(stateDb, minerStateProvider, nodeLogManager); VirtualMachine minerVirtualMachine = new VirtualMachine(minerStateProvider, minerStorageProvider, blockhashProvider, nodeLogManager); TransactionProcessor minerTransactionProcessor = new TransactionProcessor(GoerliSpecProvider.Instance, minerStateProvider, minerStorageProvider, minerVirtualMachine, nodeLogManager); BlockProcessor minerBlockProcessor = new BlockProcessor(GoerliSpecProvider.Instance, TestBlockValidator.AlwaysValid, NoBlockRewards.Instance, minerTransactionProcessor, stateDb, codeDb, traceDb, minerStateProvider, minerStorageProvider, txPool, NullReceiptStorage.Instance, new SyncConfig(), nodeLogManager); BlockchainProcessor minerProcessor = new BlockchainProcessor(blockTree, minerBlockProcessor, new AuthorRecoveryStep(snapshotManager), nodeLogManager, false, false); if (withGenesisAlreadyProcessed) { ProcessGenesis(privateKey); } CliqueBlockProducer blockProducer = new CliqueBlockProducer(txPool, minerProcessor, blockTree, _timestamp, new CryptoRandom(), minerStateProvider, snapshotManager, cliqueSealer, privateKey.Address, _cliqueConfig, nodeLogManager); blockProducer.Start(); _producers.Add(privateKey, blockProducer); return(this); }
public async Task Can_process_mined_blocks() { int timeMultiplier = 1; // for debugging TimeSpan miningDelay = TimeSpan.FromMilliseconds(50 * timeMultiplier); /* logging & instrumentation */ // OneLoggerLogManager logger = new OneLoggerLogManager(new SimpleConsoleLogger(true)); ILogManager logManager = NullLogManager.Instance; ILogger logger = logManager.GetClassLogger(); /* spec */ FakeSealer sealer = new FakeSealer(miningDelay); RopstenSpecProvider specProvider = RopstenSpecProvider.Instance; /* store & validation */ EthereumEcdsa ecdsa = new EthereumEcdsa(specProvider, logManager); MemDb receiptsDb = new MemDb(); MemDb traceDb = new MemDb(); TxPool txPool = new TxPool(NullTxStorage.Instance, Timestamp.Default, ecdsa, specProvider, new TxPoolConfig(), logManager); IReceiptStorage receiptStorage = new PersistentReceiptStorage(receiptsDb, NullDb.Instance, specProvider, logManager); BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), specProvider, txPool, logManager); Timestamp timestamp = new Timestamp(); DifficultyCalculator difficultyCalculator = new DifficultyCalculator(specProvider); HeaderValidator headerValidator = new HeaderValidator(blockTree, sealer, specProvider, logManager); OmmersValidator ommersValidator = new OmmersValidator(blockTree, headerValidator, logManager); TxValidator txValidator = new TxValidator(ChainId.Ropsten); BlockValidator blockValidator = new BlockValidator(txValidator, headerValidator, ommersValidator, specProvider, logManager); /* state & storage */ StateDb codeDb = new StateDb(); StateDb stateDb = new StateDb(); StateProvider stateProvider = new StateProvider(stateDb, codeDb, logManager); StorageProvider storageProvider = new StorageProvider(stateDb, stateProvider, logManager); TestTransactionsGenerator generator = new TestTransactionsGenerator(txPool, ecdsa, TimeSpan.FromMilliseconds(5 * timeMultiplier), NullLogManager.Instance); generator.Start(); /* blockchain processing */ BlockhashProvider blockhashProvider = new BlockhashProvider(blockTree, LimboLogs.Instance); VirtualMachine virtualMachine = new VirtualMachine(stateProvider, storageProvider, blockhashProvider, logManager); TransactionProcessor processor = new TransactionProcessor(specProvider, stateProvider, storageProvider, virtualMachine, logManager); RewardCalculator rewardCalculator = new RewardCalculator(specProvider); BlockProcessor blockProcessor = new BlockProcessor(specProvider, blockValidator, rewardCalculator, processor, stateDb, codeDb, traceDb, stateProvider, storageProvider, txPool, receiptStorage, logManager); BlockchainProcessor blockchainProcessor = new BlockchainProcessor(blockTree, blockProcessor, new TxSignaturesRecoveryStep(ecdsa, NullTxPool.Instance, LimboLogs.Instance), logManager, false, false); /* load ChainSpec and init */ ChainSpecLoader loader = new ChainSpecLoader(new EthereumJsonSerializer()); string path = "chainspec.json"; logManager.GetClassLogger().Info($"Loading ChainSpec from {path}"); ChainSpec chainSpec = loader.Load(File.ReadAllBytes(path)); foreach (var allocation in chainSpec.Allocations) { stateProvider.CreateAccount(allocation.Key, allocation.Value.Balance); if (allocation.Value.Code != null) { Keccak codeHash = stateProvider.UpdateCode(allocation.Value.Code); stateProvider.UpdateCodeHash(allocation.Key, codeHash, specProvider.GenesisSpec); } } stateProvider.Commit(specProvider.GenesisSpec); chainSpec.Genesis.Header.StateRoot = stateProvider.StateRoot; // TODO: shall it be HeaderSpec and not BlockHeader? chainSpec.Genesis.Header.Hash = BlockHeader.CalculateHash(chainSpec.Genesis.Header); if (chainSpec.Genesis.Hash != new Keccak("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d")) { throw new Exception("Unexpected genesis hash"); } /* start processing */ blockTree.SuggestBlock(chainSpec.Genesis); blockchainProcessor.Start(); MinedBlockProducer minedBlockProducer = new MinedBlockProducer(difficultyCalculator, txPool, blockchainProcessor, sealer, blockTree, timestamp, NullLogManager.Instance); minedBlockProducer.Start(); ManualResetEventSlim manualResetEvent = new ManualResetEventSlim(false); blockTree.NewHeadBlock += (sender, args) => { if (args.Block.Number == 6) { manualResetEvent.Set(); } }; manualResetEvent.Wait(miningDelay * 12 * timeMultiplier); await minedBlockProducer.StopAsync(); int previousCount = 0; int totalTx = 0; for (int i = 0; i < 6; i++) { Block block = blockTree.FindBlock(i); logger.Info($"Block {i} with {block.Transactions.Length} txs"); ManualResetEventSlim blockProcessedEvent = new ManualResetEventSlim(false); blockchainProcessor.ProcessingQueueEmpty += (sender, args) => blockProcessedEvent.Set(); blockchainProcessor.SuggestBlock(block, ProcessingOptions.ForceProcessing | ProcessingOptions.StoreReceipts | ProcessingOptions.ReadOnlyChain); blockProcessedEvent.Wait(1000); Tracer tracer = new Tracer(blockchainProcessor, receiptStorage, blockTree, new MemDb()); int currentCount = receiptsDb.Keys.Count; logger.Info($"Current count of receipts {currentCount}"); logger.Info($"Previous count of receipts {previousCount}"); if (block.Transactions.Length > 0) { GethLikeTxTrace trace = tracer.Trace(block.Transactions[0].Hash); Assert.AreSame(GethLikeTxTrace.QuickFail, trace); Assert.AreNotEqual(previousCount, currentCount, $"receipts at block {i}"); totalTx += block.Transactions.Length; } previousCount = currentCount; } Assert.AreNotEqual(0, totalTx, "no tx in blocks"); }