/// <summary> /// check cur block number should be cache ? /// if block is new just by pass /// </summary> /// <param name="chainid"></param> /// <param name="req"></param> /// <returns></returns> private static bool Check_eth_getBlockByNumber(int chainid, JsonRpcClientReq req) { if (req.Params.Length != 2) { return(false); } if (!BigInteger.TryParse(req.Params[0].ToString().Replace("0x", ""), out BigInteger result)) { return(false); } var nodes = NodeChecker.Instance.FindCheckerByChainId(chainid); if (nodes.Count == 0) { return(false); } var first = nodes.OrderByDescending(n => n.GetBlockNumber()).First(); var curBlockCount = first.GetBlockNumber(); var i = Startup.GetConfig <int>("Cache.Eth_IrrevocableBlockCount"); if (result + i < curBlockCount) { return(true); } return(false); }
public static bool EthCacheFilter(int chainid, JsonRpcClientReq req, string result) { switch (req.Method) { case "eth_getBlockByNumber": return(Check_eth_getBlockByNumber(chainid, req)); } return(false); }
private async Task <(bool result, string response)> SendRequest(JsonRpcClientReq req, string rpc) { try { using (var client = new HttpClient()) { var resp = await client.PostAsync(rpc, new StringContent( Newtonsoft.Json.JsonConvert.SerializeObject(req), Encoding.UTF8, "application/json")); if (!resp.IsSuccessStatusCode) { return(false, await resp.Content.ReadAsStringAsync()); } return(true, await resp.Content.ReadAsStringAsync()); } } catch (Exception ex) { Logger.Error(ex); return(false, ex.Message); } }
public bool AddCache(int chainid, JsonRpcClientReq req, string result) { if (!EthCacheConfig.Methods.ContainsKey(req.Method)) { return(false); } var config = EthCacheConfig.Methods[req.Method]; switch (config.RpcCacheStrategy) { case RpcCacheStrategy.NotCache: break; case RpcCacheStrategy.CacheInMemory: RedisHelper.Instance.AddRpcCache(chainid, req.Method, config.ParamDelegate?.Invoke(req), result, config.CacheOption > 0 ? TimeSpan.FromSeconds(config.CacheOption): TimeSpan.Zero); break; case RpcCacheStrategy.CacheInDb: if (config.FilterDelegate?.Invoke(chainid, req, result) == false) { Logger.Debug($"{req} cache skip"); return(false); } DbMgr.Instance.AddRpcCache(chainid, req.Method, config.ParamDelegate?.Invoke(req), result, config.CacheOption > 0 ? TimeSpan.FromSeconds(config.CacheOption): TimeSpan.Zero); break; default: throw new ArgumentOutOfRangeException(); } return(true); }
public static string EmptyParams(JsonRpcClientReq req) { return(string.Empty); }
public static string StringSplitParam(JsonRpcClientReq req) { return(string.Join("|", req.Params)); }
public async Task <IActionResult> Post(JsonRpcClientReq req, int chainid = 0) { if (chainid == 0) { return(BadRequest("chainid error")); } switch (req.Method) { case "eth_sendRawTransaction": { var signer = new TransactionSigner(); var addr = signer.GetSenderAddress(req.Params[0].ToString()); var rpc = NodeChoose.ChooseServer(chainid, addr); if (string.IsNullOrEmpty(rpc)) { return(BadRequest("not find suitable rpc server")); } var sendResult = await SendRequest(req, rpc); if (sendResult.result) { return(new ContentResult() { Content = sendResult.response, ContentType = "application/json", StatusCode = 200 }); } return(BadRequest(sendResult.response)); } default: { var cache = EthRpcCache.Instance.CheckCache(chainid, req); if (cache.hasCache) { Logger.Debug($"{req} in cache"); //update resp id var respObj = JObject.Parse(cache.result); respObj["id"] = req.Id; respObj["cache"] = cache.strategy.ToString(); return(new ContentResult() { Content = respObj.ToString(Formatting.None), ContentType = "application/json", StatusCode = 200 }); } var rpc = NodeChoose.ChooseServer(chainid); if (string.IsNullOrEmpty(rpc)) { return(BadRequest("not find suitable rpc server")); } var sendResult = await SendRequest(req, rpc); if (sendResult.result) { var respObj = JObject.Parse(sendResult.response); switch (cache.strategy) { case RpcCacheStrategy.NotCache: break; case RpcCacheStrategy.CacheInMemory: case RpcCacheStrategy.CacheInDb: var cacheResult = EthRpcCache.Instance.AddCache(chainid, req, sendResult.response); respObj["cacheOption"] = cache.strategy.ToString(); respObj["cacheResult"] = cacheResult; break; } return(new ContentResult() { Content = respObj.ToString(Formatting.None), ContentType = "application/json", StatusCode = 200 }); } return(BadRequest(sendResult.response)); } } }
public (bool hasCache, string result, RpcCacheStrategy strategy) CheckCache(int chainid, JsonRpcClientReq req) { if (!EthCacheConfig.Methods.ContainsKey(req.Method)) { return(false, string.Empty, RpcCacheStrategy.NotCache); } var config = EthCacheConfig.Methods[req.Method]; switch (config.RpcCacheStrategy) { case RpcCacheStrategy.NotCache: return(false, string.Empty, config.RpcCacheStrategy); case RpcCacheStrategy.CacheInMemory: { { var checkCache = RedisHelper.Instance.GetRpcCache(chainid, req.Method, config.ParamDelegate?.Invoke(req)); return(checkCache.hasCache, checkCache.result, config.RpcCacheStrategy); } } case RpcCacheStrategy.CacheInDb: { var checkCache = Db.DbMgr.Instance.GetRpcCache(chainid, req.Method, config.ParamDelegate?.Invoke(req)); return(checkCache.hasCache, checkCache.result, config.RpcCacheStrategy); } default: throw new ArgumentOutOfRangeException(); } }