Ejemplo n.º 1
0
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)
Ejemplo n.º 2
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)
Ejemplo n.º 3
0
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])
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
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