public void DetermineStateRootHash() { Address address = _contents.Tx0InBlock1.Signer; var blockAction = new SetStatesAtBlock(address, (Bencodex.Types.Integer) 123, 0); var policy = new BlockPolicy <Arithmetic>( blockAction: blockAction, blockInterval: TimeSpan.FromMilliseconds(3 * 60 * 60 * 1000), minimumDifficulty: 2, difficultyStability: 1 ); var stagePolicy = new VolatileStagePolicy <Arithmetic>(); PreEvaluationBlock <Arithmetic> preEvalGenesis = _contents.Genesis.Mine(policy.GetHashAlgorithm(0)); using (var fx = new DefaultStoreFixture()) { HashDigest <SHA256> genesisStateRootHash = preEvalGenesis.DetermineStateRootHash(blockAction, fx.StateStore); _output.WriteLine("#0 StateRootHash: {0}", genesisStateRootHash); Block <Arithmetic> genesis = preEvalGenesis.Sign(_contents.GenesisKey, genesisStateRootHash); _output.WriteLine("#1: {0}", genesis); var blockChain = new BlockChain <Arithmetic>( policy, stagePolicy, fx.Store, fx.StateStore, genesis ); AssertBencodexEqual((Bencodex.Types.Integer) 123, blockChain.GetState(address)); HashDigest <SHA256> identicalGenesisStateRootHash = preEvalGenesis.DetermineStateRootHash(blockChain); AssertBytesEqual(genesisStateRootHash, identicalGenesisStateRootHash); BlockContent <Arithmetic> content1 = _contents.Block1; content1.PreviousHash = genesis.Hash; content1.Difficulty = 2; content1.Transactions = new[] { _contents.Tx0InBlock1 }; PreEvaluationBlock <Arithmetic> preEval1 = content1.Mine(policy.GetHashAlgorithm(1)); HashDigest <SHA256> b1StateRootHash = preEval1.DetermineStateRootHash(blockChain); _output.WriteLine("#1 StateRootHash: {0}", b1StateRootHash); Block <Arithmetic> block1 = preEval1.Sign(_contents.Block1Key, b1StateRootHash); _output.WriteLine("#1: {0}", block1); blockChain.Append(block1); AssertBencodexEqual((Bencodex.Types.Integer) 158, blockChain.GetState(address)); } }
public override BlockChain <DumbAction> TransferAssetInBlock() { BlockChain <DumbAction> chain = base.TransferAssetInBlock(); DumbAction action = new DumbAction(_addr[0], "a", _addr[0], _addr[0], 1); Transaction <DumbAction> tx = Transaction <DumbAction> .Create( chain.GetNextTxNonce(_addr[0]), _keys[0], chain.Genesis.Hash, new[] { action } ); PreEvaluationBlock <DumbAction> preEval = TestUtils.MineNext( chain.Tip, chain.Policy.GetHashAlgorithm, new[] { tx }, miner: _keys[1].PublicKey, protocolVersion: ProtocolVersion ); chain.Append( new Block <DumbAction>( preEval, preEval.DetermineStateRootHash(chain), signature: null ) ); Assert.Equal( DumbAction.DumbCurrency * 6, chain.GetBalance(_addr[0], DumbAction.DumbCurrency) ); return(chain); }
public static BlockChain <T> MakeBlockChain <T>( IBlockPolicy <T> policy, IStore store, IStateStore stateStore, IEnumerable <T> actions = null, PrivateKey privateKey = null, DateTimeOffset?timestamp = null, IEnumerable <IRenderer <T> > renderers = null, Block <T> genesisBlock = null, int protocolVersion = Block <T> .CurrentProtocolVersion ) where T : IAction, new() { actions = actions ?? ImmutableArray <T> .Empty; privateKey = privateKey ?? ChainPrivateKey; var tx = Transaction <T> .Create( 0, privateKey, null, actions, timestamp : timestamp ?? DateTimeOffset.MinValue); if (genesisBlock is null) { var content = new BlockContent <T>() { Miner = GenesisMiner.ToAddress(), PublicKey = protocolVersion < 2 ? null : GenesisMiner.PublicKey, Timestamp = timestamp ?? DateTimeOffset.MinValue, Transactions = new[] { tx }, ProtocolVersion = protocolVersion, }; var preEval = new PreEvaluationBlock <T>( content, policy.GetHashAlgorithm(0), new Nonce(new byte[] { 0x01, 0x00, 0x00, 0x00 }) ); genesisBlock = protocolVersion < 2 ? new Block <T>( preEval, preEval.DetermineStateRootHash(policy.BlockAction, stateStore), signature: null) : preEval.Evaluate(GenesisMiner, policy.BlockAction, stateStore); } ValidatingActionRenderer <T> validator = null; #pragma warning disable S1121 var chain = new BlockChain <T>( policy, new VolatileStagePolicy <T>(), store, stateStore, genesisBlock, renderers: renderers ?? new[] { validator = new ValidatingActionRenderer <T>() } ); #pragma warning restore S1121 if (validator != null) { validator.BlockChain = chain; } return(chain); }
public void Rebuild( [Option('v', Description = "Print more logs.")] bool verbose, [Option('s', Description = "Path to the chain store.")] string storePath, [Option('c', Description = "Optional chain ID. Default is the canonical chain ID.")] Guid?chainId = null, [Option( 't', Description = "Optional topmost block to execute last. Can be either a block " + "hash or block index. Tip by default.")] string topmost = null, [Option( new char[] { 'f', 'B' }, Description = "Optional bottommost block to execute first. Can be either a " + "block hash or block index. Genesis by default.")] string bottommost = null, [Option('b', Description = "Bypass the state root hash check.")] bool bypassStateRootHashCheck = false, [Option( 'm', Description = "Use the in-memory key-value state store and dump it to " + "the specified directory path in the end.", ValueName = "DIR")] string useMemoryKvStore = null ) { using Logger logger = Utils.ConfigureLogger(verbose); CancellationToken cancellationToken = GetInterruptSignalCancellationToken(); TextWriter stderr = Console.Error; ( BlockChain <NCAction> chain, IStore store, IKeyValueStore stateKvStore, IStateStore stateStore ) = Utils.GetBlockChain( logger, storePath, chainId, useMemoryKvStore is string p ? new MemoryKeyValueStore(p, stderr) : null ); Block <NCAction> bottom = Utils.ParseBlockOffset(chain, bottommost, 0); Block <NCAction> top = Utils.ParseBlockOffset(chain, topmost); stderr.WriteLine("It will execute all actions (tx actions & block actions)"); stderr.WriteLine( " ...from the block #{0} {1}", bottom.Index.ToString(CultureInfo.InvariantCulture).PadRight( top.Index.ToString(CultureInfo.InvariantCulture).Length), bottom.Hash); stderr.WriteLine(" ...to the block #{0} {1}.", top.Index, top.Hash); IBlockPolicy <NCAction> policy = chain.Policy; (Block <NCAction>, string)? invalidStateRootHashBlock = null; long totalBlocks = top.Index - bottom.Index + 1; long blocksExecuted = 0L; long txsExecuted = 0L; DateTimeOffset started = DateTimeOffset.Now; IEnumerable <BlockHash> blockHashes = store.IterateIndexes( chain.Id, (int)bottom.Index, (int)(top.Index - bottom.Index + 1L) ); foreach (BlockHash blockHash in blockHashes) { if (cancellationToken.IsCancellationRequested) { throw new CommandExitedException(1); } Block <NCAction> block = store.GetBlock <NCAction>(policy.GetHashAlgorithm, blockHash); var preEvalBlock = new PreEvaluationBlock <NCAction>( block, block.HashAlgorithm, block.Nonce, block.PreEvaluationHash ); stderr.WriteLine( "[{0}/{1}] Executing block #{2} {3}...", block.Index - bottom.Index + 1L, top.Index - bottom.Index + 1L, block.Index, block.Hash ); IImmutableDictionary <string, IValue> delta; HashDigest <SHA256> stateRootHash = block.Index < 1 ? preEvalBlock.DetermineStateRootHash(chain.Policy.BlockAction, stateStore, out delta) : preEvalBlock.DetermineStateRootHash( chain, StateCompleterSet <NCAction> .Reject, out delta); DateTimeOffset now = DateTimeOffset.Now; if (invalidStateRootHashBlock is null && !stateRootHash.Equals(block.StateRootHash)) { string blockDump = DumpBencodexToFile( block.MarshalBlock(), $"block_{block.Index}_{block.Hash}" ); string deltaDump = DumpBencodexToFile( new Dictionary( delta.Select(kv => new KeyValuePair <IKey, IValue>(new Text(kv.Key), kv.Value))), $"delta_{block.Index}_{block.Hash}" ); string message = $"Unexpected state root hash for block #{block.Index} {block.Hash}.\n" + $" Expected: {block.StateRootHash}\n Actual: {stateRootHash}\n" + $" Block file: {blockDump}\n Evaluated delta file: {deltaDump}\n"; if (!bypassStateRootHashCheck) { throw new CommandExitedException(message, 1); } stderr.WriteLine(message); invalidStateRootHashBlock = (block, message); } blocksExecuted++; txsExecuted += block.Transactions.Count; TimeSpan elapsed = now - started; if (blocksExecuted >= totalBlocks || block.Hash.Equals(top.Hash)) { stderr.WriteLine("Elapsed: {0:c}.", elapsed); break; } else { TimeSpan estimatedRemaining = elapsed / blocksExecuted * (totalBlocks - blocksExecuted); stderr.WriteLine( "Elapsed: {0:c}, estimated remaining: {1:c}.", elapsed, estimatedRemaining ); } } if (invalidStateRootHashBlock is { } b) { stderr.WriteLine( "Note that the state root hash check is bypassed, " + "but there was an invalid state root hash for block #{0} {1}. {2}", b.Item1.Index, b.Item1.Hash, b.Item2 ); } TimeSpan totalElapsed = DateTimeOffset.Now - started; stderr.WriteLine("Total elapsed: {0:c}", totalElapsed); stderr.WriteLine("Avg block execution time: {0:c}", totalElapsed / totalBlocks); stderr.WriteLine("Avg tx execution time: {0:c}", totalElapsed / txsExecuted); stateKvStore.Dispose(); stateStore.Dispose(); }