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) utxo = testlang.child_chain.get_transaction(deposit_id) spend_tx = Transaction(*decode_utxo_id(deposit_id), 0, 0, 0, utxo.cur12, alice.address, alice_money, bob.address, bob_money) spend_tx.sign1(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, alice_utxo) bob_spend_id = testlang.spend_utxo(bob_utxo, bob, bob_money, bob) alice_spend_id = testlang.spend_utxo(alice_utxo, alice, alice_money, alice) with pytest.raises(TransactionFailed): testlang.challenge_standard_exit(alice_utxo, bob_spend_id) testlang.challenge_standard_exit(alice_utxo, alice_spend_id)
def sendtx(client, blknum1, txindex1, oindex1, blknum2, txindex2, oindex2, cur12, amount1, newowner1, amount2, newowner2, key1, key2): if cur12 == "0x0": cur12 = NULL_ADDRESS if newowner1 == "0x0": newowner1 = NULL_ADDRESS if newowner2 == "0x0": newowner2 = NULL_ADDRESS # Form a transaction tx = Transaction(blknum1, txindex1, oindex1, blknum2, txindex2, oindex2, utils.normalize_address(cur12), utils.normalize_address(newowner1), amount1, utils.normalize_address(newowner2), amount2) # Sign it if key1: tx.sign1(utils.normalize_key(key1)) if key2: tx.sign2(utils.normalize_key(key2)) client_call(client.apply_transaction, [tx], "Sent transaction")
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 transfer(self, input1, newowner1, amount1, signatory1, input2=0, newowner2=None, amount2=0, signatory2=None, cur12=NULL_ADDRESS): newowner_address1 = newowner1['address'] newowner_address2 = NULL_ADDRESS if newowner2 is not None: newowner_address2 = newowner2['address'] tx = Transaction(*decode_utxo_id(input1), *decode_utxo_id(input2), cur12, newowner_address1, amount1, newowner_address2, amount2) if signatory1 is not None: key1 = signatory1['key'] tx.sign1(key1) if signatory2 is not None: key2 = signatory2['key'] tx.sign2(key2) spend_id = self.child_chain.apply_transaction(tx) self.submit_block() return spend_id
def set_dict(self, **num): print("set test") print("Data type of argument:", type(num)) for key, value in num.items(): print("{} is {}".format(key, value)) #self.root_chain.deposit(transact={'from': owner, 'value': amount}) mapping = {} mapping.update(num) for key, value in mapping.items(): print("{} is {}".format(key, value)) #convert dict to binary string bin_mapping = pickle.dumps(mapping) blknum = self.chain.next_deposit_block new_block = Block(None, blknum, NULL_SIGNATURE) new_block.add_mapping(mapping) self.chain.add_block(new_block) print("Number {} {}".format(new_block.number, self.chain.next_deposit_block)) tx = Transaction( blknum, 0, 0, 0, 0, 0, utils.normalize_address(0x0), utils.normalize_address( '0xfd02EcEE62797e75D86BCff1642EB0844afB28c7'), 1, utils.normalize_address(NULL_ADDRESS), 1, NULL_SIGNATURE, NULL_SIGNATURE, 0, bin_mapping) key1 = '3bb369fecdc16b93b99514d8ed9c2e87c5824cf4a6a98d2e8e91b7dd0c063304' print("Data type of key1:", type(key1)) tx.sign1(utils.normalize_key(key1)) self.current_block.add_transaction(tx) print("Added {}".format(self.current_block.transaction_set[0])) print("Added {}".format(self.current_block.transaction_set[0].mapping)) self.chain.set_dict(**num)
def test_transaction(t): blknum1, txindex1, oindex1 = 1, 1, 0 blknum2, txindex2, oindex2 = 2, 2, 1 newowner1, amount1 = t.a1, 100 newowner2, amount2 = t.a2, 150 oldowner1, oldowner2 = t.a1, t.a2 key1, key2 = t.k1, t.k2 tx = Transaction(blknum1, txindex1, oindex1, blknum2, txindex2, oindex2, NULL_ADDRESS, newowner1, amount1, newowner2, amount2) assert tx.blknum1 == blknum1 assert tx.txindex1 == txindex1 assert tx.oindex1 == oindex1 assert tx.blknum2 == blknum2 assert txindex2 == txindex2 assert tx.oindex2 == oindex2 assert tx.newowner1 == newowner1 assert tx.amount1 == amount1 assert tx.newowner2 == newowner2 assert tx.amount2 == amount2 assert tx.sig1 == NULL_SIGNATURE assert tx.sig2 == NULL_SIGNATURE tx.sign1(key1) assert tx.sender1 == oldowner1 tx.sign2(key2) assert tx.sender2 == oldowner2
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 root_chain.startDepositExit(utxo_pos1, NULL_ADDRESS, tx1.amount1, sender=key) 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) tx4 = Transaction(utxo_pos1, 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 ]
def transfer(self, input1, oindex1, newowner1, amount1, signatory1, input2=None, oindex2=0, newowner2=None, amount2=None, signatory2=None, cur12=NULL_ADDRESS): newowner_address1 = newowner1['address'] amount1 = int(amount1) newowner_address2 = NULL_ADDRESS if newowner2 is not None: newowner_address2 = newowner2['address'] amount2 = int(amount2) if amount2 is not None else 0 encoded_input_tx1 = rlp.encode(self.transactions[input1]['tx']).hex() blknum1, txindex1 = self.child_chain.get_tx_pos(encoded_input_tx1) blknum2, txindex2 = 0, 0 if input2 is not None: encoded_input_tx2 = rlp.encode(self.transactions[input2]['tx']).hex() blknum2, txindex2 = self.child_chain.get_tx_pos(encoded_input_tx2) tx = Transaction(blknum1, txindex1, oindex1, blknum2, txindex2, oindex2, cur12, newowner_address1, amount1, newowner_address2, amount2) if signatory1 is not None: key1 = signatory1['key'] tx.sign1(key1) if signatory2 is not None: key2 = signatory2['key'] tx.sign2(key2) encoded_tx = rlp.encode(tx).hex() self.child_chain.apply_transaction(encoded_tx) self.transactions.append({ 'tx': tx, 'confirm_sigs': b'', 'is_deposit': False }) return len(self.transactions) - 1
def set_test(self, num): print("set test") print("Data type of argument:", type(num)) blknum = self.chain.next_deposit_block file_block = Block(None, blknum, NULL_SIGNATURE) self.chain.add_block(file_block) print("Number {} {} {}".format(num, file_block.number, self.chain.next_deposit_block)) tx = Transaction( blknum, 0, 0, 0, 0, 0, utils.normalize_address(0x0), utils.normalize_address( '0xfd02EcEE62797e75D86BCff1642EB0844afB28c7'), 1, utils.normalize_address(NULL_ADDRESS), 1, NULL_SIGNATURE, NULL_SIGNATURE, num) key1 = '3bb369fecdc16b93b99514d8ed9c2e87c5824cf4a6a98d2e8e91b7dd0c063304' print("Data type of key1:", type(key1)) tx.sign1(utils.normalize_key(key1)) self.current_block.add_transaction(tx) print("Added {}".format(self.current_block.transaction_set[0])) print("Added {}".format(self.current_block.transaction_set[0].files)) self.chain.set_test(num)
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 = tx1.confirm(root_chain.getChildChain(dep_blknum)[0], key) priority1 = dep_blknum * 1000000000 + 10000 * 0 + 1 snapshot = t.chain.snapshot() sigs = tx1.sig1 + tx1.sig2 + confirmSig1 utxoId = dep_blknum * 1000000000 + 10000 * 0 + 1 # 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 = dep_blknum * 1000000000 + 10000 * 0 + 1 assert_tx_failed(lambda: root_chain.startExit( utxo_pos1, deposit_tx_hash, proof, sigs, sender=key)) assert root_chain.getExit(priority1) == [ address_to_hex(owner), 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 = tx2.confirm(root_chain.getChildChain(child_blknum)[0], key) priority2 = child_blknum * 1000000000 + 10000 * 0 + 0 sigs = tx2.sig1 + tx2.sig2 + confirmSig1 snapshot = t.chain.snapshot() # # Single input exit utxo_pos2 = child_blknum * 1000000000 + 10000 * 0 + 0 root_chain.startExit(utxo_pos2, tx_bytes2, proof, sigs, sender=key) assert root_chain.getExit(priority2) == [ address_to_hex(owner), 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 = tx3.confirm(root_chain.getChildChain(child2_blknum)[0], key) confirmSig2 = tx3.confirm(root_chain.getChildChain(child2_blknum)[0], key) priority3 = child2_blknum * 1000000000 + 10000 * 0 + 0 sigs = tx3.sig1 + tx3.sig2 + confirmSig1 + confirmSig2 # Double input exit utxoPos3 = child2_blknum * 1000000000 + 10000 * 0 + 0 root_chain.startExit(utxoPos3, tx_bytes3, proof, sigs, sender=key) assert root_chain.getExit(priority3) == [ address_to_hex(owner), NULL_ADDRESS_HEX, 100 ]
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 exit_bond = root_chain.EXIT_BOND() root_chain.startDepositExit(utxoId, NULL_ADDRESS, tx1.amount1, sender=key, value=exit_bond) 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, value=exit_bond)) 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, value=exit_bond) 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, value=exit_bond) assert root_chain.getExit(utxo_pos3) == [ '0x' + owner.hex(), NULL_ADDRESS_HEX, 100 ]