Updated trie format and stack language

This commit is contained in:
Vitalik Buterin 2014-01-07 12:40:49 -05:00
parent 9d47cacc47
commit f1208195f4
3 changed files with 47 additions and 37 deletions

View File

@ -58,23 +58,27 @@ scriptcode_map = {
} }
params = { params = {
'stepfee': 10**16, 'stepfee': 1,
'txfee': 2**64, 'txfee': 100,
'newcontractfee': 2**64, 'newcontractfee': 100,
'memoryfee': 2**64 / 4, 'memoryfee': 20,
'datafee': 2**64 / 16, 'datafee': 4,
'cryptofee': 2**64 / 16, 'cryptofee': 10,
'extrofee': 2**64 / 16, 'extrofee': 10,
'blocktime': 60, 'blocktime': 60,
'period_1_reward': 2**80 * 1024, 'period_1_reward': 10**18 * 800,
'period_1_duration': 57600, 'period_1_duration': 57600,
'period_2_reward': 2**80 * 512, 'period_2_reward': 10**18 * 400,
'period_2_duration': 57600, 'period_2_duration': 57600,
'period_3_reward': 2**80 * 256, 'period_3_reward': 10**18 * 100,
'period_3_duration': 57600, 'period_3_duration': 57600,
'period_4_reward': 2**80 * 128 'period_4_reward': 10**18 * 50
} }
def getfee(block,t):
if t in ['stepfee','txfee','newcontractfee','memoryfee','datafee','cryptofee','extrofee']:
return int(10**24 / int(block.difficulty ** 0.5)) * params[t]
def process_transactions(block,transactions): def process_transactions(block,transactions):
while len(transactions) > 0: while len(transactions) > 0:
tx = transactions.pop(0) tx = transactions.pop(0)
@ -85,9 +89,9 @@ def process_transactions(block,transactions):
tdata = rlp.decode(block.state.get(tx.to)) or [0,0,0] tdata = rlp.decode(block.state.get(tx.to)) or [0,0,0]
# Calculate fee # Calculate fee
if tx.to == '\x00'*20: if tx.to == '\x00'*20:
fee = params['newcontractfee'] + len(tx.data) * params['memoryfee'] fee = getfee('newcontractfee') + len(tx.data) * getfee('memoryfee')
else: else:
fee = params['txfee'] fee = getfee('txfee')
# Insufficient fee, do nothing # Insufficient fee, do nothing
if fee > tx.fee: if fee > tx.fee:
sys.stderr.write("Insufficient fee\n") sys.stderr.write("Insufficient fee\n")
@ -143,11 +147,10 @@ def eval(block,transactions,timestamp,coinbase):
reward = params['period_3_reward'] reward = params['period_3_reward']
else: else:
reward = params['period_4_reward'] reward = params['period_4_reward']
print reward
miner_state[1] += reward + block.reward miner_state[1] += reward + block.reward
for uncle in block.uncles: for uncle in block.uncles:
sib_miner_state = rlp_decode(block.state.get(uncle[3])) sib_miner_state = rlp_decode(block.state.get(uncle[3]))
sib_miner_state[1] = encode(decode(sib_miner_state[1],256)+reward*7/8,256) sib_miner_state[1] += reward*7/8
block.state.update(uncle[3],sib_miner_state) block.state.update(uncle[3],sib_miner_state)
miner_state[1] += reward/8 miner_state[1] += reward/8
block.state.update(block.coinbase,rlp.encode(miner_state)) block.state.update(block.coinbase,rlp.encode(miner_state))
@ -190,18 +193,18 @@ def eval_contract(block,transaction_list,tx):
nullfee = 0 nullfee = 0
stepcounter += 1 stepcounter += 1
if stepcounter > 16: if stepcounter > 16:
minerfee += params["stepfee"] minerfee += getfee("stepfee")
c = scriptcode_map[code[0]] c = scriptcode_map[code[0]]
if c in ['STORE','LOAD']: if c in ['STORE','LOAD']:
minerfee += params["datafee"] minerfee += getfee("datafee")
if c in ['EXTRO','BALANCE']: if c in ['EXTRO','BALANCE']:
minerfee += params["extrofee"] minerfee += getfee("extrofee")
if c in ['SHA256','RIPEMD-160','ECMUL','ECADD','ECSIGN','ECRECOVER']: if c in ['SHA256','RIPEMD-160','ECMUL','ECADD','ECSIGN','ECRECOVER']:
minerfee += params["cryptofee"] minerfee += getfee("cryptofee")
if c == 'STORE': if c == 'STORE':
existing = block.get_contract_state(address,code[2]) existing = block.get_contract_state(address,code[2])
if reg[code[1]] != 0: nullfee += params["memoryfee"] if reg[code[1]] != 0: nullfee += getfee("memoryfee")
if existing: nullfee -= params["memoryfee"] if existing: nullfee -= getfee("memoryfee")
# If we can't pay the fee, break, otherwise pay it # If we can't pay the fee, break, otherwise pay it
if block.get_balance(address) < minerfee + nullfee: if block.get_balance(address) < minerfee + nullfee:
@ -356,7 +359,7 @@ def eval_contract(block,transaction_list,tx):
elif code == 'SWAP': elif code == 'SWAP':
x,y = stack_pop(2) x,y = stack_pop(2)
stack.extend([y,x]) stack.extend([y,x])
elif code = 'SWAPN': elif code == 'SWAPN':
arr = stack_pop(contract.get(encode(index + 1,256,32))) arr = stack_pop(contract.get(encode(index + 1,256,32)))
arr.append(arr[0]) arr.append(arr[0])
arr.pop(0) arr.pop(0)
@ -393,7 +396,7 @@ def eval_contract(block,transaction_list,tx):
transaction_list.insert(0,tx) transaction_list.insert(0,tx)
elif code == 'SUICIDE': elif code == 'SUICIDE':
sz = contract.get_size() sz = contract.get_size()
negfee = -sz * params["memoryfee"] negfee = -sz * getfee("memoryfee")
toaddress = encode(stack_pop(1)[0],256,20) toaddress = encode(stack_pop(1)[0],256,20)
block.pay_fee(toaddress,negfee,False) block.pay_fee(toaddress,negfee,False)
contract.root = '' contract.root = ''

View File

@ -17,12 +17,12 @@ class Transaction():
def parse(self,data): def parse(self,data):
if re.match('^[0-9a-fA-F]*$',data): if re.match('^[0-9a-fA-F]*$',data):
data = data.decode('hex') data = data.decode('hex')
o = rlp.unparse(data) o = rlp.decode(data)
self.nonce = o[0] self.nonce = o[0]
self.to = o[1] self.to = o[1]
self.value = o[2] self.value = o[2]
self.fee = o[3] self.fee = o[3]
self.data = rlp.decode(o[4]) self.data = o[4]
self.v = o[5] self.v = o[5]
self.r = o[6] self.r = o[6]
self.s = o[7] self.s = o[7]
@ -32,7 +32,7 @@ class Transaction():
return self return self
def sign(self,key): def sign(self,key):
rawhash = sha256(rlp.encode([self.to,self.value,self.fee,self.data])) rawhash = sha256(rlp.encode([self.nonce,self.to,self.value,self.fee,self.data]))
self.v,self.r,self.s = ecdsa_raw_sign(rawhash,key) self.v,self.r,self.s = ecdsa_raw_sign(rawhash,key)
self.sender = bin_sha256(privtopub(key)[1:])[-20:] self.sender = bin_sha256(privtopub(key)[1:])[-20:]
return self return self

27
trie.py
View File

@ -1,8 +1,8 @@
import leveldb import leveldb
import rlp import rlp
import hashlib from sha3 import sha3_256
def sha256(x): return hashlib.sha256(x).digest() def sha3(x): return sha3_256(x).digest()
class DB(): class DB():
def __init__(self,dbfile): self.db = leveldb.LevelDB(dbfile) def __init__(self,dbfile): self.db = leveldb.LevelDB(dbfile)
@ -45,7 +45,7 @@ class Trie():
if self.debug: print 'nk',node.encode('hex'),key if self.debug: print 'nk',node.encode('hex'),key
if len(key) == 0 or not node: if len(key) == 0 or not node:
return node return node
curnode = rlp.decode(self.db.get(node)) curnode = rlp.decode(self.__lookup(node))
if self.debug: print 'cn', curnode if self.debug: print 'cn', curnode
if not curnode: if not curnode:
raise Exception("node not found in database") raise Exception("node not found in database")
@ -61,10 +61,17 @@ class Trie():
def __put(self,node): def __put(self,node):
rlpnode = rlp.encode(node) rlpnode = rlp.encode(node)
h = sha256(rlpnode) if len(rlpnode) >= 32:
h = sha3(rlpnode)
self.db.put(h,rlpnode) self.db.put(h,rlpnode)
else:
h = rlpnode
return h return h
def __lookup(self,node):
if len(node) < 32: return node
else: return self.db.get(node)
def __update_state(self,node,key,value): def __update_state(self,node,key,value):
if value != '': return self.__insert_state(node,key,value) if value != '': return self.__insert_state(node,key,value)
else: return self.__delete_state(node,key) else: return self.__delete_state(node,key)
@ -77,7 +84,7 @@ class Trie():
if not node: if not node:
newnode = [ hexarraykey_to_bin(key), value ] newnode = [ hexarraykey_to_bin(key), value ]
return self.__put(newnode) return self.__put(newnode)
curnode = rlp.decode(self.db.get(node)) curnode = rlp.decode(self.__lookup(node))
if self.debug: print 'icn', curnode if self.debug: print 'icn', curnode
if not curnode: if not curnode:
raise Exception("node not found in database") raise Exception("node not found in database")
@ -114,7 +121,7 @@ class Trie():
if len(key) == 0 or not node: if len(key) == 0 or not node:
return '' return ''
else: else:
curnode = rlp.decode(self.db.get(node)) curnode = rlp.decode(self.__lookup(node))
if not curnode: if not curnode:
raise Exception("node not found in database") raise Exception("node not found in database")
if self.debug: print 'dcn', curnode if self.debug: print 'dcn', curnode
@ -125,7 +132,7 @@ class Trie():
return '' return ''
elif key[:len(k2)] == k2: elif key[:len(k2)] == k2:
newhash = self.__delete_state(v2,key[len(k2):]) newhash = self.__delete_state(v2,key[len(k2):])
childnode = rlp.decode(self.db.get(newhash)) childnode = rlp.decode(self.__lookup(newhash))
if len(childnode) == 2: if len(childnode) == 2:
newkey = k2 + bin_to_hexarraykey(childnode[0]) newkey = k2 + bin_to_hexarraykey(childnode[0])
newnode = [ hexarraykey_to_bin(newkey), childnode[1] ] newnode = [ hexarraykey_to_bin(newkey), childnode[1] ]
@ -144,7 +151,7 @@ class Trie():
if onlynode == 16: if onlynode == 16:
newnode2 = [ hexarraykey_to_bin([16]), newnode[onlynode] ] newnode2 = [ hexarraykey_to_bin([16]), newnode[onlynode] ]
elif onlynode >= 0: elif onlynode >= 0:
childnode = rlp.decode(self.db.get(newnode[onlynode])) childnode = rlp.decode(self.__lookup(newnode[onlynode]))
if not childnode: if not childnode:
raise Exception("?????") raise Exception("?????")
if len(childnode) == 17: if len(childnode) == 17:
@ -158,7 +165,7 @@ class Trie():
def __get_size(self,node): def __get_size(self,node):
if not node: return 0 if not node: return 0
curnode = self.db.get(node) curnode = self.__lookup(node)
if not curnode: if not curnode:
raise Exception("node not found in database") raise Exception("node not found in database")
if len(curnode) == 2: if len(curnode) == 2:
@ -174,7 +181,7 @@ class Trie():
def __to_dict(self,node): def __to_dict(self,node):
if not node: return {} if not node: return {}
curnode = rlp.decode(self.db.get(node)) curnode = rlp.decode(self.__lookup(node))
if not curnode: if not curnode:
raise Exception("node not found in database") raise Exception("node not found in database")
if len(curnode) == 2: if len(curnode) == 2: