はじめに
一年前ぐらいに投稿するつもりだったものを供養する。
gethのバージョンは古いが、現在でもここの仕様はおそらく変わっていない。
GethにはJSON-RPC APIがあり、基本的にほとんどの機能がAPI経由で実行することができる。そこでコントラクトをBlockchainにデプロイしようと思った時、コントラクトに値を渡す方法がわからなかったので、忘備録として記録しておく。
以下に詳しくは書いてある。
Ethereum Contract ABI - Github Ethereum wiki
基本的なEthereum APIの使い方は以下
JSON RPC - Github Ethereum wiki
環境
- geth 1.6.5-stable
やり方
基本的には
0x(Keccak(関数名)の先頭4byte)(渡す 引数パラメータ群)
をdataとしてContract Account宛に送ることでコントラクトの関数実行が可能である。
デプロイ時にはコントラクトをコンパイルしたソースコードの末尾に渡すパラメータ群を記述する。コンストラクタの関数名は入れる必要はないので、パラメーター群をそのまま以下のような形式で書けば良い。
引数パラメータの記述方法
基本的に32byte毎に引数一つとして記述する。例えば以下のような関数を考える。
function fuga(uint256 hoge,address user,string fuga) {
_hoge = hoge;
_user = user;
_fuga = fuga;
}
この場合、uint256型とaddress型、string型のパラメータを渡したい。
Uint256の場合
先頭はuint256型なので、渡したい値を16進数にし、パラメータ一つの全体が32byteの長さになるように左を0埋めする。
1234
-> 00000000000000000000000000000000000000000000000000000000000004d2
addressの場合
次にaddress型だが、これも左0埋めして32byteにする。
0xb8bac7b269f97350e1df5b57a45302ded9b177d3
-> 000000000000000000000000b8bac7b269f97350e1df5b57a45302ded9b177d3
Stringの場合
stringの場合は、パラメータ全体の末尾にその長さとともに記述し、正規の記述するべき順序の場所の32byteには、先頭から何byte後の部分からその順序にあるべきStringのデータが記述されているかを記述する。つまり、この場合はパラメータが3つあり、その末尾になるので、正規の記述するべき順序の場所の32byteには先頭から96byte後あることを示す。その後、末尾には、先頭32byteにそのString長の数値を左0埋め、その後ASCIIでStringを記述する。
つまり、3番目のパラメータとして、
先頭から96byte後にStringの記述開始
-> 0000000000000000000000000000000000000000000000000000000000000060
そして末尾に
hogehoge
-> 0000000000000000000000000000000000000000000000000000000000000008
686f6765686f6765000000000000000000000000000000000000000000000000
を記述する。
関数名
関数名は引数を含んだものをKeccakするので、
keccak("fuga(uint256 hoge,address user,string fuga)")
-> 5e03f4b96ab58326c1381d7b3218d9318f3b013f7d044e6d039e67f8cae2ed4d
これの先頭4byteを持つ。
送信データ
上の3つをパラメータとして、実際に送信するdataは以下である。わかりやすく32byte毎に改行している。
0x5e03f4b9
00000000000000000000000000000000000000000000000000000000000004d2
000000000000000000000000b8bac7b269f97350e1df5b57a45302ded9b177d3
0000000000000000000000000000000000000000000000000000000000000060
0000000000000000000000000000000000000000000000000000000000000008
686f6765686f6765000000000000000000000000000000000000000000000000
eth_sendTransactionのメソッドを使ってContract Account向けにトランザクションを発行することで実行できる。
# おわりに
他にも配列や、渡す型によって記述方法がそれぞれ違うのだが、全てを網羅するのは諦めた。ドキュメント読め。Mistでコンパイルし、トランザクションデータを作らせて、というのを繰り返して諸行無常をした。ちゃんとドキュメントには書いてあるので読もう。正直この辺の話は上に挙げたABIのページに書いてあるのだが、非常にわかりづらく英語もわからないので