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);
        }
Beispiel #3
0
        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());
        }
Beispiel #5
0
        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);
                }
            }
        }
Beispiel #7
0
        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);
 }
Beispiel #9
0
        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());
        }