Ethereum: イーサリアムのトランザクションに署名付きデータを埋め込み、コントラクトでその署名を検証する方法

こみー / Ryo Komiyama
KYUZAN
Published in
7 min readDec 25, 2018
Photo by Dominik Rešek on Unsplash

この記事では、イーサリアム(Ethereum)のトランザクションに署名付きデータを埋め込み、その署名をコントラクトで検証する方法を説明する。

システム内にこの仕組みを取り入れることで、一部の処理をオフチェーンで実行でき、不要なgasの削減や処理の高速化を実現できる。

  1. トランザクションの署名
  2. トランザクション内データの署名
  3. 具体的な署名・検証の実装方法
  4. まとめ

参考資料

1. トランザクションの署名

イーサリアムのトランザクションは、必ず送信者によって署名がされている。こうすることで、誰でもそのトランザクションの送信者を検証できる。

この署名には、ECDSA(Elliptic Curve Digital Signature Algorithm)というアルゴリズムが用いられている。

2. トランザクション内データの署名

ECDSAは、Solidity側でもWeb3側でも簡単に使える仕組みが提供されている。

そのため、トランザクションの署名と同じ要領で、トランザクションの中身に署名をすると、そのトランザクションに書かれている内容の一部が、トランザクション送信者以外の誰かによって書かれた(その人物の許可を得ている)ことを検証できる。

0x Protocolでの利用例

0x ProtocolとはDEXの仕組みの1つで、0x Protocolに準拠したDEXは、注文部分をオフチェーンでおこなう。0x Protocolの仕組みは、Off-chain order relay On-chain settlementという言葉で表されている。

この仕組みを上の図に対応させる。

まず売り手(0xC)は、以下の内容(一部割愛してある)に署名をして、order(signed data)を作成する。

  • 売り手のアドレス
  • 売りたいtokenとその量
  • 買いたいtokenとその量

作成されたorderは、order bookと呼ばれるリスト(オフチェーン)に追加される。

買い手(0xAに対応)は、order bookから好きなorderを選び、そのorderをデータとして含んだtransactionを作ることで、取引を成立させる。(オンチェーン)

このとき、最終的なtransactionは買い手によって作成されているが、取引内容は売り手が決定できていることに注意する。

このように0x Protocolでは、注文部分をオフチェーンで処理することによって、不要なgasの発生を防いでいる。(注文の作成・取り消しにかかるはずのgasを削減できている。)

3. 具体的な実装方法

トランザクション内データに署名することの有用性を理解したので、最後に具体的な実装を見ていく。ここでは、以下の流れを確認することを目的とする。

3.1. Web3を使ったオフチェーンでの署名
3.2. Web3を使ったオフチェーンでの検証 (optional)
3.3. Solidityを使ったオンチェーンでの検証

全体の実装例は、以下のリポジトリに公開している。

3.1. Web3を使ったオフチェーンでの署名

signatureを得るための関数はweb3.eth.accounts.signを使うといい。

その際、あらかじめmessageをhashしておくのがよく(bytes32にしておくのがよく)、それにはweb3.utils.soliditySha3が有用である。この関数は、引数をSolidityと同じように扱ってくれるため、後述するSolidity側での検証が可能になる。(例えば、正のnumberはuint256として扱う。)

https://github.com/ryokomy/solidity-ecdsa-example/blob/master/src/tools/sign.js

3.2. Web3を使ったオフチェーンでの署名の検証 (optional)

署名の検証にはweb3.eth.accounts.recoverを使うといい。

この際デフォルトでは内部的に、署名対象のデータ(messageHash)がhashされる(正確には、prefixをつけてhashされる)ことに注意する。この処理を明示的に書いたのがコメントアウトされた行で、verifiedAddressから始まる2つの行は、どちらの行をコメントアウトしても動作する。

https://github.com/ryokomy/solidity-ecdsa-example/blob/master/src/tools/sign.js

この例では、signedAddressとverifiedAddressが同じになることが確認できる。

3.3. Solidityを使ったオンチェーンでの署名の検証

3.2. と同じことをSolidity側で行なっているのが、以下の例である。

https://github.com/ryokomy/solidity-ecdsa-example/blob/master/contracts/EcdsaContract.sol

この際、ライブラリとしてOpenZeppelinのECDSAを利用している。Solidity側では、上述の内部的なhashを明示的に記述する必要がある。 (toEthSignedMessageHash)

ここで得られるverifiedAddressは、3.2で得たverifiedAddressと同じ結果になる。

4. まとめ

トランザクションの内部データに署名をすることで、そのトランザクションに書かれている内容(の一部)が誰かの許可を得ていることを検証できる。

これらは、不要なgasの削減や処理の高速化に役立ち、Web3・OpenZeppelinのライブラリを使うことで、比較的簡単に実装することができる。

--

--

こみー / Ryo Komiyama
KYUZAN
Editor for

🏔Kyuzan🏔 Blockchain Startup @ Tokyo ▼ex 東大 暦本研 ▼ex Rhizomatiks Research