├── README.md ├── run.py ├── .gitignore ├── validators_test.py └── validators.se /README.md: -------------------------------------------------------------------------------- 1 | mini-DAO 2 | 3 | This is a tiny governance contract. It was designed to maintain the list of validators for tendermint. 4 | 5 | try this: ./run.py validators -------------------------------------------------------------------------------- /run.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | from pyethereum import tester as t 4 | s=t.state() 5 | c=s.abi_contract(sys.argv[1]+".se") 6 | test=__import__(sys.argv[1]+"_test") 7 | print(test.test(c)) 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # PyInstaller 26 | # Usually these files are written by a python script from a template 27 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 28 | *.manifest 29 | *.spec 30 | 31 | # Installer logs 32 | pip-log.txt 33 | pip-delete-this-directory.txt 34 | 35 | # Unit test / coverage reports 36 | htmlcov/ 37 | .tox/ 38 | .coverage 39 | .cache 40 | nosetests.xml 41 | coverage.xml 42 | 43 | # Translations 44 | *.mo 45 | *.pot 46 | 47 | # Django stuff: 48 | *.log 49 | 50 | # Sphinx documentation 51 | docs/_build/ 52 | 53 | # PyBuilder 54 | target/ 55 | -------------------------------------------------------------------------------- /validators_test.py: -------------------------------------------------------------------------------- 1 | import bitcoin as b 2 | from pyethereum import utils 3 | 4 | def hash_list(l): 5 | def g(x): 6 | if type(x) in [int, long]: x=utils.int_to_big_endian(x) 7 | return x 8 | y=map(lambda x: g(x), l) 9 | y=[utils.zpad(x, 32) for x in y] 10 | y=''.join(y) 11 | #save for pretty print z="".join("{:02x}".format(ord(c)) for c in y) 12 | #return b.sha256(y) 13 | return utils.sha3(y).encode("hex") 14 | def mk_acc(n): 15 | out={"priv":b.sha256("brainwallet"+str(n))} 16 | out["pub"]=b.privtopub(out["priv"]) 17 | out["addr"]=int(utils.privtoaddr(out["priv"]), 16) 18 | return(out) 19 | def mk_sig(hash, priv): return list(b.ecdsa_raw_sign(hash, priv)) 20 | def mk_mk_sig(msghash): return (lambda p: mk_sig(msghash, p["priv"])) 21 | def add(a, b): return a+b 22 | def add_validator(location, addr, balance, accs, new_market_cap, new_size, c, nonce): 23 | f=mk_mk_sig(hash_list([addr, location, balance, nonce, 1337])) 24 | c.update(addr, location, balance, new_market_cap, new_size, reduce(add, map(f, accs))) 25 | def test(c): 26 | accs=map(mk_acc, [1,2,3]) 27 | balance = 10000000 28 | add_validator(1, accs[1]["addr"], balance, accs[0:1], 2*balance, 2, c, 0) 29 | add_validator(2, accs[2]["addr"], balance, accs[0:2], 3*balance, 3, c, 1) 30 | 31 | -------------------------------------------------------------------------------- /validators.se: -------------------------------------------------------------------------------- 1 | #this contract is for keeping track of which public keys are for the validator's private keys. 2 | #In storage we need to store a list of public keys with the cooresponding balance. 3 | #If more than 2/3rds of the people on the list sign an update, then they can modify the list. 4 | #def test(c): 5 | #print(c.update(2, pubkey, 10000, [v, r, s])) 6 | 7 | def init: 8 | b = 10000000 9 | self.storage["size"] = 1 10 | self.storage["nonce"] = 0 11 | self.storage["marketCap"] = b 12 | self.storage[0] = 1381215427713340411455090116682682197500678047224 #address 1 from tester file 13 | self.storage[1] = b 14 | 15 | macro verify_macro($hash, $signatures): 16 | size=self.storage["size"] 17 | signed = 0 18 | i=0 19 | while i self.storage["marketCap"]*2/3 30 | 31 | def verify_sign(hash, signatures:arr):#signatures must be in the same order as the pubkeys in memory. 32 | return verify_macro(hash, signatures) 33 | 34 | def update(new_addr, location, balance, new_market_cap, new_size, signatures:arr): 35 | #needs to have been signed by at least 2/3rds of the validators weighted by balance 36 | size=self.storage["size"] 37 | nonce = self.storage["nonce"] 38 | #h=sha256([new_addr, location, balance, nonce, 1337]:arr) 39 | h=sha3([new_addr, location, balance, nonce, 1337]:arr) 40 | if verify_macro(h, signatures): 41 | if location>size: 42 | self.storage["size"]=location 43 | self.storage["nonce"] = 1 + nonce 44 | self.storage[location*2] = new_addr 45 | self.storage[location*2+1] = balance 46 | self.storage["marketCap"] = new_market_cap 47 | self.storage["size"] = new_size 48 | log(self.storage[0]) 49 | log(self.storage[1]) 50 | log(self.storage[2]) 51 | log(self.storage[3]) 52 | log(self.storage[4]) 53 | log(self.storage[5]) 54 | --------------------------------------------------------------------------------