首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我能得到使用Nethereum的原始交易吗?

我能得到使用Nethereum的原始交易吗?
EN

Ethereum用户
提问于 2018-10-12 14:08:26
回答 1查看 2.2K关注 0票数 3

如何使用web3/ using获得区块链上的事务的原始事务?

在这里可以看到一个原始事务的示例:https://etherscan.io/getRawTx?tx=0x3866bd52ab1273b9b014e81f981fb35e6b1ec3254514e09c604921ecc17a6ad6

EN

回答 1

Ethereum用户

回答已采纳

发布于 2018-10-14 18:28:10

Nethereum不直接支持它,但是所有版本的奇偶校验钱包都支持它,最近版本的geth也支持它,所以我们可以直接发送RPC调用,而不需要使用任何not RPC调用。正在讨论的RPC方法是eth_getRawTransactionByHash

Like所以

代码语言:javascript
复制
        /// 
        /// Attempt to get the raw hex directly from the geth node
        /// 
        /// 
        /// 
        internal string GetRawTxHexByGetRawTransactionByHash(string txid)
        {
            // Extract the HttpClient object from the web3 object
            FieldInfo field = typeof(Nethereum.JsonRpc.Client.RpcClient).GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance);
            HttpClient httpClient = (HttpClient)field.GetValue(_web3.Client);

            // Make the post request to our own Geth node and deserialize the result
            RpcRequest rpcRequest = new RpcRequest
            {
                method = "eth_getRawTransactionByHash",
                @params = new string[] { txid },
            };
            HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri("/", UriKind.Relative));
            requestMessage.Content = new StringContent(JsonConvert.SerializeObject(rpcRequest), Encoding.UTF8, "application/json");
            HttpResponseMessage resp = httpClient.SendAsync(requestMessage).Result;
            if (!resp.IsSuccessStatusCode)
            {
                _logger.LogWarning($"Failed to call to eth_getRawTransactionByHash for txid={txid}.");
                return null;
            }

            EthGetRawTransactionByHashResponse txResp =
                JsonConvert.DeserializeObject(resp.Content.ReadAsStringAsync().Result);

            return txResp.result;
        }

在其中使用了下列助手类

代码语言:javascript
复制
        private abstract class Web3RpcBase
        {
            public int id { get; set; } = 67;
            public string jsonrpc { get; set; } = "2.0";
        }

        private class RpcRequest : Web3RpcBase
        {
            public string method { get; set; }
            public string[] @params { get; set; }
        }

        private class EthGetRawTransactionByHashResponse : Web3RpcBase
        {
            public string result { get; set; }
        }

如果您很不幸地使用了一个不支持eth_getRawTransactionByHash (旧的geth版本)的节点,那么仍然可以使用以下函数从可用数据中获取原始十六进制。

代码语言:javascript
复制
        private abstract class Web3RpcBase
        {
            public int id { get; set; } = 67;
            public string jsonrpc { get; set; } = "2.0";
        }

        private class RpcRequest : Web3RpcBase
        {
            public string method { get; set; }
            public string[] @params { get; set; }
        }


        private class EthGetTransactionByHashResponseResult

        {
            public string blockHash { get; set; }
            public string blockNumber { get; set; }
            public string from { get; set; }

            // This is what we usually call gas limit
            public string gas { get; set; }
            public string gasPrice { get; set; }
            public string hash { get; set; }

            // This is what we usually call data
            public string input { get; set; }
            public string nonce { get; set; }
            public string to { get; set; }
            public string transactionIndex { get; set; }
            public string value { get; set; }
            public string v { get; set; }
            public string r { get; set; }
            public string s { get; set; }
        }


        private class EthGetTransactionByHashResponse : Web3RpcBase

        {
            public EthGetTransactionByHashResponseResult result { get; set; }
        }

        private class EthGetRawTransactionByHashResponse : Web3RpcBase
        {
            public string result { get; set; }
        }


        /// 
        /// Should only be used for Ethereum, not BTC.
        /// 
        /// 
        /// 
        private static byte[] HexToByteArrayWrapper(string hexString)
        {
            // Prevent "0" from becoming "00" represented by[0]. "0" should be[], and 1 should be [0x01]
            if (string.IsNullOrEmpty(hexString) || hexString == "0" || hexString == "0x0")
            {
                return Array.Empty();
            }

            return hexString.HexToByteArray();
        }

        /// 
        /// Attempt to get the raw hex directly from the geth node
        /// 
        /// 
        /// 
        internal string GetRawTxHexByGetRawTransactionByHash(string txid)
        {
            // Extract the HttpClient object from the web3 object
            FieldInfo field = typeof(Nethereum.JsonRpc.Client.RpcClient).GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance);
            HttpClient httpClient = (HttpClient)field.GetValue(_web3.Client);

            // Make the post request to our own Geth node and deserialize the result
            RpcRequest rpcRequest = new RpcRequest
            {
                method = "eth_getRawTransactionByHash",
                @params = new string[] { txid },
            };
            HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri("/", UriKind.Relative));
            requestMessage.Content = new StringContent(JsonConvert.SerializeObject(rpcRequest), Encoding.UTF8, "application/json");
            HttpResponseMessage resp = httpClient.SendAsync(requestMessage).Result;
            if (!resp.IsSuccessStatusCode)
            {
                _logger.LogWarning($"Failed to call to eth_getRawTransactionByHash for txid={txid}.");
                return null;
            }

            EthGetRawTransactionByHashResponse txResp =
                JsonConvert.DeserializeObject(resp.Content.ReadAsStringAsync().Result);

            return txResp.result;
        }

        /// 
        /// Attempt to reconstruct the raw hex by getting the transaction info from the geth node
        /// 
        /// 
        /// 
        internal string GetRawTxHexByGetTransactionByHash(string txid)
        {
            // Extract the HttpClient object from the web3 object
            FieldInfo field = typeof(Nethereum.JsonRpc.Client.RpcClient).GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance);
            HttpClient httpClient = (HttpClient)field.GetValue(_web3.Client);

            // Make the post request to our own Geth node and deserialize the result
            RpcRequest rpcRequest = new RpcRequest
            {
                method = "eth_getTransactionByHash",
                @params = new string[] { txid },
            };
            HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri("/", UriKind.Relative));
            requestMessage.Content = new StringContent(JsonConvert.SerializeObject(rpcRequest), Encoding.UTF8, "application/json");
            HttpResponseMessage resp = httpClient.SendAsync(requestMessage).Result;
            if (!resp.IsSuccessStatusCode)
            {
                _logger.LogWarning($"Failed to call to eth_getTransactionByHash for txid={txid}.");
                return null;
            }

            EthGetTransactionByHashResponse txResp = JsonConvert.DeserializeObject(resp.Content.ReadAsStringAsync().Result);

            // Create the signature object to insert in the transaction (needed to support chain IDs above 0xff)
            Org.BouncyCastle.Math.BigInteger r = new Org.BouncyCastle.Math.BigInteger(txResp.result.r.Substring(2), 0x10);
            Org.BouncyCastle.Math.BigInteger s = new Org.BouncyCastle.Math.BigInteger(txResp.result.s.Substring(2), 0x10);
            byte[] v = new byte[] { byte.Parse(txResp.result.v.Substring(2), System.Globalization.NumberStyles.HexNumber, CultureInfo.GetCultureInfo("en-US")) };
            EthECDSASignature signature = new Nethereum.Signer.EthECDSASignature(r, s, v);

            // Create unsigned transaction object
            Nethereum.Signer.Transaction transaction = new Nethereum.Signer.Transaction(
                HexToByteArrayWrapper(txResp.result.nonce),
                HexToByteArrayWrapper(txResp.result.gasPrice),
                HexToByteArrayWrapper(txResp.result.gas),
                HexToByteArrayWrapper(txResp.result.to),
                HexToByteArrayWrapper(txResp.result.value),
                HexToByteArrayWrapper(txResp.result.input),
                Array.Empty(),
                Array.Empty(),
                0);
            transaction.SetSignature(signature);

            // Get the hex format of the RLP-encoded transaction, the rawtx
            string rawTxHex = "0x" + transaction.GetRLPEncoded().Select(x => x.ToString("x2", NumberFormatInfo.InvariantInfo)).Aggregate((acc, elem) => acc + elem);
            return rawTxHex;
        }

        /// 
        /// Given a txid return the RLP-encoded raw hex that represents the transcation on the blockchain.
        /// 
        /// 
        /// 
        internal string GetRawHex(string txid)
        {
            // First try to get the raw hex directly from the node
            string res = GetRawTxHexByGetRawTransactionByHash(txid);
            if (!String.IsNullOrWhiteSpace(res) && res != "0x")
            {
                return res;
            }

            // If that did not work, attempt to construct it from tx details
            _logger.LogInformation("Failed to get raw hex from node, calculating it locally instead.");
            return GetRawTxHexByGetTransactionByHash(txid);
        }
票数 1
EN
页面原文内容由Ethereum提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://ethereum.stackexchange.com/questions/60480

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档