public async Task <Response <EmptyPayload> > NotifyNewBlock(NewBlockNotification notification) { var requestMessage = BuildRequestMessage(HttpMethod.Post, $"api/peers/notify-new-block"); requestMessage.Content = SerializeRequestAsJson(notification); return(await SendRequest <EmptyPayload>(requestMessage).ConfigureAwait(false)); }
public void NotifyBlock(NewBlockNotification info) { if (dbService.GetLastBlock().Index >= info.LastBlock.Index) { //reject, do nothing return; } if (!IsPeersBlockValid(info.LastBlock)) { //reject, do nothing return; } UpdateChain(info); }
public async Task BroadcastNewBlockNotification( int blocksCount, long cumulativeDifficulty, string nodeUrl) { NewBlockNotification notification = new NewBlockNotification { BlocksCount = blocksCount, CumulativeDifficulty = cumulativeDifficulty, NodeUrl = nodeUrl }; foreach (string peerUrl in _peers.Values) { await SendNewBlockNotification(notification, peerUrl, 5).ConfigureAwait(false); } }
private void PropagateBlockToPeers(MinedBlockInfo block) { var tasks = new List <Task>(); var body = new NewBlockNotification { LastBlock = MinedBlockInfoResponse.FromMinedBlockInfo(block), Sender = thisPeer }; dbService.GetPeers().ForEach(p => { tasks.Add(Task.Run(() => HttpUtils.DoApiPost <NewBlockNotification, object>(p.Url, NOTIFY_API_PATH, body))); }); Task.WaitAll(tasks.ToArray()); }
private async Task SendNewBlockNotification( NewBlockNotification notification, string peerUrl, int maxRetries) { if (!_peerNodeClients.ContainsKey(peerUrl)) { return; } INodeClient nodeClient = _peerNodeClients[peerUrl]; Response <EmptyPayload> response; int retries = 0; do { retries++; response = await nodeClient.NotifyNewBlock(notification).ConfigureAwait(false); } while (response.Status == Status.Failed && retries < maxRetries); }
private void UpdateChain(NewBlockNotification info) { var lastBlock = dbService.GetLastBlock(); if (lastBlock.Index == info.LastBlock.Index - 1 && lastBlock.BlockHash == info.LastBlock.PreviousBlockHash) { //we're only missing this last block, just add it AddToCurrentChain(info.LastBlock); } else { //Just replace the whole thing var chain = GetWholeChainFromPeer(info.Sender); if (chain.All(b => IsPeersBlockValid(b))) { ReplaceCurrentChain(chain); } } }
private void SendBlockToPeers(Block block) { var tasks = new List <Task>(); List <string> peers = this.dataService.NodeInfo.PeersListUrls; peers.ForEach(peerUrl => { tasks.Add ( Task.Run(async() => { var sender = new Peer(); sender.PeerUrl = this.dataService.NodeUrl; var blockNotification = new NewBlockNotification { Block = block, Sender = sender, }; this.logger.LogInformation($"Node: has sent block {block.Index} to: {peerUrl}"); var response = await this.httpHelpers.DoApiPost(peerUrl, BlockNotifyApiPath, blockNotification); if (response.IsSuccessStatusCode) { this.logger.LogInformation($"Node: {peerUrl} successfully received block {block.Index}"); } else { this.logger.LogInformation( $"Node: {peerUrl} could not receive block {block.Index} (Status Code: {response.StatusCode}, Reason: {response.ReasonPhrase})"); } }) ); }); Task.WaitAll(tasks.ToArray()); }
public void Post([FromBody] NewBlockNotification notification) { //should we push or pull? _blockchainService.NotifyBlock(notification); }
public void ReceiveNewBlock(NewBlockNotification newBlockNotification) { // skip blocks from unknown peers if (!this.dataService.NodeInfo.PeersListUrls.Contains(newBlockNotification.Sender.PeerUrl)) { this.logger.LogInformation( $"Received block {newBlockNotification.Block.Index} from unknown peer {newBlockNotification.Sender.PeerUrl}, skipping..." ); return; } var lastBlock = this.dataService.Blocks.Last(); if (newBlockNotification.Block.Index <= lastBlock.Index) { // if we already have this block, ignore it this.logger.LogInformation($"Received existing block {newBlockNotification.Block.Index}, skipping..."); return; } // todo: validate block's POW // if (!IsBlockValid(newBlockNotification.Block)) // { // return; // } if (newBlockNotification.Block.Index == lastBlock.Index + 1 && lastBlock.BlockHash == newBlockNotification.Block.PrevBlockHash) { // if this is the last block, add it to our own chain this.logger.LogInformation($"Received next block {newBlockNotification.Block.Index}, added to blockchain"); this.dataService.Blocks.Add(newBlockNotification.Block); } else { Task.Run(async() => { // get peer chain and replace own chain with it var peerBlocks = await this.httpHelpers.DoApiGet <List <Block> >(newBlockNotification.Sender.PeerUrl, "blocks"); // todo: validate block's POW // foreach (var block in peerBlocks.Data) // { // // } if (peerBlocks.Data.Count <= this.dataService.Blocks.Count) { // don't replace own blockchain with shorter peer blockchain this.logger.LogInformation($"Peer blockchain <= own blockchain, skipping..."); return; } lock (this.dataService.Blocks) { lock (this.dataService.PendingTransactions) { this.dataService.Blocks = peerBlocks.Data; this.dataService.Blocks.ForEach(block => { //remove pending transactions that are already included in the peer's blockchain block.Transactions.ForEach(transaction => { this.dataService.PendingTransactions.Remove( this.dataService .PendingTransactions .Single(t => t.TransactionHash == transaction.TransactionHash) ); }); }); } } }); } }
public IActionResult NotifyNewBlock([FromBody] NewBlockNotification notification) { NodeService.SynchronizeChain(notification.NodeUrl); return(Ok()); }
public IActionResult Notify([FromBody] NewBlockNotification newBlockNotification) { this.nodeService.ReceiveNewBlock(newBlockNotification); return(Ok()); }