public void ReceiveStopMsg(string json) { try { var msg = JsonConvert.DeserializeObject <StopMiningMsg>(json); LogHelper.Info("Receive StopMsg"); if (this.miners == null || !this.miners.Any()) { return; } StopMsg stopMsg = new StopMsg(); stopMsg.Result = msg.StopReason == StopReason.MiningSucesses; if (stopMsg.Result) { var height = Convert.ToInt32(stopMsg.BlockHeight); var key = KeyHelper.GetMinerEffortKey(ID, height); var efforts = this.miners.Select(x => new EffortInfo { Account = x.Address, BlockHeight = height, Effort = x.MaxNonce }).ToList(); RedisManager.Current.SaveDataToRedis(key, efforts); } } catch (Exception ex) { LogHelper.Error(ex.ToString()); } }
internal static void Send(TcpState e, StopMsg stopMsg) { var stopCmd = PoolCommand.CreateCommand(CommandNames.Stop, stopMsg); if (PoolJob.TcpServer != null) { PoolJob.TcpServer.SendCommand(e, stopCmd); } }
/// <summary> /// 接收停止命令 /// 接收到的json反序列化StopMiningMsg对象,构造StopMsg类,遍历所有的矿工发送TCP停止命令 /// </summary> /// <param name="json"></param> public void ReceiveStopMsg(string json) { try { var msg = JsonConvert.DeserializeObject <StopMiningMsg>(json); LogHelper.Info("Receive StopMsg"); if (msg == null || PoolCache.CurrentTask == null) { return; } StopMsg stopMsg = new StopMsg(); stopMsg.Result = msg.StopReason == StopReason.MiningSucesses; stopMsg.BlockHeight = msg.CurrentHeight; stopMsg.StopTime = msg.StopTime; var miners = PoolCache.WorkingMiners.ToArray(); foreach (Miner item in miners) { try { TcpState tcpState = new TcpState() { Client = item.Client, Stream = item.Stream, Address = item.ClientAddress }; StopCommand.Send(tcpState, stopMsg); } catch (Exception ex) { LogHelper.Error(ex.ToString()); } } var stopTask = PoolCache.CurrentTask; //计算每个账户的工作量 if (PoolCache.Efforts.ContainsKey(stopTask.CurrentBlockHeight)) { var items = PoolCache.Efforts[stopTask.CurrentBlockHeight]; stopTask.MinerEfforts.ForEach(x => { var item = items.FirstOrDefault(p => p.Account == x.Account); if (item == null) { items.Add(new EffortInfo { Account = x.Account, Effort = x.Effort, BlockHeight = stopTask.CurrentBlockHeight }); } else { item.Effort += x.Effort; } }); } else { var efforts = stopTask.MinerEfforts.Select(x => new EffortInfo { Account = x.Account, Effort = x.Effort, BlockHeight = stopTask.CurrentBlockHeight }).ToList(); PoolCache.Efforts.Add(stopTask.CurrentBlockHeight, efforts); } //成功挖到区块,工作量保存在redis中,清空以前区块的Task if (msg.StopReason == StopReason.MiningSucesses) { TimerTasks.Current.SaveMinerEffortToRedis(msg.CurrentHeight); PoolCache.poolTasks.RemoveAll(x => x.CurrentBlockHeight <= stopMsg.BlockHeight); } PoolCache.CurrentTask = null; } catch (Exception ex) { LogHelper.Error(ex.ToString()); } }
/// <summary> /// 接收消息 /// </summary> /// <param name="e"></param> /// <param name="cmd"></param> internal static void Receive(TcpReceiveState e, PoolCommand cmd) { //TaskWork.Current.Add(new Task(() => //{ var loginMsg = new LoginMsg(); int index = 0; loginMsg.Deserialize(cmd.Payload, ref index); //验证矿工身份 if (!MinerApi.ValidateMiner(loginMsg.WalletAddress, loginMsg.SerialNo)) { RejectCommand.Send(e); return; } //TODO: address and SerialNo and account only for one Minner 第一个与条件匹配的矿工 var miner = PoolCache.WorkingMiners.FirstOrDefault(m => m.WalletAddress == loginMsg.WalletAddress || m.ClientAddress == e.Address || m.SerialNo == loginMsg.SerialNo); //矿工不为空,发送stop命令 if (miner != null) { StopMsg stopMsg = new StopMsg(); stopMsg.Result = false; if (PoolCache.CurrentTask == null) { return; } stopMsg.BlockHeight = PoolCache.CurrentTask.CurrentBlockHeight; stopMsg.StartTime = PoolCache.CurrentTask.StartTime; stopMsg.StopTime = Time.EpochTime; TcpSendState tcpSendState = new TcpSendState() { Client = miner.Client, Stream = miner.Stream, Address = miner.ClientAddress }; StopCommand.Send(tcpSendState, stopMsg); PoolCache.WorkingMiners.Remove(miner); } miner = new Miner(); miner.SerialNo = loginMsg.SerialNo; miner.WalletAddress = loginMsg.WalletAddress; miner.ClientAddress = e.Address; miner.Client = e.Client; miner.Stream = e.Stream; Random random = new Random(); miner.CheckScoopNumber = random.Next(0, POC.MAX_SCOOP_NUMBER + 1); PoolCache.WorkingMiners.Add(miner); miner.IsConnected = true; miner.ConnectedTime = Time.EpochTime; miner.LatestHeartbeatTime = Time.EpochTime; SendLoginResult(e, true); LogHelper.Info(miner.ClientAddress + " login success"); MinerLoginMsg loginMinerMsg = new MinerLoginMsg(); loginMinerMsg.Account = loginMsg.WalletAddress; loginMinerMsg.SN = loginMsg.SerialNo; loginMinerMsg.ServerId = Setting.PoolId; //MQApi.Current.SendLoginMsg(loginMinerMsg); RabbitMQApi.Current.SendLoginMsg(loginMinerMsg); if (PoolCache.CurrentTask != null) { StartCommand.Send(e, PoolCache.CurrentTask.CurrentStartMsg); } //})); }
internal static void Received(TcpReceiveState e, PoolCommand cmd) { var miner = PoolCache.WorkingMiners.FirstOrDefault(m => m.ClientAddress == e.Address && m.IsConnected); if (miner == null) { LogHelper.Info("Received invalid scoop data from " + e.Address); LogHelper.Info("Miner logout"); PoolJob.TcpServer.CloseSocket(e); return; } if (PoolCache.CurrentTask == null || PoolCache.CurrentTask.State != MiningState.Mining) { return; } var msg = new ScoopDataMsg(); int index = 0; msg.Deserialize(cmd.Payload, ref index); PoolCache.CurrentTask.LastReceiveTime = Time.EpochTime; var minerinfo = PoolCache.CurrentTask.MinerEfforts.FirstOrDefault(x => x.Account == miner.WalletAddress); if (minerinfo == null) { PoolCache.CurrentTask.MinerEfforts.Add(new Models.MinerEffort { Account = miner.WalletAddress, Effort = 1 }); } else { if (minerinfo.Effort == Setting.MaxNonceCount) { RejectCommand.Send(e); return; } minerinfo.Effort++; } if (msg.BlockHeight != PoolCache.CurrentTask.CurrentBlockHeight) { LogHelper.Info("Received invalid scoop data from " + e.Address + ", nonce is " + msg.Nonce + ", height is " + msg.BlockHeight); LogHelper.Info("Block Height invalid , Stop and Send StartMsg"); var stopMsg = new StopMsg { BlockHeight = msg.BlockHeight, Result = false, StartTime = Time.EpochTime, StopTime = Time.EpochTime }; StopCommand.Send(e, stopMsg); Task.Delay(1000).Wait(); var startMsg = PoolCache.CurrentTask.CurrentStartMsg; if (startMsg != null) { StartCommand.Send(e, startMsg); } return; } LogHelper.Info("Received scoop data from " + miner.ClientAddress + ", nonce is " + msg.Nonce + ", scoop number is " + msg.ScoopNumber + ", block height is " + msg.BlockHeight); if (msg.ScoopNumber != PoolCache.CurrentTask.CurrentScoopNumber) { LogHelper.Info("Received invalid scoop data from " + e.Address + ", nonce is " + msg.Nonce + ", ScoopNumber is " + PoolCache.CurrentTask.CurrentScoopNumber + "/" + msg.ScoopNumber); LogHelper.Info("Scoop Number invalid"); return; } var verResult = POC.Verify(PoolCache.CurrentTask.BaseTarget, msg.Target); LogHelper.Debug("Bits:" + POC.ConvertBitsToBigInt(PoolCache.CurrentTask.BaseTarget).ToString("X").PadLeft(64, '0')); LogHelper.Debug("Hash:" + Base16.Encode(msg.Target)); LogHelper.Debug("Verify Result is " + verResult); if (!verResult) { return; } ForgeMsg forgeMsg = new ForgeMsg(); forgeMsg.Account = msg.WalletAddress; forgeMsg.Nonce = msg.Nonce; forgeMsg.StartMsgId = PoolCache.CurrentTask.Id; //MQApi.SendForgeBlock(msg.WalletAddress, msg.Nonce, PoolCache.CurrentTask.Id); RabbitMQApi.SendForgeBlock(msg.WalletAddress, msg.Nonce, PoolCache.CurrentTask.Id); }