From a3af9af23ede211b9fe933fc437074393ce36dfc Mon Sep 17 00:00:00 2001 From: Vitalik Buterin Date: Wed, 25 Dec 2013 08:26:43 -0500 Subject: [PATCH] Redid RLP --- blocks.py | 17 ++++----- processblock.py | 27 +++++++------- rlp.py | 95 +++++++++++++++++++++++++++++++------------------ 3 files changed, 83 insertions(+), 56 deletions(-) diff --git a/blocks.py b/blocks.py index de1df78633..097b71cb0f 100644 --- a/blocks.py +++ b/blocks.py @@ -13,10 +13,10 @@ class Block(): if re.match('^[0-9a-fA-F]*$',data): data = data.decode('hex') - header, transaction_list, self.siblings = rlp.decode(data) + header, transaction_list, self.uncles = rlp.decode(data) [ number, self.prevhash, - self.siblings_root, + self.uncles_root, self.coinbase, state_root, self.transactions_root, @@ -36,11 +36,8 @@ class Block(): raise Exception("State Merkle root not found in database!") if bin_sha256(transaction_list) != transactions_root: raise Exception("Transaction list root hash does not match!") - if bin_sha256(sibling_list) != sibling_root: - raise Exception("Transaction list root hash does not match!") - for sibling in self.siblings: - if sibling[0] != self.prevhash: - raise Exception("Sibling's parent is not my parent!") + if bin_sha256(uncle_list) != uncle_root: + raise Exception("Uncle root hash does not match!") # TODO: check POW def send(self,tx): @@ -65,7 +62,7 @@ class Block(): self.state.update(tx.to,receiver_state) # Create a new contract else: - addr = tx.hash()[:20] + addr = tx.hash()[-20:] contract = block.get_contract(addr) if contract.root != '': return False for i in range(len(tx.data)): @@ -122,7 +119,7 @@ class Block(): txlist = [x.serialize() for x in self.transactions] header = [ encode(self.number,256), self.prevhash, - bin_sha256(rlp.encode(self.siblings)), + bin_sha256(rlp.encode(self.uncles)), self.coinbase, self.state.root, bin_sha256(rlp.encode(self.txlist)), @@ -130,7 +127,7 @@ class Block(): encode(self.timestamp,256), encode(self.nonce,256), self.extra ] - return rlp.encode([header, txlist, self.siblings ]) + return rlp.encode([header, txlist, self.uncles ]) def hash(self): return bin_sha256(self.serialize()) diff --git a/processblock.py b/processblock.py index 6f3eff24f1..3bbfa61636 100644 --- a/processblock.py +++ b/processblock.py @@ -44,12 +44,13 @@ scriptcode_map = { } params = { - 'stepfee': 2**60 * 4096, - 'txfee': 2**60 * 524288, - 'memoryfee': 2**60 * 262144, - 'datafee': 2**60 * 16384, - 'cryptofee': 2**60 * 65536, - 'extrofee': 2**60 * 65536, + 'stepfee': 2**64 / 64, + 'txfee': 2**64, + 'newcontractfee': 2**64, + 'memoryfee': 2**64 / 4, + 'datafee': 2**64 / 16, + 'cryptofee': 2**64 / 16, + 'extrofee': 2**64 / 16, 'blocktime': 60, 'period_1_reward': 2**80 * 1024, 'period_1_duration': 57600, @@ -65,9 +66,11 @@ def eval(block,transactions,timestamp,coinbase): # Process all transactions while len(transactions) > 0: tx = transactions.pop(0) - fee = params['txfee'] + len(tx.data) * params['datafee'] + fee = 0 if tx.to = '\x00'*20: - fee += len(tx.data) * params['memoryfee'] + fee += params['newcontractfee'] + len(tx.data) * params['memoryfee'] + else: + fee += params['txfee'] # Insufficient fee, do nothing if fee > tx.fee: continue # Too much data, do nothing @@ -90,10 +93,10 @@ def eval(block,transactions,timestamp,coinbase): else: reward = params['period_4_reward'] miner_balance += reward - for sibling in block.siblings: - sib_miner_state = rlp_decode(self.state.get(sibling[3])) + for uncle in block.uncles: + sib_miner_state = rlp_decode(self.state.get(uncle[3])) sib_miner_state[1] = encode(decode(sib_miner_state[1],256)+reward*7/8,256) - self.state.update(sibling[3],sib_miner_state) + self.state.update(uncle[3],sib_miner_state) miner_balance += reward/8 miner_state[1] = encode(miner_balance,256) self.state.update(self.coinbase,miner_state) @@ -108,7 +111,7 @@ def eval(block,transactions,timestamp,coinbase): block.prevhash = h block.coinbase = coinbase block.transactions = [] - block.siblings = [] + block.uncles = [] return block def eval_contract(block,transaction_list,tx): diff --git a/rlp.py b/rlp.py index 7bc5db2668..03272b6c7c 100644 --- a/rlp.py +++ b/rlp.py @@ -16,42 +16,69 @@ def from_binary(b): if len(b) == 0: return 0 else: return from_binary(b[:-1]) * 256 + ord(b[-1]) -def num_to_var_int(n): - if n < 253: s = [n] - elif n < 2**16: s = [253] + list(to_binary_array(n,2)) - elif n < 2**32: s = [254] + list(to_binary_array(n,4)) - elif n < 2**64: s = [255] + list(to_binary_array(n,8)) - else: raise Exception("number too big") - return ''.join([chr(x) for x in s]) - -def __decode(s): - if s == '': return None - o = [] - index = [0] - def read_var_int(): - si = ord(s[index[0]]) - index[0] += 1 - if si < 253: return si - elif si == 253: read = 2 - elif si == 254: read = 4 - elif si == 255: read = 8 - index[0] += read - return from_binary(s[index[0]-read:index[0]]) - while index[0] < len(s): - tp = s[index[0]] - index[0] += 1 - L = read_var_int() - item = s[index[0]:index[0]+L] - if tp == '\x00': o.append(item) - else: o.append(__decode(item)) - index[0] += L - return o +def __decode(s,pos=0): + if s == '': + return (None, 0) + else: + fchar = ord(s[pos]) + if fchar <= 24: + return (ord(s[pos]), pos+1) + elif fchar < 56: + b = ord(s[pos]) - 24 + return (from_binary(s[pos+1:pos+1+b]), pos+1+b) + elif fchar < 64: + b = ord(s[pos]) - 55 + b2 = from_binary(s[pos+1:pos+1+b]) + return (from_binary(s[pos+1+b:pos+1+b+b2]), pos+1+b+b2) + elif fchar < 120: + b = ord(s[pos]) - 64 + return (s[pos+1:pos+1+b], pos+1+b) + elif fchar < 128: + b = ord(s[pos]) - 119 + b2 = from_binary(s[pos+1:pos+1+b]) + return (s[pos+1+b:pos+1+b+b2], pos+1+b+b2) + elif fchar < 184: + b = ord(s[pos]) - 128 + o, pos = [], pos+1 + for i in range(b): + obj, pos = __decode(s,pos) + o.append(obj) + return (o,pos) + elif fchar < 192: + b = ord(s[pos]) - 183 + b2 = from_binary(s[pos+1:pos+1+b]) + o, pos = [], pos+1+b + for i in range(b): + obj, pos = __decode(s,pos) + o.append(obj) + return (o,pos) + else: + raise Exception("byte not supported: "+fchar) def decode(s): return __decode(s)[0] def encode(s): - if isinstance(s,(int,long)): return encode(to_binary(s)) - if isinstance(s,str): return '\x00'+num_to_var_int(len(s))+s + if isinstance(s,(int,long)): + if s <= 24: + return chr(s) + elif s <= 2**256: + b = to_binary(s) + return chr(len(b) + 24) + b + else: + b = to_binary(s) + b2 = to_binary(len(b)) + return chr(len(b2) + 55) + b2 + b + elif isinstance(s,str): + if len(s) < 56: + return chr(len(s) + 64) + s + else: + b2 = to_binary(len(s)) + return chr(len(b2) + 119) + b2 + s + elif isinstance(s,list): + if len(s) < 56: + return chr(len(s) + 128) + ''.join([encode(x) for x in s]) + else: + b2 = to_binary(len(s)) + return chr(len(b2) + 183) + b2 + ''.join([encode(x) for x in s]) else: - x = ''.join([encode(x) for x in s]) - return '\x01'+num_to_var_int(len(x))+x + raise Exception("Encoding for "+s+" not yet implemented")