正確的交易簽名
我正在嘗試在 nodejs 中實現投票系統。當提供使用者私鑰時,我的伺服器需要能夠創建交易並將其發送到乙太坊區塊鏈。我曾嘗試使用不同的模組這樣做,但我似乎總是遇到同樣的問題。- 與 RPC 的連接工作正常 - 交易似乎創建得恰到好處 - 交易註冊為由我的本地節點發送到網路,但永遠不會出現在區塊鏈中。
我已經設法在使用 web3 時註冊了交易,但如果我想自己簽署交易,我就不能這樣做。測試是使用測試網(ropsten 和 kovan)上的本地或遠端(infura)節點完成的。我可能有問題的提示:-使用 web3 創建事務(成功)時,我的本地節點將事務雜湊視為“0x456515 …”,地址為“0xcfnsk55sghHG …”-使用ethereumjs 執行相同操作時-tx 來簽署交易,節點將其視為“456515…”和“&cfnsk55sghHG…”我正在尋找有關問題所在或如何解決問題的任何資訊/幫助=)
var Web3 = require('web3'); var Tx = require('ethereumjs-tx'); var _ = require('lodash'); var SolidityFunction = require('web3/lib/web3/function'); var keythereum = require("keythereum"); var web3 = new Web3(); web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545")); var toAccount ='0x2824dD13D388ed0Df7Ae1b5697b7b66E737E021a'; var fromAccount = '0x4129c6A02caB77DeEdBDC221904a3dc1ab7cAAfE'; var privateKey = Buffer.from('My Private Key', 'hex' ); gasPrice = web3.eth.gasPrice; gasPriceHex = web3.toHex(gasPrice); gasLimitHex = web3.toHex(300000); console.log('Current gasPrice: ' + gasPrice + ' OR ' + gasPriceHex); nonce = web3.eth.getTransactionCount(fromAccount) ; nonceHex = web3.toHex(nonce); console.log('nonce (transaction count on fromAccount): ' + nonce + '(' + nonceHex + ')'); var rawTx = { nonce: '0x85555', gasPrice: gasPriceHex, gasLimit: gasLimitHex, to: toAccount, from: fromAccount, value: web3.toHex(web3.toWei ( 1, "ether")), data: '0x7f7465737435000', chainId: '0x3', }; var tx = new Tx(rawTx); tx.sign(privateKey); var serializedTx = tx.serialize(); web3.eth.sendRawTransaction('0x'+serializedTx.toString('hex'), function (err, hash) { if (err) { console.log('Error:'); console.log(err); } else { console.log('Transaction receipt hash pending'); console.log(hash); } });
謝謝你
我不知道這是否是發送原始交易的正確方法,但它確實有效。剛剛測試過了。
const Web3 = require('web3'); const Tx = require('ethereumjs-tx'); const config = require('./config'); const web3 = new Web3(new Web3.providers.HttpProvider(config.provider)); //link provided by Infura.io web3.eth.defaultAccount = "0xc929c890f1398d5c1ecdf4f9ecec016906ac9f7f"; const getNonce = () => { return new Promise((resolve, reject) => { web3.eth.getTransactionCount(web3.eth.defaultAccount, (error, result) => { if(error) reject(error); resolve(web3.toHex(result)); }) }) } const getGasPrice = () => { return new Promise((resolve, reject) => { web3.eth.getGasPrice((error, result) => { if(error) reject(error); resolve(web3.toHex(result.toNumber())); }) }) } const sendRawTransaction = (rawTx) => { const privateKey = "190b820c2627f26fd1b973b72dcba78ff677ca4395c64a4a2d0f4ef8de36883c"; const tx = new Tx(rawTx); const privateKeyBuffer = Buffer.from(privateKey, 'hex'); tx.sign(privateKeyBuffer); const serializedTx = tx.serialize(); web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'), function(err, hash) { console.log('Error:', err); console.log('Hash:', hash); }); } Promise.all([getNonce(), getGasPrice()]) .then(values => { const rawTx = { to: '0x203D17B4a1725E001426b7Ab3193E6657b0dBcc6', gasLimit: web3.toHex(1000000), value: web3.toHex(web3.toWei('0.1', 'ether')), nonce: values[0], gasPrice: values[1] }; console.log(rawTx); return(rawTx); }) .then(sendRawTransaction) .catch(e => console.log(e))
安慰:
{ to: '0x203D17B4a1725E001426b7Ab3193E6657b0dBcc6', gasLimit: '0xf4240', value: '0x16345785d8a0000', nonce: '0x5', gasPrice: '0x4a817c800' } Error: null Hash: 0x2a156efdaa6be587544f32cdf7bac140bbee20dafda2c561a4c9195c6fa6729c
這是我生成密鑰對和地址的方式:
const keythereum = require('keythereum'); const utils = require('ethereumjs-util'); const params = {keyBytes: 32, ivBytes: 16}; const dk = keythereum.create(params); const private = utils.bufferToHex(dk.privateKey); const public = utils.bufferToHex(utils.privateToPublic(dk.privateKey)); const address = utils.bufferToHex(utils.privateToAddress(dk.privateKey));
好吧,我終於找到了所有這些問題的答案,正如之前所說的那樣,這裡的隨機數有問題,除了它有點微妙。您使用帳戶發送的每筆交易都應該增加與該帳戶相關的隨機數。最好的方法是使用:
nonce = web3.eth.getTransactionCount(fromAccount);
但是在測試網上(ropsten,而不是 kovan),初始帳戶隨機數設置為 0x100000,因此您必須使用:
nonce = web3.eth.getTransactionCount(fromAccount) + 1048576;
在客戶端(geth、parity、…)中顯示為“&28…”或“0x28…”的地址沒有區別。使用連續隨機數時要非常小心。