public bool SubmitSolution(string digest, string fromAddress, string challenge, string difficulty, string target, string solution, Miner.IMiner sender) { if (string.IsNullOrWhiteSpace(solution) || solution == "0x") { return(false); } m_challengeReceiveDateTime = DateTime.Now; var startSubmitDateTime = DateTime.Now; if (m_runFailover) { if (SecondaryPool.SubmitSolution(digest, fromAddress, challenge, difficulty, target, solution, sender)) { LastSubmitLatency = (int)((DateTime.Now - startSubmitDateTime).TotalMilliseconds); Program.Print(string.Format("[INFO] Submission roundtrip latency: {0}ms", LastSubmitLatency)); if (m_submitDateTimeList.Count >= MAX_SUBMIT_DTM_COUNT) { m_submitDateTimeList.RemoveAt(0); } m_submitDateTimeList.Add(DateTime.Now); } return(false); } difficulty = new HexBigInteger(difficulty).Value.ToString(); // change from hex to base 10 numerics var success = false; var submitted = false; int retryCount = 0, maxRetries = 10; var devFee = (ulong)Math.Round(100 / Math.Abs(DevFee.UserPercent)); do { try { var poolAddress = fromAddress; lock (this) { if (SubmittedShares == ulong.MaxValue) { SubmittedShares = 0u; } var minerAddress = ((SubmittedShares) % devFee) == 0 ? DevFee.Address : MinerAddress; JObject submitShare; submitShare = GetPoolParameter("submitShare", solution, minerAddress, digest, difficulty, challenge, m_customDifficulity > 0 ? "true" : "false", Miner.Work.GetKingAddressString()); var response = Utils.Json.InvokeJObjectRPC(s_PoolURL, submitShare); LastSubmitLatency = (int)((DateTime.Now - startSubmitDateTime).TotalMilliseconds); var result = response.SelectToken("$.result")?.Value <string>(); success = (result ?? string.Empty).Equals("true", StringComparison.OrdinalIgnoreCase); if (!success) { RejectedShares++; } SubmittedShares++; Program.Print(string.Format("[INFO] {0} [{1}] submitted to {2} pool: {3} ({4}ms)", (minerAddress == DevFee.Address ? "Dev. fee share" : "Miner share"), SubmittedShares, IsSecondaryPool ? "secondary" : "primary", (success ? "success" : "failed"), LastSubmitLatency)); #if DEBUG Program.Print(submitShare.ToString()); Program.Print(response.ToString()); #endif } submitted = true; } catch (Exception ex) { Program.Print(string.Format("[ERROR] {0}", ex.Message)); retryCount += 1; if (retryCount < maxRetries) { Task.Delay(500); } } } while (!submitted && retryCount < maxRetries); if (success) { if (m_submitDateTimeList.Count > MAX_SUBMIT_DTM_COUNT) { m_submitDateTimeList.RemoveAt(0); } m_submitDateTimeList.Add(DateTime.Now); } else { UpdateMiningParameters(); } return(success); }
public bool SubmitSolution(string digest, string fromAddress, string challenge, string difficulty, string target, string solution, Miner.IMiner sender) { lock (this) { if (IsChallengedSubmitted(challenge)) { OnStopSolvingCurrentChallenge(this, challenge); Program.Print(string.Format("[INFO] Submission cancelled, nonce has been submitted for the current challenge.")); return(false); } m_challengeReceiveDateTime = DateTime.MinValue; var transactionID = string.Empty; var gasLimit = new HexBigInteger(m_gasLimit); var userGas = new HexBigInteger(UnitConversion.Convert.ToWei(new BigDecimal(m_gasToMine), UnitConversion.EthUnit.Gwei)); var oSolution = new BigInteger(Utils.Numerics.HexStringToByte32Array(solution).ToArray()); // Note: do not directly use -> new HexBigInteger(solution).Value //Because two's complement representation always interprets the highest-order bit of the last byte in the array //(the byte at position Array.Length - 1) as the sign bit, //the method returns a byte array with an extra element whose value is zero //to disambiguate positive values that could otherwise be interpreted as having their sign bits set. object[] dataInput = null; if (m_mintMethodInputParamCount > 1) // 0xBitcoin compatibility { dataInput = new object[] { oSolution, HexByteConvertorExtensions.HexToByteArray(digest) } } ; else // Draft EIP-918 compatibility [2018-03-07] { dataInput = new object[] { oSolution } }; var retryCount = 0u; var startSubmitDateTime = DateTime.Now; while (string.IsNullOrWhiteSpace(transactionID)) { try { var txCount = m_web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(fromAddress).Result; var estimatedGasLimit = m_mintMethod.EstimateGasAsync(from: fromAddress, gas: gasLimit, value: new HexBigInteger(0), functionInput: dataInput).Result; var transaction = m_mintMethod.CreateTransactionInput(from: fromAddress, gas: estimatedGasLimit, gasPrice: userGas, value: new HexBigInteger(0), functionInput: dataInput); var encodedTx = Web3.OfflineTransactionSigner.SignTransaction(privateKey: m_account.PrivateKey, to: m_contract.Address, amount: 0, nonce: txCount.Value, gasPrice: userGas, gasLimit: estimatedGasLimit, data: transaction.Data); if (!Web3.OfflineTransactionSigner.VerifyTransaction(encodedTx)) { throw new Exception("Failed to verify transaction."); } transactionID = m_web3.Eth.Transactions.SendRawTransaction.SendRequestAsync("0x" + encodedTx).Result; LastSubmitLatency = (int)((DateTime.Now - startSubmitDateTime).TotalMilliseconds); if (!string.IsNullOrWhiteSpace(transactionID)) { if (!IsChallengedSubmitted(challenge)) { m_submittedChallengeList.Insert(0, challenge); if (m_submittedChallengeList.Count > 100) { m_submittedChallengeList.Remove(m_submittedChallengeList.Last()); } } Task.Factory.StartNew(() => GetTransactionReciept(transactionID, fromAddress, gasLimit, userGas, LastSubmitLatency)); } } catch (AggregateException ex) { var errorMessage = "[ERROR] " + ex.Message; foreach (var iEx in ex.InnerExceptions) { errorMessage += "\n " + iEx.Message; } Program.Print(errorMessage); if (IsChallengedSubmitted(challenge)) { return(false); } } catch (Exception ex) { var errorMessage = "[ERROR] " + ex.Message; if (ex.InnerException != null) { errorMessage += "\n " + ex.InnerException.Message; } Program.Print(errorMessage); if (IsChallengedSubmitted(challenge) || ex.Message == "Failed to verify transaction.") { return(false); } } System.Threading.Thread.Sleep(1000); if (string.IsNullOrWhiteSpace(transactionID)) { retryCount++; } if (retryCount > 10) { Program.Print("[ERROR] Failed to submit solution for more than 10 times, please check settings."); sender.StopMining(); } } if (m_submitDateTimeList.Count >= MAX_SUBMIT_DTM_COUNT) { m_submitDateTimeList.RemoveAt(0); } m_submitDateTimeList.Add(DateTime.Now); return(true); } }
public void SubmitSolution(string digest, string fromAddress, string challenge, string difficulty, string target, string solution, Miner.IMiner sender) { if (m_runFailover) { ((INetworkInterface)SecondaryPool).SubmitSolution(digest, fromAddress, challenge, difficulty, target, solution, sender); return; } if (string.IsNullOrWhiteSpace(solution) || solution == "0x") { return; } difficulty = new HexBigInteger(difficulty).Value.ToString(); // change from hex to base 10 numerics var success = false; var submitted = false; int retryCount = 0, maxRetries = 10; var devFee = (ulong)Math.Round(100 / Math.Abs(DevFee.UserPercent)); do { try { var poolAddress = fromAddress; lock (this) { if (SubmittedShares == ulong.MaxValue) { SubmittedShares = 0u; } var minerAddress = ((SubmittedShares) % devFee) == 0 ? DevFee.Address : s_MinerAddress; JObject submitShare; submitShare = GetPoolParameter("submitShare", solution, minerAddress, digest, difficulty, challenge, m_customDifficulity > 0 ? "true" : "false", Miner.Work.GetKingAddressString()); var response = Utils.Json.InvokeJObjectRPC(s_PoolURL, submitShare); var result = response.SelectToken("$.result")?.Value <string>(); success = (result ?? string.Empty).Equals("true", StringComparison.OrdinalIgnoreCase); if (!success) { RejectedShares++; } SubmittedShares++; Program.Print(string.Format("[INFO] {0} [{1}] submitted: {2}", (minerAddress == DevFee.Address ? "Dev. fee share" : "Miner share"), SubmittedShares, (success ? "success" : "failed"))); #if DEBUG Program.Print(submitShare.ToString()); Program.Print(response.ToString()); #endif } submitted = true; } catch (Exception ex) { Program.Print(string.Format("[ERROR] {0}", ex.Message)); retryCount += 1; if (retryCount < maxRetries) { Task.Delay(500); } } } while (!submitted && retryCount < maxRetries); if (!success) { UpdateMiningParameters(); } }