def commit_state(self): """Commit account caches""" """Write the acount caches on the corresponding tries.""" changes = [] if len(self.journal) == 0: # log_state.trace('delta', changes=[]) return addresses = sorted(list(self.caches['all'].keys())) for addr in addresses: acct = self._get_acct(addr) # storage for field in ('balance', 'nonce', 'code', 'storage'): if addr in self.caches[field]: v = self.caches[field][addr] changes.append([field, addr, v]) setattr(acct, field, v) t = SecureTrie(Trie(self.db, acct.storage)) for k, v in self.caches.get(b'storage:' + addr, {}).items(): enckey = utils.zpad(utils.coerce_to_bytes(k), 32) val = rlp.encode(v) changes.append(['storage', addr, k, v]) if v: t.update(enckey, val) else: t.delete(enckey) acct.storage = t.root_hash self.state.update(addr, rlp.encode(acct)) log_state.trace('delta', changes=changes) self.reset_cache() self.db.put(b'validated:' + self.hash, '1')
def account_to_dict(self, address, with_storage_root=False, with_storage=True): """Serialize an account to a dictionary with human readable entries. :param address: the 20 bytes account address :param with_storage_root: include the account's storage root :param with_storage: include the whole account's storage """ if len(address) == 40: address = decode_hex(address) assert len(address) == 20 if with_storage_root: # if there are uncommited account changes the current storage root # is meaningless assert len(self.journal) == 0 med_dict = {} account = self._get_acct(address) for field in ('balance', 'nonce'): value = self.caches[field].get(address, getattr(account, field)) med_dict[field] = to_string(value) code = self.caches['code'].get(address, account.code) med_dict['code'] = b'0x' + encode_hex(code) storage_trie = SecureTrie(Trie(self.db, account.storage)) if with_storage_root: med_dict['storage_root'] = encode_hex(storage_trie.get_root_hash()) if with_storage: med_dict['storage'] = {} d = storage_trie.to_dict() subcache = self.caches.get(b'storage:' + address, {}) subkeys = [utils.zpad(utils.coerce_to_bytes(kk), 32) for kk in list(subcache.keys())] for k in list(d.keys()) + subkeys: v = d.get(k, None) v2 = subcache.get(utils.big_endian_to_int(k), None) hexkey = b'0x' + encode_hex(utils.zunpad(k)) if v2 is not None: if v2 != 0: med_dict['storage'][hexkey] = \ b'0x' + encode_hex(utils.int_to_big_endian(v2)) elif v is not None: med_dict['storage'][hexkey] = b'0x' + encode_hex(rlp.decode(v)) return med_dict
def get_storage_data(self, address, index): """Get a specific item in the storage of an account. :param address: the address of the account (binary or hex string) :param index: the index of the requested item in the storage """ if len(address) == 40: address = decode_hex(address) assert len(address) == 20 CACHE_KEY = b'storage:' + address if CACHE_KEY in self.caches: if index in self.caches[CACHE_KEY]: return self.caches[CACHE_KEY][index] key = utils.zpad(utils.coerce_to_bytes(index), 32) storage = self.get_storage(address).get(key) if storage: return rlp.decode(storage, big_endian_int) else: return 0