public IEnumerator CoMiner() { while (true) { var txs = new HashSet <Transaction <PolymorphicAction <ActionBase> > >(); var task = Task.Run(() => { var block = _blocks.MineBlock(Address); _swarm.BroadcastBlocks(new[] { block }); return(block); }); yield return(new WaitUntil(() => task.IsCompleted)); if (!task.IsCanceled && !task.IsFaulted) { var block = task.Result; Debug.Log($"created block index: {block.Index}, difficulty: {block.Difficulty}"); #if BLOCK_LOG_USE FileHelper.AppendAllText("Block.log", task.Result.ToVerboseString()); #endif } else { var invalidTxs = txs; var retryActions = new HashSet <IImmutableList <PolymorphicAction <ActionBase> > >(); if (task.IsFaulted) { foreach (var ex in task.Exception.InnerExceptions) { if (ex is InvalidTxNonceException invalidTxNonceException) { var invalidNonceTx = _blocks.Transactions[invalidTxNonceException.TxId]; if (invalidNonceTx.Signer == Address) { Debug.Log($"Tx[{invalidTxNonceException.TxId}] nonce is invalid. Retry it."); retryActions.Add(invalidNonceTx.Actions); } } if (ex is InvalidTxException invalidTxException) { Debug.Log($"Tx[{invalidTxException.TxId}] is invalid. mark to unstage."); invalidTxs.Add(_blocks.Transactions[invalidTxException.TxId]); } Debug.LogException(ex); } } _blocks.UnstageTransactions(invalidTxs); foreach (var retryAction in retryActions) { MakeTransaction(retryAction, true); } } } }
public IEnumerator CoMiner() { while (true) { var txs = new HashSet <Transaction <PolymorphicAction <ActionBase> > >(); var task = Task.Run(async() => { var block = await _blocks.MineBlock(Address); if (_swarm?.Running ?? false) { _swarm.BroadcastBlocks(new[] { block }); } return(block); }); yield return(new WaitUntil(() => task.IsCompleted)); if (!task.IsCanceled && !task.IsFaulted) { var block = task.Result; Debug.Log($"created block index: {block.Index}, difficulty: {block.Difficulty}"); } else { var invalidTxs = txs; var retryActions = new HashSet <IImmutableList <PolymorphicAction <ActionBase> > >(); if (task.IsFaulted) { foreach (var ex in task.Exception.InnerExceptions) { if (ex is InvalidTxNonceException invalidTxNonceException) { var invalidNonceTx = _store.GetTransaction <PolymorphicAction <ActionBase> >(invalidTxNonceException.TxId); if (invalidNonceTx.Signer == Address) { Debug.Log($"Tx[{invalidTxNonceException.TxId}] nonce is invalid. Retry it."); retryActions.Add(invalidNonceTx.Actions); } } if (ex is InvalidTxException invalidTxException) { Debug.Log($"Tx[{invalidTxException.TxId}] is invalid. mark to unstage."); invalidTxs.Add( _store.GetTransaction <PolymorphicAction <ActionBase> >(invalidTxException.TxId)); } Debug.LogException(ex); } } _blocks.UnstageTransactions(invalidTxs); foreach (var retryAction in retryActions) { MakeTransaction(retryAction, true); } } } }
public async Task CanBroadcastBlock() { Swarm <DumbAction> swarmA = _swarms[0]; Swarm <DumbAction> swarmB = _swarms[1]; Swarm <DumbAction> swarmC = _swarms[2]; BlockChain <DumbAction> chainA = _blockchains[0]; BlockChain <DumbAction> chainB = _blockchains[1]; BlockChain <DumbAction> chainC = _blockchains[2]; // chainA, chainB and chainC shares genesis block. Block <DumbAction> 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); await StartAsync(swarmB); await StartAsync(swarmC); await swarmA.AddPeersAsync(new[] { swarmB.AsPeer }); await swarmA.AddPeersAsync(new[] { swarmC.AsPeer }); await EnsureExchange(swarmA, swarmB); await EnsureExchange(swarmA, swarmC); await EnsureExchange(swarmB, swarmC); swarmB.BroadcastBlocks(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); swarmA.BroadcastBlocks(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()); } }