Solidityのprivate修飾子がついた変数を確認する方法を調べたので、記しておく。
目次
private変数とは
Solidityの変数や関数には
- private
- public
- external
- internal
- view
- pure
のような修飾子が存在する。
それぞれの役割については別途調べれば比較的容易に記事を見つけられる。
その中のprivate修飾子がついているコントラクト変数のことを、「private変数」と呼んでいる。
private変数のアクセス範囲
定義されたコントラクト内でのみ使用可能。
継承されたコントラクトや外部からの使用はできません。
「private」の勘違いポイント
スマートコントラクトの中にある変数は、もれなく全て世界に公開されている情報です。
当然のことです。
しかし、「private」修飾子が「他のコントラクトからアクセスすることができない」という性質を、
private修飾子をつけた変数は外部に漏れないものだと思い込んでしまいがちです。
privateがアクセスを制限しているのは、あくまでもプログラムの中の話であって、その変数自体を知る手段が存在していないわけではありません。しっかりweb3.jsなどから情報の内部を確認できます。
private修飾子の内容をweb3.jsから確認する方法!
contractの中にあるprivate変数の値をweb3.jsから取得してみようと思います。
web3.jsの、getStorageAt関数を使用します。
web3.eth.getStorageAt(コントラクトアドレス, スロット番号)
第一引数には、読みたいprivate変数が存在するコントラクトのコントラクトアドレスを入れます。
第二引数にあるのは「スロット番号」です。
現段階では、変数の定義を上から順番に0、1、…と番号をつけた時の数字です。
// スロット番号
// 変数の定義順に0からカウントした値と思えば良い。
contract Sample {
address private a; // スロット番号「0」
address private b;// スロット番号「1」
address private owner = address(0x0....); // スロット番号「2」
}
上記の例だと、ownerというprivate変数のスロット番号は「2」になります。
スロット番号について詳しく知るためには、Solidity、EVMがコントラクトのstorage変数をどのように保存しているかを勉強する必要がありますね。
⏫ついては別途詳しく勉強して記事を書く予定です。
もし秘匿変数をコントラクトに入れたいならば。。
To ensure that data is private, it needs to be encrypted before being put onto the blockchain. In this scenario, the decryption key should never be sent on-chain, as it will then be visible to anyone who looks for it. zk-SNARKs provide a way to determine whether someone possesses a secret parameter, without ever having to reveal the parameter.
https://ethernaut.openzeppelin.com/ のValut
もしデータを秘匿情報として扱うのであれば、ブロックチェーンに保存する前に暗号化する必要があります。
この場合での、復号化のための鍵(パスワード的な)は、チェーンとは関係のないところで保管されている必要があります。
ちなみに!
zk-SNARKsをご存知でしょうか?
パラメータを明らかにすることなく、誰かが秘密のパラメータを持っているかどうかを判断する方法
だそうです。
こういう技術もあるよって紹介されていました。
zk-SNARKsとは非対話なゼロ知識証明を構築し、ブロックチェーンでのトランザクションの秘匿化やイーサリアムのスケーリング問題のソリューションとして応用されています。ゼロ知識証明が持つ3つの性質に加えてさらにSNARKを示す4つの性質を追加します。
https://zenn.dev/kyosuke/articles/a1854b9be26c01df13eb
こちらの記事(https://zenn.dev/kyosuke/articles/a1854b9be26c01df13eb)でとても詳しくzk-SNARKsについて書かれていました。内容がガチなので、読むのは後程、、っていう感じにしたいと思いました笑。
まとめ
private変数をコントラクト内で使用したときに、それが秘匿情報として扱えると思い込んでパスワードのような情報を管理しないように気をつけようと改めて実感しました💪