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