def test_used_receipt_store(): shard_id = 0 c = chain(shard_id) shard_state = c.shard_head_state[shard_id] x = t.ABIContract(c, get_urs_ct(shard_id), get_urs_contract(shard_id)['addr'], shard_id=shard_id) assert not x.get_used_receipts(0) urs_addr = get_urs_contract(shard_id)['addr'] # test add_used_receipt: only USED_RECEIPT_STORE can call itself with msg with pytest.raises(MessageFailed): call_contract_inconstantly(shard_state, get_urs_ct(shard_id), urs_addr, 'add_used_receipt', [0], 0, sender_addr=t.a0) assert call_contract_inconstantly(shard_state, get_urs_ct(shard_id), urs_addr, 'add_used_receipt', [0], 0, sender_addr=urs_addr) assert x.get_used_receipts(0)
def send_msg_add_used_receipt(state, shard_id, receipt_id): ct = get_urs_ct(shard_id) urs_addr = get_urs_contract(shard_id)['addr'] return call_contract_inconstantly(state, ct, urs_addr, 'add_used_receipt', [receipt_id], 0, sender_addr=urs_addr)
def test_used_receipt_store(): shard_id = 0 c = chain(shard_id) state = c.shard_head_state[shard_id] receipt_id = 1 assert not call_urs(state, shard_id, 'get_used_receipts', [receipt_id]) urs_addr = get_urs_contract(shard_id)['addr'] assert call_contract_inconstantly( state, get_urs_ct(shard_id), urs_addr, 'add_used_receipt', [receipt_id], 0, sender_addr=urs_addr ) assert call_urs(state, shard_id, 'get_used_receipts', [receipt_id])
def add_test_shard(self, shard_id, setup_urs_contracts=True, alloc=None): """Initial shard with fake accounts """ assert not self.chain.has_shard(shard_id) initial_state = mk_basic_state(base_alloc if alloc is None else alloc, None, self.chain.env) initial_state.delta_balance( used_receipt_store_utils.get_urs_contract(shard_id)['addr'], (10**9) * utils.denoms.ether) initial_state.commit() shard = ShardChain(shard_id=shard_id, initial_state=initial_state) self.chain.add_shard(shard) self.__init_shard_var(shard_id) if setup_urs_contracts: self.setup_and_deploy_urs_contracts(k0, shard_id)
def test_receipt_consuming_transaction(c): valmgr = t.ABIContract(c, get_valmgr_ct(), get_valmgr_addr()) to_addr = utils.privtoaddr(utils.sha3("test_to_addr")) data = b'123' # registre receipts in mainchain shard_id = 0 startgas = 100000 gasprice = 1 valmgr.tx_to_shard(to_addr, shard_id, startgas, gasprice, b'', sender=t.k0, value=1) value = 500000 receipt_id = valmgr.tx_to_shard(to_addr, shard_id, startgas, gasprice, data, sender=t.k0, value=value) # Setup the environment in shard `shard_id` ################# # create the contract USED_RECEIPT_STORE in shard `shard_id` c.add_test_shard(shard_id) shard_state = c.shard_head_state[shard_id] c.mine(1) urs0 = t.ABIContract(c, get_urs_ct(shard_id), get_urs_contract(shard_id)['addr'], shard_id=shard_id) assert not urs0.get_used_receipts(receipt_id) c.mine(1) # test receipt-consuming-tx: wrong receipt_id rctx = mk_testing_receipt_consuming_tx(0, to_addr, value, 300000, 1) with pytest.raises(InvalidTransaction): success, output = apply_shard_transaction(c.head_state, shard_state, shard_id, rctx) assert not urs0.get_used_receipts(receipt_id) # test receipt-consuming-tx: to_addr is not correct rctx = mk_testing_receipt_consuming_tx(receipt_id, t.a9, value, 300000, 1) with pytest.raises(InvalidTransaction): success, output = apply_shard_transaction(c.head_state, shard_state, shard_id, rctx) assert not urs0.get_used_receipts(receipt_id) # test receipt-consuming-tx: value is not correct rctx = mk_testing_receipt_consuming_tx(receipt_id, to_addr, value - 1, 300000, 1) with pytest.raises(InvalidTransaction): success, output = apply_shard_transaction(c.head_state, shard_state, shard_id, rctx) assert not urs0.get_used_receipts(receipt_id) # test receipt-consuming-tx: correct receipt_id to_addr_orig_balance = shard_state.get_balance(to_addr) urs0_orig_balance = shard_state.get_balance( get_urs_contract(shard_id)['addr']) rctx = mk_testing_receipt_consuming_tx(receipt_id, to_addr, value, startgas, gasprice) success, output = apply_shard_transaction(c.head_state, shard_state, shard_id, rctx) assert success and urs0.get_used_receipts(receipt_id) # TODO: not sure how much the balance should increase. It still depends on # whether we should deduct the tx.intrinsic gas assert to_addr_orig_balance < shard_state.get_balance(to_addr) # There shouldn't be extra money generated in the urs0 assert shard_state.get_balance(get_urs_contract(shard_id)['addr']) == \ urs0_orig_balance - (value - rctx.startgas * rctx.gasprice) # test receipt-consuming-tx: tx.value - tx.startgas * tx.gasprice <= 0 receipt_id = valmgr.tx_to_shard(to_addr, shard_id, 260000, 2, data, sender=t.k0, value=500000) rctx = mk_testing_receipt_consuming_tx(receipt_id, to_addr, 500000, 260000, 2) with pytest.raises(InvalidTransaction): success, output = apply_shard_transaction(c.head_state, shard_state, shard_id, rctx) # test receipt-consuming-tx: after update gasprice, tx.value > tx.startgas * tx.gasprice assert valmgr.update_gasprice(receipt_id, 1, sender=t.k0) rctx = mk_testing_receipt_consuming_tx(receipt_id, to_addr, 500000, 260000, 1) success, output = apply_shard_transaction(c.head_state, shard_state, shard_id, rctx) assert success # test is_valid_receipt_consuming_tx: ban tx.to == b'' rctx = mk_testing_receipt_consuming_tx(0, b'', value, 300000, 1) assert not is_valid_receipt_consuming_tx(c.head_state, shard_state, shard_id, rctx)
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