Exemplo n.º 1
0
def test_challenge_in_flight_exit_input_spent_should_succeed_for_all_indices(
    testlang, double_spend_output_index, challenge_input_index
):
    alice, bob, carol = testlang.accounts[0], testlang.accounts[1], testlang.accounts[2]
    deposit_amount = 100
    deposit_id = testlang.deposit(alice, deposit_amount)

    tx_output_amount = deposit_amount // PAYMENT_TX_MAX_OUTPUT_SIZE
    outputs = [(alice.address, NULL_ADDRESS, tx_output_amount)] * PAYMENT_TX_MAX_OUTPUT_SIZE

    input_tx_id = testlang.spend_utxo([deposit_id], [alice], outputs=outputs)
    blknum, tx_index, _ = decode_utxo_id(input_tx_id)
    double_spend_utxo = encode_utxo_id(blknum, tx_index, double_spend_output_index)

    ife_output_amount = tx_output_amount
    ife_tx_id = testlang.spend_utxo(
        [double_spend_utxo],
        [alice],
        [(bob.address, NULL_ADDRESS, ife_output_amount)]
    )

    inputs = []
    for i in range(0, PAYMENT_TX_MAX_INPUT_SIZE):
        if i == challenge_input_index:
            inputs.append(double_spend_utxo)
        else:
            inputs.append(testlang.deposit(alice, tx_output_amount))

    challenge_tx_id = testlang.spend_utxo(
        inputs,
        [alice] * PAYMENT_TX_MAX_INPUT_SIZE,
        [
            (carol.address, NULL_ADDRESS, tx_output_amount),
        ],
        force_invalid=True
    )

    testlang.start_in_flight_exit(ife_tx_id, sender=bob)
    testlang.piggyback_in_flight_exit_input(ife_tx_id, 0, alice)
    testlang.challenge_in_flight_exit_input_spent(ife_tx_id, challenge_tx_id, carol)

    in_flight_exit = testlang.get_in_flight_exit(ife_tx_id)
    for i in range(0, PAYMENT_TX_MAX_INPUT_SIZE):
        assert not in_flight_exit.input_piggybacked(i)
Exemplo n.º 2
0
def test_finalize_exits_priority_for_in_flight_exits_corresponds_to_the_age_of_youngest_input(
        testlang):
    owner, amount = testlang.accounts[0], 100
    deposit_0_id = testlang.deposit(owner, amount)
    deposit_1_id = testlang.deposit(owner, amount)

    spend_00_id = testlang.spend_utxo([deposit_0_id], [owner.key],
                                      [(owner.address, NULL_ADDRESS, 30),
                                       (owner.address, NULL_ADDRESS, 70)])
    blknum, txindex, _ = decode_utxo_id(spend_00_id)
    spend_01_id = encode_utxo_id(blknum, txindex, 1)
    spend_1_id = testlang.spend_utxo([spend_01_id], [owner.key],
                                     [(owner.address, NULL_ADDRESS, 70)])
    testlang.ethtester.chain.mine()
    spend_2_id = testlang.spend_utxo([deposit_1_id], [owner.key],
                                     [(owner.address, NULL_ADDRESS, 100)])

    testlang.start_standard_exit(spend_00_id, owner.key)

    testlang.start_in_flight_exit(spend_1_id)
    testlang.piggyback_in_flight_exit_output(spend_1_id, 0, owner.key)
    testlang.start_standard_exit(spend_2_id, owner.key)

    testlang.forward_timestamp(2 * MIN_EXIT_PERIOD + 1)

    balance = testlang.get_balance(owner)

    testlang.process_exits(NULL_ADDRESS,
                           testlang.get_standard_exit_id(spend_00_id), 1)
    assert testlang.get_balance(
        owner) == balance + 30 + testlang.root_chain.standardExitBond()

    balance = testlang.get_balance(owner)
    testlang.process_exits(NULL_ADDRESS,
                           testlang.get_in_flight_exit_id(spend_1_id), 1)
    assert testlang.get_balance(
        owner) == balance + 70 + testlang.root_chain.inFlightExitBond(
        ) + testlang.root_chain.piggybackBond()

    balance = testlang.get_balance(owner)
    testlang.process_exits(NULL_ADDRESS,
                           testlang.get_standard_exit_id(spend_2_id), 1)
    assert testlang.get_balance(
        owner) == balance + 100 + testlang.root_chain.standardExitBond()
Exemplo n.º 3
0
 def spend_utxo(self,
                input_ids,
                accounts,
                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,
                       accounts[i],
                       verifying_contract=self.root_chain.plasma_framework)
     blknum = self.submit_block([spend_tx], force_invalid=force_invalid)
     spend_id = encode_utxo_id(blknum, 0, 0)
     return spend_id
Exemplo n.º 4
0
def application(request):
    # Dispatcher is dictionary {<method_name>: callable}
    dispatcher["submit_block"] = lambda block: child_chain.submit_block(
        rlp.decode(utils.decode_hex(block), Block))
    dispatcher[
        "apply_transaction"] = lambda transaction: child_chain.apply_transaction(
            rlp.decode(utils.decode_hex(transaction), Transaction))
    dispatcher["get_transaction"] = lambda blknum, txindex: rlp.encode(
        child_chain.get_transaction(encode_utxo_id(blknum, txindex, 0)),
        Transaction).hex()
    dispatcher["get_current_block"] = lambda: rlp.encode(
        child_chain.get_current_block(), Block).hex()
    dispatcher[
        "get_current_block_num"] = lambda: child_chain.get_current_block_num()
    dispatcher["get_block"] = lambda blknum: rlp.encode(
        child_chain.get_block(blknum), Block).hex()
    dispatcher["get_all_blocks"] = lambda: child_chain.get_all_blocks()
    response = JSONRPCResponseManager.handle(request.data, dispatcher)
    return Response(response.json, mimetype='application/json')
Exemplo n.º 5
0
def test_start_standard_exit_on_piggyback_in_flight_exit_valid_output_owner_should_fail(testlang, num_outputs):
    # exit cross-spend test, case 9
    owner_1, amount = testlang.accounts[0], 100
    deposit_id = testlang.deposit(owner_1, amount)
    outputs = []
    for i in range(0, num_outputs):
        outputs.append((testlang.accounts[i].address, NULL_ADDRESS, 1))
    spend_id = testlang.spend_utxo([deposit_id], [owner_1.key], outputs)

    testlang.start_in_flight_exit(spend_id)

    output_index = num_outputs - 1
    testlang.piggyback_in_flight_exit_output(spend_id, output_index, testlang.accounts[output_index].key)

    in_flight_exit = testlang.get_in_flight_exit(spend_id)
    assert in_flight_exit.output_piggybacked(output_index)

    blknum, txindex, _ = decode_utxo_id(spend_id)
    output_id = encode_utxo_id(blknum, txindex, output_index)

    with pytest.raises(TransactionFailed):
        testlang.start_standard_exit(output_id, testlang.accounts[output_index].key)
Exemplo n.º 6
0
def test_start_fee_exit(t, u, root_chain, assert_tx_failed):
    two_weeks = 60 * 60 * 24 * 7 * 2
    value_1 = 100
    blknum = root_chain.getDepositBlock()
    root_chain.deposit(value=value_1)
    expected_utxo_pos = root_chain.currentFeeExit()
    expected_exitable_at = t.chain.head_state.timestamp + two_weeks + 1
    assert root_chain.currentFeeExit() == 1
    root_chain.startFeeExit(NULL_ADDRESS, 1)
    assert root_chain.currentFeeExit() == 2
    exitable_at, utxo_pos = root_chain.getNextExit(NULL_ADDRESS)
    fee_priority = exitable_at << 128 | utxo_pos
    assert utxo_pos == expected_utxo_pos
    assert exitable_at == expected_exitable_at

    expected_utxo_pos = encode_utxo_id(blknum, 0, 0)
    root_chain.startDepositExit(expected_utxo_pos, NULL_ADDRESS, value_1)
    created_at, utxo_pos = root_chain.getNextExit(NULL_ADDRESS)
    deposit_priority = created_at << 128 | utxo_pos
    assert fee_priority > deposit_priority
    # Fails if transaction sender isn't the authority
    assert_tx_failed(
        lambda: root_chain.startFeeExit(NULL_ADDRESS, 1, sender=t.k1))
Exemplo n.º 7
0
def test_finalize_exits(t, u, root_chain):
    two_weeks = 60 * 60 * 24 * 14
    owner, value_1, key = t.a1, 100, t.k1
    tx1 = Transaction(0, 0, 0, 0, 0, 0, NULL_ADDRESS, owner, value_1,
                      NULL_ADDRESS, 0)
    dep1_blknum = root_chain.getDepositBlock()
    root_chain.deposit(value=value_1, sender=key)
    utxo_pos1 = encode_utxo_id(dep1_blknum, 0, 0)
    root_chain.startDepositExit(utxo_pos1,
                                NULL_ADDRESS,
                                tx1.amount1,
                                sender=key)
    t.chain.head_state.timestamp += two_weeks * 2
    assert root_chain.exits(utxo_pos1) == [
        '0x' + owner.hex(), NULL_ADDRESS_HEX, 100
    ]
    pre_balance = t.chain.head_state.get_balance(owner)
    root_chain.finalizeExits(sender=t.k2)
    post_balance = t.chain.head_state.get_balance(owner)
    assert post_balance == pre_balance + value_1
    assert root_chain.exits(utxo_pos1) == [
        NULL_ADDRESS_HEX, NULL_ADDRESS_HEX, value_1
    ]
Exemplo n.º 8
0
def test_start_deposit_exit(t, u, root_chain, assert_tx_failed):
    two_weeks = 60 * 60 * 24 * 7 * 2
    value_1 = 100
    # Deposit once to make sure everything works for deposit block
    root_chain.deposit(value=value_1)
    blknum = root_chain.getDepositBlock()
    root_chain.deposit(value=value_1)
    expected_utxo_pos = encode_utxo_id(blknum, 0, 0)
    expected_exitable_at = t.chain.head_state.timestamp + two_weeks
    exit_bond = root_chain.EXIT_BOND()
    root_chain.startDepositExit(expected_utxo_pos, NULL_ADDRESS, value_1, value=exit_bond)
    exitable_at, utxo_pos = root_chain.getNextExit(NULL_ADDRESS)
    assert utxo_pos == expected_utxo_pos
    assert exitable_at == expected_exitable_at
    assert root_chain.exits(utxo_pos) == ['0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1', NULL_ADDRESS_HEX, 100]
    # Same deposit cannot be exited twice
    assert_tx_failed(lambda: root_chain.startDepositExit(utxo_pos, NULL_ADDRESS, value_1, value=exit_bond))
    # Fails if transaction sender is not the depositor
    assert_tx_failed(lambda: root_chain.startDepositExit(utxo_pos, NULL_ADDRESS, value_1, sender=t.k1, value=exit_bond))
    # Fails if utxo_pos is wrong
    assert_tx_failed(lambda: root_chain.startDepositExit(utxo_pos * 2, NULL_ADDRESS, value_1, value=exit_bond))
    # Fails if value given is not equal to deposited value
    assert_tx_failed(lambda: root_chain.startDepositExit(utxo_pos, NULL_ADDRESS, value_1 + 1, value=exit_bond))
Exemplo n.º 9
0
    def spend_utxo(self, utxo_id, new_owner, amount, signer):
        """Creates a spending transaction and inserts it into the chain.

        Args:
            utxo_id (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(*decode_utxo_id(utxo_id), 0, 0, 0, NULL_ADDRESS,
                               new_owner.address, amount, NULL_ADDRESS, 0)
        spend_tx.sign1(signer.key)

        blknum = self.root_chain.currentChildBlock()
        block = Block(transaction_set=[spend_tx], number=blknum)
        block.sign(self.operator.key)
        self.root_chain.submitBlock(block.root)
        self.child_chain.add_block(block)
        return encode_utxo_id(blknum, 0, 0)
def test_output_exited_via_se_and_then_ife_withdraws_once(testlang, plasma_framework, num_outputs):
    owner, amount, amount_spent = testlang.accounts[0], 100, 1
    deposit_id = testlang.deposit(owner, amount)

    outputs = []
    for i in range(0, num_outputs):
        outputs.append((owner.address, NULL_ADDRESS, amount_spent))
    spend_id = testlang.spend_utxo([deposit_id], [owner], outputs)

    output_index = num_outputs - 1

    blknum, txindex, _ = decode_utxo_id(spend_id)
    output_id = encode_utxo_id(blknum, txindex, output_index)
    testlang.start_standard_exit(output_id, account=owner)

    pre_exit_balance = testlang.get_balance(plasma_framework.eth_vault)

    testlang.start_in_flight_exit(spend_id)
    testlang.piggyback_in_flight_exit_output(spend_id, output_index, owner)
    testlang.forward_timestamp(2 * MIN_EXIT_PERIOD + 1)
    testlang.process_exits(NULL_ADDRESS, 0, 10)

    post_exit_balance = testlang.get_balance(plasma_framework.eth_vault)
    assert post_exit_balance == pre_exit_balance - amount_spent
Exemplo n.º 11
0
def withdrawdeposit(client, owner, blknum, amount):
    deposit_pos = encode_utxo_id(blknum, 0, 0)
    client.withdraw_deposit(owner, deposit_pos, amount)
    print("Submitted withdrawal")
Exemplo n.º 12
0
 def identifier(self):
     return encode_utxo_id(self.blknum, self.txindex, self.oindex)
Exemplo n.º 13
0
def test_start_exit(t, root_chain, assert_tx_failed):
    week_and_a_half = 60 * 60 * 24 * 13
    owner, value_1, key = t.a1, 100, t.k1
    tx1 = Transaction(0, 0, 0, 0, 0, 0, NULL_ADDRESS, owner, value_1,
                      NULL_ADDRESS, 0)
    deposit_tx_hash = get_deposit_hash(owner, NULL_ADDRESS, value_1)
    dep_blknum = root_chain.getDepositBlock()
    assert dep_blknum == 1
    root_chain.deposit(value=value_1, sender=key)
    merkle = FixedMerkle(16, [deposit_tx_hash], True)
    proof = merkle.create_membership_proof(deposit_tx_hash)
    confirmSig1 = confirm_tx(tx1,
                             root_chain.getPlasmaBlock(dep_blknum)[0], key)
    snapshot = t.chain.snapshot()
    sigs = tx1.sig1 + tx1.sig2 + confirmSig1
    utxoId = encode_utxo_id(dep_blknum, 0, 0)
    # Deposit exit
    root_chain.startDepositExit(utxoId, NULL_ADDRESS, tx1.amount1, sender=key)

    t.chain.head_state.timestamp += week_and_a_half
    # Cannot exit twice off of the same utxo
    utxo_pos1 = encode_utxo_id(dep_blknum, 0, 0)
    assert_tx_failed(lambda: root_chain.startExit(
        utxo_pos1, deposit_tx_hash, proof, sigs, sender=key))
    assert root_chain.getExit(utxo_pos1) == [
        '0x' + owner.hex(), NULL_ADDRESS_HEX, 100
    ]
    t.chain.revert(snapshot)

    tx2 = Transaction(dep_blknum, 0, 0, 0, 0, 0, NULL_ADDRESS, owner, value_1,
                      NULL_ADDRESS, 0)
    tx2.sign1(key)
    tx_bytes2 = rlp.encode(tx2, UnsignedTransaction)
    merkle = FixedMerkle(16, [tx2.merkle_hash], True)
    proof = merkle.create_membership_proof(tx2.merkle_hash)
    child_blknum = root_chain.currentChildBlock()
    assert child_blknum == 1000
    root_chain.submitBlock(merkle.root)
    confirmSig1 = confirm_tx(tx2,
                             root_chain.getPlasmaBlock(child_blknum)[0], key)
    sigs = tx2.sig1 + tx2.sig2 + confirmSig1
    snapshot = t.chain.snapshot()
    # # Single input exit
    utxo_pos2 = encode_utxo_id(child_blknum, 0, 0)
    root_chain.startExit(utxo_pos2, tx_bytes2, proof, sigs, sender=key)
    assert root_chain.getExit(utxo_pos2) == [
        '0x' + owner.hex(), NULL_ADDRESS_HEX, 100
    ]
    t.chain.revert(snapshot)
    dep2_blknum = root_chain.getDepositBlock()
    assert dep2_blknum == 1001
    root_chain.deposit(value=value_1, sender=key)
    tx3 = Transaction(child_blknum, 0, 0, dep2_blknum, 0, 0, NULL_ADDRESS,
                      owner, value_1, NULL_ADDRESS, 0, 0)
    tx3.sign1(key)
    tx3.sign2(key)
    tx_bytes3 = rlp.encode(tx3, UnsignedTransaction)
    merkle = FixedMerkle(16, [tx3.merkle_hash], True)
    proof = merkle.create_membership_proof(tx3.merkle_hash)
    child2_blknum = root_chain.currentChildBlock()
    assert child2_blknum == 2000
    root_chain.submitBlock(merkle.root)
    confirmSig1 = confirm_tx(tx3,
                             root_chain.getPlasmaBlock(child2_blknum)[0], key)
    confirmSig2 = confirm_tx(tx3,
                             root_chain.getPlasmaBlock(child2_blknum)[0], key)
    sigs = tx3.sig1 + tx3.sig2 + confirmSig1 + confirmSig2
    # Double input exit
    utxo_pos3 = encode_utxo_id(child2_blknum, 0, 0)
    root_chain.startExit(utxo_pos3, tx_bytes3, proof, sigs, sender=key)
    assert root_chain.getExit(utxo_pos3) == [
        '0x' + owner.hex(), NULL_ADDRESS_HEX, 100
    ]
Exemplo n.º 14
0
 def apply_transaction(self, tx):
     self.chain.validate_transaction(tx, self.current_block.spent_utxos)
     self.current_block.add_transaction(tx)
     return encode_utxo_id(self.current_block.number,
                           len(self.current_block.transaction_set) - 1, 0)
Exemplo n.º 15
0
def test_challenge_exit(t, u, root_chain, assert_tx_failed):
    owner, value_1, key = t.a1, 100, t.k1
    tx1 = Transaction(0, 0, 0, 0, 0, 0, NULL_ADDRESS, owner, value_1,
                      NULL_ADDRESS, 0)
    deposit_tx_hash = get_deposit_hash(owner, NULL_ADDRESS, value_1)
    utxo_pos1 = encode_utxo_id(root_chain.getDepositBlock(), 0, 0)
    root_chain.deposit(value=value_1, sender=key)
    utxo_pos2 = encode_utxo_id(root_chain.getDepositBlock(), 0, 0)
    root_chain.deposit(value=value_1, sender=key)
    merkle = FixedMerkle(16, [deposit_tx_hash], True)
    proof = merkle.create_membership_proof(deposit_tx_hash)
    confirmSig1 = confirm_tx(tx1, root_chain.getPlasmaBlock(utxo_pos1)[0], key)
    sigs = tx1.sig1 + tx1.sig2 + confirmSig1
    exit_bond = root_chain.EXIT_BOND()
    root_chain.startDepositExit(utxo_pos1,
                                NULL_ADDRESS,
                                tx1.amount1,
                                sender=key,
                                value=exit_bond)
    tx3 = Transaction(utxo_pos2, 0, 0, 0, 0, 0, NULL_ADDRESS, owner, value_1,
                      NULL_ADDRESS, 0)
    tx3.sign1(key)
    tx_bytes3 = rlp.encode(tx3, UnsignedTransaction)
    merkle = FixedMerkle(16, [tx3.merkle_hash], True)
    proof = merkle.create_membership_proof(tx3.merkle_hash)
    child_blknum = root_chain.currentChildBlock()
    root_chain.submitBlock(merkle.root)
    confirmSig = confirm_tx(tx3,
                            root_chain.getPlasmaBlock(child_blknum)[0], key)
    sigs = tx3.sig1 + tx3.sig2
    utxo_pos3 = encode_utxo_id(child_blknum, 0, 0)

    utxo1_blknum, _, _ = decode_utxo_id(utxo_pos1)
    tx4 = Transaction(utxo1_blknum, 0, 0, 0, 0, 0, NULL_ADDRESS, owner,
                      value_1, NULL_ADDRESS, 0)
    tx4.sign1(key)
    tx_bytes4 = rlp.encode(tx4, UnsignedTransaction)
    merkle = FixedMerkle(16, [tx4.merkle_hash], True)
    proof = merkle.create_membership_proof(tx4.merkle_hash)
    child_blknum = root_chain.currentChildBlock()
    root_chain.submitBlock(merkle.root)
    confirmSig = confirm_tx(tx4,
                            root_chain.getPlasmaBlock(child_blknum)[0], key)
    sigs = tx4.sig1 + tx4.sig2
    utxo_pos4 = encode_utxo_id(child_blknum, 0, 0)
    oindex1 = 0
    assert root_chain.exits(utxo_pos1) == [
        '0x' + owner.hex(), NULL_ADDRESS_HEX, 100
    ]
    # Fails if transaction after exit doesn't reference the utxo being exited
    assert_tx_failed(lambda: root_chain.challengeExit(
        utxo_pos3, oindex1, tx_bytes3, proof, sigs, confirmSig))
    # Fails if transaction proof is incorrect
    assert_tx_failed(lambda: root_chain.challengeExit(
        utxo_pos4, oindex1, tx_bytes4, proof[::-1], sigs, confirmSig))
    # Fails if transaction confirmation is incorrect
    assert_tx_failed(lambda: root_chain.challengeExit(
        utxo_pos4, oindex1, tx_bytes4, proof, sigs, confirmSig[::-1]))
    root_chain.challengeExit(utxo_pos4, oindex1, tx_bytes4, proof, sigs,
                             confirmSig)
    assert root_chain.exits(utxo_pos1) == [
        NULL_ADDRESS_HEX, NULL_ADDRESS_HEX, value_1
    ]
Exemplo n.º 16
0
 def withdraw(self, blknum, txindex, oindex, tx, proof, sigs):
     utxo_pos = encode_utxo_id(blknum, txindex, oindex)
     encoded_transaction = rlp.encode(tx, UnsignedTransaction)
     self.root_chain.startExit(utxo_pos, encoded_transaction, proof, sigs, transact={'from': '0x' + tx.newowner1.hex()})