private void EnsureInitialWorkSent(StratumClient client) { var context = client.ContextAs <AionWorkerContext>(); ArrayList arrayTarget = new ArrayList(); var sendInitialWork = false; lock (context) { if (context.IsSubscribed && context.IsAuthorized && !context.IsInitialWorkSent) { context.IsInitialWorkSent = true; string newTarget = AionUtils.diffToTarget(context.Difficulty); arrayTarget.Add(newTarget); sendInitialWork = true; } } if (sendInitialWork) { // send intial update // await client.NotifyAsync(AionStratumMethods.MiningNotify, currentJobParams); // await client.NotifyAsync(AionStratumMethods.SetTarget, arrayTarget); client.Notify(AionStratumMethods.MiningNotify, currentJobParams); client.Notify(AionStratumMethods.SetTarget, arrayTarget); } }
private async Task <string> getLatestNonce() { var latest = await daemon.ExecuteCmdSingleAsync <string>(logger, AionCommands.GetTransactionCount, new[] { poolConfig.Address }); if (AionUtils.fromHex(latest.Response).Equals(latestNonce) || usedLatestNonce) { latestNonce = latestNonce + 1; usedLatestNonce = false; } else { latestNonce = AionUtils.fromHex(latest.Response); usedLatestNonce = true; } return(AionUtils.AppendHexStart(latestNonce.ToString("X"))); }
protected void OnNewJobAsync(object jobParams) { currentJobParams = jobParams; logger.Debug(() => $"Broadcasting job"); // logger.Info(() => "!!! src/Miningcore/Blockchain/Aion/AionPool.cs/OnNewJobAsync"); ForEachClient(client => { var context = client.ContextAs <AionWorkerContext>(); if (context.IsSubscribed && context.IsAuthorized && context.IsInitialWorkSent) { // check alive var lastActivityAgo = clock.Now - context.LastActivity; if (poolConfig.ClientConnectionTimeout > 0 && lastActivityAgo.TotalSeconds > poolConfig.ClientConnectionTimeout) { logger.Info(() => $"Booting zombie-worker (idle-timeout exceeded)"); DisconnectClient(client); return; } // varDiff: if the client has a pending difficulty change, apply it now if (context.ApplyPendingDifficulty()) { // await client.NotifyAsync(AionStratumMethods.SetDifficulty, new object[] { context.Difficulty }); client.Notify(AionStratumMethods.SetDifficulty, new object[] { context.Difficulty }); } string newTarget = AionUtils.diffToTarget(context.Difficulty); ArrayList arrayTarget = new ArrayList(); arrayTarget.Add(newTarget); // await client.NotifyAsync(AionStratumMethods.MiningNotify, currentJobParams); // await client.NotifyAsync(AionStratumMethods.SetTarget, arrayTarget); client.Notify(AionStratumMethods.MiningNotify, currentJobParams); client.Notify(AionStratumMethods.SetTarget, arrayTarget); } }); }
protected override async Task OnVarDiffUpdateAsync(StratumClient client, double newDiff) { await base.OnVarDiffUpdateAsync(client, newDiff); // apply immediately and notify client var context = client.ContextAs <AionWorkerContext>(); if (context.HasPendingDifficulty) { context.ApplyPendingDifficulty(); string newTarget = AionUtils.diffToTarget(newDiff); ArrayList targetArray = new ArrayList(); targetArray.Add(newTarget); // send job // await client.NotifyAsync(AionStratumMethods.MiningNotify, currentJobParams); // await client.NotifyAsync(AionStratumMethods.SetTarget, targetArray); client.Notify(AionStratumMethods.MiningNotify, currentJobParams); client.Notify(AionStratumMethods.SetTarget, targetArray); } }
private async Task <DaemonResponse <string> > SendTransactionPrivateKey(Balance balance) { logger.Info(() => $"[{LogCategory}] Sending {FormatAmount(balance.Amount)} to {balance.Address} using the private key."); var latestNonce = await getLatestNonce(); var txData = new AionTransaction { Nonce = AionUtils.AppendHexStart(latestNonce), To = balance.Address, Value = AionUtils.AppendHexStart(((BigInteger)Math.Floor(balance.Amount * AionConstants.Wei)).ToString("x")), Data = "", Gas = AionUtils.AppendHexStart(new BigInteger(22000).ToString("x")), GasPrice = AionUtils.AppendHexStart(new BigInteger(10000000000).ToString("x")), Timestamp = AionUtils.AppendHexStart(DateTime.Now.Ticks.ToString("x2")), Type = "0x01" }; txData.Sign(extraConfig.PrivateKey); string serializedTx = txData.Serialize(); return(await daemon.ExecuteCmdSingleAsync <string>(logger, AionCommands.SendRawTx, new[] { serializedTx })); }
private (Share Share, string nonce, string solution, string headerHash, string nTime) ProcessShareInternal( StratumClient worker, string nonce, string nTime, string solution) { var context = worker.ContextAs <AionWorkerContext>(); var solutionBytes = solution.HexToByteArray(); // serialize block-header var headerBytes = SerializeHeader(nonce); // verify solution if (!equihash.Verify(headerBytes, solutionBytes)) { throw new StratumException(StratumError.Other, "invalid solution"); } // hash block-header var headerSolutionBytes = headerBytes.Concat(solutionBytes).ToArray(); Span <byte> headerHash = stackalloc byte[32]; headerHasher.Digest(headerSolutionBytes, headerHash); var headerHashReversed = headerHash.ToNewReverseArray(); var headerValue = headerHashReversed.ToBigInteger(); var target = new BigInteger(blockTarget.ToBytes()); var isBlockCandidate = target > headerValue; logger.Debug(() => $"context.Difficulty:{context.Difficulty} Difficulty: {Difficulty}"); // calc share-diff var stratumDifficulty = context.Difficulty > Difficulty ? Difficulty : context.Difficulty; var shareDiff = stratumDifficulty; var ratio = shareDiff / stratumDifficulty; var sentTargetInt = new uint256(AionUtils.diffToTarget(context.Difficulty).HexToReverseByteArray()); var sentTarget = new BigInteger(sentTargetInt.ToBytes()); var isLowDiffShare = sentTarget <= headerValue; if (isLowDiffShare) { throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})"); } var result = new Share { BlockHeight = (long)BlockTemplate.Height, IpAddress = worker.RemoteEndpoint?.Address?.ToString(), Miner = context.MinerName, Worker = context.WorkerName, UserAgent = context.UserAgent, NetworkDifficulty = Difficulty, Difficulty = stratumDifficulty, IsBlockCandidate = isBlockCandidate, TransactionConfirmationData = headerHash.ToHexString(), }; if (isBlockCandidate) { // result.BlockReward = AionUtils.calculateReward((long) BlockTemplate.Height); result.BlockHash = headerHashReversed.ToHexString(); } return(result, nonce, solution, BlockTemplate.HeaderHash, nTime); }