如何使用web3/ using获得区块链上的事务的原始事务?
在这里可以看到一个原始事务的示例:https://etherscan.io/getRawTx?tx=0x3866bd52ab1273b9b014e81f981fb35e6b1ec3254514e09c604921ecc17a6ad6
发布于 2018-10-14 18:28:10
Nethereum不直接支持它,但是所有版本的奇偶校验钱包都支持它,最近版本的geth也支持它,所以我们可以直接发送RPC调用,而不需要使用任何not RPC调用。正在讨论的RPC方法是eth_getRawTransactionByHash。
Like所以
///
/// 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;
}在其中使用了下列助手类
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版本)的节点,那么仍然可以使用以下函数从可用数据中获取原始十六进制。
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);
}https://ethereum.stackexchange.com/questions/60480
复制相似问题