Esempio n. 1
0
        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));
        }
Esempio n. 2
0
        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}");
            });
        }