private Result <BlockInfoDTO> GetBlockInfo(RpcConfig rpcConfig, IDataExtractorService dataExtractor, IMapper mapper, string blockHash) { var blockResult = dataExtractor.RpcCall <RpcBlockResult>(rpcConfig, "getblock", blockHash); if (blockResult.HasFailed()) { return(Result <BlockInfoDTO> .Fail(blockResult.Messages.ToArray())); } var block = mapper.Map <BlockInfoDTO>(blockResult.Value); return(Result <BlockInfoDTO> .Ok(block)); }
public void Execute(RpcConfig rpcConfig) { // Compare chain tips var lastSeenTips = _cache.GetOrCreate <ChainTip[]>(Constants.LastSeenTipKey, entry => null); ChainTip[] tips = null; Handle(_dataExtractor.RpcCall <GetChainTipsResult>(rpcConfig, "getchaintips"), r => { tips = r.Result; var shouldSend = true; var desc = "ForkWatch started"; if (lastSeenTips != null) { (shouldSend, desc) = DiffTip(lastSeenTips, tips); } if (shouldSend) { var url = string.Empty; // TODO: upload to pastbin and get url var message = $"{desc}\n{url}"; _notificationManager.TriggerHook(message); } _cache.Set(Constants.LastSeenTipKey, tips); }); if (tips == null || tips.Length == 0) { _logger.LogWarning("ForkWatch: Got malformed tip from RPC"); } if (lastSeenTips != null && lastSeenTips[0].Hash == tips[0].Hash) { // Short-circurit: no new block found return; } // Check virtual checkpoint rolled-back var lastCheckpoint = _cache.GetOrCreate <VirtualCheckpointDTO>(Constants.VirtualCheckpointKey, entry => null); if (lastCheckpoint != null) { bool foundReorg = false; // Check if the checkpoint is still in the main chain Handle(_dataExtractor.RpcCall <RpcResult>(rpcConfig, "getblockhash", lastCheckpoint.Height), r => { var hash = r.Result; foundReorg = hash != lastCheckpoint.Hash; var message = $"ForkWatch: Virtual checkpoint {lastCheckpoint.Hash} at height {lastCheckpoint.Height} replaced by {hash}"; _notificationManager.TriggerHook(message); }); // TODO: if foundReorg, move to "PREPARE" } // Update virtual checkpoint var height = tips[0].Height; var toFinalize = height - VIRTUALFINALIZEBLOCKS; _logger.LogWarning("getblockhash({0})", toFinalize); Handle(_dataExtractor.RpcCall <RpcResult>(rpcConfig, "getblockhash", toFinalize), r => { var hash = r.Result; _cache.Set(Constants.VirtualCheckpointKey, new VirtualCheckpointDTO() { Hash = hash, Height = toFinalize }); _notificationManager.TriggerHook($"ForkWatch: new checkpoint {hash} at {toFinalize} ({-VIRTUALFINALIZEBLOCKS}) tip: {height}"); }); }