public void GetStatesReturnsEarlyForNonexistentAccount()
        {
            var tracker = new StoreTracker(_fx.Store);
            var chain   = new BlockChain <DumbAction>(
                new NullPolicy <DumbAction>(),
                tracker
                );

            Block <DumbAction> b = TestUtils.MineGenesis <DumbAction>();

            chain.Append(b);
            for (int i = 0; i < 20; ++i)
            {
                b = TestUtils.MineNext(b);
                chain.Append(b);
            }

            tracker.ClearLogs();
            Address         nonexistent = new PrivateKey().PublicKey.ToAddress();
            AddressStateMap result      = chain.GetStates(new[] { nonexistent });

            Assert.False(result.ContainsKey(nonexistent));
            var callCount = tracker.Logs.Where(
                triple => triple.Item1.Equals("GetBlockStates")
                ).Select(triple => triple.Item2).Count();

            Assert.True(
                callCount <= 1,
                $"GetBlocksStates() was called {callCount} times"
                );
        }
 public void ValidateWithMultipleAlgorithms()
 {
     using (var fx = new MemoryStoreFixture())
     {
         IBlockPolicy <DumbAction> policy = new MultiAlgoPolicy <DumbAction>();
         BlockChain <DumbAction>   chain  = TestUtils.MakeBlockChain(
             policy,
             fx.Store,
             fx.StateStore,
             new DumbAction[0]
             );
         HashAlgorithmType  invalidAlgo  = HashAlgorithmType.Of <SHA1>();
         Block <DumbAction> invalidBlock = TestUtils.MineNext(
             chain.Genesis,
             _ => invalidAlgo,
             miner: TestUtils.ChainPrivateKey.PublicKey,
             difficulty: policy.GetNextBlockDifficulty(chain)
             ).Evaluate(TestUtils.ChainPrivateKey, chain);
         Assert.Throws <InvalidBlockHashAlgorithmTypeException>(
             () => chain.Append(invalidBlock));
         HashAlgorithmType  validAlgo  = HashAlgorithmType.Of <MD5>();
         Block <DumbAction> validBlock = TestUtils.MineNext(
             chain.Genesis,
             _ => validAlgo,
             miner: TestUtils.ChainPrivateKey.PublicKey,
             difficulty: policy.GetNextBlockDifficulty(chain)
             ).Evaluate(TestUtils.ChainPrivateKey, chain);
         chain.Append(validBlock);
     }
 }
Exemple #3
0
        public void ForkBlockIndex(int branchPointIndex)
        {
            var store = Fx.Store;

            var blocks = new BlockChain <DumbAction>(
                new NullPolicy <DumbAction>(),
                store,
                Fx.GenesisBlock
                );

            blocks.Append(Fx.Block1);
            blocks.Append(Fx.Block2);
            blocks.Append(Fx.Block3);

            var forked = new BlockChain <DumbAction>(
                new NullPolicy <DumbAction>(),
                store,
                Guid.NewGuid(),
                Fx.GenesisBlock
                );

            store.ForkBlockIndexes(blocks.Id, forked.Id, blocks[branchPointIndex].Hash);

            Assert.Equal(
                store.IterateIndexes(blocks.Id, 0, branchPointIndex + 1).ToList(),
                store.IterateIndexes(forked.Id).ToList()
                );

            Assert.Equal(branchPointIndex + 1, store.CountIndex(forked.Id));
        }
Exemple #4
0
        private void ValidateNextBlockInvalidStateRootHash()
        {
            IKeyValueStore stateKeyValueStore     = new MemoryKeyValueStore(),
                           stateHashKeyValueStore = new MemoryKeyValueStore();
            var policy = new BlockPolicy <DumbAction>(
                null,
                TimeSpan.FromHours(3),
                1024,
                128);
            var stateStore = new TrieStateStore(stateKeyValueStore, stateHashKeyValueStore);
            // FIXME: It assumes that _fx.GenesisBlock doesn't update any states with transactions.
            //        Actually, it depends on BlockChain<T> to update states and it makes hard to
            //        calculate state root hash. To resolve this problem,
            //        it should be moved into StateStore.
            var genesisBlock = TestUtils.MineGenesis <DumbAction>(
                blockAction: policy.BlockAction, checkStateRootHash: true);
            var store = new DefaultStore(null);
            var chain = new BlockChain <DumbAction>(
                policy,
                store,
                stateStore,
                genesisBlock);

            var validNext = Block <DumbAction> .Mine(
                1,
                1024,
                genesisBlock.TotalDifficulty,
                genesisBlock.Miner.Value,
                genesisBlock.Hash,
                genesisBlock.Timestamp.AddSeconds(1),
                _emptyTransaction);

            chain.ExecuteActions(validNext);
            validNext =
                new Block <DumbAction>(validNext, stateStore.GetRootHash(validNext.Hash));
            chain.Append(validNext);

            var invalidStateRootHash = Block <DumbAction> .Mine(
                2,
                1032,
                validNext.TotalDifficulty,
                genesisBlock.Miner.Value,
                validNext.Hash,
                validNext.Timestamp.AddSeconds(1),
                _emptyTransaction);

            var actionEvaluations = _blockChain.BlockEvaluator.EvaluateActions(
                invalidStateRootHash,
                StateCompleterSet <DumbAction> .Recalculate);

            chain.SetStates(invalidStateRootHash, actionEvaluations, false);
            invalidStateRootHash = new Block <DumbAction>(
                invalidStateRootHash,
                new HashDigest <SHA256>(TestUtils.GetRandomBytes(HashDigest <SHA256> .Size)));
            Assert.Throws <InvalidBlockStateRootHashException>(() =>
                                                               chain.Append(invalidStateRootHash));
        }
        public void GetStatesOnlyDrillsDownUntilRequestedAddressesAreFound()
        {
            var tracker = new StoreTracker(_fx.Store);
            var chain   = new BlockChain <DumbAction>(
                new NullPolicy <DumbAction>(),
                tracker
                );

            Block <DumbAction> b = TestUtils.MineGenesis <DumbAction>();

            chain.Append(b);
            Address[] addresses = new Address[30];
            for (int i = 0; i < addresses.Length; ++i)
            {
                var     privateKey = new PrivateKey();
                Address address    = privateKey.PublicKey.ToAddress();
                addresses[i] = address;
                DumbAction[] actions =
                {
                    new DumbAction(address,                            "foo"),
                    new DumbAction(i < 1 ? address : addresses[i - 1], "bar"),
                };
                Transaction <DumbAction>[] txs =
                {
                    Transaction <DumbAction> .Create(privateKey, actions),
                };
                b = TestUtils.MineNext(b, txs);
                chain.Append(b);
            }

            tracker.ClearLogs();
            int testingDepth = addresses.Length / 2;

            Address[] targetAddresses = Enumerable.Range(
                testingDepth,
                Math.Min(10, addresses.Length - testingDepth - 1)
                ).Select(i => addresses[i]).ToArray();
            AddressStateMap result       = chain.GetStates(targetAddresses);
            string          resultString = string.Join(", ", result.Keys);
            string          targetString = string.Join(", ", targetAddresses);
            string          message      =
                $"The result dictionary ({resultString}) does not " +
                $"cover all requested addresses ({targetString}).";

            foreach (Address targetAddress in targetAddresses)
            {
                Assert.True(result.ContainsKey(targetAddress), message);
            }

            var callCount = tracker.Logs.Where(
                triple => triple.Item1.Equals("GetBlockStates")
                ).Select(triple => triple.Item2).Count();

            Assert.True(testingDepth >= callCount);
        }
        public void ValidateNextBlockInvalidIndex()
        {
            _chain.Append(_validNext);

            var invalidIndexBlock = Block <DumbAction> .Mine(
                1,
                1,
                _genesis.Miner.Value,
                _validNext.Hash,
                _validNext.Timestamp.AddSeconds(1),
                _emptyTransaction);

            Assert.IsType <InvalidBlockIndexException>(
                _policy.ValidateNextBlock(_chain, invalidIndexBlock));
        }
        public async Task TransferNCGHistories()
        {
            PrivateKey minerPrivateKey = new PrivateKey();
            Address    sender = minerPrivateKey.ToAddress(), recipient = new PrivateKey().ToAddress();

            await BlockChain.MineBlock(sender);

            await BlockChain.MineBlock(recipient);

            var currency = new GoldCurrencyState((Dictionary)BlockChain.GetState(Addresses.GoldCurrency)).Currency;
            var transferAsset = new TransferAsset(sender, recipient, new FungibleAssetValue(currency, 10, 0));
            var tx       = BlockChain.MakeTransaction(minerPrivateKey, new PolymorphicAction <ActionBase>[] { transferAsset });
            var block    = await BlockChain.MineBlock(minerPrivateKey.ToAddress(), append : false);

            BlockChain.Append(block);
            Assert.NotNull(StandaloneContextFx.Store?.GetTxExecution(block.Hash, tx.Id));

            var blockHashHex = ByteUtil.Hex(block.Hash.ToByteArray());
            var result       =
                await ExecuteQueryAsync(
                    $"{{ transferNCGHistories(blockHash: \"{blockHashHex}\") {{ blockHash txId sender recipient amount }} }}");

            Assert.Null(result.Errors);
            Assert.Equal(new List <object>
            {
                new Dictionary <string, object>
                {
                    ["blockHash"] = block.Hash.ToString(),
                    ["txId"]      = tx.Id.ToString(),
                    ["sender"]    = transferAsset.Sender.ToString(),
                    ["recipient"] = transferAsset.Recipient.ToString(),
                    ["amount"]    = transferAsset.Amount.GetQuantityString(),
                }
            }, result.Data.As <Dictionary <string, object> >()["transferNCGHistories"]);
        }
        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 }
                );

            chain.Append(
                TestUtils.MineNext(
                    chain.Tip,
                    new[] { tx },
                    protocolVersion: ProtocolVersion
                    ).AttachStateRootHash(chain.StateStore, chain.Policy.BlockAction)
                );
            Assert.Equal(
                DumbAction.DumbCurrency * 6,
                chain.GetBalance(_addr[0], DumbAction.DumbCurrency)
                );

            return(chain);
        }
        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 }
                );

            chain.Append(
                TestUtils.MineNext(
                    chain.Tip,
                    chain.Policy.GetHashAlgorithm,
                    new[] { tx },
                    miner: _keys[1].PublicKey,
                    protocolVersion: ProtocolVersion
                    ).Evaluate(_keys[1], chain)
                );
            Assert.Equal(
                DumbAction.DumbCurrency * 5,
                chain.GetBalance(_addr[0], DumbAction.DumbCurrency)
                );

            return(chain);
        }
Exemple #10
0
        public void Copy()
        {
            using (StoreFixture fx = FxConstructor())
                using (StoreFixture fx2 = FxConstructor())
                {
                    IStore s1 = fx.Store, s2 = fx2.Store;
                    var    blocks = new BlockChain <DumbAction>(
                        new NullPolicy <DumbAction>(),
                        s1,
                        Fx.GenesisBlock
                        );

                    // FIXME: Need to add more complex blocks/transactions.
                    blocks.Append(Fx.Block1);
                    blocks.Append(Fx.Block2);
                    blocks.Append(Fx.Block3);

                    s1.Copy(to: Fx.Store);
                    Fx.Store.Copy(to: s2);

                    Assert.Equal(s1.ListChainIds().ToHashSet(), s2.ListChainIds().ToHashSet());
                    Assert.Equal(s1.GetCanonicalChainId(), s2.GetCanonicalChainId());
                    foreach (Guid chainId in s1.ListChainIds())
                    {
                        Assert.Equal(s1.IterateIndexes(chainId), s2.IterateIndexes(chainId));
                        foreach (HashDigest <SHA256> blockHash in s1.IterateIndexes(chainId))
                        {
                            Assert.Equal(
                                s1.GetBlock <DumbAction>(blockHash),
                                s2.GetBlock <DumbAction>(blockHash)
                                );
                            Assert.Equal(
                                s1.GetBlockStates(blockHash),
                                s2.GetBlockStates(blockHash)
                                );
                        }

                        Assert.Equal(
                            s1.ListAllStateReferences(chainId),
                            s2.ListAllStateReferences(chainId)
                            );
                    }

                    // ArgumentException is thrown if the destination store is not empty.
                    Assert.Throws <ArgumentException>(() => Fx.Store.Copy(fx2.Store));
                }
        }
        public void ValidateNextBlock()
        {
            _policy.ValidateNextBlock(_chain, _genesis);
            _chain.Append(_genesis);

            var validNextBlock = Block <DumbAction> .Mine(
                1,
                1,
                _genesis.Miner.Value,
                _genesis.Hash,
                _genesis.Timestamp.AddDays(1),
                _emptyTransaction);

            _policy.ValidateNextBlock(_chain, validNextBlock);
        }
        public void AppendValidatesBlock()
        {
            var blockChain = new BlockChain <DumbAction>(
                new NullPolicy <DumbAction>(
                    new InvalidBlockDifficultyException(string.Empty)),
                _fx.Store);

            Assert.Throws <InvalidBlockDifficultyException>(
                () => blockChain.Append(_fx.Block1));
        }
Exemple #13
0
        public void ForkBlockIndex(int branchPointIndex)
        {
            var store = Fx.Store;

            var blocks = new BlockChain <DumbAction>(
                new NullPolicy <DumbAction>(),
                new VolatileStagePolicy <DumbAction>(),
                store,
                Fx.StateStore,
                Fx.GenesisBlock
                );

            blocks.Append(Fx.Block1);
            blocks.Append(Fx.Block2);
            blocks.Append(Fx.Block3);

            var forked = new BlockChain <DumbAction>(
                new NullPolicy <DumbAction>(),
                new VolatileStagePolicy <DumbAction>(),
                store,
                Fx.StateStore,
                Guid.NewGuid(),
                Fx.GenesisBlock,
                renderers: null
                );

            Logger.CompareBothChains(
                LogEventLevel.Debug,
                nameof(blocks),
                blocks,
                nameof(forked),
                forked
                );

            store.ForkBlockIndexes(blocks.Id, forked.Id, blocks[branchPointIndex].Hash);

            Assert.Equal(
                store.IterateIndexes(blocks.Id, 0, branchPointIndex + 1).ToList(),
                store.IterateIndexes(forked.Id).ToList()
                );

            Assert.Equal(branchPointIndex + 1, store.CountIndex(forked.Id));
        }
Exemple #14
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));
            }
        }
Exemple #15
0
        public async Task IgnoreExistingBlocks()
        {
            var keyA = new PrivateKey();
            var keyB = new PrivateKey();

            Swarm <DumbAction> swarmA = CreateSwarm(keyA);
            Swarm <DumbAction> swarmB = CreateSwarm(keyB);

            BlockChain <DumbAction> chainA = swarmA.BlockChain;
            BlockChain <DumbAction> chainB = swarmB.BlockChain;

            Block <DumbAction> genesis = await chainA.MineBlock(keyA);

            chainB.Append(genesis);

            foreach (int i in Enumerable.Range(0, 3))
            {
                await chainA.MineBlock(keyA);
            }

            try
            {
                await StartAsync(swarmA);
                await StartAsync(swarmB);

                await BootstrapAsync(swarmB, swarmA.AsPeer);

                swarmA.BroadcastBlock(chainA[-1]);
                await swarmB.BlockAppended.WaitAsync();

                Assert.Equal(chainA.BlockHashes, chainB.BlockHashes);

                CancellationTokenSource cts = new CancellationTokenSource();
                swarmA.BroadcastBlock(chainA[-1]);
                Task t = swarmB.BlockAppended.WaitAsync(cts.Token);

                // Actually, previous code may pass this test if message is
                // delayed over 5 seconds.
                await Task.Delay(5000);

                Assert.False(t.IsCompleted);

                cts.Cancel();
            }
            finally
            {
                await StopAsync(swarmA);
                await StopAsync(swarmB);
            }
        }
Exemple #16
0
        public void ForkStateReferencesChainIdNotFound()
        {
            var     targetChainId = Guid.NewGuid();
            Address address       = Fx.Address1;

            Assert.Throws <ChainIdNotFoundException>(() =>
                                                     Fx.Store.ForkStateReferences(Fx.StoreChainId, targetChainId, Fx.Block1)
                                                     );

            var chain = new BlockChain <DumbAction>(new NullPolicy <DumbAction>(), Fx.Store);

            chain.Append(Fx.Block1);

            // Even if state references in a chain are empty it should not throw
            // ChainIdNotFoundException unless the chain in itself does not exist.
            Fx.Store.ForkStateReferences(chain.Id, targetChainId, Fx.Block1);
        }
        public void ListAllStateReferences(StoreFixture fx)
        {
            Address address1 = fx.Address1;
            Address address2 = fx.Address2;
            Address address3 = new PrivateKey().PublicKey.ToAddress();

            Transaction <DumbAction> tx4 = fx.MakeTransaction(
                new[]
            {
                new DumbAction(address1, "foo1"),
                new DumbAction(address2, "foo2"),
            }
                );
            Block <DumbAction> block4 = TestUtils.MineNext(fx.Block3, new[] { tx4 });

            Transaction <DumbAction> tx5 = fx.MakeTransaction(
                new[]
            {
                new DumbAction(address1, "bar1"),
                new DumbAction(address3, "bar3"),
            }
                );
            Block <DumbAction> block5 = TestUtils.MineNext(block4, new[] { tx5 });

            Block <DumbAction> block6 = TestUtils.MineNext(block5, new Transaction <DumbAction> [0]);

            var chain = new BlockChain <DumbAction>(new NullPolicy <DumbAction>(), fx.Store);

            chain.Append(fx.Block1);
            chain.Append(fx.Block2);
            chain.Append(fx.Block3);
            chain.Append(block4);
            chain.Append(block5);
            chain.Append(block6);

            IImmutableDictionary <Address, IImmutableList <HashDigest <SHA256> > > refs =
                fx.Store.ListAllStateReferences(chain.Id.ToString());

            Assert.Equal(
                new HashSet <Address> {
                address1, address2, address3
            },
                refs.Keys.ToHashSet()
                );
            Assert.Equal(new[] { block4.Hash, block5.Hash }, refs[address1]);
            Assert.Equal(new[] { block4.Hash }, refs[address2]);
            Assert.Equal(new[] { block5.Hash }, refs[address3]);
        }
Exemple #18
0
        public async Task GetDemandBlockHashes()
        {
            Swarm <DumbAction> minerSwarm    = CreateSwarm();
            Swarm <DumbAction> receiverSwarm = CreateSwarm();

            Log.Logger.Information("Miner:    {0}", minerSwarm.Address);
            Log.Logger.Information("Receiver: {0}", receiverSwarm.Address);

            BlockChain <DumbAction> minerChain    = minerSwarm.BlockChain;
            BlockChain <DumbAction> receiverChain = receiverSwarm.BlockChain;

            (_, IEnumerable <Block <DumbAction> > blocks) =
                await MakeFixtureBlocksForPreloadAsyncCancellationTest();

            foreach (Block <DumbAction> block in blocks)
            {
                minerChain.Append(block);
            }

            minerSwarm.FindNextHashesChunkSize = 2;
            await StartAsync(minerSwarm);

            (BoundPeer, long)[] peers =
Exemple #19
0
        public async Task <Block <NCAction> > MineBlockAsync(
            CancellationToken cancellationToken)
        {
            var txs        = new HashSet <Transaction <NCAction> >();
            var invalidTxs = txs;

            Block <NCAction> block = null;

            try
            {
                if (AuthorizedMiner)
                {
                    _chain
                    .GetStagedTransactionIds()
                    .Select(txid => _chain.GetTransaction(txid)).ToList()
                    .ForEach(tx => _chain.UnstageTransaction(tx));
                }

                IEnumerable <Transaction <NCAction> > bannedTxs = _chain.GetStagedTransactionIds()
                                                                  .Select(txId => _chain.GetTransaction(txId))
                                                                  .Where(tx => _bannedAccounts.Contains(tx.Signer));
                foreach (Transaction <NCAction> tx in bannedTxs)
                {
                    _chain.UnstageTransaction(tx);
                }

                // All miner needs proof in permissioned mining:
                Transaction <NCAction> proof = StageProofTransaction();

                // Proof txs have priority over other txs:
                IComparer <Transaction <NCAction> > txPriority = GetProofTxPriority(proof);

                block = await _chain.MineBlock(
                    _privateKey,
                    DateTimeOffset.UtcNow,
                    cancellationToken : cancellationToken,
                    append : false,
                    txPriority : txPriority);

                _chain.Append(block);
                if (_swarm is Swarm <NCAction> s && s.Running)
                {
                    s.BroadcastBlock(block);
                }
            }
            catch (OperationCanceledException)
            {
                Log.Debug("Mining was canceled due to change of tip.");
            }
            catch (InvalidTxException invalidTxException)
            {
                var invalidTx = _chain.GetTransaction(invalidTxException.TxId);

                Log.Debug($"Tx[{invalidTxException.TxId}] is invalid. mark to unstage.");
                invalidTxs.Add(invalidTx);
            }
            catch (UnexpectedlyTerminatedActionException actionException)
            {
                if (actionException.TxId is TxId txId)
                {
                    Log.Debug(
                        $"Tx[{actionException.TxId}]'s action is invalid. mark to unstage. {actionException}");
                    invalidTxs.Add(_chain.GetTransaction(txId));
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, $"exception was thrown. {ex}");
            }
            finally
            {
#pragma warning disable LAA1002
                foreach (var invalidTx in invalidTxs)
#pragma warning restore LAA1002
                {
                    _chain.UnstageTransaction(invalidTx);
                }
            }

            return(block);
        }
Exemple #20
0
        public void ValidateNextBlockWithManyTransactionsPerSigner()
        {
            var adminPrivateKey   = new PrivateKey();
            var adminPublicKey    = adminPrivateKey.PublicKey;
            var blockPolicySource = new BlockPolicySource(Logger.None);
            IBlockPolicy <PolymorphicAction <ActionBase> > policy = blockPolicySource.GetPolicy(
                minimumDifficulty: 10_000,
                hashAlgorithmTypePolicy: null,
                maxBlockBytesPolicy: null,
                minTransactionsPerBlockPolicy: null,
                maxTransactionsPerBlockPolicy: MaxTransactionsPerBlockPolicy
                .Default
                .Add(new SpannedSubPolicy <int>(0, null, null, 10)),
                maxTransactionsPerSignerPerBlockPolicy: MaxTransactionsPerSignerPerBlockPolicy
                .Default
                .Add(new SpannedSubPolicy <int>(2, null, null, 5)),
                authorizedMinersPolicy: null,
                permissionedMinersPolicy: null);
            IStagePolicy <PolymorphicAction <ActionBase> > stagePolicy =
                new VolatileStagePolicy <PolymorphicAction <ActionBase> >();
            Block <PolymorphicAction <ActionBase> > genesis =
                MakeGenesisBlock(adminPublicKey.ToAddress(), ImmutableHashSet <Address> .Empty);

            using var store = new DefaultStore(null);
            var stateStore = new TrieStateStore(new MemoryKeyValueStore());
            var blockChain = new BlockChain <PolymorphicAction <ActionBase> >(
                policy,
                stagePolicy,
                store,
                stateStore,
                genesis
                );

            int nonce = 0;

            List <Transaction <PolymorphicAction <ActionBase> > > GenerateTransactions(int count)
            {
                var list = new List <Transaction <PolymorphicAction <ActionBase> > >();

                for (int i = 0; i < count; i++)
                {
                    list.Add(Transaction <PolymorphicAction <ActionBase> > .Create(
                                 nonce++,
                                 adminPrivateKey,
                                 genesis.Hash,
                                 new PolymorphicAction <ActionBase>[] { }
                                 ));
                }

                return(list);
            }

            Assert.Equal(1, blockChain.Count);
            Block <PolymorphicAction <ActionBase> > block1 = new BlockContent <PolymorphicAction <ActionBase> >
            {
                Index           = 1,
                Difficulty      = policy.GetNextBlockDifficulty(blockChain),
                TotalDifficulty = blockChain.Tip.Difficulty + policy.GetNextBlockDifficulty(blockChain),
                PublicKey       = adminPublicKey,
                PreviousHash    = blockChain.Tip.Hash,
                Timestamp       = DateTimeOffset.MinValue,
                Transactions    = GenerateTransactions(10),
            }.Mine(policy.GetHashAlgorithm(1)).Evaluate(adminPrivateKey, blockChain);

            // Should be fine since policy hasn't kicked in yet.
            blockChain.Append(block1);
            Assert.Equal(2, blockChain.Count);
            Assert.True(blockChain.ContainsBlock(block1.Hash));

            Block <PolymorphicAction <ActionBase> > block2 = new BlockContent <PolymorphicAction <ActionBase> >
            {
                Index           = 2,
                Difficulty      = policy.GetNextBlockDifficulty(blockChain),
                TotalDifficulty = blockChain.Tip.Difficulty + policy.GetNextBlockDifficulty(blockChain),
                PublicKey       = adminPublicKey,
                PreviousHash    = blockChain.Tip.Hash,
                Timestamp       = DateTimeOffset.MinValue,
                Transactions    = GenerateTransactions(10),
            }.Mine(policy.GetHashAlgorithm(2)).Evaluate(adminPrivateKey, blockChain);

            // Subpolicy kicks in.
            Assert.Throws <InvalidBlockTxCountPerSignerException>(() => blockChain.Append(block2));
            Assert.Equal(2, blockChain.Count);
            Assert.False(blockChain.ContainsBlock(block2.Hash));
            // Since failed, roll back nonce.
            nonce -= 10;

            // Limit should also pass.
            Block <PolymorphicAction <ActionBase> > block3 = new BlockContent <PolymorphicAction <ActionBase> >
            {
                Index           = 2,
                Difficulty      = policy.GetNextBlockDifficulty(blockChain),
                TotalDifficulty = blockChain.Tip.Difficulty + policy.GetNextBlockDifficulty(blockChain),
                PublicKey       = adminPublicKey,
                PreviousHash    = blockChain.Tip.Hash,
                Timestamp       = DateTimeOffset.MinValue,
                Transactions    = GenerateTransactions(5),
            }.Mine(policy.GetHashAlgorithm(2)).Evaluate(adminPrivateKey, blockChain);

            blockChain.Append(block3);
            Assert.Equal(3, blockChain.Count);
            Assert.True(blockChain.ContainsBlock(block3.Hash));
        }
        public async Task Preload()
        {
            Swarm <DumbAction> minerSwarm    = _swarms[0];
            Swarm <DumbAction> receiverSwarm = _swarms[1];

            BlockChain <DumbAction> minerChain    = _blockchains[0];
            BlockChain <DumbAction> receiverChain = _blockchains[1];

            var blocks = new List <Block <DumbAction> >();

            foreach (int i in Enumerable.Range(0, 11))
            {
                blocks.Add(TestUtils.MineNext(
                               previousBlock: i == 0 ? minerChain.Genesis : blocks[i - 1],
                               difficulty: 1024));
                if (i != 10)
                {
                    minerChain.Append(blocks[i]);
                }
            }

            var actualStates = new List <PreloadState>();
            var progress     = new Progress <PreloadState>(state =>
            {
                _logger.Information("Received a progress event: {@State}", state);
                lock (actualStates)
                {
                    actualStates.Add(state);

                    if (actualStates.Count == 9)
                    {
                        minerChain.Append(blocks[10]);
                    }
                }
            });

            try
            {
                await StartAsync(minerSwarm);

                await receiverSwarm.AddPeersAsync(new[] { minerSwarm.AsPeer }, null);

                _logger.Verbose("Both chains before synchronization:");
                _logger.CompareBothChains(
                    LogEventLevel.Verbose,
                    "Miner chain",
                    minerChain,
                    "Receiver chain",
                    receiverChain
                    );

                minerSwarm.FindNextHashesChunkSize = 2;
                await receiverSwarm.PreloadAsync(TimeSpan.FromSeconds(15), progress);

                // Await 1 second to make sure all progresses is reported.
                await Task.Delay(1000);

                _logger.Verbose(
                    $"Both chains after synchronization ({nameof(receiverSwarm.PreloadAsync)}):"
                    );
                _logger.CompareBothChains(
                    LogEventLevel.Verbose,
                    "Miner chain",
                    minerChain,
                    "Receiver chain",
                    receiverChain
                    );
                Assert.Equal(minerChain.BlockHashes, receiverChain.BlockHashes);

                var expectedStates = new List <PreloadState>();

                for (var i = 1; i < minerChain.Count; i++)
                {
                    var b     = minerChain[i];
                    var state = new BlockHashDownloadState
                    {
                        EstimatedTotalBlockHashCount = 10,
                        ReceivedBlockHashCount       = 1,
                        SourcePeer = minerSwarm.AsPeer as BoundPeer,
                    };
                    expectedStates.Add(state);
                }

                for (var i = 1; i < minerChain.Count; i++)
                {
                    var b     = minerChain[i];
                    var state = new BlockDownloadState
                    {
                        ReceivedBlockHash  = b.Hash,
                        TotalBlockCount    = i == 9 || i == 10 ? 11 : 10,
                        ReceivedBlockCount = i,
                        SourcePeer         = minerSwarm.AsPeer as BoundPeer,
                    };
                    expectedStates.Add(state);
                }

                for (var i = 1; i < minerChain.Count; i++)
                {
                    var b     = minerChain[i];
                    var state = new BlockVerificationState
                    {
                        VerifiedBlockHash  = b.Hash,
                        TotalBlockCount    = i == 9 || i == 10 ? 11 : 10,
                        VerifiedBlockCount = i,
                    };
                    expectedStates.Add(state);
                }

                for (var i = 1; i < minerChain.Count; i++)
                {
                    var b     = minerChain[i];
                    var state = new ActionExecutionState
                    {
                        ExecutedBlockHash  = b.Hash,
                        TotalBlockCount    = 11,
                        ExecutedBlockCount = i,
                    };
                    expectedStates.Add(state);
                }

                _logger.Debug("Expected preload states: {@expectedStates}", expectedStates);
                _logger.Debug("Actual preload states: {@actualStates}", actualStates);

                Assert.Equal(expectedStates.Count, actualStates.Count);
                foreach (var states in expectedStates.Zip(actualStates, ValueTuple.Create))
                {
                    Assert.Equal(states.Item1, states.Item2);
                }
            }
            finally
            {
                await StopAsync(minerSwarm);
                await StopAsync(receiverSwarm);
            }
        }
        public void ForkStateReferences()
        {
            Address addr1 = new PrivateKey().PublicKey.ToAddress();
            Address addr2 = new PrivateKey().PublicKey.ToAddress();

            Transaction <DumbAction>[] txsA =
            {
                _fx.MakeTransaction(new[]
                {
                    new DumbAction(addr1, "foo"),
                }),
            };
            Transaction <DumbAction>[] txsB =
            {
                _fx.MakeTransaction(new[]
                {
                    new DumbAction(addr2, "bar"),
                }),
            };

            Block <DumbAction> genesis = TestUtils.MineGenesis <DumbAction>();

            _blockChain.Append(genesis);

            Block <DumbAction> b1 = TestUtils.MineNext(
                genesis,
                txsA,
                null,
                _blockChain.Policy.GetNextBlockDifficulty(_blockChain));

            _blockChain.Append(b1);

            Block <DumbAction> b2 = TestUtils.MineNext(
                b1,
                txsB,
                null,
                _blockChain.Policy.GetNextBlockDifficulty(_blockChain));

            _blockChain.Append(b2);

            Block <DumbAction> b3 = TestUtils.MineNext(
                b2,
                txsB,
                null,
                _blockChain.Policy.GetNextBlockDifficulty(_blockChain));

            _blockChain.Append(b3);

            // Fork from genesis and append two empty blocks.
            BlockChain <DumbAction> forked = _blockChain.Fork(genesis.Hash);
            string             fId         = forked.Id.ToString();
            Block <DumbAction> fb1         = TestUtils.MineNext(genesis, difficulty: b1.Difficulty);
            Block <DumbAction> fb2         = TestUtils.MineNext(fb1, difficulty: b2.Difficulty);

            forked.Append(fb1);
            forked.Append(fb2);

            Assert.Null(
                forked.Store.LookupStateReference(fId, addr1, forked.Tip));
            Assert.Null(
                forked.Store.LookupStateReference(fId, addr2, forked.Tip));

            // Fork from b1 and append a empty block.
            forked = _blockChain.Fork(b1.Hash);
            fId    = forked.Id.ToString();
            fb2    = TestUtils.MineNext(b1, difficulty: b2.Difficulty);
            forked.Append(fb2);

            Assert.Equal(
                b1.Hash,
                forked.Store.LookupStateReference(fId, addr1, forked.Tip));
            Assert.Null(
                forked.Store.LookupStateReference(fId, addr2, forked.Tip));

            // Fork from b2.
            forked = _blockChain.Fork(b2.Hash);
            fId    = forked.Id.ToString();

            Assert.Equal(
                b1.Hash,
                forked.Store.LookupStateReference(fId, addr1, forked.Tip));
            Assert.Equal(
                b2.Hash,
                forked.Store.LookupStateReference(fId, addr2, forked.Tip));
        }
        public void Swap()
        {
            // FIXME: Poor man's fixture --- should make a proper fixture.
            Append();

            BlockChain <DumbAction> fork =
                _blockChain.Fork(_blockChain.Tip.Hash);

            Address[] addresses = Enumerable.Repeat(0, 4)
                                  .Select(_ => new PrivateKey().PublicKey.ToAddress())
                                  .ToArray();

            Transaction <DumbAction>[][] txsA =
            {
                new[]
                {
                    _fx.MakeTransaction(new[]
                    {
                        new DumbAction(addresses[0], "foo"),
                    }),
                    _fx.MakeTransaction(new[]
                    {
                        new DumbAction(addresses[1], "bar"),
                    }),
                },
                new[]
                {
                    _fx.MakeTransaction(new[]
                    {
                        new DumbAction(addresses[2], "baz"),
                    }),
                    _fx.MakeTransaction(new[]
                    {
                        new DumbAction(addresses[3], "qux"),
                    }),
                },
            };

            foreach (Transaction <DumbAction>[] txs in txsA)
            {
                Block <DumbAction> b = TestUtils.MineNext(
                    _blockChain.Tip,
                    txs,
                    null,
                    _blockChain.Policy.GetNextBlockDifficulty(_blockChain)
                    );
                _blockChain.Append(b);
            }

            Transaction <DumbAction>[] txsB =
            {
                _fx.MakeTransaction(new[]
                {
                    new DumbAction(addresses[0], "fork-foo"),
                }),
                _fx.MakeTransaction(new[]
                {
                    new DumbAction(addresses[1], "fork-bar"),
                    new DumbAction(addresses[2], "fork-baz"),
                }),
            };

            try
            {
                DumbAction.RenderRecords.Value =
                    ImmutableList <DumbAction.RenderRecord> .Empty;

                Block <DumbAction> forkTip = TestUtils.MineNext(
                    fork.Tip,
                    txsB,
                    null,
                    _blockChain.Policy.GetNextBlockDifficulty(_blockChain)
                    );
                fork.Append(forkTip, DateTimeOffset.UtcNow, render: false);

                _blockChain.Swap(fork);
                var renders = DumbAction.RenderRecords.Value;

                int actionsCountA = txsA.Sum(
                    a => a.Sum(tx => tx.Actions.Count)
                    );
                int actionsCountB = txsB.Sum(tx => tx.Actions.Count);

                Assert.Equal(actionsCountB + actionsCountA, renders.Count);
                Assert.True(renders.Take(actionsCountA).All(r => r.Unrender));
                Assert.True(renders.Skip(actionsCountA).All(r => r.Render));

                Assert.Equal("qux", renders[0].Action.Item);
                Assert.Equal("baz", renders[1].Action.Item);
                Assert.Equal("bar", renders[2].Action.Item);
                Assert.Equal("foo", renders[3].Action.Item);
                Assert.Equal("fork-foo", renders[4].Action.Item);
                Assert.Equal("fork-bar", renders[5].Action.Item);
                Assert.Equal("fork-baz", renders[6].Action.Item);
            }
            finally
            {
                DumbAction.RenderRecords.Value =
                    ImmutableList <DumbAction.RenderRecord> .Empty;
            }
        }
        public async Task DetermineCanonicalChain(short canonComparerType)
        {
            IComparer <IBlockExcerpt> canonComparer;

            switch (canonComparerType)
            {
            default:
                canonComparer = new TotalDifficultyComparer();
                break;

            case 1:
                canonComparer = new AnonymousComparer <IBlockExcerpt>((a, b) =>
                                                                      string.Compare(
                                                                          a.Hash.ToString(),
                                                                          b.Hash.ToString(),
                                                                          StringComparison.Ordinal
                                                                          )
                                                                      );
                break;
            }

            var policy = new BlockPolicy <DumbAction>(
                new MinerReward(1),
                canonicalChainComparer: canonComparer
                );
            BlockChain <DumbAction> chain1 = TestUtils.MakeBlockChain(
                policy,
                new DefaultStore(null),
                new TrieStateStore(new MemoryKeyValueStore())
                );
            BlockChain <DumbAction> chain2 = TestUtils.MakeBlockChain(
                policy,
                new DefaultStore(null),
                new TrieStateStore(new MemoryKeyValueStore())
                );

            var key1 = new PrivateKey();
            var key2 = new PrivateKey();

            Swarm <DumbAction> miner1 = CreateSwarm(chain1, key1);
            Swarm <DumbAction> miner2 = CreateSwarm(chain2, key2);

            await chain1.MineBlock(key1);

            await chain1.MineBlock(key2);

            Block <DumbAction> bestBlock;

            switch (canonComparerType)
            {
            default:
                long nextDifficulty =
                    (long)chain1.Tip.TotalDifficulty + policy.GetNextBlockDifficulty(chain2);
                bestBlock = TestUtils.MineNext(
                    chain2.Tip,
                    policy.GetHashAlgorithm,
                    difficulty: nextDifficulty,
                    blockInterval: TimeSpan.FromMilliseconds(1),
                    miner: TestUtils.ChainPrivateKey.PublicKey
                    ).Evaluate(TestUtils.ChainPrivateKey, chain2);
                _output.WriteLine("chain1's total difficulty: {0}", chain1.Tip.TotalDifficulty);
                _output.WriteLine("chain2's total difficulty: {0}", bestBlock.TotalDifficulty);
                break;

            case 1:
                string chain1TipHash = chain1.Tip.Hash.ToString();
                string hashStr;
                do
                {
                    bestBlock = TestUtils.MineNext(
                        chain2.Tip,
                        policy.GetHashAlgorithm,
                        difficulty: policy.GetNextBlockDifficulty(chain2),
                        blockInterval: TimeSpan.FromMilliseconds(1),
                        miner: TestUtils.ChainPrivateKey.PublicKey
                        ).Evaluate(TestUtils.ChainPrivateKey, chain2);
                    hashStr = bestBlock.Hash.ToString();
                    _output.WriteLine("chain1's tip hash: {0}", chain1.Tip.Hash);
                    _output.WriteLine("chain2's tip hash: {0}", bestBlock.Hash);
                    _output.WriteLine(string.Empty);
                }while (string.Compare(chain1TipHash, hashStr, StringComparison.Ordinal) >= 0);
                break;
            }

            Assert.True(
                canonComparer.Compare(
                    new BlockPerception(bestBlock),
                    chain1.PerceiveBlock(chain1.Tip)
                    ) > 0
                );
            chain2.Append(bestBlock);

            try
            {
                await StartAsync(miner1);
                await StartAsync(miner2);

                await BootstrapAsync(miner2, miner1.AsPeer);

                miner2.BroadcastBlock(bestBlock);
                _output.WriteLine("miner1 is waiting for a new block...");
                await miner1.BlockReceived.WaitAsync();

                Assert.Equal(miner1.BlockChain.Tip, bestBlock);
                Assert.Equal(miner2.BlockChain.Tip, bestBlock);
            }
            finally
            {
                await StopAsync(miner1);
                await StopAsync(miner2);

                miner1.Dispose();
                miner2.Dispose();
            }
        }
Exemple #25
0
        public async Task <Block <PolymorphicAction <ActionBase> > > MineBlockAsync(
            int maxTransactions,
            CancellationToken cancellationToken)
        {
            var txs        = new HashSet <Transaction <PolymorphicAction <ActionBase> > >();
            var invalidTxs = txs;

            Transaction <PolymorphicAction <ActionBase> > authProof = null;
            Block <PolymorphicAction <ActionBase> >       block     = null;

            try
            {
                if (AuthorizedMiner)
                {
                    authProof = StageProofTransaction();
                }
                block = await _chain.MineBlock(
                    Address,
                    DateTimeOffset.UtcNow,
                    cancellationToken : cancellationToken,
                    maxTransactions : maxTransactions,
                    append : false);

                if (authProof is Transaction <PolymorphicAction <ActionBase> > proof &&
                    !block.Transactions.Contains(proof))
                {
                    // For any reason, if the proof tx is not contained mine a new block again
                    // without any transactions except for the proof tx.
                    block = Block <PolymorphicAction <ActionBase> > .Mine(
                        block.Index,
                        block.Difficulty,
                        block.TotalDifficulty - block.Difficulty,
                        Address,
                        block.PreviousHash,
                        DateTimeOffset.UtcNow,
                        new[] { proof },
                        block.ProtocolVersion,
                        cancellationToken
                        );
                }

                _chain.Append(block);
                if (_swarm is Swarm <PolymorphicAction <ActionBase> > s && s.Running)
                {
                    s.BroadcastBlock(block);
                }
            }
            catch (OperationCanceledException)
            {
                Log.Debug("Mining was canceled due to change of tip.");
            }
            catch (InvalidTxException invalidTxException)
            {
                var invalidTx = _chain.GetTransaction(invalidTxException.TxId);

                Log.Debug($"Tx[{invalidTxException.TxId}] is invalid. mark to unstage.");
                invalidTxs.Add(invalidTx);
            }
            catch (UnexpectedlyTerminatedActionException actionException)
            {
                if (actionException.TxId is TxId txId)
                {
                    Log.Debug(
                        $"Tx[{actionException.TxId}]'s action is invalid. mark to unstage. {actionException}");
                    invalidTxs.Add(_chain.GetTransaction(txId));
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, $"exception was thrown. {ex}");
            }
            finally
            {
#pragma warning disable LAA1002
                foreach (var invalidTx in invalidTxs)
#pragma warning restore LAA1002
                {
                    _chain.UnstageTransaction(invalidTx);
                }
            }

            return(block);
        }
Exemple #26
0
        public async Task GetMultipleBlocksAtOnce()
        {
            var privateKey = new PrivateKey();

            BlockChain <DumbAction> chainA = _blockchains[0];
            BlockChain <DumbAction> chainB = _blockchains[1];

            Swarm <DumbAction> swarmA = _swarms[0];
            Swarm <DumbAction> swarmB = new Swarm <DumbAction>(
                chainB,
                privateKey,
                1,
                host: IPAddress.Loopback.ToString());

            Block <DumbAction> genesis = chainA.MineBlock(_fx1.Address1);

            chainB.Append(genesis); // chainA and chainB shares genesis block.
            chainA.MineBlock(_fx1.Address1);
            chainA.MineBlock(_fx1.Address1);

            try
            {
                await StartAsync(swarmA);
                await StartAsync(swarmB);

                var peer = swarmA.AsPeer;

                await swarmB.AddPeersAsync(new[] { peer });

                IEnumerable <HashDigest <SHA256> > hashes =
                    await swarmB.GetBlockHashesAsync(
                        peer,
                        new BlockLocator(new[] { genesis.Hash }),
                        null);

                var netMQAddress = $"tcp://{peer.EndPoint.Host}:{peer.EndPoint.Port}";
                using (var socket = new DealerSocket(netMQAddress))
                {
                    var request = new GetBlocks(hashes, 2);
                    await socket.SendMultipartMessageAsync(
                        request.ToNetMQMessage(privateKey));

                    NetMQMessage response = await socket.ReceiveMultipartMessageAsync();

                    Message parsedMessage = Message.Parse(response, true);
                    Libplanet.Net.Messages.Blocks blockMessage =
                        (Libplanet.Net.Messages.Blocks)parsedMessage;

                    Assert.Equal(2, blockMessage.Payloads.Count);

                    response = await socket.ReceiveMultipartMessageAsync();

                    parsedMessage = Message.Parse(response, true);
                    blockMessage  = (Libplanet.Net.Messages.Blocks)parsedMessage;

                    Assert.Single(blockMessage.Payloads);
                }
            }
            finally
            {
                await Task.WhenAll(
                    swarmA.StopAsync(),
                    swarmB.StopAsync());
            }
        }
Exemple #27
0
        public void ValidateNextBlockWithManyTransactions()
        {
            var adminPrivateKey = new PrivateKey();
            var adminAddress = new Address(adminPrivateKey.PublicKey);
            var blockPolicySource = new BlockPolicySource(Logger.None);
            IBlockPolicy<PolymorphicAction<ActionBase>> policy = blockPolicySource.GetPolicy(3000, 10);
            Block<PolymorphicAction<ActionBase>> genesis = MakeGenesisBlock(adminAddress, ImmutableHashSet<Address>.Empty);

            using var store = new DefaultStore(null);
            var stateStore = new NoOpStateStore();
            var blockChain = new BlockChain<PolymorphicAction<ActionBase>>(
                policy,
                store,
                stateStore,
                genesis
            );

            int nonce = 0;
            List<Transaction<PolymorphicAction<ActionBase>>> GenerateTransactions(int count)
            {
                var list = new List<Transaction<PolymorphicAction<ActionBase>>>();
                for (int i = 0; i < count; i++)
                {
                    list.Add(Transaction<PolymorphicAction<ActionBase>>.Create(
                        nonce++,
                        adminPrivateKey,
                        genesis.Hash,
                        new PolymorphicAction<ActionBase>[] { }
                    ));
                }

                return list;
            }

            Assert.Equal(1, blockChain.Count);
            Block<PolymorphicAction<ActionBase>> block1 = Block<PolymorphicAction<ActionBase>>.Mine(
                index: 1,
                difficulty: policy.GetNextBlockDifficulty(blockChain),
                previousTotalDifficulty: blockChain.Tip.TotalDifficulty,
                miner: adminAddress,
                previousHash: blockChain.Tip.Hash,
                timestamp: DateTimeOffset.MinValue,
                transactions: GenerateTransactions(5));
            blockChain.Append(block1);
            Assert.Equal(2, blockChain.Count);
            Assert.True(blockChain.ContainsBlock(block1.Hash));
            Block<PolymorphicAction<ActionBase>> block2 = Block<PolymorphicAction<ActionBase>>.Mine(
                index: 2,
                difficulty: policy.GetNextBlockDifficulty(blockChain),
                previousTotalDifficulty: blockChain.Tip.TotalDifficulty,
                miner: adminAddress,
                previousHash: blockChain.Tip.Hash,
                timestamp: DateTimeOffset.MinValue,
                transactions: GenerateTransactions(10));
            blockChain.Append(block2);
            Assert.Equal(3, blockChain.Count);
            Assert.True(blockChain.ContainsBlock(block2.Hash));
            Block<PolymorphicAction<ActionBase>> block3 = Block<PolymorphicAction<ActionBase>>.Mine(
                index: 3,
                difficulty: policy.GetNextBlockDifficulty(blockChain),
                previousTotalDifficulty: blockChain.Tip.TotalDifficulty,
                miner: adminAddress,
                previousHash: blockChain.Tip.Hash,
                timestamp: DateTimeOffset.MinValue,
                transactions: GenerateTransactions(11));
            Assert.Throws<BlockExceedingTransactionsException>(() => blockChain.Append(block3));
            Assert.Equal(3, blockChain.Count);
            Assert.False(blockChain.ContainsBlock(block3.Hash));
        }
Exemple #28
0
        public async Task CanGetBlock()
        {
            Swarm swarmA = _swarms[0];
            Swarm swarmB = _swarms[1];

            BlockChain <BaseAction> chainA = _blockchains[0];
            BlockChain <BaseAction> chainB = _blockchains[1];

            Block <BaseAction> genesis = chainA.MineBlock(_fx1.Address1);

            chainB.Append(genesis); // chainA and chainB shares genesis block.
            Block <BaseAction> block1 = chainA.MineBlock(_fx1.Address1);
            Block <BaseAction> block2 = chainA.MineBlock(_fx1.Address1);

            try
            {
                await StartAsync(swarmA, chainA);
                await StartAsync(swarmB, chainA);

                await Assert.ThrowsAsync <PeerNotFoundException>(
                    async() => await swarmB.GetBlockHashesAsync(
                        swarmA.AsPeer,
                        new BlockLocator(new[] { genesis.Hash }),
                        null));

                await swarmB.AddPeersAsync(new[] { swarmA.AsPeer });

                IEnumerable <HashDigest <SHA256> > inventories1 =
                    await swarmB.GetBlockHashesAsync(
                        swarmA.AsPeer,
                        new BlockLocator(new[] { genesis.Hash }),
                        null);

                Assert.Equal(
                    new[] { genesis.Hash, block1.Hash, block2.Hash },
                    inventories1);

                IEnumerable <HashDigest <SHA256> > inventories2 =
                    await swarmB.GetBlockHashesAsync(
                        swarmA.AsPeer,
                        new BlockLocator(new[] { genesis.Hash }),
                        block1.Hash);

                Assert.Equal(
                    new[] { genesis.Hash, block1.Hash },
                    inventories2);

                List <Block <BaseAction> > receivedBlocks =
                    await swarmB.GetBlocksAsync <BaseAction>(
                        swarmA.AsPeer, inventories1
                        ).ToListAsync();

                Assert.Equal(
                    new[] { genesis, block1, block2 },
                    receivedBlocks);
            }
            finally
            {
                await Task.WhenAll(
                    swarmA.StopAsync(),
                    swarmB.StopAsync());
            }
        }
Exemple #29
0
        public async Task CanBroadcastBlock()
        {
            Swarm swarmA = _swarms[0];
            Swarm swarmB = _swarms[1];
            Swarm swarmC = _swarms[2];

            BlockChain <BaseAction> chainA = _blockchains[0];
            BlockChain <BaseAction> chainB = _blockchains[1];
            BlockChain <BaseAction> chainC = _blockchains[2];

            // chainA, chainB and chainC shares genesis block.
            Block <BaseAction> genesis = chainA.MineBlock(_fx1.Address1);

            chainB.Append(genesis);
            chainC.Append(genesis);

            foreach (int i in Enumerable.Range(0, 10))
            {
                chainA.MineBlock(_fx1.Address1);
                await Task.Delay(100);
            }

            foreach (int i in Enumerable.Range(0, 3))
            {
                chainB.MineBlock(_fx2.Address1);
                await Task.Delay(100);
            }

            try
            {
                await StartAsync(swarmA, chainA);
                await StartAsync(swarmB, chainB);
                await StartAsync(swarmC, chainC);

                await swarmA.AddPeersAsync(new[] { swarmB.AsPeer });

                await swarmA.AddPeersAsync(new[] { swarmC.AsPeer });

                await EnsureExchange(swarmA, swarmB);
                await EnsureExchange(swarmA, swarmC);
                await EnsureExchange(swarmB, swarmC);

                await swarmB.BroadcastBlocksAsync(new[] { chainB.Last() });

                await swarmC.BlockReceived.WaitAsync();

                await swarmA.BlockReceived.WaitAsync();

                Assert.Equal(chainB.AsEnumerable(), chainC);

                // chainB doesn't applied to chainA since chainB is shorter
                // than chainA
                Assert.NotEqual(chainB.AsEnumerable(), chainA);

                await swarmA.BroadcastBlocksAsync(new[] { chainA.Last() });

                await swarmB.BlockReceived.WaitAsync();

                await swarmC.BlockReceived.WaitAsync();

                Assert.Equal(chainA.AsEnumerable(), chainB);
                Assert.Equal(chainA.AsEnumerable(), chainC);
            }
            finally
            {
                await Task.WhenAll(
                    swarmA.StopAsync(),
                    swarmB.StopAsync(),
                    swarmC.StopAsync());
            }
        }
Exemple #30
0
        public async Task PreloadAsyncCancellation(int cancelAfter)
        {
            Swarm <DumbAction> minerSwarm    = CreateSwarm();
            Swarm <DumbAction> receiverSwarm = CreateSwarm();

            Log.Logger.Information("Miner:    {0}", minerSwarm.Address);
            Log.Logger.Information("Receiver: {0}", receiverSwarm.Address);

            BlockChain <DumbAction> minerChain    = minerSwarm.BlockChain;
            BlockChain <DumbAction> receiverChain = receiverSwarm.BlockChain;

            Guid receiverChainId = receiverChain.Id;

            (Address address, IEnumerable <Block <DumbAction> > blocks) =
                await MakeFixtureBlocksForPreloadAsyncCancellationTest();

            var blockArray = blocks.ToArray();

            foreach (Block <DumbAction> block in blockArray)
            {
                minerChain.Append(block);
            }

            receiverChain.Append(blockArray[0]);

            Assert.NotNull(minerChain.Tip);

            minerSwarm.FindNextHashesChunkSize = 2;
            await StartAsync(minerSwarm);

            await receiverSwarm.AddPeersAsync(new[] { minerSwarm.AsPeer }, null);

            CancellationTokenSource cts = new CancellationTokenSource();

            cts.CancelAfter(cancelAfter);
            bool canceled = true;

            try
            {
                await receiverSwarm.PreloadAsync(cancellationToken : cts.Token);

                canceled = false;
                Log.Logger.Debug($"{nameof(receiverSwarm.PreloadAsync)}() normally finished.");
            }
            catch (OperationCanceledException)
            {
                Log.Logger.Debug($"{nameof(receiverSwarm.PreloadAsync)}() aborted.");
            }
            catch (AggregateException ae) when(ae.InnerException is TaskCanceledException)
            {
                Log.Logger.Debug($"{nameof(receiverSwarm.PreloadAsync)}() aborted.");
            }

            cts.Dispose();

            Assert.InRange(receiverChain.Store.ListChainIds().Count(), 0, 1);

            if (canceled)
            {
                Assert.Equal(receiverChainId, receiverChain.Id);
                Assert.Equal(
                    (blockArray[0].Index, blockArray[0].Hash),
                    (receiverChain.Tip.Index, receiverChain.Tip.Hash)
                    );
                Assert.Equal(blockArray[0], receiverChain.Tip);
                Assert.Equal(
                    (Text)string.Join(",", Enumerable.Range(0, 5).Select(j => $"Item0.{j}")),
                    receiverChain.GetState(address)
                    );
            }
            else
            {
                Assert.NotEqual(receiverChainId, receiverChain.Id);
                Assert.Equal(minerChain.Tip, receiverChain.Tip);
                Assert.Equal(
                    (Text)string.Join(
                        ",",
                        Enumerable.Range(0, 20).Select(i =>
                                                       string.Join(",", Enumerable.Range(0, 5).Select(j => $"Item{i}.{j}"))
                                                       )
                        ),
                    receiverChain.GetState(address)
                    );
            }
        }