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); }
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."); }
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(); } }
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(); } }
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(); } }