以太坊交易哈希: 如何预先获取?

5
请告诉我如何提前获取交易哈希(transactionHash)?
// I have these tx opts:
var txOpts = {
  "to":"0x345cA3e014Aaf5dcA488057592ee47305D9B3e10",
  "nonce":"0x8",
  "gasPrice":1,
  "gas":250000,
  "value":"0xde0b6b3a7640000",
  "data":"0xd0e30db0"
}

// I create and sign tx:
var tx = new ethereumjs.Tx(txOpts);
tx.sign(new ethereumjs.Buffer.Buffer("c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3", "hex"));

// I've got raw tx:
var rawTx = tx.serialize().toString('hex');
"f86c08018303d09094345ca3e014aaf5dca488057592ee47305d9b3e10880de0b6b3a764000084d0e30db01ca0625e358100f4aacb9a65e6e054d963138565e3ceafb20eae4c9c8aaa583a29eea01d8f74faba33ab577ec36ac383dd5bd5298216bcf69fe2c09bba2d3003ecd008"

当我将这个交易发送给ganache-cli时,我收到了如下日志:
eth_sendRawTransaction
   > {
   >   "jsonrpc": "2.0",
   >   "id": 7,
   >   "method": "eth_sendRawTransaction",
   >   "params": [
   >     "0xf86c08018303d09094345ca3e014aaf5dca488057592ee47305d9b3e10880de0b6b3a764000084d0e30db01ca0625e358100f4aacb9a65e6e054d963138565e3ceafb20eae4c9c8aaa583a29eea01d8f74faba33ab577ec36ac383dd5bd5298216bcf69fe2c09bba2d3003ecd008"
   >   ],
   >   "external": true
   > }

  Transaction: 0x73d419e3a9a63aab7ee4f3be43c0df0175f4395615945d395c827bffb3bbfecc
  Gas usage: 29634
  Block Number: 9
  Block Time: Fri Jan 12 2018 23:21:22 GMT-0700

交易哈希是0x73d419e3a9a63aab7ee4f3be43c0df0175f4395615945d395c827bffb3bbfecc,如何提前获取?

// use ethereumjs.hash function (is that rlp-hash?):
var hash = tx.hash().toString('hex')
"**71ef26c4c1c1b01a5f87525e8e9b3ca7ffe5c9ae30ee1e70b353bf9b14db96be**"

这不等于73d419e3a9a63aab7ee4f3be43c0df0175f4395615945d395c827bffb3bbfecc!

在挖矿之前有没有可能提前计算出正确的交易哈希值?请告诉我应该使用哪些函数。

非常感谢!

4个回答

6

我稍微查了一下,得到了答案。

不要仅仅调用 tx.hash().toString('hex'),你需要像这样调用 tx.hash(true).toString('hex'),其中 true 代表计算哈希时应包括签名。

如果你好奇的话,这是方法(https://github.com/ethereumjs/ethereumjs-tx/blob/9a6324f64f4da1cb550a3eec4eaef95da4ab441b/src/transaction.ts#L177)。

你也可以通过以下方式从 rawTx 中获得相同的结果:

import * as ethUtil from 'ethereumjs-util';
const rawTx = `0x${signedTx.serialize().toString('hex')}`;    // 0x is important
const res1 = `0x${ethUtil.keccak(rawTx).toString('hex')}`;
const res2 = `0x${signedTx.hash(true).toString('hex')}`;
res1 === res2; // true

希望这能有所帮助。


1
这只是一个与ganache有关的问题。queueRawTransaction使用FakeTransaction,它忽略了您交易上的实际签名并伪造了它。我不完全确定为什么会这样,但我相信您的代码将针对提交到实际以太坊网络的交易执行正确的操作。
如果您想获得ganache正在计算的相同交易哈希值,可以尝试此方法,但它不会是您从以太坊正式网络获得的交易哈希值:
const EthereumTx = require('ethereumjs-tx');
const FakeTx = require('ethereumjs-tx/fake.js');

var txOpts = {
  "to":"0x345cA3e014Aaf5dcA488057592ee47305D9B3e10",
  "nonce":"0x8",
  "gasPrice":1,
  "gas":250000,
  "value":"0xde0b6b3a7640000",
  "data":"0xd0e30db0"
}

var tx = new EthereumTx(txOpts);
tx.sign(Buffer.from("c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3", "hex"));

const raw = tx.serialize().toString('hex');
const fake = new FakeTx(raw);
fake.from = tx.getSenderAddress();

console.log(fake.hash(true).toString('hex'));

// Output:
// 71ef26c4c1c1b01a5f87525e8e9b3ca7ffe5c9ae30ee1e70b353bf9b14db96be

1

事先无法获取交易哈希,只能在执行交易后立即获取交易哈希。

但是,如果交易未被任何矿工选择,则此交易哈希将是临时的。如果您发送的交易费用非常少,则有可能您的交易不会被任何矿工选择。


1
这不是完全正确的。 一旦所有交易输入数据已知(例如来自地址,目标合约地址,要调用的函数签名+输入参数,nonce,要转移的eth数量等...),全部编码为原始交易格式并且此原始交易已签名,那么您可以获得Tx id(tx hash)- 在实际发送交易到网络之前完成所有这些步骤... - PeterB

1
我们从ganache获得的实际tx哈希是:

0x73d419e3a9a63aab7ee4f3be43c0df0175f4395615945d395c827bffb3bbfecc

FakeTx和ethereumjs-tx为签名交易返回相同的哈希值:

71ef26c4c1c1b01a5f87525e8e9b3ca7ffe5c9ae30ee1e70b353bf9b14db96be

然而,如果交易未签名,“tx.hash().toString('hex')”返回与ganache cli完全相同的值。即使在txOpts中没有添加“from”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接