public async Task CanGetTx() { Swarm swarmA = _swarms[0]; Swarm swarmB = _swarms[1]; BlockChain <BaseAction> chainA = _blockchains[0]; BlockChain <BaseAction> chainB = _blockchains[1]; Transaction <BaseAction> tx = Transaction <BaseAction> .Make( new PrivateKey(), new PrivateKey().PublicKey.ToAddress(), new BaseAction[] { }, DateTimeOffset.UtcNow ); chainB.StageTransactions(new[] { tx }.ToHashSet()); chainB.MineBlock(_fx1.Address1); try { await StartAsync(swarmA, chainA); await StartAsync(swarmB, chainB); Assert.Throws <PeerNotFoundException>( () => swarmB.GetTxsAsync <BaseAction>( swarmA.AsPeer, new[] { tx.Id })); await swarmA.AddPeersAsync(new[] { swarmB.AsPeer }); List <Transaction <BaseAction> > txs = await swarmA.GetTxsAsync <BaseAction>( swarmB.AsPeer, new[] { tx.Id } ).ToListAsync(); Assert.Equal(new[] { tx }, txs); } finally { await Task.WhenAll( swarmA.StopAsync(), swarmB.StopAsync()); } }
public async Task InitialBlockDownloadStates() { Swarm <DumbAction> minerSwarm = _swarms[0]; Swarm <DumbAction> receiverSwarm = _swarms[1]; BlockChain <DumbAction> minerChain = _blockchains[0]; BlockChain <DumbAction> receiverChain = _blockchains[1]; var key = new PrivateKey(); var address = key.ToAddress(); minerChain.MakeTransaction(key, new[] { new DumbAction(address, "foo") }); await minerChain.MineBlock(_fx1.Address1); minerChain.MakeTransaction(key, new[] { new DumbAction(address, "bar") }); await minerChain.MineBlock(_fx1.Address1); minerChain.MakeTransaction(key, new[] { new DumbAction(address, "baz") }); await minerChain.MineBlock(_fx1.Address1); try { await StartAsync(minerSwarm); await receiverSwarm.AddPeersAsync(new[] { minerSwarm.AsPeer }, null); var trustedStateValidators = new[] { minerSwarm.Address }.ToImmutableHashSet(); await receiverSwarm.PreloadAsync(trustedStateValidators : trustedStateValidators); await receiverSwarm.PreloadAsync(); var state = receiverChain.GetState(address); Assert.Equal((Text)"foo,bar,baz", state); Assert.Equal(minerChain.BlockHashes, receiverChain.BlockHashes); } finally { await StopAsync(minerSwarm); } }
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 = MakeBlockChain( policy, new MemoryStore(), 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); Assert.NotEqual(seedChain.Tip, receiverChain.Tip); } finally { await StopAsync(seedSwarm); await StopAsync(receiverSwarm); seedSwarm.Dispose(); } }
public async Task ExchangeWithIceServer() { Uri turnUrl = FactOnlyTurnAvailable.TurnUri; string username = FactOnlyTurnAvailable.Username; string password = FactOnlyTurnAvailable.Password; IEnumerable <IceServer> iceServers = new[] { new IceServer( urls: new[] { turnUrl }, username: username, credential: password), }; var seed = new Swarm(new PrivateKey(), 1, host: "localhost"); var swarmA = new Swarm(new PrivateKey(), 1, iceServers: iceServers); var swarmB = new Swarm(new PrivateKey(), 1, iceServers: iceServers); try { await StartAsync(seed, _blockchains[0]); await StartAsync(swarmA, _blockchains[1]); await StartAsync(swarmB, _blockchains[2]); await swarmA.AddPeersAsync(new[] { seed.AsPeer }); await swarmB.AddPeersAsync(new[] { seed.AsPeer }); await EnsureExchange(swarmA, swarmB); Assert.Contains(swarmA.AsPeer, swarmB); Assert.Contains(swarmB.AsPeer, swarmA); } finally { await Task.WhenAll( seed.StopAsync(), swarmA.StopAsync(), swarmB.StopAsync()); } }
public async Task HandleDifferentAppProtocolVersion() { var isCalled = false; void GameHandler(object sender, DifferentProtocolVersionEventArgs e) { isCalled = true; } BlockChain <DumbAction> chain = _blockchains[0]; var a = new Swarm <DumbAction>( chain, new PrivateKey(), host: IPAddress.Loopback.ToString(), appProtocolVersion: 2, differentVersionPeerEncountered: GameHandler); var b = new Swarm <DumbAction>( chain, new PrivateKey(), host: IPAddress.Loopback.ToString(), appProtocolVersion: 3); try { await StartAsync(a); await StartAsync(b); await a.AddPeersAsync(new[] { b.AsPeer }); Assert.True(isCalled); } finally { await a.StopAsync(); await b.StopAsync(); } }
private async Task CheckStaticPeersAsync( IEnumerable <Peer> peers, CancellationToken cancellationToken) { var peerArray = peers as Peer[] ?? peers.ToArray(); while (!cancellationToken.IsCancellationRequested) { try { await Task.Delay(TimeSpan.FromMinutes(1), cancellationToken); Log.Warning("Checking static peers. {Peers}", peerArray); var peersToAdd = peerArray.Where(peer => !Swarm.Peers.Contains(peer)).ToArray(); if (peersToAdd.Any()) { Log.Warning("Some of peers are not in routing table. {Peers}", peersToAdd); await Swarm.AddPeersAsync( peersToAdd, TimeSpan.FromSeconds(5), cancellationToken); } } catch (OperationCanceledException e) { Log.Warning(e, $"{nameof(CheckStaticPeersAsync)}() is cancelled."); throw; } catch (Exception e) { var msg = "Unexpected exception occurred during " + $"{nameof(CheckStaticPeersAsync)}(): {{0}}"; Log.Warning(e, msg, e); } } }
public async Task TxStagedNotToBroadcast() { Swarm <DumbAction> swarmA = _swarms[0]; Swarm <DumbAction> swarmB = _swarms[1]; BlockChain <DumbAction> chainA = _blockchains[0]; BlockChain <DumbAction> chainB = _blockchains[1]; Transaction <DumbAction> txA = chainA.MakeTransaction( new PrivateKey(), new DumbAction[] { }, broadcast: true); Transaction <DumbAction> txB = chainA.MakeTransaction( new PrivateKey(), new DumbAction[] { }, broadcast: false); try { await StartAsync(swarmA); await StartAsync(swarmB); await swarmA.AddPeersAsync(new[] { swarmB.AsPeer }); await swarmB.TxReceived.WaitAsync(); Assert.Equal(txA, chainB.Transactions[txA.Id]); Assert.False(chainB.Transactions.ContainsKey(txB.Id)); } finally { await Task.WhenAll( swarmA.StopAsync(), swarmB.StopAsync()); } }
public async Task StopGracefullyWhileStarting() { Swarm <DumbAction> a = _swarms[0]; Swarm <DumbAction> b = _swarms[1]; await StartAsync(b); await a.AddPeersAsync(new[] { b.AsPeer }); Task t = await StartAsync(a); bool canceled = false; try { await Task.WhenAll(a.StopAsync(), t); } catch (OperationCanceledException) { canceled = true; } Assert.True(canceled); }
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()); } }
public async Task CanBroadcastWhlieMining() { Swarm a = _swarms[0]; Swarm b = _swarms[1]; BlockChain <BaseAction> chainA = _blockchains[0]; BlockChain <BaseAction> chainB = _blockchains[1]; Task CreateMiner( Swarm swarm, BlockChain <BaseAction> chain, int delay, CancellationToken cancellationToken ) { return(Task.Run(async() => { while (!cancellationToken.IsCancellationRequested) { var block = chain.MineBlock(_fx1.Address1); Log.Debug( $"Block mined. " + $"[Swarm: {swarm.Address}, Block: {block.Hash}]"); await swarm.BroadcastBlocksAsync(new[] { block }); await Task.Delay(delay); } await swarm.BroadcastBlocksAsync(new[] { chain.Last() }); Log.Debug("Mining complete."); })); } var minerCanceller = new CancellationTokenSource(); Task miningA = CreateMiner(a, chainA, 5000, minerCanceller.Token); Task miningB = CreateMiner(b, chainB, 8000, minerCanceller.Token); try { await StartAsync(a, chainA); await StartAsync(b, chainB); await b.AddPeersAsync(new[] { a.AsPeer }); await EnsureExchange(a, b); await Task.Delay(10000); minerCanceller.Cancel(); await Task.WhenAll(miningA, miningB); await Task.Delay(5000); } finally { await a.StopAsync(); await b.StopAsync(); } Log.Debug($"chainA: {string.Join(",", chainA)}"); Log.Debug($"chainB: {string.Join(",", chainB)}"); Assert.Subset( chainA.AsEnumerable().ToHashSet(), chainB.AsEnumerable().ToHashSet()); }
public async Task WorksAsExpected() { Swarm a = _swarms[0]; Swarm b = _swarms[1]; Swarm c = _swarms[2]; Blockchain <BaseAction> chain = _blockchains[0]; DateTime lastDistA; Peer aAsPeer; try { await b.InitContextAsync(); await c.InitContextAsync(); try { await a.InitContextAsync(); var at = Task.Run(async() => await a.RunAsync(chain, 250)); await b.AddPeersAsync(new[] { a.AsPeer }); var bt = Task.Run(async() => await b.RunAsync(chain, 250)); await EnsureExchange(a, b); Assert.Equal(new[] { b.AsPeer }.ToImmutableHashSet(), a.ToImmutableHashSet()); Assert.Equal(new[] { a.AsPeer }.ToImmutableHashSet(), b.ToImmutableHashSet()); await c.AddPeersAsync(new[] { a.AsPeer }); var ct = Task.Run(async() => await c.RunAsync(chain, 250)); await EnsureExchange(a, c); await EnsureExchange(a, b); Assert.Equal(new[] { b.AsPeer, c.AsPeer }.ToImmutableHashSet(), a.ToImmutableHashSet()); Assert.Equal(new[] { a.AsPeer, c.AsPeer }.ToImmutableHashSet(), b.ToImmutableHashSet()); Assert.Equal(new[] { a.AsPeer, b.AsPeer }.ToImmutableHashSet(), c.ToImmutableHashSet()); lastDistA = a.LastDistributed; aAsPeer = a.AsPeer; } finally { await a.DisposeAsync(); } Assert.True(lastDistA < a.LastDistributed); await EnsureRecvAsync(b, aAsPeer, a.LastDistributed); await EnsureRecvAsync(c, aAsPeer, a.LastDistributed); await EnsureExchange(b, c); Assert.Equal(new[] { c.AsPeer }.ToImmutableHashSet(), b.ToImmutableHashSet()); Assert.Equal(new[] { b.AsPeer }.ToImmutableHashSet(), c.ToImmutableHashSet()); } finally { await b.DisposeAsync(); await c.DisposeAsync(); } }
public async Task BroadcastWhileMining() { var minerA = new PrivateKey(); var minerB = new PrivateKey(); Swarm <DumbAction> a = CreateSwarm(minerA); Swarm <DumbAction> b = CreateSwarm(minerB); BlockChain <DumbAction> chainA = a.BlockChain; BlockChain <DumbAction> chainB = b.BlockChain; Task CreateMiner( PrivateKey miner, Swarm <DumbAction> swarm, BlockChain <DumbAction> chain, int delay, CancellationToken cancellationToken ) { return(Task.Run(async() => { while (!cancellationToken.IsCancellationRequested) { try { var block = await chain.MineBlock(miner); Log.Debug( "Block mined. [Node: {0}, Block: {1}]", swarm.Address, block.Hash); swarm.BroadcastBlock(block); } catch (OperationCanceledException) { continue; } finally { await Task.Delay(delay); } } swarm.BroadcastBlock(chain[-1]); Log.Debug("Mining complete."); })); } try { await StartAsync(a); await StartAsync(b); await a.AddPeersAsync(new[] { b.AsPeer }, null); var minerCanceller = new CancellationTokenSource(); Task miningA = CreateMiner(minerA, a, chainA, 5000, minerCanceller.Token); Task miningB = CreateMiner(minerB, b, chainB, 8000, minerCanceller.Token); await Task.Delay(10000); minerCanceller.Cancel(); await Task.WhenAll(miningA, miningB); await Task.Delay(5000); } finally { await StopAsync(a); await StopAsync(b); } _logger.CompareBothChains(LogEventLevel.Debug, "A", chainA, "B", chainB); Assert.Equal(chainA.BlockHashes, chainB.BlockHashes); }
public async Task PreloadFromNominer() { Swarm <DumbAction> minerSwarm = _swarms[0]; Swarm <DumbAction> receiverSwarm = _swarms[1]; var fxForNominers = new StoreFixture[2]; fxForNominers[0] = new DefaultStoreFixture(memory: true); fxForNominers[1] = new DefaultStoreFixture(memory: true); var policy = new BlockPolicy <DumbAction>(); var blockChainsForNominers = new[] { TestUtils.MakeBlockChain(policy, fxForNominers[0].Store), TestUtils.MakeBlockChain(policy, fxForNominers[1].Store), }; var nominerSwarm0 = CreateSwarm(blockChainsForNominers[0]); var nominerSwarm1 = CreateSwarm(blockChainsForNominers[1]); BlockChain <DumbAction> minerChain = _blockchains[0]; BlockChain <DumbAction> receiverChain = _blockchains[1]; foreach (int i in Enumerable.Range(0, 10)) { await minerChain.MineBlock(_fx1.Address1); } var actualStates = new List <PreloadState>(); var progress = new Progress <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( expectedStates.ToHashSet(), actualStates.ToHashSet() ); } finally { await StopAsync(minerSwarm); await StopAsync(nominerSwarm0); await StopAsync(nominerSwarm1); await StopAsync(receiverSwarm); nominerSwarm0.Dispose(); nominerSwarm1.Dispose(); fxForNominers[0].Dispose(); fxForNominers[1].Dispose(); } }
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 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(); } }
public async Task CanExchangePeer() { BlockChain <DumbAction> chain = _blockchains[0]; var a = new Swarm <DumbAction>( chain, new PrivateKey(), 1, host: IPAddress.Loopback.ToString()); var b = new Swarm <DumbAction>( chain, new PrivateKey(), 1, host: IPAddress.Loopback.ToString()); var c = new Swarm <DumbAction>( chain, new PrivateKey(), 1, host: IPAddress.Loopback.ToString()); DateTimeOffset lastDistA; Peer aAsPeer; try { try { await StartAsync(a); await StartAsync(b); await StartAsync(c); await b.AddPeersAsync(new[] { a.AsPeer }); await EnsureExchange(a, b); Assert.Equal( new[] { b.AsPeer }.ToImmutableHashSet(), a.Peers.ToImmutableHashSet()); Assert.Equal( new[] { a.AsPeer }.ToImmutableHashSet(), b.Peers.ToImmutableHashSet()); await c.AddPeersAsync(new[] { a.AsPeer }); await EnsureExchange(a, c); await EnsureExchange(a, b); Assert.Equal( new[] { b.AsPeer, c.AsPeer }.ToImmutableHashSet(), a.Peers.ToImmutableHashSet() ); Assert.Equal( new[] { a.AsPeer, c.AsPeer }.ToImmutableHashSet(), b.Peers.ToImmutableHashSet() ); Assert.Equal( new[] { a.AsPeer, b.AsPeer }.ToImmutableHashSet(), c.Peers.ToImmutableHashSet() ); lastDistA = a.LastDistributed; aAsPeer = a.AsPeer; } finally { await a.StopAsync(); } Assert.True(lastDistA < a.LastDistributed); await EnsureRecvAsync(b, aAsPeer, a.LastDistributed); await EnsureRecvAsync(c, aAsPeer, a.LastDistributed); await EnsureExchange(b, c); Assert.Equal(new[] { c.AsPeer }.ToImmutableHashSet(), b.Peers.ToImmutableHashSet()); Assert.Equal(new[] { b.AsPeer }.ToImmutableHashSet(), c.Peers.ToImmutableHashSet()); } finally { await b.StopAsync(); await c.StopAsync(); } }
public async Task Preload() { Swarm <DumbAction> minerSwarm = _swarms[0]; Swarm <DumbAction> receiverSwarm = _swarms[1]; BlockChain <DumbAction> minerChain = _blockchains[0]; BlockChain <DumbAction> receiverChain = _blockchains[1]; foreach (int i in Enumerable.Range(0, 10)) { minerChain.MineBlock(_fx1.Address1); } var actualStates = new List <PreloadState>(); var progress = new Progress <PreloadState>(state => { lock (actualStates) { actualStates.Add(state); if (actualStates.Count == 8) { minerChain.MineBlock(_fx1.Address1); } } }); try { await StartAsync(minerSwarm); await receiverSwarm.AddPeersAsync(new[] { minerSwarm.AsPeer }); minerChain.FindNextHashesChunkSize = 2; await receiverSwarm.PreloadAsync(progress); Assert.Equal(minerChain.AsEnumerable(), receiverChain.AsEnumerable()); PreloadState[] expectedStates = minerChain.Select((b, i) => { return(new BlockDownloadState { ReceivedBlockHash = b.Hash, TotalBlockCount = 10, ReceivedBlockCount = i + 1, }); }).ToArray(); (expectedStates[10] as BlockDownloadState).TotalBlockCount = 11; expectedStates = expectedStates.Concat(minerChain.Select( (b, i) => new ActionExecutionState() { ExecutedBlockHash = b.Hash, TotalBlockCount = 11, ExecutedBlockCount = i + 1, })).ToArray(); Assert.True(expectedStates.ToImmutableHashSet() .SetEquals(actualStates.ToImmutableHashSet())); } finally { await Task.WhenAll( minerSwarm.StopAsync(), receiverSwarm.StopAsync()); } }
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) ); } }
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()); } }
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()); } }