def test_challenge_standard_exit_wrong_oindex_should_fail(testlang):
    from plasma_core.utils.transactions import decode_utxo_id, encode_utxo_id
    from plasma_core.transaction import Transaction
    alice, bob, alice_money, bob_money = testlang.accounts[
        0], testlang.accounts[1], 10, 90

    deposit_id = testlang.deposit(alice, alice_money + bob_money)
    deposit_blknum, _, _ = decode_utxo_id(deposit_id)

    spend_tx = Transaction(inputs=[decode_utxo_id(deposit_id)],
                           outputs=[(alice.address, NULL_ADDRESS, alice_money),
                                    (bob.address, NULL_ADDRESS, bob_money)])
    spend_tx.sign(0, alice.key)
    blknum = testlang.submit_block([spend_tx])
    alice_utxo = encode_utxo_id(blknum, 0, 0)
    bob_utxo = encode_utxo_id(blknum, 0, 1)

    testlang.start_standard_exit(alice_utxo, alice.key)

    bob_spend_id = testlang.spend_utxo([bob_utxo], [bob.key],
                                       outputs=[(bob.address, NULL_ADDRESS,
                                                 bob_money)])
    alice_spend_id = testlang.spend_utxo([alice_utxo], [alice.key],
                                         outputs=[(alice.address, NULL_ADDRESS,
                                                   alice_money)])

    with pytest.raises(TransactionFailed):
        testlang.challenge_standard_exit(alice_utxo, bob_spend_id)

    testlang.challenge_standard_exit(alice_utxo, alice_spend_id)
def test_should_not_allow_to_withdraw_outputs_from_two_ifes_marked_as_canonical_but_sharing_an_input(testlang, plasma_framework, token):
    alice, amount_token = testlang.accounts[0], 200
    caroline, amount_eth = testlang.accounts[1], 100

    deposit_id_token = testlang.deposit_token(alice, token, amount_token)
    deposit_id_eth = testlang.deposit(caroline, amount_eth)

    swap_tx_id = testlang.spend_utxo(
        [deposit_id_token, deposit_id_eth], [alice, caroline], [(alice.address, NULL_ADDRESS, amount_eth), (caroline.address, token.address, amount_token)])

    # in-flight transaction not included in Plasma
    steal_tx = Transaction(inputs=[decode_utxo_id(deposit_id_eth)], outputs=[(caroline.address, NULL_ADDRESS, amount_eth)])
    steal_tx.sign(0, caroline, verifying_contract=testlang.root_chain.plasma_framework)

    testlang.start_in_flight_exit(swap_tx_id)
    testlang.start_in_flight_exit(None, spend_tx=steal_tx)

    caroline_token_balance_before = token.balanceOf(caroline.address)
    caroline_eth_balance_before = testlang.get_balance(caroline)

    testlang.piggyback_in_flight_exit_output(swap_tx_id, 1, caroline)
    testlang.piggyback_in_flight_exit_output(None, 0, caroline, spend_tx=steal_tx)

    testlang.forward_timestamp(2 * MIN_EXIT_PERIOD + 1)
    testlang.process_exits(token.address, 0, 1)
    testlang.process_exits(NULL_ADDRESS, 0, 1)

    # caroline exits with the tokens (previously owned by alice)
    caroline_token_balance = token.balanceOf(caroline.address)
    assert caroline_token_balance == caroline_token_balance_before + amount_token

    # but she can not exit with Eth
    caroline_eth_balance = testlang.get_balance(caroline)
    assert caroline_eth_balance == caroline_eth_balance_before
Esempio n. 3
0
def test_challenge_standard_exit_with_in_flight_exit_tx_should_succeed(
        ethtester, testlang):
    # exit cross-spend test, cases 3 and 4
    owner, amount = testlang.accounts[0], 100
    deposit_id = testlang.deposit(owner, amount)
    spend_id = testlang.spend_utxo([deposit_id], [owner.key],
                                   outputs=[(owner.address, NULL_ADDRESS,
                                             amount)])

    ife_tx = Transaction(inputs=[decode_utxo_id(spend_id)],
                         outputs=[(owner.address, NULL_ADDRESS, amount)])
    ife_tx.sign(0, owner.key)

    (encoded_spend, encoded_inputs, proofs,
     signatures) = testlang.get_in_flight_exit_info(None, spend_tx=ife_tx)
    bond = testlang.root_chain.inFlightExitBond()
    testlang.root_chain.startInFlightExit(encoded_spend,
                                          encoded_inputs,
                                          proofs,
                                          signatures,
                                          value=bond,
                                          sender=owner.key)

    testlang.start_standard_exit(spend_id, owner.key)
    assert testlang.get_standard_exit(spend_id).amount == 100

    exit_id = testlang.get_standard_exit_id(spend_id)
    # FIXME a proper way of getting encoded body of IFE tx is to get it out of generated events
    testlang.root_chain.challengeStandardExit(exit_id, ife_tx.encoded, 0,
                                              ife_tx.signatures[0])

    assert testlang.get_standard_exit(spend_id) == [
        NULL_ADDRESS_HEX, NULL_ADDRESS_HEX, 0, 0
    ]
def test_not_canonial_in_flight_exit_processed_successfully(testlang, plasma_framework):
    owner, deposit_1_amount, deposit_2_amount = testlang.accounts[0], 100, 200
    deposit_id_1 = testlang.deposit(owner, deposit_1_amount)
    deposit_id_2 = testlang.deposit(owner, deposit_2_amount)

    starting_vault_balance = testlang.get_balance(plasma_framework.eth_vault)

    amount_spent = 100
    spend_deposit_2_id = testlang.spend_utxo([deposit_id_2], [owner], outputs=[(owner.address, NULL_ADDRESS, amount_spent)])
    testlang.start_standard_exit(spend_deposit_2_id, account=owner)

    testlang.forward_timestamp(2 * MIN_EXIT_PERIOD + 1)
    testlang.process_exits(NULL_ADDRESS, 0, 1)

    vault_balance = testlang.get_balance(plasma_framework.eth_vault)
    assert vault_balance == starting_vault_balance - amount_spent

    # in-flight transaction not included in Plasma
    inputs = [decode_utxo_id(deposit_id_1), decode_utxo_id(deposit_id_2)]
    spend_deposits_tx = Transaction(inputs=inputs, outputs=[(owner.address, NULL_ADDRESS, deposit_2_amount + deposit_1_amount)])
    for i in range(0, len(inputs)):
        spend_deposits_tx.sign(i, owner, verifying_contract=testlang.root_chain.plasma_framework)

    testlang.start_in_flight_exit(None, spend_tx=spend_deposits_tx)
    testlang.piggyback_in_flight_exit_input(None, 0, owner, spend_tx=spend_deposits_tx)
    testlang.challenge_in_flight_exit_not_canonical(None, spend_deposit_2_id, account=owner, in_flight_tx=spend_deposits_tx)

    testlang.forward_timestamp(2 * MIN_EXIT_PERIOD + 1)
    testlang.process_exits(NULL_ADDRESS, 0, 1)

    vault_balance = testlang.get_balance(plasma_framework.eth_vault)
    # deposit 1 is withdrawn
    assert vault_balance == starting_vault_balance - amount_spent - deposit_1_amount
Esempio n. 5
0
 def spend_utxo(self, input_ids, keys, outputs=[], force_invalid=False):
     inputs = [decode_utxo_id(input_id) for input_id in input_ids]
     spend_tx = Transaction(inputs=inputs, outputs=outputs)
     for i in range(0, len(inputs)):
         spend_tx.sign(i, keys[i])
     blknum = self.submit_block([spend_tx], force_invalid=force_invalid)
     spend_id = encode_utxo_id(blknum, 0, 0)
     return spend_id
Esempio n. 6
0
def test_decode_mallability(testlang, plasma_core_test):
    owner, amount = testlang.accounts[0], 100
    null = '0x0000000000000000000000000000000000000000'
    tx = Transaction(outputs=[(owner.address, null, amount)])
    tx.sign(0, owner.key)
    import rlp
    encoded_with_signatures = rlp.encode(tx, Transaction)

    with pytest.raises(TransactionFailed):
        plasma_core_test.getOutput(encoded_with_signatures, 0)
def test_should_not_allow_to_withdraw_inputs_and_outputs_when_ifes_processing_interchanges(testlang, plasma_framework, token):
    alice, amount_token = testlang.accounts[0], 200
    caroline, amount_eth = testlang.accounts[1], 100

    deposit_id_token = testlang.deposit_token(alice, token, amount_token)
    deposit_id_eth = testlang.deposit(caroline, amount_eth)

    swap_tx_id = testlang.spend_utxo(
        [deposit_id_token, deposit_id_eth], [alice, caroline], [(alice.address, NULL_ADDRESS, amount_eth), (caroline.address, token.address, amount_token)])

    # in-flight transaction not included in Plasma
    steal_tx = Transaction(inputs=[decode_utxo_id(deposit_id_eth)], outputs=[(caroline.address, NULL_ADDRESS, amount_eth)])
    steal_tx.sign(0, caroline, verifying_contract=testlang.root_chain.plasma_framework)

    alice_token_balance_before = token.balanceOf(alice.address)
    alice_eth_balance_before = testlang.get_balance(alice)
    caroline_token_balance_before = token.balanceOf(caroline.address)
    caroline_eth_balance_before = testlang.get_balance(caroline)

    testlang.start_in_flight_exit(swap_tx_id)
    testlang.start_in_flight_exit(None, spend_tx=steal_tx)

    testlang.piggyback_in_flight_exit_input(swap_tx_id, 0, alice)
    testlang.piggyback_in_flight_exit_input(swap_tx_id, 1, caroline)
    testlang.piggyback_in_flight_exit_output(swap_tx_id, 0, alice)
    testlang.piggyback_in_flight_exit_output(swap_tx_id, 1, caroline)

    # we have encounter flaky tests. we are guessing it is caused by two exits being enqueued in the time that is too close.
    # within same root chain block time span, the priority in the queue could be the same and hard to differentiate.
    # https://github.com/omgnetwork/plasma-contracts/issues/606
    TIME_DIFF_FOR_ENSUREING_EXIT_PRIORITY = 10
    testlang.forward_timestamp(TIME_DIFF_FOR_ENSUREING_EXIT_PRIORITY)

    testlang.piggyback_in_flight_exit_output(None, 0, caroline, spend_tx=steal_tx)
    testlang.piggyback_in_flight_exit_input(None, 0, caroline, spend_tx=steal_tx)

    testlang.forward_timestamp(2 * MIN_EXIT_PERIOD + 1)
    # process swap_tx Eth exit and then steal_tx Eth exit
    testlang.process_exits(NULL_ADDRESS, 0, 2)
    # process token exit
    testlang.process_exits(token.address, 0, 1)

    # caroline exits with the tokens
    caroline_token_balance = token.balanceOf(caroline.address)
    assert caroline_token_balance == caroline_token_balance_before + amount_token
    # but she does not get ETH back
    caroline_eth_balance = testlang.get_balance(caroline)
    assert caroline_eth_balance == caroline_eth_balance_before

    # alice exits with eth
    alice_eth_balance = testlang.get_balance(alice)
    assert alice_eth_balance == alice_eth_balance_before + amount_eth
    # but she does not get token back
    alice_token_balance = token.balanceOf(alice.address)
    assert alice_token_balance == alice_token_balance_before
Esempio n. 8
0
 def spend_utxo(self,
                input_ids,
                keys,
                outputs=None,
                metadata=None,
                force_invalid=False):
     if outputs is None:
         outputs = []
     inputs = [decode_utxo_id(input_id) for input_id in input_ids]
     spend_tx = Transaction(inputs=inputs,
                            outputs=outputs,
                            metadata=metadata)
     for i in range(0, len(inputs)):
         spend_tx.sign(i, keys[i], verifyingContract=self.root_chain)
     blknum = self.submit_block([spend_tx], force_invalid=force_invalid)
     spend_id = encode_utxo_id(blknum, 0, 0)
     return spend_id
def test_start_standard_exit_wrong_oindex_should_fail(testlang):
    alice, bob, alice_money, bob_money = testlang.accounts[0], testlang.accounts[1], 10, 90

    deposit_id = testlang.deposit(alice, alice_money + bob_money)

    spend_tx = Transaction(inputs=[decode_utxo_id(deposit_id)],
                           outputs=[(alice.address, NULL_ADDRESS, alice_money), (bob.address, NULL_ADDRESS, bob_money)])
    spend_tx.sign(0, alice, verifying_contract=testlang.root_chain)
    blknum = testlang.submit_block([spend_tx])
    alice_utxo = encode_utxo_id(blknum, 0, 0)
    bob_utxo = encode_utxo_id(blknum, 0, 1)

    with pytest.raises(TransactionFailed):
        testlang.start_standard_exit(bob_utxo, alice)

    with pytest.raises(TransactionFailed):
        testlang.start_standard_exit(alice_utxo, bob)

    testlang.start_standard_exit(alice_utxo, alice)
    testlang.start_standard_exit(bob_utxo, bob)
Esempio n. 10
0
    def spend_utxo(self, utxo_position, new_owner, amount, signer):
        """Creates a spending transaction and inserts it into the chain.

        Args:
            utxo_position (int): Identifier of the UTXO to spend.
            new_owner (EthereumAccount): Account to own the output of this spend.
            amount (int): Amount to spend.
            signer (EthereumAccount): Account to sign this transaction.

        Returns:
            int: Unique identifier of the spend.
        """

        spend_tx = Transaction(inputs=[decode_utxo_position(utxo_position)],
                               outputs=[(new_owner.address, amount)])
        spend_tx.sign(0, signer.key)

        blknum = self.root_chain.currentPlasmaBlockNumber()
        block = Block(transactions=[spend_tx], number=blknum)
        self.commit_plasma_block_root(block)
        return encode_utxo_position(blknum, 0, 0)
Esempio n. 11
0
def test_challenge_standard_exit_with_in_flight_exit_tx_should_succeed(testlang):
    # exit cross-spend test, cases 3 and 4
    owner, amount = testlang.accounts[0], 100
    deposit_id = testlang.deposit(owner, amount)
    spend_id = testlang.spend_utxo([deposit_id], [owner], outputs=[(owner.address, NULL_ADDRESS, amount)])

    ife_tx = Transaction(inputs=[decode_utxo_id(spend_id)], outputs=[(owner.address, NULL_ADDRESS, amount)])
    ife_tx.sign(0, owner, verifying_contract=testlang.root_chain.plasma_framework)

    (encoded_spend, encoded_inputs, proofs, signatures) = testlang.get_in_flight_exit_info(None, spend_tx=ife_tx)
    bond = testlang.root_chain.inFlightExitBond()
    testlang.root_chain.startInFlightExit(encoded_spend, encoded_inputs, proofs, signatures,
                                          **{'value': bond, 'from': owner.address})

    testlang.start_standard_exit(spend_id, owner)
    assert testlang.get_standard_exit(spend_id).amount == 100

    exit_id = testlang.get_standard_exit_id(spend_id)
    exiting_tx = testlang.get_transaction(spend_id)
    # FIXME a proper way of getting encoded body of IFE tx is to get it out of generated events
    testlang.root_chain.challengeStandardExit(exit_id, ife_tx.encoded, 0, ife_tx.signatures[0], exiting_tx.encoded)

    assert testlang.get_standard_exit(spend_id) == [NULL_ADDRESS_HEX, 0, 0, False]
def test_should_not_allow_to_withdraw_inputs_and_outputs_when_ifes_processing_interchanges(
        testlang, plasma_framework, token):
    alice, amount_token = testlang.accounts[0], 200
    caroline, amount_eth = testlang.accounts[1], 100

    deposit_id_token = testlang.deposit_token(alice, token, amount_token)
    deposit_id_eth = testlang.deposit(caroline, amount_eth)

    swap_tx_id = testlang.spend_utxo(
        [deposit_id_token, deposit_id_eth], [alice, caroline],
        [(alice.address, NULL_ADDRESS, amount_eth),
         (caroline.address, token.address, amount_token)])

    # in-flight transaction not included in Plasma
    steal_tx = Transaction(inputs=[decode_utxo_id(deposit_id_eth)],
                           outputs=[(caroline.address, NULL_ADDRESS,
                                     amount_eth)])
    steal_tx.sign(0,
                  caroline,
                  verifying_contract=testlang.root_chain.plasma_framework)

    alice_token_balance_before = token.balanceOf(alice.address)
    alice_eth_balance_before = testlang.get_balance(alice)
    caroline_token_balance_before = token.balanceOf(caroline.address)
    caroline_eth_balance_before = testlang.get_balance(caroline)

    testlang.start_in_flight_exit(swap_tx_id)
    testlang.start_in_flight_exit(None, spend_tx=steal_tx)

    testlang.piggyback_in_flight_exit_input(swap_tx_id, 0, alice)
    testlang.piggyback_in_flight_exit_input(swap_tx_id, 1, caroline)
    testlang.piggyback_in_flight_exit_output(swap_tx_id, 0, alice)
    testlang.piggyback_in_flight_exit_output(swap_tx_id, 1, caroline)
    testlang.piggyback_in_flight_exit_output(None,
                                             0,
                                             caroline,
                                             spend_tx=steal_tx)
    testlang.piggyback_in_flight_exit_input(None,
                                            0,
                                            caroline,
                                            spend_tx=steal_tx)

    testlang.forward_timestamp(2 * MIN_EXIT_PERIOD + 1)
    # process swap_tx Eth exit and then steal_tx Eth exit
    testlang.process_exits(NULL_ADDRESS, 0, 2)
    # process token exit
    testlang.process_exits(token.address, 0, 1)

    # caroline exits with the tokens
    caroline_token_balance = token.balanceOf(caroline.address)
    assert caroline_token_balance == caroline_token_balance_before + amount_token
    # but she does not get ETH back
    caroline_eth_balance = testlang.get_balance(caroline)
    assert caroline_eth_balance == caroline_eth_balance_before

    # alice exits with eth
    alice_eth_balance = testlang.get_balance(alice)
    assert alice_eth_balance == alice_eth_balance_before + amount_eth
    # but she does not get token back
    alice_token_balance = token.balanceOf(alice.address)
    assert alice_token_balance == alice_token_balance_before