Smart Contract design pattern#5(コントラクトのアップデートvol.1)

Tomoya Ishida
Oct 9, 2018 · 7 min read
Photo by fabio on Unsplash

Smart contract design patternのMaintenanceの中から、Data Segregation PatternSatellite Patternを紹介していきます。

「なぜデザインパターンが重要視されているのか」「なんのために学ぶのか」という部分はこちらの記事で紹介しているので、まだ読まれていない方は是非ご覧になってください。

この記事は前回に引き続きこちらの文献を参考にしています。

Maintenance Patterns

Maintenance Patternsはライブオペレーションコントラクトのためのメカニズムを提供するグループです。

バグが検出されたときに更新可能な通常の分散アプリケーションとは対照的に、Ethereum上で構築されたスマートコントラクトは不可逆的で不変です。
その性質が契約の透明性、改竄耐性を担保しているのですが、その代償として「更新」という通常のアプリケーションが当たり前に持っている性質を基本的には持っていないのです。

しかしあらかじめアップデートを想定したコントラクトを実装することは可能であり、それにより不測の自体に備えることができます。

Data Segregation Pattern

課題

通常コントラクトデータとそのロジックは同じコントラクト内に保持されており、コントラクトを新しいバージョンに置き換えると元のコントラクトのデータを新しいコントラクトに移行する必要がある。

解決

オペレーションロジックとそのデータを別々のコントラクトに分離する。

Data segregation patternはコントラクトのロジックをデータするため関数が変更された場合にデータ移行をする必要がありません。したがって、新しいコントラクトでは前のコントラクトに含まれていた既存のデータを再構築すること必要がないのです。

Sample Code: 分離されたData Contract

GitHubはこちら

pragma solidity ^0.4.24;contract DataStorage {
mapping(bytes32 => uint) uintStorage;
function getUintValue(bytes32 key) public constant
returns (uint) {
return uintStorage[key];
}
function setUintValue(bytes32 key, uint value) public {
uintStorage[key] = value;
}
}

Sample Code: 分離されたLogic Contract

pragma solidity ^0.4.24;import "./DataStorage.sol";contract Logic {
DataStorage dataStorage;
constructor(address _address) public {
dataStorage = DataStorage(_address);
}
function f() public {
bytes32 key = keccak256("emergency");
dataStorage.setUintValue(key, 911);
dataStorage.getUintValue(key);
}
}

Satellite Pattern

課題

コントラクトは不変であるため、変更するには新たなコントラクトをデプロイする必要がある。

解決

独立しているSatellite Contractに、変更される可能性が高い関数をアウトソーシングし、利用する際にこれらのコントラクトを参照する。

Satellite patternはコントラクトを変更して置き換えることを可能にします。これは特定のコントラクトをカプセル化する別々のSatelitte コントラクトによって実現されます。

これらのSetelite ContractのアドレスはBase Contractに格納されています。このコントラクトは格納されているアドレスポインタを使用して、特定の関数を参照する必要があるときにSatelite Contractを呼び出すことができます。

このパターンが正しく実装されている場合、新しいContractを作成し、関数を変更することは対応するSatelliteアドレスを変更することで簡単に実現可能。

Sample Code: 特定のContractをカプセル化するSatellite Contract

GitHubはこちら

pragma solidity ^0.4.24;contract Satellite {
function calculateVariable() public pure returns (uint) {
// calculate var
return 2 * 3;
}
}
  • 3行目でSatellite Contractを定義。
  • 4行目でcalculateVariable関数を定義。pure修飾子はブロックチェーンへの書き込みも読み込みもできない。そのためトランザクションが発生しないことからガスコストも発生しない。

Sample Code: Satellite Contractを参照するBase Contract

pragma solidity ^0.4.24;import "../../authorization/Ownership.sol";
import "./Satellite.sol";
contract Base is Owned {
uint public variable;
address satelliteAddress;
function setVariable() public onlyOwner {
Satellite s = Satellite(satelliteAddress);
variable = s.calculateVariable();
}
function updateSatelliteAddress(address _address) public onlyOwner {
satelliteAddress = _address;
}
}
  • 8行目でOwned Contractを継承。
  • 10行目でsetVariable関数を定義。コントラクトのオーナーだけが実行可能。
  • 15行目でupdateSatelliteAddres関数を定義。satelliteAddressをアップデートするために使われる。オーナーだけが実行可能。

追記:10/13続編を公開しました!

おわりに

最後まで読んでいただきありがとうございます。次回も引き続きコントラクトのアップデートに関してまとめていきます。
また、認識違いなどありましたら、どしどしご指摘お願いいたします!

ツイッターでは日々暗号通貨やブロックチェーンの発信を行っています。よろしければフォローをお待ちしてます!

Tomoya Ishida

Written by

’92/Tokyo Web Application and Blockchain Developer. Ruby, Rails, Blockchain, Ethereum, EOS, Solidity, UI/UX