def to_dict(self): state = self.state.to_dict(True) nstate = {} for s in state: t = Trie(STATEDB_DIR, state[s][STORAGE_INDEX]) o = [0] * ACCT_RLP_LENGTH o[NONCE_INDEX] = decode_int(state[s][NONCE_INDEX]) o[BALANCE_INDEX] = decode_int(state[s][BALANCE_INDEX]) o[CODE_INDEX] = state[s][CODE_INDEX] td = t.to_dict(True) o[STORAGE_INDEX] = {decode_int(k): decode_int(td[k]) for k in td} nstate[s.encode('hex')] = o return { "number": self.number, "prevhash": self.prevhash, "uncles_root": self.uncles_root, "coinbase": self.coinbase, "state": nstate, "transactions_root": self.transactions_root, "difficulty": self.difficulty, "timestamp": self.timestamp, "extradata": self.extradata, "nonce": self.nonce }
def create_contract(block,tx,msg): oldroot = block.state.root senderstate = block.state.get(msg.sender) or ['','','',''] recvstate = ['','',sha3(msg.data),''] recvaddr = sha3(rlp.encode([msg.sender,senderstate[NONCE_INDEX]]))[12:] code = msg.data statedb.put(sha3(msg.data),msg.data) compustate = Compustate(gas=msg.gas) # Not enough vaue to send, instaquit if decode_int(senderstate[BALANCE_INDEX]) < msg.value: recvstate[2] = [] block.state.update(recvaddr,recvstate) return recvaddr, compustate.gas # Transfer value and update nonce senderstate[BALANCE_INDEX] = encode_int(decode_int(senderstate[BALANCE_INDEX])-msg.value) senderstate[NONCE_INDEX] = encode_int(decode_int(senderstate[NONCE_INDEX])+1) recvstate[BALANCE_INDEX] = encode_int(decode_int(senderstate[BALANCE_INDEX])+msg.value) block.state.update(msg.sender.decode('hex'),senderstate) block.state.update(recvaddr,recvstate) # Temporary pre-POC5: don't do the code/init thing return recvaddr, compustate.gas # Main loop while 1: o = apply_op(block,tx,msg,msg.data,compustate.op) if o is not None: if o == OUT_OF_GAS: block.state.root = oldroot return 0, 0 else: recvstate = block.state.get(recvaddr) recvstate[CODE_INDEX] = sha3(map(chr,o)) statedb.put(sha3(map(chr,o)),map(chr,o)) block.state.update(recvaddr,recvstate) return recvaddr, recvstate
def to_dict(self): state = self.state.to_dict(True) nstate = {} for s in state: t = Trie('statedb', state[s][STORAGE_INDEX]) o = [0] * ACCT_RLP_LENGTH o[NONCE_INDEX] = decode_int(state[s][NONCE_INDEX]) o[BALANCE_INDEX] = decode_int(state[s][BALANCE_INDEX]) o[CODE_INDEX] = state[s][CODE_INDEX] td = t.to_dict(True) o[STORAGE_INDEX] = {k: decode_int(td[k]) for k in td} nstate[s.encode('hex')] = o return { "number": self.number, "prevhash": self.prevhash, "uncles_root": self.uncles_root, "coinbase": self.coinbase, "state": nstate, "transactions_root": self.transactions_root, "difficulty": self.difficulty, "timestamp": self.timestamp, "extradata": self.extradata, "nonce": self.nonce }
def delta_index(self,address,index,value): if len(address) == 40: address = address.decode('hex') acct = self.state.get(address) or ['','','',''] if decode_int(acct[index]) + value < 0: return False acct[index] = encode_int(decode_int(acct[index])+value) self.state.update(address,acct) return True
def account_to_dict(self, address): med_dict = {} for i, val in enumerate(self.get_acct(address)): med_dict[acct_structure[i][0]] = val strie = trie.Trie(utils.get_db_path(), med_dict['storage']).to_dict() med_dict['storage'] = {utils.decode_int(k): utils.decode_int(v) for k, v in strie.iteritems()} return med_dict
def delta_index(self, address, index, value): if len(address) == 40: address = address.decode('hex') acct = self.state.get(address) or ['', '', '', ''] if decode_int(acct[index]) + value < 0: return False acct[index] = encode_int(decode_int(acct[index]) + value) self.state.update(address, acct) return True
def account_to_dict(self, address): med_dict = {} for i, val in enumerate(self.get_acct(address)): med_dict[acct_structure[i][0]] = val strie = trie.Trie(utils.get_db_path(), med_dict['storage']).to_dict() med_dict['storage'] = { utils.decode_int(k): utils.decode_int(v) for k, v in strie.iteritems() } return med_dict
def apply_tx(block,tx): fee = tx.gasprice * tx.startgas addrstate = block.state.get(tx.sender.decode('hex')) if not addrstate: raise Exception("Sending from a not-yet-existent account!") if decode_int(addrstate[NONCE_INDEX]) != tx.nonce: print decode_int(addrstate[NONCE_INDEX]), tx.nonce raise Exception("Invalid nonce!") if decode_int(addrstate[BALANCE_INDEX]) < fee: raise Exception("Not enough in account to pay fee!") addrstate[NONCE_INDEX] = encode_int(decode_int(addrstate[NONCE_INDEX])+1) addrstate[BALANCE_INDEX] = encode_int(decode_int(addrstate[BALANCE_INDEX])-fee) block.state.update(tx.sender.decode('hex'),addrstate) block.gas_consumed += fee medroot = block.state.root message_gas = tx.startgas - GTXDATA * len(tx.data) message = Message(tx.sender,tx.to,tx.value,message_gas,tx.data) if tx.to: s,g,d = apply_msg(block,tx,message) else: s,g = create_contract(block,tx,message) if not s: block.state.root = medroot minerstate = block.state.get(block.coinbase) minerstate[BALANCE_INDEX] = encode_int(decode_int(minerstate[BALANCE_INDEX])+fee) block.state.update(block.coinbase,minerstate) else: addrstate[BALANCE_INDEX] = encode_int(decode_int(addrstate[BALANCE_INDEX])+tx.gasprice * g) block.state.update(tx.sender.decode('hex'),addrstate) minerstate = block.state.get(block.coinbase.decode('hex')) or ['','','',''] minerstate[BALANCE_INDEX] = encode_int(decode_int(minerstate[BALANCE_INDEX])+(fee - g * tx.gasprice)) block.state.update(block.coinbase.decode('hex'),minerstate)
def _account_to_dict(self, acct): med_dict = {} for i, (name, typ, default) in enumerate(acct_structure): med_dict[name] = utils.decoders[typ](acct[i]) chash = med_dict['code'] strie = trie.Trie(utils.get_db_path(), med_dict['storage']).to_dict() med_dict['code'] = \ self.state.db.get(chash).encode('hex') if chash else '' med_dict['storage'] = { utils.decode_int(k): utils.decode_int(strie[k]) for k in strie } return med_dict
def account_to_dict(self, address): if len(address) == 40: address = address.decode('hex') acct = self.state.get(address) or ['', '', '', ''] chash = acct[CODE_INDEX] stdict = Trie(STATEDB_DIR, acct[STORAGE_INDEX]).to_dict(True) return { 'nonce': decode_int(acct[NONCE_INDEX]), 'balance': decode_int(acct[BALANCE_INDEX]), 'code': self.state.db.get(chash).encode('hex') if chash else '', 'storage': {decode_int(k): decode_int(stdict[k]) for k in stdict} }
def _delta_item(self, address, index, value): ''' add value to account item :param address: account address, can be binary or hex string :param index: item index :param value: can be positive or negative ''' if len(address) == 40: address = address.decode('hex') acct = self.state.get(address) or ['', '', '', ''] if decode_int(acct[index]) + value < 0: return False acct[index] = encode_int(decode_int(acct[index]) + value) self.state.update(address, acct) return True
def _delta_item(self, address, param, value): ''' add value to account item :param address: account address, can be binary or hex string :param param: parameter to increase/decrease :param value: can be positive or negative ''' if len(address) == 40: address = address.decode('hex') acct = self.state.get(address) or ['', '', '', ''] index = acct_structure_rev[param][0] if utils.decode_int(acct[index]) + value < 0: return False acct[index] = utils.encode_int(utils.decode_int(acct[index]) + value) self.state.update(address, acct) return True
def decode_datalist(arr): if isinstance(arr, list): arr = ''.join(map(chr, arr)) o = [] for i in range(0, len(arr), 32): o.append(decode_int(arr[i:i + 32])) return o
def remote_blocks_received_handler(sender, block_lst, peer, **kwargs): logger.debug("received %d remote blocks", len(block_lst)) old_head = chain_manager.head # assuming chain order w/ newest block first for block_data in reversed(block_lst): try: block = blocks.Block.deserialize(rlp.encode(block_data)) except blocks.UnknownParentException: # no way to ask peers for older parts of chain bhash = utils.sha3(rlp.encode(block_data)).encode('hex')[:4] phash = block_data[0][0].encode('hex')[:4] number = utils.decode_int(block_data[0][6]) if phash == blocks.GENESIS_PREVHASH: logger.debug('Incompatible Genesis %r', block) peer.send_Disconnect(reason='Wrong genesis block') else: logger.debug( 'Block(#%d %s %s) with unknown parent, requesting ...', number, bhash, phash.encode('hex')[:4]) chain_manager.synchronize_blockchain() break if block.hash in chain_manager: logger.debug('Known %r', block) else: if block.has_parent(): # add block & set HEAD if it's longest chain success = chain_manager.add_block(block) if success: logger.debug('Added %r', block) else: logger.debug('Orphant %r', block) if chain_manager.head != old_head: chain_manager.synchronize_blockchain()
def to_dict(self, with_state=False, full_transactions=False, with_storage_roots=False): """ serializes the block with_state: include state for all accounts full_transactions: include serialized tx (hashes otherwise) """ b = {} for name, typ, default in block_structure: b[name] = utils.printers[typ](getattr(self, name)) txlist = [] for i in range(self.transaction_count): tx_rlp = self.transactions.get(rlp.encode(utils.encode_int(i))) tx, msr, gas = rlp.decode(tx_rlp) if full_transactions: txjson = transactions.Transaction.create(tx).to_dict() else: txjson = utils.sha3(rlp.descend(tx_rlp, 0)).encode('hex') # tx hash txlist.append({ "tx": txjson, "medstate": msr.encode('hex'), "gas": str(utils.decode_int(gas)) }) b["transactions"] = txlist if with_state: state_dump = {} for address, v in self.state.to_dict().iteritems(): state_dump[address.encode('hex')] = \ self.account_to_dict(address, with_storage_roots) b['state'] = state_dump return b
def get_transaction(self, txhash): "return (tx, block)" blockhash, tx_num_enc = rlp.decode(self.db.get(txhash)) blk = blocks.get_block(blockhash) num = utils.decode_int(tx_num_enc) tx_data, msr, gas = blk.get_transaction(num) return Transaction.create(tx_data), blk
def to_dict(self, with_state=False, full_transactions=False): """ serializes the block with_state: include state for all accounts full_transactions: include serialized tx (hashes otherwise) """ self.commit_state() b = {} for name, typ, default in block_structure: b[name] = utils.printers[typ](getattr(self, name)) txlist = [] for i in range(self.transaction_count): tx_rlp = self.transactions.get(rlp.encode(utils.encode_int(i))) tx, msr, gas = rlp.decode(tx_rlp) if full_transactions: txjson = transactions.Transaction.create(tx).to_dict() else: txjson = utils.sha3(rlp.descend(tx_rlp, 0)).encode('hex') # tx hash txlist.append({ "tx": txjson, "medstate": msr.encode('hex'), "gas": str(utils.decode_int(gas)) }) b["transactions"] = txlist if with_state: state_dump = {} for address, v in self.state.to_dict().iteritems(): state_dump[address.encode('hex')] = self.account_to_dict( address) b['state'] = state_dump return b
def remote_blocks_received_handler(sender, block_lst, peer, **kwargs): logger.debug("received %d remote blocks", len(block_lst)) old_head = chain_manager.head # assuming chain order w/ newest block first for block_data in reversed(block_lst): try: block = blocks.Block.deserialize(rlp.encode(block_data)) except blocks.UnknownParentException: # no way to ask peers for older parts of chain bhash = utils.sha3(rlp.encode(block_data)).encode('hex')[:4] phash = block_data[0][0].encode('hex')[:4] number = utils.decode_int(block_data[0][6]) logger.debug('Block(#%d %s %s) with unknown parent, requesting ...', number, bhash, phash.encode('hex')[:4]) chain_manager.synchronize_blockchain() break if block.hash in chain_manager: logger.debug('Known %r', block) else: if block.has_parent(): # add block & set HEAD if it's longest chain success = chain_manager.add_block(block) if success: logger.debug('Added %r', block) else: logger.debug('Orphant %r', block) if chain_manager.head != old_head: chain_manager.synchronize_blockchain()
def deserialize_child(self, rlpdata): """ deserialization w/ replaying transactions """ header_args, transaction_list, uncles = rlp.decode(rlpdata) assert len(header_args) == len(block_structure) kargs = dict(transaction_list=transaction_list, uncles=uncles) # Deserialize all properties for i, (name, typ, default) in enumerate(block_structure): kargs[name] = utils.decoders[typ](header_args[i]) block = Block.init_from_parent(self, kargs['coinbase'], extra_data=kargs['extra_data'], timestamp=kargs['timestamp'], uncles=uncles) # replay transactions for tx_lst_serialized, _state_root, _gas_used_encoded in \ transaction_list: tx = transactions.Transaction.create(tx_lst_serialized) # logger.debug('state:\n%s', utils.dump_state(block.state)) # logger.debug('applying %r', tx) success, output = processblock.apply_transaction(block, tx) #block.add_transaction_to_list(tx) # < this is done by processblock # logger.debug('state:\n%s', utils.dump_state(block.state)) logger.debug('d %s %s', _gas_used_encoded, block.gas_used) assert utils.decode_int(_gas_used_encoded) == block.gas_used, \ "Gas mismatch (ours %d, theirs %d) on block: %r" % \ (block.gas_used, _gas_used_encoded, block.to_dict(False, True, True)) assert _state_root == block.state.root_hash, \ "State root mismatch (ours %r theirs %r) on block: %r" % \ (block.state.root_hash.encode('hex'), _state_root.encode('hex'), block.to_dict(False, True, True)) block.finalize() block.uncles_hash = kargs['uncles_hash'] block.nonce = kargs['nonce'] block.min_gas_price = kargs['min_gas_price'] # checks assert block.prevhash == self.hash assert block.gas_used == kargs['gas_used'] assert block.gas_limit == kargs['gas_limit'] assert block.timestamp == kargs['timestamp'] assert block.difficulty == kargs['difficulty'] assert block.number == kargs['number'] assert block.extra_data == kargs['extra_data'] assert utils.sha3(rlp.encode(block.uncles)) == kargs['uncles_hash'] assert block.tx_list_root == kargs['tx_list_root'] assert block.state.root_hash == kargs['state_root'], ( block.state.root_hash, kargs['state_root']) return block
def verify_independent_transaction_spv_proof(proof): _, prevheader, header, index, nodes = rlp.decode(proof) index = utils.decode_int(index) pb = blocks.Block.deserialize_header(prevheader) b = blocks.Block.init_from_header(header) b.set_proof_mode(blocks.VERIFYING, nodes) if index != 0: _, pre_med, pre_gas = b.get_transaction(index - 1) else: pre_med, pre_gas = pb['state_root'], '' if utils.sha3(rlp.encode(prevheader)) != b.prevhash: return False b.state_root = pre_med b.gas_used = utils.decode_int(pre_gas) tx, post_med, post_gas = b.get_transaction(index) tx = transactions.Transaction.create(tx) o = verify_transaction_spv_proof(b, tx, nodes) return o and b.state_root == post_med and b.gas_used == utils.decode_int(post_gas)
def __init__(self, data=None): self.reward = 10**18 self.gas_consumed = 0 self.gaslimit = 1000000 # for now if not data: self.number = 0 self.prevhash = '' self.uncles_root = '' self.coinbase = '0' * 40 self.state = Trie('statedb') self.transactions_root = '' self.transactions = [] self.uncles = [] self.difficulty = 2**23 self.timestamp = 0 self.extradata = '' self.nonce = 0 return if re.match('^[0-9a-fA-F]*$', data): data = data.decode('hex') header, transaction_list, self.uncles = rlp.decode(data) self.number = decode_int(header[0]) self.prevhash = header[1] self.uncles_root = header[2] self.coinbase = header[3].encode('hex') self.state = Trie('statedb', header[4]) self.transactions_root = header[5] self.difficulty = decode_int(header[6]) self.timestamp = decode_int(header[7]) self.extradata = header[8] self.nonce = decode_int(header[9]) self.transactions = [Transaction(x) for x in transaction_list] # Verifications if self.state.root != '' and self.state.db.get(self.state.root) == '': raise Exception("State Merkle root not found in database!") if sha3(rlp.encode(transaction_list)) != self.transactions_root: raise Exception("Transaction list root hash does not match!") if sha3(rlp.encode(self.uncles)) != self.uncles_root: raise Exception("Uncle root hash does not match!")
def __init__(self, data=None): self.reward = 10 ** 18 self.gas_consumed = 0 self.gaslimit = 1000000 # for now if not data: self.number = 0 self.prevhash = '' self.uncles_root = '' self.coinbase = '0' * 40 self.state = Trie(get_db_path()) self.transactions_root = '' self.transactions = [] self.uncles = [] self.difficulty = 2 ** 23 self.timestamp = 0 self.extradata = '' self.nonce = 0 return if re.match('^[0-9a-fA-F]*$', data): data = data.decode('hex') header, transaction_list, self.uncles = rlp.decode(data) self.number = decode_int(header[0]) self.prevhash = header[1] self.uncles_root = header[2] self.coinbase = header[3].encode('hex') self.state = Trie(STATEDB_DIR, header[4]) self.transactions_root = header[5] self.difficulty = decode_int(header[6]) self.timestamp = decode_int(header[7]) self.extradata = header[8] self.nonce = decode_int(header[9]) self.transactions = [Transaction(x) for x in transaction_list] # Verifications if self.state.root != '' and self.state.db.get(self.state.root) == '': raise Exception("State Merkle root not found in database!") if sha3(rlp.encode(transaction_list)) != self.transactions_root: raise Exception("Transaction list root hash does not match!") if sha3(rlp.encode(self.uncles)) != self.uncles_root: raise Exception("Uncle root hash does not match!")
def parse(cls, data): if re.match('^[0-9a-fA-F]*$', data): data = data.decode('hex') o = rlp.decode(data) + ['', '', ''] tx = cls(decode_int(o[0]), decode_int(o[1]), decode_int(o[2]), decode_int(o[3]), o[4].encode('hex'), o[5], decode_int(o[6]), decode_int(o[7]), decode_int(o[8])) return tx
def deserialize_child(self, rlpdata): """ deserialization w/ replaying transactions """ header_args, transaction_list, uncles = rlp.decode(rlpdata) assert len(header_args) == len(block_structure) kargs = dict(transaction_list=transaction_list, uncles=uncles) # Deserialize all properties for i, (name, typ, default) in enumerate(block_structure): kargs[name] = utils.decoders[typ](header_args[i]) block = Block.init_from_parent(self, kargs['coinbase'], extra_data=kargs['extra_data'], timestamp=kargs['timestamp'], uncles=uncles) # replay transactions for tx_lst_serialized, _state_root, _gas_used_encoded in \ transaction_list: tx = transactions.Transaction.create(tx_lst_serialized) # logger.debug('state:\n%s', utils.dump_state(block.state)) # logger.debug('applying %r', tx) success, output = processblock.apply_transaction(block, tx) #block.add_transaction_to_list(tx) # < this is done by processblock # logger.debug('state:\n%s', utils.dump_state(block.state)) logger.debug('d %s %s', _gas_used_encoded, block.gas_used) assert utils.decode_int(_gas_used_encoded) == block.gas_used, \ "Gas mismatch (ours %d, theirs %d) on block: %r" % \ (block.gas_used, _gas_used_encoded, block.to_dict(False, True, True)) assert _state_root == block.state.root_hash, \ "State root mismatch (ours %r theirs %r) on block: %r" % \ (block.state.root_hash.encode('hex'), _state_root.encode('hex'), block.to_dict(False, True, True)) block.finalize() block.uncles_hash = kargs['uncles_hash'] block.nonce = kargs['nonce'] block.min_gas_price = kargs['min_gas_price'] # checks assert block.prevhash == self.hash assert block.gas_used == kargs['gas_used'] assert block.gas_limit == kargs['gas_limit'] assert block.timestamp == kargs['timestamp'] assert block.difficulty == kargs['difficulty'] assert block.number == kargs['number'] assert block.extra_data == kargs['extra_data'] assert utils.sha3(rlp.encode(block.uncles)) == kargs['uncles_hash'] assert block.tx_list_root == kargs['tx_list_root'] assert block.state.root_hash == kargs['state_root'], (block.state.root_hash, kargs['state_root']) return block
def verify_independent_transaction_spv_proof(proof): _, prevheader, header, index, nodes = rlp.decode(proof) index = utils.decode_int(index) pb = blocks.Block.deserialize_header(prevheader) b = blocks.Block.init_from_header(header) b.set_proof_mode(blocks.VERIFYING, nodes) if index != 0: _, pre_med, pre_gas = b.get_transaction(index - 1) else: pre_med, pre_gas = pb['state_root'], '' if utils.sha3(rlp.encode(prevheader)) != b.prevhash: return False b.state_root = pre_med b.gas_used = utils.decode_int(pre_gas) tx, post_med, post_gas = b.get_transaction(index) tx = transactions.Transaction.create(tx) o = verify_transaction_spv_proof(b, tx, nodes) return o and b.state_root == post_med and b.gas_used == utils.decode_int( post_gas)
def chain_difficulty(self): # calculate the summarized_difficulty (on the fly for now) if self.is_genesis(): return self.difficulty elif 'difficulty:' + self.hex_hash() in self.state.db: return utils.decode_int( self.state.db.get('difficulty:' + self.hex_hash())) else: o = self.difficulty + self.get_parent().chain_difficulty() self.state.db.put('difficulty:' + self.hex_hash(), utils.encode_int(o)) return o
def chain_difficulty(self): # calculate the summarized_difficulty (on the fly for now) if self.is_genesis(): return self.difficulty elif 'difficulty:'+self.hex_hash() in self.state.db: return utils.decode_int( self.state.db.get('difficulty:'+self.hex_hash())) else: o = self.difficulty + self.get_parent().chain_difficulty() self.state.db.put('difficulty:'+self.hex_hash(), utils.encode_int(o)) return o
def chain_difficulty(self): # calculate the summarized_difficulty if self.is_genesis(): return self.difficulty elif "difficulty:" + self.hex_hash() in self.state.db: return utils.decode_int(self.state.db.get("difficulty:" + self.hex_hash())) else: _idx, _typ, _ = block_structure_rev["difficulty"] o = self.difficulty + self.get_parent().chain_difficulty() o += sum([utils.decoders[_typ](u[_idx]) for u in self.uncles]) self.state.db.put("difficulty:" + self.hex_hash(), utils.encode_int(o)) return o
def to_dict(self): state = self.state.to_dict(True) nstate = {} for s in state: t = Trie('statedb',state[s][3]) nstate[s.encode('hex')] = [ decode_int(state[s][0]), decode_int(state[s][1]), state[s][2], t.to_dict(True) ] return { "number": self.number, "prevhash": self.prevhash, "uncles_root": self.uncles_root, "coinbase": self.coinbase, "state": nstate, "transactions_root": self.transactions_root, "difficulty": self.difficulty, "timestamp": self.timestamp, "extradata": self.extradata, "nonce": self.nonce }
def chain_difficulty(self): # calculate the summarized_difficulty if self.is_genesis(): return self.difficulty elif 'difficulty:' + self.hex_hash() in self.state.db: return utils.decode_int( self.state.db.get('difficulty:' + self.hex_hash())) else: _idx, _typ, _ = block_structure_rev['difficulty'] o = self.difficulty + self.get_parent().chain_difficulty() o += sum([self.decoders[_typ](u[_idx]) for u in self.uncles]) self.state.db.put('difficulty:' + self.hex_hash(), utils.encode_int(o)) return o
def apply_msg(block,tx,msg): oldroot = block.state.root senderstate = block.state.get(msg.sender) recvstate = block.state.get(msg.to) or ['','','',''] codehash = recvstate[CODE_INDEX] code = statedb.get(codehash) compustate = Compustate(gas=msg.gas) # Not enough value to send, instaquit if decode_int(senderstate[BALANCE_INDEX]) < msg.value: return 1, compustate.gas, [] # Transfer value senderstate[BALANCE_INDEX] = encode_int(decode_int(senderstate[BALANCE_INDEX]) - msg.value) recvstate[BALANCE_INDEX] = encode_int(decode_int(senderstate[BALANCE_INDEX]) + msg.value) block.state.update(msg.sender,senderstate) block.state.update(msg.to,recvstate) # Main loop while 1: o = apply_op(block,tx,msg,code,compustate,op) if o is not None: if o == OUT_OF_GAS: block.state.root = oldroot return 0, 0, [] else: return 1, compustate.gas, o
def verify_independent_transaction_spv_proof(db, proof): _, prevheader, header, index, nodes = rlp.decode(proof) index = utils.decode_int(index) pb = blocks.Block.deserialize_header(prevheader) b = blocks.Block.init_from_header(db, header) b.set_proof_mode(blocks.VERIFYING, nodes) if index != 0: pre_med, pre_gas, _, _ = b.get_receipt(index - 1) else: pre_med, pre_gas = pb['state_root'], '' if utils.sha3(rlp.encode(prevheader)) != b.prevhash: return False b.state_root = pre_med b.gas_used = utils.decode_int(pre_gas) tx = b.get_transaction(index) post_med, post_gas, bloom, logs = b.get_receipt(index) tx = transactions.Transaction.create(tx) o = verify_transaction_spv_proof(b, tx, nodes) if b.state_root == post_med: if b.gas_used == utils.decode_int(post_gas): if [x.serialize() for x in b.logs] == logs: if b.mk_log_bloom() == bloom: return o return False
def deserialize_child(self, rlpdata): """ deserialization w/ replaying transactions """ header_args, transaction_list, uncles = rlp.decode(rlpdata) assert len(header_args) == len(block_structure) kargs = dict(transaction_list=transaction_list, uncles=uncles) # Deserialize all properties for i, (name, typ, default) in enumerate(block_structure): kargs[name] = utils.decoders[typ](header_args[i]) block = Block.init_from_parent( self, kargs["coinbase"], extra_data=kargs["extra_data"], timestamp=kargs["timestamp"], uncles=uncles ) # replay transactions for tx_lst_serialized, _state_root, _gas_used_encoded in transaction_list: tx = transactions.Transaction.create(tx_lst_serialized) # logger.debug('state:\n%s', utils.dump_state(block.state)) # logger.debug('applying %r', tx) success, output = processblock.apply_transaction(block, tx) # block.add_transaction_to_list(tx) # < this is done by processblock # logger.debug('state:\n%s', utils.dump_state(block.state)) logger.debug("d %s %s", _gas_used_encoded, block.gas_used) assert utils.decode_int(_gas_used_encoded) == block.gas_used assert _state_root == block.state.root_hash block.finalize() block.uncles_hash = kargs["uncles_hash"] block.nonce = kargs["nonce"] block.min_gas_price = kargs["min_gas_price"] # checks assert block.prevhash == self.hash assert block.gas_used == kargs["gas_used"] assert block.gas_limit == kargs["gas_limit"] assert block.timestamp == kargs["timestamp"] assert block.difficulty == kargs["difficulty"] assert block.number == kargs["number"] assert block.extra_data == kargs["extra_data"] assert utils.sha3(rlp.encode(block.uncles)) == kargs["uncles_hash"] assert block.tx_list_root == kargs["tx_list_root"] assert block.state.root_hash == kargs["state_root"], (block.state.root_hash, kargs["state_root"]) return block
def parse(cls, data): if re.match('^[0-9a-fA-F]*$', data): data = data.decode('hex') o = rlp.decode(data) + ['','',''] tx = cls(decode_int(o[0]), decode_int(o[1]), decode_int(o[2]), decode_int(o[3]), o[4].encode('hex'), o[5], decode_int(o[6]), decode_int(o[7]), decode_int(o[8])) return tx
def to_dict(self, with_state=False, full_transactions=False, with_storage_roots=False, with_uncles=False): """ serializes the block with_state: include state for all accounts full_transactions: include serialized tx (hashes otherwise) with_uncles: include uncle hashes """ b = {} for name, typ, default in block_structure: b[name] = utils.printers[typ](getattr(self, name)) txlist = [] for i in range(self.transaction_count): tx_rlp = self.transactions.get(rlp.encode(utils.encode_int(i))) tx = rlp.decode(tx_rlp) receipt_rlp = self.receipts.get(rlp.encode(utils.encode_int(i))) msr, gas, mybloom, mylogs = rlp.decode(receipt_rlp) if full_transactions: txjson = transactions.Transaction.create(tx).to_dict() else: # tx hash txjson = utils.sha3(rlp.descend(tx_rlp, 0)).encode('hex') txlist.append({ "tx": txjson, "medstate": msr.encode('hex'), "gas": str(utils.decode_int(gas)), "logs": mylogs, "bloom": mybloom.encode('hex') }) b["transactions"] = txlist if with_state: state_dump = {} for address, v in self.state.to_dict().iteritems(): state_dump[address.encode('hex')] = \ self.account_to_dict(address, with_storage_roots) b['state'] = state_dump if with_uncles: b['uncles'] = [ utils.sha3(rlp.encode(u)).encode('hex') for u in self.uncles ] return b
def deserialize_child(self, rlpdata): """ deserialization w/ replaying transactions """ header_args, transaction_list, uncles = rlp.decode(rlpdata) assert len(header_args) == len(block_structure) kargs = dict(transaction_list=transaction_list, uncles=uncles) # Deserialize all properties for i, (name, typ, default) in enumerate(block_structure): kargs[name] = utils.decoders[typ](header_args[i]) block = Block.init_from_parent(self, kargs['coinbase'], extra_data=kargs['extra_data'], timestamp=kargs['timestamp']) # replay transactions for tx_lst_serialized, _state_root, _gas_used_encoded in transaction_list: tx = transactions.Transaction.create(tx_lst_serialized) success, output = processblock.apply_transaction(block, tx) block.add_transaction_to_list(tx) assert utils.decode_int(_gas_used_encoded) == block.gas_used assert _state_root == block.state.root_hash block.finalize() block.uncles_hash = kargs['uncles_hash'] block.nonce = kargs['nonce'] block.min_gas_price = kargs['min_gas_price'] # checks assert block.prevhash == self.hash assert block.gas_used == kargs['gas_used'] assert block.gas_limit == kargs['gas_limit'] assert block.timestamp == kargs['timestamp'] assert block.difficulty == kargs['difficulty'] assert block.number == kargs['number'] assert block.extra_data == kargs['extra_data'] assert utils.sha3(rlp.encode(block.uncles)) == kargs['uncles_hash'] assert block.tx_list_root == kargs['tx_list_root'] assert block.state.root_hash == kargs['state_root'] return block
def parse(cls, data): if re.match('^[0-9a-fA-F]*$', data): data = data.decode('hex') o = rlp.decode(data) tx = cls(decode_int(o[0]), decode_int(o[1]), decode_int(o[2]), decode_int(o[3]), o[4].encode('hex'), o[5], decode_int(o[6]), decode_int(o[7]), decode_int(o[8])) rawhash = sha3(rlp.encode(tx.serialize(False))) pub = encode_pubkey( ecdsa_raw_recover(rawhash, (tx.v, tx.r, tx.s)), 'bin') tx.sender = sha3(pub[1:])[-20:].encode('hex') return tx
def to_dict(self): b = {} for name, typ, default in block_structure: b[name] = getattr(self, name) for key in ["nonce", "state_root", "uncles_hash", "prevhash"]: b[key] = b[key].encode("hex") b["state"] = {} for address, v in self.state.to_dict().iteritems(): b["state"][address.encode('hex')] = self.account_to_dict(address) txlist = [] for i in range(self.transaction_count): td = self.transactions.get(utils.encode_int(i)) tx, msr, gas = map(lambda i: rlp.descend(td, i), range(3)) txjson = transactions.Transaction.deserialize(tx).to_dict() txlist.append({ "tx": txjson, "medstate": msr, "gas": utils.decode_int(gas) }) b["transactions"] = txlist return b
def to_dict(self): self.commit_state() b = {} for name, typ, default in block_structure: b[name] = utils.printers[typ](getattr(self, name)) b["state"] = {} for address, v in self.state.to_dict().iteritems(): b["state"][address.encode('hex')] = self.account_to_dict(address) txlist = [] for i in range(self.transaction_count): td = self.transactions.get(rlp.encode(utils.encode_int(i))) tx = rlp.descend(td, 0) msr = rlp.descend_to_val(td, 1) gas = rlp.descend_to_val(td, 2) txjson = transactions.Transaction.deserialize(tx).to_dict() txlist.append({ "tx": txjson, "medstate": msr.encode('hex'), "gas": str(utils.decode_int(gas)) }) b["transactions"] = txlist return b
def get_storage_data(self, address, index): t = self.get_storage(address) val = t.get(utils.coerce_to_bytes(index)) return utils.decode_int(val) if val else 0
def get_nonce(self,address): return decode_int(self.get_index(address,NONCE_INDEX))
def get_balance(self,address): return decode_int(self.get_index(address,BALANCE_INDEX))
def get_balance(self, address): return decode_int(self.get_index(address, BALANCE_INDEX))
def get_nonce(self, address): return decode_int(self.get_index(address, NONCE_INDEX))
def apply_op(block, tx, msg, code, compustate): op, in_args, out_args = get_op_data(code, compustate.pc) # empty stack error if in_args > len(compustate.stack): return [] # out of gas error fee = calcfee(block, tx, msg, compustate, op) if fee > compustate.gas: if debug: print "Out of gas", compustate.gas, "need", fee print op, list(reversed(compustate.stack)) return OUT_OF_GAS stackargs = [] for i in range(in_args): stackargs.append(compustate.stack.pop()) if debug: if op[:4] == 'PUSH': start, n = compustate.pc + 1, int(op[4:]) print op, decode_int(code[start:start + n]) else: print op, ' '.join(map(str, stackargs)) # Apply operation oldgas = compustate.gas oldpc = compustate.pc compustate.gas -= fee compustate.pc += 1 stk = compustate.stack mem = compustate.memory if op == 'STOP': return [] elif op == 'ADD': stk.append((stackargs[0] + stackargs[1]) % 2**256) elif op == 'SUB': stk.append((stackargs[0] - stackargs[1]) % 2**256) elif op == 'MUL': stk.append((stackargs[0] * stackargs[1]) % 2**256) elif op == 'DIV': if stackargs[1] == 0: return [] stk.append(stackargs[0] / stackargs[1]) elif op == 'MOD': if stackargs[1] == 0: return [] stk.append(stackargs[0] % stackargs[1]) elif op == 'SDIV': if stackargs[1] == 0: return [] if stackargs[0] >= 2**255: stackargs[0] -= 2**256 if stackargs[1] >= 2**255: stackargs[1] -= 2**256 stk.append((stackargs[0] / stackargs[1]) % 2**256) elif op == 'SMOD': if stackargs[1] == 0: return [] if stackargs[0] >= 2**255: stackargs[0] -= 2**256 if stackargs[1] >= 2**255: stackargs[1] -= 2**256 stk.append((stackargs[0] % stackargs[1]) % 2**256) elif op == 'EXP': stk.append(pow(stackargs[0], stackargs[1], 2**256)) elif op == 'NEG': stk.append(2**256 - stackargs[0]) elif op == 'LT': stk.append(1 if stackargs[0] < stackargs[1] else 0) elif op == 'GT': stk.append(1 if stackargs[0] > stackargs[1] else 0) elif op == 'EQ': stk.append(1 if stackargs[0] == stackargs[1] else 0) elif op == 'NOT': stk.append(0 if stackargs[0] else 1) elif op == 'AND': stk.append(stackargs[0] & stackargs[1]) elif op == 'OR': stk.append(stackargs[0] | stackargs[1]) elif op == 'XOR': stk.append(stackargs[0] ^ stackargs[1]) elif op == 'BYTE': if stackargs[0] >= 32: stk.append(0) else: stk.append((stackargs[1] / 256**stackargs[0]) % 256) elif op == 'SHA3': if len(mem) < stackargs[0] + stackargs[1]: mem.extend([0] * (stackargs[0] + stackargs[1] - len(mem))) data = ''.join(map(chr, mem[stackargs[0]:stackargs[0] + stackargs[1]])) stk.append(decode(sha3(data), 256)) elif op == 'ADDRESS': stk.append(msg.to) elif op == 'BALANCE': stk.append(block.get_balance(msg.to)) elif op == 'ORIGIN': stk.append(tx.sender) elif op == 'CALLER': stk.append(utils.coerce_to_int(msg.sender)) elif op == 'CALLVALUE': stk.append(msg.value) elif op == 'CALLDATALOAD': if stackargs[0] >= len(msg.data): stk.append(0) else: dat = msg.data[stackargs[0]:stackargs[0] + 32] stk.append(decode_int(dat + '\x00' * (32 - len(dat)))) elif op == 'CALLDATASIZE': stk.append(len(msg.data)) elif op == 'GASPRICE': stk.append(tx.gasprice) elif op == 'PREVHASH': stk.append(decode_int(block.prevhash)) elif op == 'COINBASE': stk.append(decode_int(block.coinbase.decode('hex'))) elif op == 'TIMESTAMP': stk.append(block.timestamp) elif op == 'NUMBER': stk.append(block.number) elif op == 'DIFFICULTY': stk.append(block.difficulty) elif op == 'GASLIMIT': stk.append(block.gaslimit) elif op == 'POP': pass elif op == 'DUP': stk.append(stackargs[0]) stk.append(stackargs[0]) elif op == 'SWAP': stk.append(stackargs[0]) stk.append(stackargs[1]) elif op == 'MLOAD': if len(mem) < stackargs[0] + 32: mem.extend([0] * (stackargs[0] + 32 - len(mem))) data = ''.join(map(chr, mem[stackargs[0]:stackargs[0] + 32])) stk.append(decode_int(data)) elif op == 'MSTORE': if len(mem) < stackargs[0] + 32: mem.extend([0] * (stackargs[0] + 32 - len(mem))) v = stackargs[1] for i in range(31, -1, -1): mem[stackargs[0] + i] = v % 256 v /= 256 elif op == 'MSTORE8': if len(mem) < stackargs[0] + 1: mem.extend([0] * (stackargs[0] + 1 - len(mem))) mem[stackargs[0]] = stackargs[1] % 256 elif op == 'SLOAD': stk.append(block.get_storage_data(msg.to, stackargs[0])) elif op == 'SSTORE': block.set_storage_data(msg.to, stackargs[0], stackargs[1]) elif op == 'JUMP': compustate.pc = stackargs[0] elif op == 'JUMPI': if stackargs[1]: compustate.pc = stackargs[0] elif op == 'PC': stk.append(compustate.pc) elif op == 'MSIZE': stk.append(len(mem)) elif op == 'GAS': stk.append(oldgas) elif op[:4] == 'PUSH': pushnum = int(op[4:]) compustate.pc = oldpc + 1 + pushnum dat = code[oldpc + 1:oldpc + 1 + pushnum] stk.append(decode_int(dat)) elif op == 'CREATE': if len(mem) < stackargs[2] + stackargs[3]: mem.extend([0] * (stackargs[2] + stackargs[3] - len(mem))) value = stackargs[0] gas = stackargs[1] data = ''.join(map(chr, mem[stackargs[2]:stackargs[2] + stackargs[3]])) if debug: print "Sub-contract:", msg.to, value, gas, data create_contract(block, tx, Message(msg.to, '', value, gas, data)) elif op == 'CALL': if len(mem) < stackargs[3] + stackargs[4]: mem.extend([0] * (stackargs[3] + stackargs[4] - len(mem))) if len(mem) < stackargs[5] + stackargs[6]: mem.extend([0] * (stackargs[5] + stackargs[6] - len(mem))) to = encode_int(stackargs[0]) to = (('\x00' * (32 - len(to))) + to)[12:] value = stackargs[1] gas = stackargs[2] data = ''.join(map(chr, mem[stackargs[3]:stackargs[3] + stackargs[4]])) if debug: print "Sub-call:", utils.coerce_addr_to_hex( msg.to), utils.coerce_addr_to_hex(to), value, gas, data result, gas, data = apply_msg(block, tx, Message(msg.to, to, value, gas, data)) if debug: print "Output of sub-call:", result, data, "length", len( data), "expected", stackargs[6] for i in range(stackargs[6]): mem[stackargs[5] + i] = 0 if result == 0: stk.append(0) else: stk.append(1) compustate.gas += gas for i in range(len(data)): mem[stackargs[5] + i] = data[i] elif op == 'RETURN': if len(mem) < stackargs[0] + stackargs[1]: mem.extend([0] * (stackargs[0] + stackargs[1] - len(mem))) return mem[stackargs[0]:stackargs[0] + stackargs[1]] elif op == 'SUICIDE': to = encode_int(stackhash[0]) to = (('\x00' * (32 - len(to))) + to)[12:] block.delta_balance(to, block.get_balance(msg.to)) block.state.update(msg.to, '') return []
def get_storage_data(self, address, index): t = self.get_storage(address) return decode_int(t.get(utils.coerce_to_bytes(index)))