Solidityのデータ保存について
Solidityではデータの保存にstorageとmemoryの2種類があります。
storageはブロックチェーンにデータを永久に保存するもので、memoryはコントラクト実行時に一時的にデータを保持するものです。
もっと簡単にいうとstorageはブロックチェーンに保存され、memoryはブロックチェーンに保存されることはありません。
Ethereumのスマートコントラクトではこの2つのデータ保持の特性を理解しておくことがコスト節約に対して非常に重要になります。
しかし、基本的にはSolidityのコンパイラが自動でstorageなのかmemoryなのかは判定してくれる素晴らしい仕組みになっています。
ガスコストの高いstorage
Solidityで一番コストが高いのはstorageを使うことです。なぜ高くなるかというと、ブロックチェーンにデータを書き込むからです。
storageに書き込まれたデータは世界中に存在する数千、数万のノードのハードディスクに保存されるため非常にコストが高いです。ノードが増えればそれだけ資源を消費してしまうからです。
Solidityでは必要最低限のデータ以外はstorageに保存せずにmemoryに保存することでコストを削減できます。
ちなみに、関数外で宣言した変数はstorageとなりブロックチェーに保存されます。
コストのかからないmemory
memoryはブロックチェーンに書き込まないのでコストはかかりません。関数内で使われる変数はmemoryとなるので特に意識しなくともSolidityのコンパイラが自動で対応してくれるみたいです。
サンプルコード
下記はstorageとmemoryを使ったサンプルコードです。ここの内容が理解できればstorageとmemoryは理解したと言って大丈夫かと思います。
contract BookFactory { struct Book { string name; string status; } Book[] books; function getBook(uint _index) public { // この場合、コンパイラがstorageかmemoryをつけてと注意してくれる // Book book1 = books[_index]; // ブロックチェーンに書き込む場合 // 要素への参照を渡しているのでブロックチェーンを更新できる Book storage book1 = books[_index]; book1.status = "Read!"; // 値のコピーにはmemoryを使う // memoryの値を変更してもブロックチェーンには書き込まれない Book memory book2 = books[_index + 1]; book2.status = "Read!"; // memoryを使ってブロックチェーンに書き込む books[_index] = book2; } }
まとめ
分散アプリケーションはこれまでのWEBサービスを作るときに気をつけるべきことが異なるので戸惑うことが多いなと感じます。今回のstorageとmemoryの考え方は特にそうで、全く違う考え方をしないと行けないのは逆に面白く分散アプリケーションにはどんどんハマっていきそうです。
今後もSolidityの基礎について書いていくので楽しみにしていてください。
おすすめ書籍
Ethereumを使ったDApps開発を学びたいなら今だとこの1冊が1番良いです!開発環境の構築から使うべきツール、フレームワーク、実装方法・注意点まで網羅的に解説されている書籍なのでおすすめです。出版も2018年1月ということでかなり新しい本で、DMM Bitcoinを作っているネクストカレンシー所属の方が書いているので信頼できます。
ビットコインとブロックチェーンの詳細をしっかりと学びたい方にはこちらの書籍が非常におすすめです。ウォレットの仕組み、楕円曲線暗号、P2Pプロトコル、公開鍵暗号などビットコインを支える技術について詳細に解説されています。また、サンプルコードを通して実際に手を動かして学べるので非常に濃い内容となっています。
髙妻智一
最新記事 by 髙妻智一 (全て見る)
- Polkadot(Substrate)のアドレスとトランザクションについて - 2023-03-09
- 【無料公開】「Goで始めるBitcoin」3章 Bitcoinノードとの通信 技術書典8 - 2020-03-08
- エンジニアがゼロから技術ブログを書くための方法をまとめました - 2019-05-25
memoryとstorageの使い分けはとてもよくわかったのですが、サンプルの謎コードで戸惑いました。
// memoryを使ってブロックチェーンに書き込む
sandwiches[_index + 1] = anotherSandwich;
どこにも宣言されていない変数が二つも突然現れてます。
ひっとしてsolidityやethereumのキーワードなのかと思いググルも見当たらず。
消化不良となってしまいました。
他のサンプルコードと混ざってしまってたのでbooksに修正しました!
ご指摘ありがとうございます。