private Swarm <T> CreateSwarm <T>(
            BlockChain <T> blockChain,
            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
            )
            where T : IAction, new()
        {
            if (host is null && !(iceServers?.Any() ?? false))
            {
                host = IPAddress.Loopback.ToString();
            }

            options ??= new SwarmOptions();
            string type = Environment.GetEnvironmentVariable("TRANSPORT_TYPE");

            _logger.Debug("Transport type: {Type}", type);
            switch (type)
            {
            case "tcp":
                options.Type = SwarmOptions.TransportType.TcpTransport;
                break;

            case "netmq":
                options.Type = SwarmOptions.TransportType.NetMQTransport;
                break;
            }

            var swarm = new Swarm <T>(
                blockChain,
                privateKey ?? new PrivateKey(),
                appProtocolVersion ?? DefaultAppProtocolVersion,
                5,
                host,
                listenPort,
                iceServers,
                differentAppProtocolVersionEncountered,
                trustedAppProtocolVersionSigners,
                options);

            _finalizers.Add(async() =>
            {
                try
                {
                    await StopAsync(swarm);
                    swarm.Dispose();
                }
                catch (ObjectDisposedException)
                {
                    _logger.Debug("Swarm {Swarm} is already disposed.", swarm);
                }
            });
            return(swarm);
        }
Esempio n. 2
0
        public async Task BroadcastBlockToReconnectedPeer()
        {
            var miner = new PrivateKey();
            Swarm <DumbAction>      seed            = CreateSwarm(miner);
            BlockChain <DumbAction> chainWithBlocks = seed.BlockChain;

            var privateKey            = new PrivateKey();
            Swarm <DumbAction> swarmA = CreateSwarm(privateKey: privateKey);
            Swarm <DumbAction> swarmB = CreateSwarm(privateKey: privateKey);

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

            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);

                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(chainWithBlocks.Tip);

                await swarmB.BlockAppended.WaitAsync();

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

                seed.Dispose();
                swarmA.Dispose();
                swarmB.Dispose();
            }
        }
        public override void Dispose()
        {
            base.Dispose();

            Log.Debug($"Disposing {nameof(DevLibplanetNodeService<T>)}...");

            SubSwarm?.Dispose();
            Log.Debug("Sub swarm disposed.");

            SubStore?.Dispose();
            Log.Debug("Sub store disposed.");
        }
Esempio n. 4
0
        public async Task BroadcastIgnoreFromDifferentGenesisHash()
        {
            var receiverKey = new PrivateKey();
            Swarm <DumbAction>      receiverSwarm = CreateSwarm(receiverKey);
            BlockChain <DumbAction> receiverChain = receiverSwarm.BlockChain;
            var seedStateStore = new TrieStateStore(new MemoryKeyValueStore());
            IBlockPolicy <DumbAction> policy            = receiverChain.Policy;
            Block <DumbAction>        mismatchedGenesis = new BlockContent <DumbAction>
            {
                PublicKey = receiverKey.PublicKey,
                Timestamp = DateTimeOffset.MinValue,
            }
            .Mine(policy.GetHashAlgorithm(0))
            .Evaluate(receiverKey, policy.BlockAction, seedStateStore);
            BlockChain <DumbAction> seedChain = TestUtils.MakeBlockChain(
                policy,
                new DefaultStore(path: null),
                seedStateStore,
                genesisBlock: mismatchedGenesis);
            var seedMiner = new PrivateKey();
            Swarm <DumbAction> seedSwarm = CreateSwarm(seedChain, seedMiner);

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

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

                Block <DumbAction> block = await seedChain.MineBlock(seedMiner);

                seedSwarm.BroadcastBlock(block);
                while (!((NetMQTransport)receiverSwarm.Transport).MessageHistory
                       .Any(msg => msg is BlockHeaderMessage))
                {
                    await Task.Delay(100);
                }

                await Task.Delay(100);

                Assert.NotEqual(seedChain.Tip, receiverChain.Tip);
            }
            finally
            {
                await StopAsync(seedSwarm);
                await StopAsync(receiverSwarm);

                seedSwarm.Dispose();
            }
        }
Esempio n. 5
0
        public async Task BroadcastIgnoreFromDifferentGenesisHash()
        {
            Swarm <DumbAction>      receiverSwarm = CreateSwarm();
            BlockChain <DumbAction> receiverChain = receiverSwarm.BlockChain;
            var invalidGenesisBlock = new Block <DumbAction>(
                0,
                0,
                0,
                new Nonce(new byte[] { 0x10, 0x00, 0x00, 0x00 }),
                receiverSwarm.Address,
                null,
                DateTimeOffset.MinValue,
                Enumerable.Empty <Transaction <DumbAction> >());
            BlockChain <DumbAction> seedChain = TestUtils.MakeBlockChain(
                receiverChain.Policy,
                new DefaultStore(path: null),
                new TrieStateStore(new MemoryKeyValueStore(), new MemoryKeyValueStore()),
                genesisBlock: invalidGenesisBlock);
            Swarm <DumbAction> seedSwarm = CreateSwarm(seedChain);

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

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

                Block <DumbAction> block = await seedChain.MineBlock(seedSwarm.Address);

                seedSwarm.BroadcastBlock(block);
                while (!((NetMQTransport)receiverSwarm.Transport).MessageHistory
                       .Any(msg => msg is BlockHeaderMessage))
                {
                    await Task.Delay(100);
                }

                await Task.Delay(100);

                Assert.NotEqual(seedChain.Tip, receiverChain.Tip);
            }
            finally
            {
                await StopAsync(seedSwarm);
                await StopAsync(receiverSwarm);

                seedSwarm.Dispose();
            }
        }
Esempio n. 6
0
        private Swarm <T> CreateSwarm <T>(
            BlockChain <T> blockChain,
            PrivateKey privateKey = null,
            AppProtocolVersion?appProtocolVersion = null,
            int tableSize                      = Kademlia.TableSize,
            int bucketSize                     = Kademlia.BucketSize,
            string host                        = null,
            int?listenPort                     = null,
            DateTimeOffset?createdAt           = null,
            IEnumerable <IceServer> iceServers = null,
            DifferentAppProtocolVersionEncountered differentAppProtocolVersionEncountered = null,
            IEnumerable <PublicKey> trustedAppProtocolVersionSigners = null,
            SwarmOptions options = null
            )
            where T : IAction, new()
        {
            if (host is null && !(iceServers?.Any() ?? false))
            {
                host = IPAddress.Loopback.ToString();
            }

            var swarm = new Swarm <T>(
                blockChain,
                privateKey ?? new PrivateKey(),
                appProtocolVersion ?? DefaultAppProtocolVersion,
                tableSize,
                bucketSize,
                5,
                host,
                listenPort,
                createdAt,
                iceServers,
                differentAppProtocolVersionEncountered,
                trustedAppProtocolVersionSigners,
                options);

            _finalizers.Add(async() =>
            {
                await StopAsync(swarm);
                swarm.Dispose();
            });
            return(swarm);
        }
        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();
            }
        }
        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();
            }
        }