Created
November 24, 2015 16:13
-
-
Save Gustav-Simonsson/04c72e9677790f267dd3 to your computer and use it in GitHub Desktop.
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
// WARNING: WORK IN PROGRESS & UNTESTED | |
// | |
// @AUTHORS: Gustav Simonsson <gustav@ethdev.com> | |
// @DATE: 2015-10-30 | |
// @VERSION: 0.1 | |
// @LICENSE: GNUBL 2.0 (https://github.com/Gustav-Simonsson/GNUBL/blob/master/LICENSE) | |
// | |
// contract tracking versions added by designated signers. | |
// designed to track versions of geth (go-ethereum) recommended by the | |
// go-ethereum team. geth client interfaces with contract through ABI by simply | |
// reading the full state and then deciding on recommended version based on | |
// some logic (e.g. version date & number of signers). | |
// | |
// to keep things simple, the contract does not use FSM for multisig | |
// but rather allows any designated signer to add a version or vote for an | |
// existing version. this avoids need to track voting-in-progress states and | |
// also provides history of all past versions. | |
// | |
contract Versions { | |
struct V { | |
bytes32 v; | |
uint64 ts; | |
address[] signers; | |
} | |
address[] public parties; // owners/signers | |
address[] public deleteAcks; // votes to suicide contract | |
uint public deleteAcksReq; // number of votes needed | |
V[] public versions; | |
modifier canAccess(address addr) { | |
bool access = false; | |
for (uint i = 0; i < parties.length; i++) { | |
if (parties[i] == addr) { | |
access = true; | |
break; | |
} | |
} | |
if (access == false) { | |
throw; | |
} | |
_ | |
} | |
function Versions(address[] addrs) { | |
if (addrs.length < 2) { | |
throw; | |
} | |
parties = addrs; | |
deleteAcksReq = (addrs.length / 2) + 1; | |
} | |
// either submit a new version or acknowledge an existing one | |
function AckVersion(bytes32 ver) | |
canAccess(msg.sender) | |
{ | |
/* | |
for (uint i = 0; i < versions.length; i++) { | |
if (versions[i].v == ver) { | |
for (uint j = 0; j < versions[i].signers.length; j++) { | |
if (versions[i].signers[j] == msg.sender) { | |
// already signed | |
throw; | |
} | |
} | |
// add sender as signer of existing version | |
versions[i].signers.push(msg.sender); | |
return; | |
} | |
} | |
*/ | |
// version is new, add it | |
address[] memory s; | |
s[0] = msg.sender; | |
versions.push(V({ v: ver, ts: uint64(block.timestamp), signers: s })); | |
} | |
// delete-this-contract vote, suicide if enough votes | |
function AckDelete() | |
canAccess(msg.sender) | |
{ | |
for (uint i = 0; i < deleteAcks.length; i++) { | |
if (deleteAcks[i] == msg.sender) { | |
throw; // already acked delete | |
} | |
} | |
deleteAcks.push(msg.sender); | |
if (deleteAcks.length >= deleteAcksReq) { | |
suicide(msg.sender); | |
} | |
} | |
// remove sender's delete-this-contract vote, if present | |
function NackDelete() | |
canAccess(msg.sender) | |
{ | |
uint len = deleteAcks.length; | |
for (uint i = 0; i < len; i++) { | |
if (deleteAcks[i] == msg.sender) { | |
if (len > 1) { | |
deleteAcks[i] = deleteAcks[len-1]; | |
} | |
deleteAcks.length -= 1; | |
} | |
} | |
} | |
// For ABI call in go-ethereum: | |
// accessor function 'versions' is auto-generated by solidity | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment