广播信息
主动广播信息
private void Broadcast(CommandBase command)
{
ConnectionNode[] internalnodes;
lock (this.nodes)
{
internalnodes = this.nodes
.Where(_ => _.Status == ConnectionStatus.Connected)
.ToArray();
}
foreach (var node in internalnodes)
{
node.Peer.Send(command);
}
}
广播区块
public class ConnectionPool : IDisposable
{
public ConnectionPool(...)
{
...
this.selfNode.Engine.OnNewBlockCreated += Engine_OnNewBlockCreated;
}
private void Engine_OnNewBlockCreated(object sender, BlockHead e)
{
var blk = this.selfNode.Engine.BlockChain.GetBlock(e.Hash);
this.Broadcast(new BlockCommand { Block = blk });
}
}
public class BlockCommand : CommandBase
{
public Block Block { get; set; }
public override void OnReceived(Node node, ConnectionNode connectionNode)
{
var engine = node.Engine;
var bc = engine.BlockChain;
if (bc.BlockHeadDictionary.ContainsKey(this.Block.Hash)) return;
bc.AddSyncBlock(this.Block);
}
}
internal void AddSyncBlock(Block block)
{
CacheBlock(block);
// just cache block if prevous block not exist
if (!this.BlockHeadDictionary.ContainsKey(block.Head.PreviousBlockHash)) return;
if (this.TryMoveSyncTail(block.Head))
{
this.cancelSearchNonce = true;
}
}
private void CacheBlock(Block block)
{
this.BlockDictionary[block.Hash] = block;
this.InitBlocks(block.Head);
}
private bool TryMoveSyncTail(BlockHead newTail)
{
var listnow = this.ReverseIterateBlockHeaders(GenesisBlockHead.Hash, this.Tail.Hash).ToArray();
var listnew = this.ReverseIterateBlockHeaders(GenesisBlockHead.Hash, newTail.Hash).ToArray();
// broken chain should not count
if (listnew.LastOrDefault()?.Hash != GenesisBlockHead.Hash) return false;
var cnow = listnow.Length;
var cnew = listnew.Length;
if (cnew > cnow)
{
MaintainBlockChain(newTail);
return true;
}
return false;
}
广播交易
public class ConnectionPool : IDisposable
{
public ConnectionPool(...)
{
...
this.selfNode.Engine.OnNewTxCreated += Engine_OnNewTxCreated;
}
private void Engine_OnNewTxCreated(object sender, Transaction e)
{
this.Broadcast(new TransactionCommand { Transaction = e });
} 13. }
public class TransactionCommand : CommandBase
{
public Transaction Transaction { get; set; }
public override void OnReceived(Node node, ConnectionNode connectionNode)
{
var bc = node.Engine.BlockChain;
bc.SyncTx(this.Transaction);
}
}
internal void SyncTx(Transaction tx)
{
this.TxQueue.Enqueue(tx);
}
广播清单
public enum InventoryType
{
Transaction,
Block,
}
代码:ClassicBlockChain\Network\RpcCommands\InventoryEntity.cs
public class InventoryEntity
{
public InventoryType Type { get; set; }
public UInt256 Hash { get; set; }
}
public class InventoryCommand : CommandBase
{
public InventoryEntity[] Items { get; set; }
public override void OnReceived(Node node, ConnectionNode connectionNode)
{
var responseCmd = new GetDataCommand { Items = this.Items };
connectionNode.Peer.Send(responseCmd);
}
}