Skip to content

Instantly share code, notes, and snippets.

@Gustav-Simonsson
Created November 24, 2015 16:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Gustav-Simonsson/04c72e9677790f267dd3 to your computer and use it in GitHub Desktop.
Save Gustav-Simonsson/04c72e9677790f267dd3 to your computer and use it in GitHub Desktop.
// 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