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);
        }
Exemple #2
0
        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);
            }
        }
Exemple #3
0
        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();
            }
        }