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);
     }
 }
        private Swarm <DumbAction> CreateSwarm(
            PrivateKey privateKey = null,
            AppProtocolVersion?appProtocolVersion = null,
            string host    = null,
            int?listenPort = null,
            IEnumerable <IceServer> iceServers = null,
            DifferentAppProtocolVersionEncountered differentAppProtocolVersionEncountered = null,
            IEnumerable <PublicKey> trustedAppProtocolVersionSigners = null,
            SwarmOptions options             = null,
            IBlockPolicy <DumbAction> policy = null,
            Block <DumbAction> genesis       = null)
        {
            policy = policy ?? new BlockPolicy <DumbAction>(new MinerReward(1));
            var fx         = new MemoryStoreFixture(policy.BlockAction);
            var blockchain = MakeBlockChain(
                policy,
                fx.Store,
                fx.StateStore,
                genesisBlock: genesis
                );

            return(CreateSwarm(
                       blockchain,
                       privateKey,
                       appProtocolVersion,
                       host,
                       listenPort,
                       iceServers,
                       differentAppProtocolVersionEncountered,
                       trustedAppProtocolVersionSigners,
                       options));
        }
Beispiel #3
0
        public async Task PreloadWithFailedActions()
        {
            var policy        = new BlockPolicy <ThrowException>();
            var fx1           = new MemoryStoreFixture();
            var fx2           = new MemoryStoreFixture();
            var minerChain    = MakeBlockChain(policy, fx1.Store, fx1.StateStore);
            var receiverChain = MakeBlockChain(policy, fx2.Store, fx2.StateStore);

            var minerKey = new PrivateKey();

            Swarm <ThrowException> minerSwarm    = CreateSwarm(minerChain, minerKey);
            Swarm <ThrowException> receiverSwarm = CreateSwarm(receiverChain);

            foreach (var unused in Enumerable.Range(0, 10))
            {
                await minerSwarm.BlockChain.MineBlock(minerKey);
            }

            try
            {
                await StartAsync(minerSwarm);

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

                await receiverSwarm.PreloadAsync(TimeSpan.FromSeconds(1));

                var action = new ThrowException {
                    ThrowOnExecution = true
                };

                var chainId = receiverChain.Id;
                Transaction <ThrowException> tx = Transaction <ThrowException> .Create(
                    0,
                    new PrivateKey(),
                    minerSwarm.BlockChain.Genesis.Hash,
                    new[] { action },
                    ImmutableHashSet <Address> .Empty,
                    DateTimeOffset.UtcNow
                    );

                Block <ThrowException> block = MineNext(
                    minerChain.Tip,
                    minerChain.Policy.GetHashAlgorithm,
                    new[] { tx },
                    miner: ChainPrivateKey.PublicKey,
                    difficulty: policy.GetNextBlockDifficulty(minerChain),
                    blockInterval: TimeSpan.FromSeconds(1)
                    ).Evaluate(ChainPrivateKey, minerChain);
                minerSwarm.BlockChain.Append(block, false, true, false);

                await receiverSwarm.PreloadAsync(TimeSpan.FromSeconds(1));

                // Preloading should succeed even if action throws exception.
                Assert.Equal(minerChain.Tip, receiverChain.Tip);
            }
            finally
            {
                await StopAsync(minerSwarm);
            }
        }
Beispiel #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 MemoryStoreFixture())
            {
                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));
            }
        }
        MakeFixtureBlocksForPreloadAsyncCancellationTest()
        {
            Block <DumbAction>[] blocks = _fixtureBlocksForPreloadAsyncCancellationTest;

            if (blocks is null)
            {
                var policy = new BlockPolicy <DumbAction>(new MinerReward(1));
                using (var storeFx = new MemoryStoreFixture())
                {
                    var     chain   = MakeBlockChain(policy, storeFx.Store, storeFx.StateStore);
                    var     miner   = new PrivateKey();
                    var     signer  = new PrivateKey();
                    Address address = signer.ToAddress();
                    Log.Logger.Information("Fixture blocks:");
                    for (int i = 0; i < 20; i++)
                    {
                        for (int j = 0; j < 5; j++)
                        {
                            chain.MakeTransaction(
                                signer,
                                new[] { new DumbAction(address, $"Item{i}.{j}", idempotent: true) }
                                );
                        }

                        Block <DumbAction> block = await chain.MineBlock(miner);

                        Log.Logger.Information("  #{0,2} {1}", block.Index, block.Hash);
                    }

                    var blockList = new List <Block <DumbAction> >();
                    for (var i = 1; i < chain.Count; i++)
                    {
                        Block <DumbAction> block = chain[i];
                        blockList.Add(block);
                    }

                    blocks = blockList.ToArray();

                    _fixtureBlocksForPreloadAsyncCancellationTest = blocks;
                }
            }

            return(blocks[1].Transactions.First().Actions.First().TargetAddress, blocks);
        }
        public async Task MineBlockWithMultipleAlgorithms()
        {
            using (var fx = new MemoryStoreFixture())
            {
                IBlockPolicy <DumbAction> policy = new MultiAlgoPolicy <DumbAction>();
                BlockChain <DumbAction>   chain  = TestUtils.MakeBlockChain(
                    policy,
                    fx.Store,
                    fx.StateStore,
                    new DumbAction[0]
                    );
                var key = new PrivateKey();
                Block <DumbAction> block1 = await chain.MineBlock(key);

                Assert.Equal(16, block1.PreEvaluationHash.Length);
                Block <DumbAction> block2 = await chain.MineBlock(key);

                Assert.Equal(20, block2.PreEvaluationHash.Length);
            }
        }
Beispiel #7
0
 protected StagePolicyTest()
 {
     _policy = new BlockPolicy <DumbAction>();
     _fx     = new MemoryStoreFixture();
     _chain  = new BlockChain <DumbAction>(
         _policy,
         StagePolicy,
         _fx.Store,
         _fx.StateStore,
         _fx.GenesisBlock
         );
     _key = new PrivateKey();
     _txs = Enumerable.Range(0, 5).Select(i =>
                                          Transaction <DumbAction> .Create(
                                              i,
                                              _key,
                                              _fx.GenesisBlock.Hash,
                                              Enumerable.Empty <DumbAction>()
                                              )
                                          ).ToArray();
 }
Beispiel #8
0
        public async Task QueryAppProtocolVersion(SwarmOptions.TransportType transportType)
        {
            var fx                 = new MemoryStoreFixture();
            var policy             = new BlockPolicy <DumbAction>();
            var blockchain         = MakeBlockChain(policy, fx.Store, fx.StateStore);
            var apvKey             = new PrivateKey();
            var swarmKey           = new PrivateKey();
            AppProtocolVersion apv = AppProtocolVersion.Sign(apvKey, 1);

            string host = IPAddress.Loopback.ToString();
            int    port = FreeTcpPort();

            var option = new SwarmOptions
            {
                Type = transportType,
            };

            using (var swarm = new Swarm <DumbAction>(
                       blockchain,
                       swarmKey,
                       apv,
                       host: host,
                       listenPort: port,
                       options: option))
            {
                var peer = new BoundPeer(swarmKey.PublicKey, new DnsEndPoint(host, port));
                // Before swarm starting...
                await Assert.ThrowsAsync <TimeoutException>(async() =>
                {
                    if (swarm.Transport is NetMQTransport)
                    {
                        peer.QueryAppProtocolVersionNetMQ(timeout: TimeSpan.FromSeconds(1));
                    }
                    else if (swarm.Transport is TcpTransport)
                    {
                        await peer.QueryAppProtocolVersionTcp(timeout: TimeSpan.FromSeconds(1));
                    }
                    else
                    {
                        throw new XunitException(
                            "Each type of transport must have corresponding test case.");
                    }
                });

                _ = swarm.StartAsync();
                try
                {
                    AppProtocolVersion receivedAPV = default;
                    if (swarm.Transport is NetMQTransport)
                    {
                        receivedAPV = peer.QueryAppProtocolVersionNetMQ();
                    }
                    else if (swarm.Transport is TcpTransport)
                    {
                        receivedAPV = await peer.QueryAppProtocolVersionTcp();
                    }
                    else
                    {
                        throw new XunitException(
                                  "Each type of transport must have corresponding test case.");
                    }

                    Assert.Equal(apv, receivedAPV);
                }
                finally
                {
                    await swarm.StopAsync();
                }
            }

            if (transportType == SwarmOptions.TransportType.NetMQTransport)
            {
                NetMQConfig.Cleanup(false);
            }
        }
        public async Task BroadcastBlockWithSkip()
        {
            var policy           = new BlockPolicy <DumbAction>(new MinerReward(1));
            var fx1              = new MemoryStoreFixture();
            var blockChain       = MakeBlockChain(policy, fx1.Store, fx1.StateStore);
            var privateKey       = new PrivateKey();
            var minerSwarm       = CreateSwarm(blockChain, privateKey);
            var fx2              = new MemoryStoreFixture();
            var receiverRenderer = new RecordingActionRenderer <DumbAction>();
            var loggedRenderer   = new LoggedActionRenderer <DumbAction>(
                receiverRenderer,
                _logger);
            var receiverChain = MakeBlockChain(
                policy,
                fx2.Store,
                fx2.StateStore,
                renderers: new[] { loggedRenderer });
            Swarm <DumbAction> receiverSwarm = CreateSwarm(receiverChain);

            int renderCount = 0;

            receiverRenderer.RenderEventHandler += (_, a) => renderCount += a is DumbAction ? 1 : 0;

            Transaction <DumbAction>[] transactions =
            {
                fx1.MakeTransaction(
                    new[]
                {
                    new DumbAction(fx1.Address2, "foo"),
                    new DumbAction(fx1.Address2, "bar"),
                },
                    timestamp: DateTimeOffset.MinValue,
                    nonce: 0,
                    privateKey: privateKey),
                fx1.MakeTransaction(
                    new[]
                {
                    new DumbAction(fx1.Address2, "baz"),
                    new DumbAction(fx1.Address2, "qux"),
                },
                    timestamp: DateTimeOffset.MinValue.AddSeconds(5),
                    nonce: 1,
                    privateKey: privateKey),
            };

            Block <DumbAction> block1 = MineNext(
                blockChain.Genesis,
                policy.GetHashAlgorithm,
                new[] { transactions[0] },
                null,
                policy.GetNextBlockDifficulty(blockChain),
                miner: GenesisMiner.PublicKey
                ).Evaluate(GenesisMiner, blockChain);

            blockChain.Append(block1, true, true, false);
            Block <DumbAction> block2 = MineNext(
                block1,
                policy.GetHashAlgorithm,
                new[] { transactions[1] },
                null,
                policy.GetNextBlockDifficulty(blockChain),
                miner: GenesisMiner.PublicKey
                ).Evaluate(GenesisMiner, blockChain);

            blockChain.Append(block2, true, true, false);

            try
            {
                await StartAsync(minerSwarm);
                await StartAsync(receiverSwarm);

                await BootstrapAsync(receiverSwarm, minerSwarm.AsPeer);

                minerSwarm.BroadcastBlock(block2);

                await AssertThatEventually(
                    () => receiverChain.Tip.Equals(block2),
                    5_000
                    );

                Assert.Equal(3, receiverChain.Count);
                Assert.Equal(4, renderCount);
            }
            finally
            {
                await StopAsync(minerSwarm);
                await StopAsync(receiverSwarm);

                fx1.Dispose();
                minerSwarm.Dispose();
            }
        }
        public async Task BroadcastTxAsyncMany()
        {
            int size = 5;

            var policy = new BlockPolicy <DumbAction>();

            StoreFixture[]            fxs         = new StoreFixture[size];
            BlockChain <DumbAction>[] blockChains = new BlockChain <DumbAction> [size];
            Swarm <DumbAction>[]      swarms      = new Swarm <DumbAction> [size];

            for (int i = 0; i < size; i++)
            {
                fxs[i]         = new MemoryStoreFixture();
                blockChains[i] = new BlockChain <DumbAction>(
                    policy,
                    new VolatileStagePolicy <DumbAction>(),
                    fxs[i].Store,
                    fxs[i].StateStore,
                    fxs[i].GenesisBlock
                    );
                swarms[i] = CreateSwarm(blockChains[i]);
            }

            Transaction <DumbAction> tx = Transaction <DumbAction> .Create(
                0,
                new PrivateKey(),
                blockChains[size - 1].Genesis.Hash,
                new DumbAction[] { }
                );

            blockChains[size - 1].StageTransaction(tx);

            try
            {
                for (int i = 0; i < size; i++)
                {
                    await StartAsync(swarms[i]);
                }

                List <Task> tasks = new List <Task>();
                for (int i = 1; i < size; i++)
                {
                    await BootstrapAsync(swarms[i], swarms[0].AsPeer);
                }

                for (int i = 0; i < size - 1; i++)
                {
                    tasks.Add(swarms[i].TxReceived.WaitAsync());
                }

                await Task.WhenAll(tasks);

                for (int i = 0; i < size; i++)
                {
                    Assert.Equal(tx, blockChains[i].GetTransaction(tx.Id));
                }
            }
            finally
            {
                for (int i = 0; i < size; i++)
                {
                    await StopAsync(swarms[i]);

                    fxs[i].Dispose();
                    swarms[i].Dispose();
                }
            }
        }
        public async Task BroadcastBlockToReconnectedPeer()
        {
            var miner      = new PrivateKey();
            var policy     = new NullBlockPolicy <DumbAction>();
            var fx         = new MemoryStoreFixture(policy.BlockAction);
            var minerChain = MakeBlockChain(policy, fx.Store, fx.StateStore);

            foreach (int i in Enumerable.Range(0, 10))
            {
                await minerChain.MineBlock(miner);
            }

            Swarm <DumbAction> seed = CreateSwarm(
                miner,
                policy: policy,
                genesis: minerChain.Genesis
                );
            BlockChain <DumbAction> seedChain = seed.BlockChain;

            var privateKey            = new PrivateKey();
            Swarm <DumbAction> swarmA = CreateSwarm(
                privateKey: privateKey,
                policy: policy,
                genesis: minerChain.Genesis
                );
            Swarm <DumbAction> swarmB = CreateSwarm(
                privateKey: privateKey,
                policy: policy,
                genesis: minerChain.Genesis
                );

            foreach (BlockHash blockHash in minerChain.BlockHashes.Skip(1).Take(4))
            {
                seedChain.Append(minerChain[blockHash]);
            }

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

                Assert.Equal(swarmA.AsPeer, swarmB.AsPeer);

                await swarmA.AddPeersAsync(new[] { seed.AsPeer }, null);
                await StopAsync(swarmA);

                await seed.PeerDiscovery.RefreshTableAsync(
                    TimeSpan.Zero,
                    default(CancellationToken));

                Assert.DoesNotContain(swarmA.AsPeer, seed.Peers);

                foreach (BlockHash blockHash in minerChain.BlockHashes.Skip(5))
                {
                    seedChain.Append(minerChain[blockHash]);
                }

                await swarmB.AddPeersAsync(new[] { seed.AsPeer }, null);

                // This is added for context switching.
                await Task.Delay(100);

                Assert.Contains(swarmB.AsPeer, seed.Peers);
                Assert.Contains(seed.AsPeer, swarmB.Peers);

                seed.BroadcastBlock(seedChain.Tip);

                await swarmB.BlockAppended.WaitAsync();

                Assert.NotEqual(seedChain.BlockHashes, swarmA.BlockChain.BlockHashes);
                Assert.Equal(seedChain.BlockHashes, swarmB.BlockChain.BlockHashes);
            }
            finally
            {
                await StopAsync(seed);
                await StopAsync(swarmA);
                await StopAsync(swarmB);

                seed.Dispose();
                swarmA.Dispose();
                swarmB.Dispose();
            }
        }
Beispiel #12
0
        public async Task PreloadFromNominer()
        {
            var minerKey = new PrivateKey();
            Swarm <DumbAction> minerSwarm    = CreateSwarm(minerKey);
            Swarm <DumbAction> receiverSwarm = CreateSwarm();
            var fxForNominers = new StoreFixture[2];
            var policy        = new BlockPolicy <DumbAction>(new MinerReward(1));

            fxForNominers[0] = new MemoryStoreFixture(policy.BlockAction);
            fxForNominers[1] = new MemoryStoreFixture(policy.BlockAction);
            var blockChainsForNominers = new[]
            {
                MakeBlockChain(
                    policy,
                    fxForNominers[0].Store,
                    fxForNominers[0].StateStore),
                MakeBlockChain(
                    policy,
                    fxForNominers[1].Store,
                    fxForNominers[1].StateStore),
            };
            var nominerSwarm0 = CreateSwarm(blockChainsForNominers[0]);
            var nominerSwarm1 = CreateSwarm(blockChainsForNominers[1]);

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

            foreach (int i in Enumerable.Range(0, 10))
            {
                await minerChain.MineBlock(minerKey);
            }

            var actualStates = new List <PreloadState>();
            var progress     = new ActionProgress <PreloadState>(state =>
            {
                lock (actualStates)
                {
                    actualStates.Add(state);
                }
            });

            try
            {
                await StartAsync(minerSwarm);
                await StartAsync(nominerSwarm0);
                await StartAsync(nominerSwarm1);

                minerSwarm.FindNextHashesChunkSize    = 2;
                nominerSwarm0.FindNextHashesChunkSize = 2;
                nominerSwarm1.FindNextHashesChunkSize = 2;

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

                await nominerSwarm0.PreloadAsync();

                await nominerSwarm1.AddPeersAsync(new[] { nominerSwarm0.AsPeer }, null);

                await nominerSwarm1.PreloadAsync();

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

                await receiverSwarm.PreloadAsync(TimeSpan.FromSeconds(15), progress);

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

                Assert.Equal(minerChain.BlockHashes, receiverChain.BlockHashes);

                var expectedStates = new List <PreloadState>();

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

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

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

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

                // FIXME: this test does not ensures block download in order
                Assert.Equal(
                    new HashSet <PreloadState>(expectedStates),
                    new HashSet <PreloadState>(actualStates)
                    );
            }
            finally
            {
                await StopAsync(minerSwarm);
                await StopAsync(nominerSwarm0);
                await StopAsync(nominerSwarm1);
                await StopAsync(receiverSwarm);

                nominerSwarm0.Dispose();
                nominerSwarm1.Dispose();

                fxForNominers[0].Dispose();
                fxForNominers[1].Dispose();
            }
        }