Example #1
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();
            Address   address     = signer.ToAddress();
            var       timestamp   = DateTimeOffset.UtcNow;
            var       txs         = new[]
            {
                Transaction <RandomAction> .Create(
                    0,
                    signer,
                    null,
                    new[] { new RandomAction(address), }),
            };
            var stateStore =
                new TrieStateStore(new MemoryKeyValueStore(), new MemoryKeyValueStore());
            Block <RandomAction> noStateRootBlock = TestUtils.MineGenesis(
                timestamp: timestamp,
                transactions: txs);
            Block <RandomAction> stateRootBlock = TestUtils.MineGenesis(
                timestamp: timestamp,
                transactions: txs).AttachStateRootHash(stateStore, null);
            var blockEvaluator =
                new BlockEvaluator <RandomAction>(null, NullStateGetter, NullBalanceGetter, null);
            var generatedRandomNumbers = new List <int>();

            Assert.NotEqual(stateRootBlock.Hash, noStateRootBlock.Hash);
            Assert.Equal(stateRootBlock.PreEvaluationHash, noStateRootBlock.PreEvaluationHash);

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

            for (int i = 1; i < generatedRandomNumbers.Count; ++i)
            {
                Assert.Equal(generatedRandomNumbers[0], generatedRandomNumbers[i]);
            }
        }
Example #2
0
        public static Block <T> MineGenesis <T>(
            Address?miner = null,
            IEnumerable <Transaction <T> > transactions = null,
            DateTimeOffset?timestamp = null,
            IAction blockAction      = null,
            bool checkStateRootHash  = false
            )
            where T : IAction, new()
        {
            if (transactions is null)
            {
                transactions = new List <Transaction <T> >();
            }

            var block = new Block <T>(
                index: 0,
                difficulty: 0,
                totalDifficulty: 0,
                nonce: new Nonce(new byte[] { 0x01, 0x00, 0x00, 0x00 }),
                miner: miner ?? GenesisMinerAddress,
                previousHash: null,
                timestamp: timestamp ?? new DateTimeOffset(2018, 11, 29, 0, 0, 0, TimeSpan.Zero),
                transactions: transactions
                );

            if (checkStateRootHash)
            {
                var blockEvaluator = new BlockEvaluator <T>(
                    blockAction,
                    (address, digest, arg3) => null,
                    (address, currency, arg3, arg4) => new FungibleAssetValue(currency));
                var actionEvaluationResult = blockEvaluator
                                             .EvaluateActions(block, StateCompleterSet <T> .Reject)
                                             .GetTotalDelta(BlockChain <T> .ToStateKey, BlockChain <T> .ToFungibleAssetKey);
                var trie = new MerkleTrie(new DefaultKeyValueStore(null));
                foreach (var pair in actionEvaluationResult)
                {
                    trie.Set(Encoding.UTF8.GetBytes(pair.Key), pair.Value);
                }

                var stateRootHash = trie.Commit(rehearsal: true).Hash;
                block = new Block <T>(block, stateRootHash);
            }

            return(block);
        }
Example #3
0
        public static Block <T> AttachStateRootHash <T>(
            this Block <T> block, IStateStore stateStore, IAction blockAction)
            where T : IAction, new()
        {
            IValue StateGetter(
                Address address, HashDigest <SHA256>?blockHash, StateCompleter <T> stateCompleter) =>
            blockHash is null
                    ? null
                    : stateStore.GetState(ToStateKey(address), blockHash.Value);

            FungibleAssetValue FungibleAssetValueGetter(
                Address address,
                Currency currency,
                HashDigest <SHA256>?blockHash,
                FungibleAssetStateCompleter <T> stateCompleter)
            {
                if (blockHash is null)
                {
                    return(FungibleAssetValue.FromRawValue(currency, 0));
                }

                IValue value = stateStore.GetState(
                    ToFungibleAssetKey(address, currency), blockHash.Value);

                return(FungibleAssetValue.FromRawValue(
                           currency,
                           value is Bencodex.Types.Integer i ? i.Value : 0));
            }

            var blockEvaluator = new BlockEvaluator <T>(
                blockAction, StateGetter, FungibleAssetValueGetter, null);
            var actionEvaluationResult = blockEvaluator
                                         .EvaluateActions(block, StateCompleterSet <T> .Reject)
                                         .GetTotalDelta(ToStateKey, ToFungibleAssetKey);

            stateStore.SetStates(block, actionEvaluationResult);
            if (stateStore is TrieStateStore trieStateStore)
            {
                block = new Block <T>(block, trieStateStore.GetRootHash(block.Hash));
                stateStore.SetStates(block, actionEvaluationResult);
            }

            return(block);
        }