Ethereum rawトランザクション 実装


イーサリアム rawトランザクション

キー取得、署名、送信を実際に実行したときのログ

$ geth --datadir ~/eth_private_net init ~/eth_private_net/myGenesis.json
$ geth --networkid 12345 --datadir ~/eth_private_net --nodiscover --rpc --rpccorsdomain "*" --rpcport 8545 --rpcaddr "localhost" --rpcapi "web3,eth,net,personal" console 2>> ~/eth_private_net/geth.log
> personal.newAccount("password");
"0x16b90716ec7c5e820711b1377daaf59dde4e1553"

keythereumをインストール

$ npm install keythereum

鍵を取得する処理を作成

$ cat work/create_raw.js

const keythereum = require('keythereum');
const address = '0x95d0ab3bcb76b3a56d4cd0c5289cccdf972c3766';
const datadir = '/home/oho/eth_private_net';
const password = 'hogehoge1';
let str;
keythereum.importFromFile(address, datadir, function (keyObject) {
  keythereum.recover(password, keyObject, function (privateKey) {
    console.log(privateKey.toString('hex'));
  });
});
$ node work/raw.js 
a9aa071329aa851824239f2ba5bd1b5120c330f7f427352a524fe5a61425f7f0

鍵を取得できた

トランザクションを実行

> personal.unlockAccount(eth.accounts[0],'hogehoge1');
true
> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[2], value: web3.toWei(0.001,"ether")});
"0x1c6b6b8c1628cb460219f7842a634163fe759847b6d3631c2e096ab1df3a0270"

トランザクションIDをコピーする

ethereumjs-txをインストール

$ npm install ethereumjs-tx

トランザクション署名処理を作成

$ cat work/create_raw.js

const ethTx = require('ethereumjs-tx');
const to1 = '0x95d0ab3bcb76b3a56d4cd0c5289cccdf972c3766';
const to2 = '0x16b90716ec7c5e820711b1377daaf59dde4e1553';
const key1 = 'bbcffe2cea44b406ee97fe0b1d61dbc1a702e6324f2786d21650a90d45797bf3';
const key2 = 'a9aa071329aa851824239f2ba5bd1b5120c330f7f427352a524fe5a61425f7f0';
const amount = 0.00005;
const txParams = {
  nonce: 0x6,// Replace by nonce for your account on geth node
  gasPrice: '0x09184e72a000', 
  gasLimit: '0x700000',
  to: to2, 
  value: 0.00005
};
// Transaction is created
const tx = new ethTx(txParams);
const privKey = Buffer.from(key1, 'hex');
// Transaction is signed
tx.sign(privKey);
const serializedTx = tx.serialize();
const rawTx = '0x' + serializedTx.toString('hex');
console.log(rawTx);

トランザクションIDに署名

$ node create_raw.js 
0xf866068609184e72a000830300009495d0ab3bcb76b3a56d4cd0c5289cccdf972c376680801ca05a991fb2ffa8d543e04b1abb6995f30b4ae
9fded4cc98be32374f95c68fb2974a06742050231cbb91b5471bbc0e55a87f22b0a1e4184291ec2e891889f074a20f7

署名済みIDを使用してsendRawTransactionを実行

失敗時

> eth.sendRawTransaction('0xf866068609184e72a000830300009495d0ab3bcb76b3a56d4cd0c5289cccdf972c376680801ca05a991fb2f
fa8d543e04b1abb6995f30b4ae9fded4cc98be32374f95c68fb2974a06742050231cbb91b5471bbc0e55a87f22b0a1e4184291ec2e891889f07
4a20f7');
Error: insufficient funds for gas * price + value
    at web3.js:3143:20
    at web3.js:6347:15
    at web3.js:5081:36
    at <anonymous>:1:1
$ node work/create_raw.js 
0xf865068609184e72a0008227109416b90716ec7c5e820711b1377daaf59dde4e155380801ca023b74cc39bf6bce9fe10bfb1fa5861e7b7a38e5cdd5bb9446fd05ee065f98d2ca02a974ff5cbd028cb2d041f81354f128a1992f7c895a5c4e43f40b49c65030c49

失敗時

> eth.sendRawTransaction('0xf865068609184e72a0008227109416b90716ec7c5e820711b1377daaf59dde4e155380801ca023b74cc39bf
6bce9fe10bfb1fa5861e7b7a38e5cdd5bb9446fd05ee065f98d2ca02a974ff5cbd028cb2d041f81354f128a1992f7c895a5c4e43f40b49c6503
0c49');
Error: intrinsic gas too low
    at web3.js:3143:20
    at web3.js:6347:15
    at web3.js:5081:36
    at <anonymous>:1:1

sendRawTransaction成功時

> eth.sendRawTransaction('0xf866068609184e72a000837000009416b90716ec7c5e820711b1377daaf59dde4e155380801ba01fe2ddcc57c0bfb96d88c4acb059e9b1419b91c50c4e058ee7aaf6b7666ab532a01cc7b79c1664a45235c7130ced05b1ceb6258efa71887bb1d95ceb53a11f2b46');
"0xf68a31bfeb12f1ef7a48aa3492e27147ae5324821dcc07196f9d071ffbd44912"