コード例 #1
0
ファイル: TestUtils.cs プロジェクト: planetarium/libplanet
        public static Block <T> MineNextBlock <T>(
            Block <T> previousBlock,
            HashAlgorithmGetter hashAlgorithmGetter,
            PrivateKey miner,
            IReadOnlyList <Transaction <T> > txs = null,
            byte[] nonce                      = null,
            long difficulty                   = 1,
            TimeSpan?blockInterval            = null,
            int protocolVersion               = Block <T> .CurrentProtocolVersion,
            HashDigest <SHA256> stateRootHash = default
            )
            where T : IAction, new()
        {
            PreEvaluationBlock <T> preEval = MineNext(
                previousBlock,
                hashAlgorithmGetter,
                txs,
                nonce,
                difficulty,
                miner?.PublicKey,
                blockInterval,
                protocolVersion
                );

            return(protocolVersion < 2
                ? new Block <T>(preEval, stateRootHash, null)
                : preEval.Sign(miner, stateRootHash));
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        public void Idempotent()
        {
            // NOTE: This test checks that blocks can be evaluated idempotently. Also it checks
            // the action results in pre-evaluation step and in evaluation step are equal.
            const int repeatCount = 2;
            var       signer      = new PrivateKey();
            var       timestamp   = DateTimeOffset.UtcNow;
            var       txAddress   = signer.ToAddress();
            var       txs         = new[]
            {
                Transaction <RandomAction> .Create(
                    nonce : 0,
                    privateKey : signer,
                    genesisHash : null,
                    actions : new[] { new RandomAction(txAddress), }),
            };
            var stateStore = new TrieStateStore(new MemoryKeyValueStore());
            HashAlgorithmGetter hashAlgorithmGetter            = _ => HashAlgorithmType.Of <SHA256>();
            PreEvaluationBlock <RandomAction> noStateRootBlock = MineGenesis(
                hashAlgorithmGetter: hashAlgorithmGetter,
                miner: GenesisMiner.PublicKey,
                timestamp: timestamp,
                transactions: txs
                );
            Block <RandomAction> stateRootBlock =
                noStateRootBlock.Evaluate(GenesisMiner, null, stateStore);
            var actionEvaluator =
                new ActionEvaluator <RandomAction>(
                    hashAlgorithmGetter: hashAlgorithmGetter,
                    policyBlockAction: null,
                    stateGetter: ActionEvaluator <RandomAction> .NullStateGetter,
                    balanceGetter: ActionEvaluator <RandomAction> .NullBalanceGetter,
                    trieGetter: null);
            var generatedRandomNumbers = new List <int>();

            AssertPreEvaluationBlocksEqual(stateRootBlock, noStateRootBlock);

            for (int i = 0; i < repeatCount; ++i)
            {
                var actionEvaluations = actionEvaluator.Evaluate(
                    noStateRootBlock,
                    StateCompleterSet <RandomAction> .Reject);
                generatedRandomNumbers.Add(
                    (Integer)actionEvaluations[0].OutputStates.GetState(txAddress));
                actionEvaluations = actionEvaluator.Evaluate(
                    stateRootBlock,
                    StateCompleterSet <RandomAction> .Reject);
                generatedRandomNumbers.Add(
                    (Integer)actionEvaluations[0].OutputStates.GetState(txAddress));
            }

            for (int i = 1; i < generatedRandomNumbers.Count; ++i)
            {
                Assert.Equal(generatedRandomNumbers[0], generatedRandomNumbers[i]);
            }
        }
コード例 #4
0
        public void Evaluate()
        {
            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())
            {
                Block <Arithmetic> genesis =
                    preEvalGenesis.Evaluate(_contents.GenesisKey, blockAction, fx.StateStore);
                AssertPreEvaluationBlocksEqual(preEvalGenesis, genesis);
                _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(genesis.StateRootHash, 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));

                Block <Arithmetic> block1 = preEval1.Evaluate(_contents.Block1Key, blockChain);
                AssertPreEvaluationBlocksEqual(preEval1, block1);
                _output.WriteLine("#1: {0}", block1);

                HashDigest <SHA256> identicalBlock1StateRootHash =
                    preEval1.DetermineStateRootHash(blockChain);
                AssertBytesEqual(block1.StateRootHash, identicalBlock1StateRootHash);

                blockChain.Append(block1);
                AssertBencodexEqual((Bencodex.Types.Integer) 158, blockChain.GetState(address));
            }
        }
コード例 #5
0
        public override void UnsafeConstructor()
        {
            BlockContent <Arithmetic> content = _contents.Genesis.Copy();
            var preEvalBlock =
                new PreEvaluationBlock <Arithmetic>(content, _sha256, _validGenesisProof);

            AssertBlockContentsEqual(content, preEvalBlock);
            AssertBytesEqual(_validGenesisProof.Nonce, preEvalBlock.Nonce);
            Assert.Same(_sha256, preEvalBlock.HashAlgorithm);
            AssertBytesEqual(_validGenesisProof.PreEvaluationHash, preEvalBlock.PreEvaluationHash);

            content      = _contents.Block1.Copy();
            preEvalBlock = new PreEvaluationBlock <Arithmetic>(content, _sha256, _validBlock1Proof);
            AssertBlockContentsEqual(content, preEvalBlock);
            AssertBytesEqual(_validBlock1Proof.Nonce, preEvalBlock.Nonce);
            Assert.Same(_sha256, preEvalBlock.HashAlgorithm);
            AssertBytesEqual(_validBlock1Proof.PreEvaluationHash, preEvalBlock.PreEvaluationHash);

            Assert.Throws <InvalidBlockNonceException>(
                () => new PreEvaluationBlock <Arithmetic>(content, _sha256, _invalidBlock1Proof)
                );

            content = _contents.Block1.Copy();
            content.PreviousHash = null;
            Assert.Throws <InvalidBlockPreviousHashException>(
                () => new PreEvaluationBlock <Arithmetic>(content, _sha256, _validBlock1Proof)
                );

            content = _contents.Genesis.Copy();
            content.PreviousHash = _contents.GenesisHash;
            Assert.Throws <InvalidBlockPreviousHashException>(
                () => new PreEvaluationBlock <Arithmetic>(content, _sha256, _validGenesisProof)
                );

            content            = _contents.Block1.Copy();
            content.Difficulty = 0L;
            Assert.Throws <InvalidBlockDifficultyException>(
                () => new PreEvaluationBlock <Arithmetic>(content, _sha256, _validBlock1Proof.Nonce)
                );

            content            = _contents.Genesis.Copy();
            content.Difficulty = 1L;
            Assert.Throws <InvalidBlockDifficultyException>(
                () => new PreEvaluationBlock <Arithmetic>(content, _sha256, _validGenesisProof)
                );

            content = _contents.Genesis.Copy();
            content.TotalDifficulty = 1;
            Assert.Throws <InvalidBlockTotalDifficultyException>(
                () => new PreEvaluationBlock <Arithmetic>(content, _sha256, _validGenesisProof)
                );
        }
コード例 #6
0
ファイル: BlockTest.cs プロジェクト: longfin/libplanet.net
        public void Constructor()
        {
            var contents      = new BlockContentFixture();
            var random        = new System.Random();
            var stateRootHash = random.NextHashDigest <SHA256>();
            PreEvaluationBlock <Arithmetic> preEval = contents.Genesis.Mine(_fx.GetHashAlgorithm(0));
            ImmutableArray <byte>           sig     = preEval.MakeSignature(contents.GenesisKey, stateRootHash);
            var block = new Block <Arithmetic>(preEval, stateRootHash, sig);

            AssertPreEvaluationBlocksEqual(preEval, block);
            AssertBytesEqual(stateRootHash, block.StateRootHash);
            AssertBytesEqual(sig, block.Signature);
        }
コード例 #7
0
        public override void SafeConstructorWithPreEvaluationHash()
        {
            BlockContent <Arithmetic> content = _contents.Genesis.Copy();
            var preEvalBlock = new PreEvaluationBlock <Arithmetic>(
                content,
                hashAlgorithm: _sha256,
                nonce: _validGenesisProof.Nonce,
                preEvaluationHash: _validGenesisProof.PreEvaluationHash
                );

            AssertBlockContentsEqual(content, preEvalBlock);
            AssertBytesEqual(_validGenesisProof.Nonce, preEvalBlock.Nonce);
            Assert.Same(_sha256, preEvalBlock.HashAlgorithm);
            AssertBytesEqual(_validGenesisProof.PreEvaluationHash, preEvalBlock.PreEvaluationHash);

            content      = _contents.Block1.Copy();
            preEvalBlock = new PreEvaluationBlock <Arithmetic>(
                content,
                hashAlgorithm: _sha256,
                nonce: _validBlock1Proof.Nonce,
                preEvaluationHash: _validBlock1Proof.PreEvaluationHash
                );
            AssertBlockContentsEqual(content, preEvalBlock);
            AssertBytesEqual(_validBlock1Proof.Nonce, preEvalBlock.Nonce);
            Assert.Same(_sha256, preEvalBlock.HashAlgorithm);
            AssertBytesEqual(_validBlock1Proof.PreEvaluationHash, preEvalBlock.PreEvaluationHash);

            // Mutating the BlockContent<T> instance does not affect PreEvaluatingBlock<T> instance:
            content.Index++;
            Assert.Equal(_contents.Block1.Index, preEvalBlock.Index);

            content = _contents.Block1.Copy();
            Assert.Throws <InvalidBlockNonceException>(() =>
                                                       new PreEvaluationBlock <Arithmetic>(
                                                           content,
                                                           hashAlgorithm: _sha256,
                                                           nonce: _invalidBlock1Proof.Nonce,
                                                           preEvaluationHash: _invalidBlock1Proof.PreEvaluationHash
                                                           )
                                                       );
            Assert.Throws <InvalidBlockPreEvaluationHashException>(() =>
                                                                   new PreEvaluationBlock <Arithmetic>(
                                                                       content,
                                                                       hashAlgorithm: _sha256,
                                                                       nonce: _validBlock1Proof.Nonce,
                                                                       preEvaluationHash: _invalidBlock1Proof.PreEvaluationHash
                                                                       )
                                                                   );
        }
コード例 #8
0
        public void Mine()
        {
            var codec = new Codec();

            HashAlgorithmType sha256 = HashAlgorithmType.Of <SHA256>();
            PreEvaluationBlock <Arithmetic> preEvalBlock = Genesis.Mine(sha256);

            Assert.True(ByteUtil.Satisfies(preEvalBlock.PreEvaluationHash, Genesis.Difficulty));
            AssertBytesEqual(
                sha256.Digest(codec.Encode(Genesis.MakeCandidateData(preEvalBlock.Nonce))),
                preEvalBlock.PreEvaluationHash.ToArray()
                );

            HashAlgorithmType sha512 = HashAlgorithmType.Of <SHA512>();

            preEvalBlock = Block1.Mine(sha512);
            Assert.True(ByteUtil.Satisfies(preEvalBlock.PreEvaluationHash, Block1.Difficulty));
            AssertBytesEqual(
                sha512.Digest(codec.Encode(Block1.MakeCandidateData(preEvalBlock.Nonce))),
                preEvalBlock.PreEvaluationHash.ToArray()
                );
        }
コード例 #9
0
        public override void DontCheckPreEvaluationHashWithProtocolVersion0()
        {
            // Since PreEvaluationHash comparison between the actual and the expected was not
            // implemented in ProtocolVersion == 0, we need to maintain this bug on
            // ProtocolVersion < 1 for backward compatibility:
            BlockContent <Arithmetic> contentPv0 = _contents.Block1.Copy();

            contentPv0.ProtocolVersion = 0;
            contentPv0.PublicKey       = null;
            contentPv0.Timestamp      += TimeSpan.FromSeconds(1);
            var preEvalBlockPv0 = new PreEvaluationBlock <Arithmetic>(
                contentPv0,
                hashAlgorithm: _sha256,
                nonce: _validBlock1Proof.Nonce,
                preEvaluationHash: _validBlock1Proof.PreEvaluationHash
                );

            AssertBlockContentsEqual(contentPv0, preEvalBlockPv0);
            AssertBytesEqual(_validBlock1Proof.Nonce, preEvalBlockPv0.Nonce);
            Assert.Same(_sha256, preEvalBlockPv0.HashAlgorithm);
            AssertBytesEqual(
                _validBlock1Proof.PreEvaluationHash,
                preEvalBlockPv0.PreEvaluationHash
                );

            // However, such bug must be fixed after ProtocolVersion > 0:
            BlockContent <Arithmetic> contentPv1 = _contents.Block1.Copy();

            contentPv1.PublicKey  = null;
            contentPv1.Timestamp += TimeSpan.FromSeconds(1);
            Assert.Throws <InvalidBlockPreEvaluationHashException>(() =>
                                                                   new PreEvaluationBlock <Arithmetic>(
                                                                       contentPv1,
                                                                       hashAlgorithm: _sha256,
                                                                       nonce: _validBlock1Proof.Nonce,
                                                                       preEvaluationHash: _validBlock1Proof.PreEvaluationHash
                                                                       )
                                                                   );
        }
コード例 #10
0
ファイル: TestUtils.cs プロジェクト: planetarium/libplanet
        public static Block <T> MineGenesisBlock <T>(
            HashAlgorithmGetter hashAlgorithmGetter,
            PrivateKey miner,
            IReadOnlyList <Transaction <T> > transactions = null,
            DateTimeOffset?timestamp          = null,
            int protocolVersion               = Block <T> .CurrentProtocolVersion,
            HashDigest <SHA256> stateRootHash = default
            )
            where T : IAction, new()
        {
            PreEvaluationBlock <T> preEval = MineGenesis(
                hashAlgorithmGetter,
                miner?.PublicKey,
                transactions,
                timestamp,
                protocolVersion
                );

            return(protocolVersion < 2
                ? new Block <T>(preEval, stateRootHash, null)
                : preEval.Sign(miner, stateRootHash));
        }
コード例 #11
0
ファイル: TestUtils.cs プロジェクト: planetarium/libplanet
        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);
        }
コード例 #12
0
        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();
        }