Last active
April 6, 2024 04:32
-
-
Save tjade273/69e3cb5dce1789738830 to your computer and use it in GitHub Desktop.
Example of separated storage and logic
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
contract Database{ | |
mapping(uint => uint) public _data; | |
mapping(address => bool) _owners; | |
function Database(address[] owners){ //Called once at creation, pass in initial owners | |
for(uint i; i<owners.length; i++){ | |
_owners[owners[i]]=true; | |
} | |
} | |
function setData(uint id, uint data) public returns (bool){ | |
if(_owners[msg.sender]){ | |
_data[id] = data; | |
return true; | |
} | |
return false; | |
} | |
function changeOwners(address owner, bool permission) public returns(bool){ | |
if(_owners[msg.sender]){ | |
_owners[owner] = permission; | |
return true; | |
} | |
return false; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var owners = [eth.accounts[0]];/* Initial owners*/ ; | |
/* First time - initialize the database */ | |
var databaseContract = web3.eth.contract([{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"_data","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"id","type":"uint256"},{"name":"data","type":"uint256"}],"name":"setData","outputs":[{"name":"","type":"bool"}],"type":"function"},{"constant":false,"inputs":[{"name":"owner","type":"address"},{"name":"permission","type":"bool"}],"name":"changeOwners","outputs":[{"name":"","type":"bool"}],"type":"function"},{"inputs":[{"name":"owners","type":"address[]"}],"type":"constructor"}]); | |
var database = databaseContract.new( | |
owners, | |
{ | |
from: web3.eth.accounts[0], | |
data: '606060405260405161015b38038061015b8339810160405280510160005b81518110156075576001600160005060008484815181101560025790602001906020020151600160a060020a0316815260200190815260200160002060006101000a81548160ff02191690830217905550600101601d565b505060d7806100846000396000f3606060405260e060020a600035046303a7f8258114602e5780634848b1a5146045578063f9b30d03146085575b005b60cd60043560006020819052908152604090205481565b60cd600435602435600160a060020a03331660009081526001602052604081205460ff1615607f5782815260208190526040902081905560015b92915050565b60cd600435602435600160a060020a03331660009081526001602052604081205460ff1615607f57600160a060020a038316815260409020805460ff1916821790556001607f565b6060908152602090f3', | |
gas: 1000000 | |
} | |
) | |
/* --------------- To add logic contracts ----------------- */ | |
var data = database.address; /* Address of database */ ; | |
var logicContract = web3.eth.contract([{"constant":false,"inputs":[{"name":"newContract","type":"address"}],"name":"update","outputs":[],"type":"function"},{"constant":false,"inputs":[],"name":"example","outputs":[],"type":"function"},{"inputs":[{"name":"data","type":"address"}],"type":"constructor"}]); | |
var logic = logicContract.new( | |
data, // This is where the address gets passed in | |
{ | |
from: web3.eth.accounts[0], | |
data: '60606040526040516020806101dd83395060806040525160008054600160a060020a03191682179055506101a6806100376000396000f3606060405260e060020a60003504631c1b8772811461002657806354353f2f146100d0575b005b6100246004356000805460e060020a63f9b30d03026060908152600160a060020a0384811660645260016084529091169163f9b30d039160a491602091906044908290876161da5a03f1156100025750604080516000805460e060020a63f9b30d0302835230600160a060020a03908116600485015260248401839052935193169450604482810193602093909290839003909101908290876161da5a03f1156100025750505050565b610024600080547f03a7f825000000000000000000000000000000000000000000000000000000006060908152610539606452600160a060020a03909116906303a7f8259060849060209060248187876161da5a03f11561000257505060408051805184547f4848b1a500000000000000000000000000000000000000000000000000000000835261053960048401526104d2602484015292519094600160a060020a03939093169350634848b1a5926044808401936020939290839003909101908290876161da5a03f115610002575050505056', | |
gas: 1000000 | |
}) | |
// To update the permissions in the database (first wait for logic to be mined) | |
database.changeOwners(logic.address, true,{from:eth.accounts[0],gas:100000}); | |
//Or if there already is a logic contract | |
oldLogic.update(logic.address, {from:eth.accounts[0],gas:100000}); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
contract Database{ | |
function _data(uint id) public constant returns (uint data); | |
function setData(uint id, uint data) public returns (bool); | |
function changeOwners(address owner, bool permission) public returns(bool); | |
} | |
contract Logic{ | |
Database database; | |
function Logic (address data){ | |
database = Database(data); | |
} | |
// Logic here | |
function update(address newContract) public { | |
database.changeOwners(newContract,true); // Give new contract write permissions | |
database.changeOwners(this,false); // Revokes it's own permissions | |
} | |
function example(){ | |
uint foo = database._data(1337); // get data | |
database.setData(1337,1234); // set data | |
} | |
} |
The database contract is created only once, then the address is passed as an argument to the constructor of each new logic contract. Make sure to properly change the permissions, or you will lose access to the DB and will have to copy all the data to a new one :(
There is an issue with web3 RPC to use string as key. One workaround I found is -
mapping(bytes32 => int) private mymapping;
mymapping[sha3(#inputstring)]
so instead of string use sha3(string) as key. Hope that helps.
I am wondering, what's the difference between the two Database contracts, and why do you define it twice?
edit, nevermind, rereading everything sometimes help.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Using string arguments as mapping keys doesn't seem to work, so the DB now uses unique IDs instead of names. In real life, using a (uint => data) mapping where data is a custom struct would probably make the most sense.