Example #1
0
        private async Task <string> SignIfRequiredAsync <T>(T response)
        {
            string payload = HelperTools.JSONSerialize(response, false);

            if (minerId == null)
            {
                // Do not sign if we do not have miner id
                return(payload);
            }

            lastMinerId ??= await minerId.GetCurrentMinerIdAsync();

            async Task <JsonEnvelope> TryToSign()
            {
                async Task <(string signature, string publicKey)> signWithMinerId(string sigHashHex)
                {
                    var signature = await minerId.SignWithMinerIdAsync(lastMinerId, sigHashHex);

                    return(signature, lastMinerId);
                }

                var envelope = await JsonEnvelopeSignature.CreateJSonSignatureAsync(payload, signWithMinerId);

                // Verify a signature - some implementation might have incorrect race conditions when rotating the keys
                if (!JsonEnvelopeSignature.VerifySignature(envelope))
                {
                    return(null);
                }

                return(envelope);
            }

            var jsonEnvelope = await TryToSign();

            if (jsonEnvelope == null)
            {
                throw new Exception("Error while validating signature. Possible reason: incorrect configuration or key rotation");
            }
            return(HelperTools.JSONSerialize(new SignedPayloadViewModel(jsonEnvelope), true));
        }
        /// <summary>
        /// Signs response if required. If response already contains minerId (for example as part of policy quote), pass it in as currentMinerId
        /// To make sure that correct key is used even key rotation just occured
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="response"></param>
        /// <param name="responseMinerId"></param>
        /// <returns></returns>
        async Task <ActionResult> SignIfRequiredAsync <T>(T response, string responseMinerId)
        {
            string payload = HelperTools.JSONSerialize(response, false);

            if (string.IsNullOrEmpty(responseMinerId))
            {
                // Do not sing if we do not have miner id
                return(Ok(new JSONEnvelopeViewModel(payload)));
            }


            async Task <(string signature, string publicKey)> SignWithMinerId(string sigHashHex)
            {
                var signature = await minerId.SignWithMinerIdAsync(responseMinerId, sigHashHex);

                return(signature, responseMinerId);
            }

            var jsonEnvelope = await JsonEnvelopeSignature.CreateJSonSignatureAsync(payload, SignWithMinerId);

            var ret = new SignedPayloadViewModel(jsonEnvelope);

            return(Ok(ret));
        }
Example #3
0
        static async Task SendTransactionsBatch(IEnumerable <string> transactions, HttpClient client, Stats stats, string url, string callbackUrl, string callbackToken, string callbackEncryption)
        {
            var query = new List <string>();

            string doCallbacks = string.IsNullOrEmpty(callbackUrl) ? "false" : "true";

            query.Add($"defaultDsCheck={doCallbacks}");
            query.Add($"defaultMerkleProof={doCallbacks}");

            if (!string.IsNullOrEmpty(callbackUrl))
            {
                query.Add("defaultCallbackUrl=" + WebUtility.UrlEncode(callbackUrl));

                if (!string.IsNullOrEmpty(callbackToken))
                {
                    query.Add("defaultCallbackToken=" + WebUtility.UrlEncode(callbackToken));
                }

                if (!string.IsNullOrEmpty(callbackEncryption))
                {
                    query.Add("defaultCallbackEncryption=" + WebUtility.UrlEncode(callbackEncryption));
                }
            }

            string queryString = string.Join("&", query.ToArray());

            var ub = new UriBuilder(url);

            if (ub.Query.Length == 0)
            {
                ub.Query = queryString; // automatically adds ? at the beginning
            }
            else
            {
                ub.Query = ub.Query.Substring(1) + "&" + queryString; // remove leading ?  it is added back automatically
            }

            string urlWithParams = ub.Uri.ToString();

            string callbackHost = "";

            if (!string.IsNullOrEmpty(callbackUrl))
            {
                callbackHost = new Uri(callbackUrl).Host;
            }


            // We currently submit through REST interface., We could also use binary  interface
            var request = transactions.Select(t => new SubmitTransactionViewModel
            {
                RawTx = t,
                // All other parameters are passed in query string
                CallbackUrl        = null,
                CallbackToken      = null,
                CallbackEncryption = null,
                MerkleProof        = null,
                DsCheck            = null
            }).ToArray();

            var requestString = HelperTools.JSONSerialize(request, false);
            var response      = await client.PostAsync(urlWithParams,
                                                       new StringContent(requestString, new UTF8Encoding(false), MediaTypeNames.Application.Json));

            var responseAsString = await response.Content.ReadAsStringAsync();

            if (!response.IsSuccessStatusCode)
            {
                Console.WriteLine($"Error while submitting transaction request {responseAsString}");
                stats.IncrementRequestErrors();
            }
            else
            {
                var rEnvelope  = HelperTools.JSONDeserialize <SignedPayloadViewModel>(responseAsString);
                var r          = HelperTools.JSONDeserialize <SubmitTransactionsResponseViewModel>(rEnvelope.Payload);
                int printLimit = 10;
                var errorItems = r.Txs.Where(t => t.ReturnResult != "success").ToArray();

                var okItems = r.Txs.Where(t => t.ReturnResult == "success").ToArray();

                stats.AddRequestTxFailures(callbackHost, errorItems.Select(x => new uint256(x.Txid)));
                stats.AddOkSubmited(callbackHost, okItems.Select(x => new uint256(x.Txid)));

                var errors = errorItems
                             .Select(t => t.Txid + " " + t.ReturnResult + " " + t.ResultDescription).ToArray();



                var limitedErrors = string.Join(Environment.NewLine, errors.Take(printLimit));
                if (errors.Any())
                {
                    Console.WriteLine($"Error while submitting transactions. Printing  up to {printLimit} out of {errors.Length} errors : {limitedErrors}");
                }
            }
        }