private void ValidateTx( RelayResponse returnedTx, TransactionInput transaction, BigInteger txFee, BigInteger gasPrice, BigInteger gasLimit, BigInteger nonce, string relayHubAddress, string relayAddress) { var tx = returnedTx.ToTransaction(); var signer = tx.Key.GetPublicAddress(); var functionEncodingService = new FunctionMessageEncodingService <RelayCallFunction>(); var relayCall = functionEncodingService.DecodeInput(new RelayCallFunction(), returnedTx.Input); var returnedTxHash = GetTransactionHash( relayCall.From, relayCall.To, relayCall.EncodedFunction.ToHex(), relayCall.TransactionFee, relayCall.GasPriceParam, relayCall.GasLimit, relayCall.NonceParam, returnedTx.To, signer); var hash = GetTransactionHash( transaction.From, transaction.To, transaction.Data, txFee, transaction.GasPrice.Value, transaction.Gas.Value, nonce, relayHubAddress, relayAddress); if (returnedTxHash.EnsureHexPrefix().ToLower() != hash.EnsureHexPrefix().ToLower() || signer.EnsureHexPrefix().ToLower() != relayAddress.EnsureHexPrefix().ToLower()) { throw new GSNRelayInvalidResponseException(); } }
private async Task <string> SendViaRelay( string relayUrl, TransactionInput transaction, BigInteger txFee, BigInteger gasPrice, BigInteger gasLimit, BigInteger nonce, string relayHubAddress, string relayAddress, string signature, string approvalData, BigInteger relayMaxNonce) { var requestData = new RelayRequest { EncodedFunction = transaction.Data, Signature = signature.HexToByteArray(), ApprovalData = approvalData.HexToByteArray(), From = transaction.From, To = transaction.To, GasPrice = gasPrice, GasLimit = gasLimit, RelayFee = txFee, RecipientNonce = nonce, RelayMaxNonce = relayMaxNonce, RelayHubAddress = relayHubAddress, UserAgent = _options.UserAgent }; RelayResponse relayResponse = await _relayClient.RelayAsync(new Uri(relayUrl), requestData) .ConfigureAwait(false); if (!string.IsNullOrEmpty(relayResponse.Error)) { throw new Exception(relayResponse.Error); } if (relayResponse.Nonce.Value.IsZero) { throw new Exception("Empty body received from server, or neither 'error' nor 'nonce' fields present."); } ValidateTx( relayResponse, transaction, txFee, gasPrice, gasLimit, nonce, relayHubAddress, relayAddress); var tx = relayResponse.ToTransaction(); string hash = string.Empty; var ethSendTransaction = new EthSendRawTransaction(_client); try { hash = await ethSendTransaction.SendRequestAsync(tx.GetRLPEncoded().ToHex().EnsureHexPrefix()) .ConfigureAwait(false); } catch (Exception ex) { if (!ex.Message.Contains("the tx doesn't have the correct nonce") && !ex.Message.Contains("known transaction") && !ex.Message.Contains("nonce too low")) { throw ex; } } var txHash = relayResponse.Hash; if (!string.IsNullOrEmpty(hash) && relayResponse.Hash.EnsureHexPrefix().ToLower() != hash.EnsureHexPrefix().ToLower()) { txHash = hash; } return(txHash); }