def state_from_genesis_declaration(genesis_data, env, block=None, allow_empties=False): if block: assert isinstance(block, Block) else: block = block_from_genesis_declaration(genesis_data, env) state = State(env=env) for addr, data in genesis_data["alloc"].items(): addr = normalize_address(addr) assert len(addr) == 20 if 'wei' in data: state.set_balance(addr, parse_as_int(data['wei'])) if 'balance' in data: state.set_balance(addr, parse_as_int(data['balance'])) if 'code' in data: state.set_code(addr, parse_as_bin(data['code'])) if 'nonce' in data: state.set_nonce(addr, parse_as_int(data['nonce'])) if 'storage' in data: for k, v in data['storage'].items(): state.set_storage_data(addr, big_endian_to_int(parse_as_bin(k)), big_endian_to_int(parse_as_bin(v))) get_consensus_strategy(state.config).initialize(state, block) state.commit(allow_empties=allow_empties) print('deleting %d' % len(state.deletes)) rdb = RefcountDB(state.db) for delete in state.deletes: rdb.delete(delete) block.header.state_root = state.trie.root_hash state.prev_headers=[block.header] return state
def dict_to_prev_header(h): return FakeHeader(hash=parse_as_bin(h['hash']), number=parse_as_int(h['number']), timestamp=parse_as_int(h['timestamp']), difficulty=parse_as_int(h['difficulty']), gas_used=parse_as_int(h.get('gas_used', '0')), gas_limit=parse_as_int(h['gas_limit']), uncles_hash=parse_as_bin(h.get('uncles_hash', '0x' + encode_hex(BLANK_UNCLES_HASH))))
def block_from_genesis_declaration(genesis_data, env): h = BlockHeader(nonce=parse_as_bin(genesis_data["nonce"]), difficulty=parse_as_int(genesis_data["difficulty"]), mixhash=parse_as_bin(genesis_data.get("mixhash", genesis_data.get("mixHash", "0"*64))), coinbase=parse_as_bin(genesis_data["coinbase"]), bloom=parse_as_int(genesis_data.get("bloom", "0")), timestamp=parse_as_int(genesis_data["timestamp"]), prevhash=parse_as_bin(genesis_data["parentHash"]), extra_data=parse_as_bin(genesis_data["extraData"]), gas_used=parse_as_int(genesis_data.get("gasUsed", "0")), gas_limit=parse_as_int(genesis_data["gasLimit"])) return Block(h, [], [])
def mk_basic_state(alloc, header=None, env=None, executing_on_head=False): env = env or Env() state = State(env=env, executing_on_head=executing_on_head) if not header: header = { "number": 0, "gas_limit": env.config['BLOCK_GAS_LIMIT'], "gas_used": 0, "timestamp": 1467446877, "difficulty": 1, "uncles_hash": '0x' + encode_hex(BLANK_UNCLES_HASH) } h = BlockHeader(number=parse_as_int(header['number']), timestamp=parse_as_int(header['timestamp']), difficulty=parse_as_int(header['difficulty']), gas_limit=parse_as_int(header['gas_limit']), uncles_hash=parse_as_bin(header['uncles_hash'])) state.prev_headers = [h] for addr, data in alloc.items(): addr = normalize_address(addr) assert len(addr) == 20 if 'wei' in data: state.set_balance(addr, parse_as_int(data['wei'])) if 'balance' in data: state.set_balance(addr, parse_as_int(data['balance'])) if 'code' in data: state.set_code(addr, parse_as_bin(data['code'])) if 'nonce' in data: state.set_nonce(addr, parse_as_int(data['nonce'])) if 'storage' in data: for k, v in data['storage'].items(): state.set_storage_data(addr, parse_as_bin(k), parse_as_bin(v)) state.block_number = header["number"] state.gas_limit = header["gas_limit"] state.timestamp = header["timestamp"] state.block_difficulty = header["difficulty"] state.commit() return state
def from_snapshot(cls, snapshot_data, env, executing_on_head=False): state = State(env=env) if "alloc" in snapshot_data: for addr, data in snapshot_data["alloc"].items(): if len(addr) == 40: addr = decode_hex(addr) assert len(addr) == 20 if 'wei' in data: state.set_balance(addr, parse_as_int(data['wei'])) if 'balance' in data: state.set_balance(addr, parse_as_int(data['balance'])) if 'code' in data: state.set_code(addr, parse_as_bin(data['code'])) if 'nonce' in data: state.set_nonce(addr, parse_as_int(data['nonce'])) if 'storage' in data: for k, v in data['storage'].items(): state.set_storage_data( addr, big_endian_to_int(parse_as_bin(k)), big_endian_to_int(parse_as_bin(v))) elif "state_root" in snapshot_data: state.trie.root_hash = parse_as_bin(snapshot_data["state_root"]) else: raise Exception( "Must specify either alloc or state root parameter") for k, default in STATE_DEFAULTS.items(): default = copy.copy(default) v = snapshot_data[k] if k in snapshot_data else None if is_numeric(default): setattr(state, k, parse_as_int(v) if k in snapshot_data else default) elif is_string(default): setattr(state, k, parse_as_bin(v) if k in snapshot_data else default) elif k == 'prev_headers': if k in snapshot_data: headers = [dict_to_prev_header(h) for h in v] else: headers = default setattr(state, k, headers) elif k == 'recent_uncles': if k in snapshot_data: uncles = {} for height, _uncles in v.items(): uncles[int(height)] = [] for uncle in _uncles: uncles[int(height)].append(parse_as_bin(uncle)) else: uncles = default setattr(state, k, uncles) if executing_on_head: state.executing_on_head = True state.commit() state.changed = {} return state
def mk_poststate_of_blockhash(self, blockhash, convert=False): if blockhash not in self.db: raise Exception("Block hash %s not found" % encode_hex(blockhash)) block_rlp = self.db.get(blockhash) if block_rlp == b'GENESIS': return State.from_snapshot( json.loads(self.db.get(b'GENESIS_STATE')), self.env) block = rlp.decode(block_rlp, Block) state = State(env=self.env) state.trie.root_hash = block.header.state_root if convert else self.db.get( b'state:' + blockhash) update_block_env_variables(state, block) state.gas_used = block.header.gas_used state.txindex = len(block.transactions) state.recent_uncles = {} state.prev_headers = [] b = block header_depth = state.config['PREV_HEADER_DEPTH'] for i in range(header_depth + 1): state.prev_headers.append(b.header) if i < 6: state.recent_uncles[state.block_number - i] = [] for u in b.uncles: state.recent_uncles[state.block_number - i].append(u.hash) try: b = rlp.decode(state.db.get(b.header.prevhash), Block) except: break if i < header_depth: if state.db.get(b.header.prevhash) == b'GENESIS': jsondata = json.loads(state.db.get(b'GENESIS_STATE')) for h in jsondata["prev_headers"][:header_depth - i]: state.prev_headers.append(dict_to_prev_header(h)) for blknum, uncles in jsondata["recent_uncles"].items(): if int(blknum) >= state.block_number - int( state.config['MAX_UNCLE_DEPTH']): state.recent_uncles[blknum] = [ parse_as_bin(u) for u in uncles ] else: raise Exception("Dangling prevhash") assert len(state.journal) == 0, state.journal return state
def normalize_hash(hash): if len(hash) != 32: hash = parse_as_bin(hash) assert len(hash) == 32 return hash
STARTGAS = 3141592 # TODO: use config GASPRICE = 1 # TODO: use config DEPOSIT_SIZE = sharding_config['DEPOSIT_SIZE'] WITHDRAW_HASH = utils.sha3("withdraw") ADD_HEADER_TOPIC = utils.sha3("add_header()") _valmgr_ct = None _valmgr_code = None _valmgr_bytecode = None _valmgr_addr = None _valmgr_sender_addr = None _valmgr_tx = None viper_rlp_decoder_tx = rlp.decode( utils.parse_as_bin( "0xf90237808506fc23ac00830330888080b902246102128061000e60003961022056600060007f010000000000000000000000000000000000000000000000000000000000000060003504600060c082121515585760f882121561004d5760bf820336141558576001905061006e565b600181013560f783036020035260005160f6830301361415585760f6820390505b5b368112156101c2577f010000000000000000000000000000000000000000000000000000000000000081350483602086026040015260018501945060808112156100d55760018461044001526001828561046001376001820191506021840193506101bc565b60b881121561014357608081038461044001526080810360018301856104600137608181141561012e5760807f010000000000000000000000000000000000000000000000000000000000000060018401350412151558575b607f81038201915060608103840193506101bb565b60c08112156101b857600182013560b782036020035260005160388112157f010000000000000000000000000000000000000000000000000000000000000060018501350402155857808561044001528060b6838501038661046001378060b6830301830192506020810185019450506101ba565bfe5b5b5b5061006f565b601f841315155857602060208502016020810391505b6000821215156101fc578082604001510182826104400301526020820391506101d8565b808401610420528381018161044003f350505050505b6000f31b2d4f" ), Transaction) viper_rlp_decoder_addr = viper_rlp_decoder_tx.creates sighasher_tx = rlp.decode( utils.parse_as_bin( "0xf9016d808506fc23ac0083026a508080b9015a6101488061000e6000396101565660007f01000000000000000000000000000000000000000000000000000000000000006000350460f8811215610038576001915061003f565b60f6810391505b508060005b368312156100c8577f01000000000000000000000000000000000000000000000000000000000000008335048391506080811215610087576001840193506100c2565b60b881121561009d57607f8103840193506100c1565b60c08112156100c05760b68103600185013560b783036020035260005101840193505b5b5b50610044565b81810360388112156100f4578060c00160005380836001378060010160002060e052602060e0f3610143565b61010081121561010557600161011b565b6201000081121561011757600261011a565b60035b5b8160005280601f038160f701815382856020378282600101018120610140526020610140f350505b505050505b6000f31b2d4f" ), Transaction) sighasher_addr = sighasher_tx.creates class MessageFailed(Exception): pass def mk_validation_code(address):
def send_msg_transfer_value(mainchain_state, shard_state, shard_id, tx): urs_addr = get_urs_contract(shard_id)['addr'] log_rctx.debug("Begin: urs.balance={}, tx.to.balance={}".format( shard_state.get_balance(urs_addr), shard_state.get_balance(tx.to))) receipt_id = tx.r # we should deduct the startgas of this message in advance, because # the message may be possibly a contract, not only a normal value transfer. value = tx.value - tx.gasprice * tx.startgas log_rctx.debug( "value={}, tx.value={}, tx.gasprice={}, tx.startgas={}".format( value, tx.value, tx.gasprice, tx.startgas)) if value <= 0: return False, None # start transactioning if not send_msg_add_used_receipt(shard_state, shard_id, receipt_id): return False, None receipt_sender_hex = call_valmgr(mainchain_state, 'get_receipts__sender', [receipt_id]) receipt_data = call_valmgr(mainchain_state, 'get_receipts__data', [receipt_id]) msg_data = (b'00' * 12) + utils.parse_as_bin(receipt_sender_hex) + receipt_data msg = vm.Message(urs_addr, tx.to, value, tx.startgas - tx.intrinsic_gas_used, msg_data) env_tx = Transaction(0, tx.gasprice, tx.startgas, b'', 0, b'') env_tx._sender = urs_addr ext = VMExt(shard_state, env_tx) log_rctx.debug( "before apply_msg: urs_addr.balance={}, tx.to.balance={}".format( shard_state.get_balance(urs_addr), shard_state.get_balance(tx.to))) # even if `transfer_value` in `apply_msg` fails, no error occurs. # it seems no raise in apply_msg result, gas_remained, data = apply_msg(ext, msg) log_rctx.debug( "after apply_msg: urs_addr.balance={}, tx.to.balance={}".format( shard_state.get_balance(urs_addr), shard_state.get_balance(tx.to))) assert gas_remained >= 0 gas_used = tx.startgas - gas_remained # Transaction failed if not result: log_rctx.debug('TX FAILED', reason='out of gas', startgas=tx.startgas, gas_remained=gas_remained) shard_state.gas_used += tx.startgas shard_state.delta_balance(tx.to, tx.gasprice * gas_remained) shard_state.delta_balance(shard_state.block_coinbase, tx.gasprice * gas_used) output = b'' success = 0 # Transaction success else: log_rctx.debug('TX SUCCESS', data=data) shard_state.refunds += len(set( shard_state.suicides)) * opcodes.GSUICIDEREFUND if shard_state.refunds > 0: log_rctx.debug('Refunding', gas_refunded=min(shard_state.refunds, gas_used // 2)) gas_remained += min(shard_state.refunds, gas_used // 2) gas_used -= min(shard_state.refunds, gas_used // 2) shard_state.refunds = 0 # sell remaining gas shard_state.delta_balance(tx.to, tx.gasprice * gas_remained) log_rctx.debug("gas_remained={}, gasprice={}".format( gas_remained, tx.gasprice)) log_rctx.debug("End: urs.balance={}, tx.to.balance={}".format( shard_state.get_balance(urs_addr), shard_state.get_balance(tx.to))) shard_state.delta_balance(shard_state.block_coinbase, tx.gasprice * gas_used) shard_state.gas_used += gas_used if tx.to: output = utils.bytearray_to_bytestr(data) else: output = data success = 1 # Clear suicides suicides = shard_state.suicides shard_state.suicides = [] for s in suicides: shard_state.set_balance(s, 0) shard_state.del_account(s) # Pre-Metropolis: commit state after every tx if not shard_state.is_METROPOLIS() and not SKIP_MEDSTATES: shard_state.commit() # Construct a receipt r = mk_receipt(shard_state, success, shard_state.logs) _logs = list(shard_state.logs) shard_state.logs = [] shard_state.add_receipt(r) shard_state.set_param('bloom', shard_state.bloom | r.bloom) shard_state.set_param('txindex', shard_state.txindex + 1) return success, output