forked from omgnetwork/plasma-cash
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Also, fix a minor bug that the depth of merkle tree should be 257.
- Loading branch information
Showing
15 changed files
with
410 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
integration_tests/features/challenge_double_spending_flow.feature
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
Feature: Challenge double spending flow | ||
|
||
Scenario: userA first transfers to userB and then tries to double spend the same funds to userC. userC tries to withdraw the funds and userB challenges the exit. | ||
Given userA deposits 1 eth in plasma cash | ||
And userA transfers 1 eth to userB | ||
And userA tries to double spend 1 eth to userC | ||
When userC starts to exit 1 eth from plasma cash | ||
Then root chain got the start-exit record from double spending challenge | ||
When userB challenges the exit | ||
Then the challenge is successful and root chain cancels the exit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
Feature: Challenge history flow | ||
|
||
Scenario: userA transfers funds to userB, userB transfers to userC, and userC transfers to userD. userD starts an exit and userB challenges the history. Then userD responds to the history challenge. | ||
Given userA deposits 1 eth in plasma cash | ||
And userA transfers 1 eth to userB | ||
And userB transfers 1 eth to userC | ||
And userC transfers 1 eth to userD | ||
When userD starts to exit 1 eth from plasma cash | ||
Then root chain got the start-exit record from history challenge | ||
When userB challenges the exit history with deposit tx | ||
Then root chain got the challenge record | ||
When userD responds to the history challenge | ||
Then root chain cancels the challenge |
10 changes: 10 additions & 0 deletions
10
integration_tests/features/challenge_spent_coin_flow.feature
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
Feature: Challenge spent coin flow | ||
|
||
Scenario: userA deposits to plasma cash and transfers to userB. userB transfers to userC and tries to withdraw the funds. Then userC challenges the exit. | ||
Given userA deposits 1 eth in plasma cash | ||
And userA transfers 1 eth to userB | ||
And userB transfers 1 eth to userC | ||
When userB starts to exit 1 eth from plasma cash | ||
Then root chain got the start-exit record from coin spent challenge | ||
When userC challenges the coin spent exit | ||
Then the challenge is successful and root chain cancels the coin spent exit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
integration_tests/features/steps/challenge_double_spending_flow.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import rlp | ||
import time | ||
|
||
from behave import given, then, when | ||
from ethereum import utils | ||
|
||
from integration_tests.features.utils import has_value | ||
from plasma_cash.child_chain.transaction import Transaction | ||
from plasma_cash.dependency_config import container | ||
from plasma_cash.utils.merkle.sparse_merkle_tree import SparseMerkleTree | ||
|
||
operator = '0x3B0884f4E50e9BC2CE9b224aB72feA89a81CDF7c' | ||
userA = '0xb83e232458A092696bE9717045d9A605FB0FEc2b' | ||
userB = '0x08d92dcA9038eA9433254996a2D4F08D43BE8227' | ||
userC = '0xDF29cFbD5d793Fa5B22D5c730A8E8450740C6f8f' | ||
operator_key = '0xa18969817c2cefadf52b93eb20f917dce760ce13b2ac9025e0361ad1e7a1d448' | ||
userA_key = '0xe4807cf08191b310fe1821e6e5397727ee6bc694e92e25115eca40114e3a4e6b' | ||
eth_currency = '0x0000000000000000000000000000000000000000' | ||
uid = 1693390459388381052156419331572168595237271043726428428352746834777341368960 | ||
|
||
DEPOSIT_TX_BLOCK = 1 | ||
TRANSFER_TX_1_BLOCK = 2 | ||
TRANSFER_TX_2_BLOCK = 3 | ||
|
||
|
||
@given('userA deposits {amount:d} eth in plasma cash') | ||
def userA_deposits_some_amount_of_eth_in_plasma_cash(context, amount): | ||
client = container.get_client() | ||
client.deposit( | ||
amount=amount, | ||
depositor=userA, | ||
currency=eth_currency | ||
) | ||
time.sleep(5) | ||
client.submit_block(operator_key) | ||
|
||
|
||
@given('userA transfers {amount:d} eth to userB') | ||
def userA_transfers_some_eth_to_userB(context, amount): | ||
prev_block = DEPOSIT_TX_BLOCK | ||
client = container.get_client() | ||
client.send_transaction(prev_block, uid, amount, userB, userA_key) | ||
client.submit_block(operator_key) | ||
|
||
|
||
@given('userA tries to double spend {amount:d} eth to userC') | ||
def userA_tries_to_double_spend_some_eth_to_userC(context, amount): | ||
invalid_tx = Transaction(DEPOSIT_TX_BLOCK, uid, 1, utils.normalize_address(userC)) | ||
invalid_tx.sign(utils.normalize_key(userA_key)) | ||
invalid_tx_merkle = SparseMerkleTree(257, {uid: invalid_tx.merkle_hash}) | ||
|
||
root_chain = container.get_root_chain() | ||
root_chain.functions.submitBlock(invalid_tx_merkle.root, TRANSFER_TX_2_BLOCK).transact({ | ||
'from': operator | ||
}) | ||
|
||
|
||
@when('userC starts to exit {amount:d} eth from plasma cash') | ||
def userC_starts_to_exit_some_eth_from_plasma_cash(context, amount): | ||
client = container.get_client() | ||
|
||
deposit_block = client.get_block(DEPOSIT_TX_BLOCK) | ||
deposit_tx = deposit_block.get_tx_by_uid(uid) | ||
deposit_block.merklize_transaction_set() | ||
deposit_tx_proof = deposit_block.merkle.create_merkle_proof(uid) | ||
|
||
# invalid tx doesn't exist in child chain | ||
invalid_tx = Transaction(DEPOSIT_TX_BLOCK, uid, 1, utils.normalize_address(userC)) | ||
invalid_tx.sign(utils.normalize_key(userA_key)) | ||
invalid_tx_merkle = SparseMerkleTree(257, {uid: invalid_tx.merkle_hash}) | ||
invalid_tx_proof = invalid_tx_merkle.create_merkle_proof(uid) | ||
|
||
root_chain = container.get_root_chain() | ||
root_chain.functions.startExit( | ||
rlp.encode(deposit_tx), | ||
deposit_tx_proof, | ||
DEPOSIT_TX_BLOCK, | ||
rlp.encode(invalid_tx), | ||
invalid_tx_proof, | ||
TRANSFER_TX_2_BLOCK | ||
).transact({'from': userC}) | ||
time.sleep(5) | ||
|
||
|
||
@then('root chain got the start-exit record from double spending challenge') | ||
def root_chain_got_the_start_exit_record_from_double_spending_challenge(context): | ||
root_chain = container.get_root_chain() | ||
assert has_value(root_chain.functions.exits(uid).call({'from': userC})) | ||
|
||
|
||
@when('userB challenges the exit') | ||
def userC_challenges_the_exit(context): | ||
client = container.get_client() | ||
client.challenge_exit(userC, uid, tx_blk_num=TRANSFER_TX_1_BLOCK) | ||
time.sleep(5) | ||
|
||
|
||
@then('the challenge is successful and root chain cancels the exit') | ||
def the_challenge_is_successful_and_root_chain_cancels_the_exit(context): | ||
root_chain = container.get_root_chain() | ||
assert not has_value(root_chain.functions.exits(uid).call({'from': userB})) |
124 changes: 124 additions & 0 deletions
124
integration_tests/features/steps/challenge_history_flow.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import rlp | ||
import time | ||
|
||
from behave import given, then, when | ||
|
||
from integration_tests.features.utils import has_value | ||
from plasma_cash.dependency_config import container | ||
|
||
userA = '0xb83e232458A092696bE9717045d9A605FB0FEc2b' | ||
userB = '0x08d92dcA9038eA9433254996a2D4F08D43BE8227' | ||
userC = '0xDF29cFbD5d793Fa5B22D5c730A8E8450740C6f8f' | ||
userD = '0xc5016A1Dc1F2556FD237AbBa2681D221Edf31A20' | ||
operator_key = '0xa18969817c2cefadf52b93eb20f917dce760ce13b2ac9025e0361ad1e7a1d448' | ||
userA_key = '0xe4807cf08191b310fe1821e6e5397727ee6bc694e92e25115eca40114e3a4e6b' | ||
userB_key = '0xee092298d0c0db61969cc4466d57571cf3ca36ca62db94273d5c1513312aeb30' | ||
userC_key = '0x8af3051eb765261b245d586a88700e606431b199f2cce4c825d2b1921086b35c' | ||
eth_currency = '0x0000000000000000000000000000000000000000' | ||
uid = 1693390459388381052156419331572168595237271043726428428352746834777341368960 | ||
|
||
DEPOSIT_TX_BLOCK = 1 | ||
TRANSFER_TX_1_BLOCK = 2 | ||
TRANSFER_TX_2_BLOCK = 3 | ||
TRANSFER_TX_3_BLOCK = 4 | ||
|
||
|
||
@given('userA deposits {amount:d} eth in plasma cash') | ||
def userA_deposits_some_amount_of_eth_in_plasma_cash(context, amount): | ||
client = container.get_client() | ||
client.deposit( | ||
amount=amount, | ||
depositor=userA, | ||
currency=eth_currency | ||
) | ||
time.sleep(5) | ||
client.submit_block(operator_key) | ||
|
||
|
||
@given('userA transfers {amount:d} eth to userB') | ||
def userA_transfers_some_eth_to_userB(context, amount): | ||
prev_block = DEPOSIT_TX_BLOCK | ||
client = container.get_client() | ||
client.send_transaction(prev_block, uid, amount, userB, userA_key) | ||
client.submit_block(operator_key) | ||
|
||
|
||
@given('userB transfers {amount:d} eth to userC') | ||
def userB_transfers_some_eth_to_userC(context, amount): | ||
prev_block = TRANSFER_TX_1_BLOCK | ||
client = container.get_client() | ||
client.send_transaction(prev_block, uid, amount, userC, userB_key) | ||
client.submit_block(operator_key) | ||
|
||
|
||
@given('userC transfers {amount:d} eth to userD') | ||
def userC_transfers_some_eth_to_userD(context, amount): | ||
prev_block = TRANSFER_TX_2_BLOCK | ||
client = container.get_client() | ||
client.send_transaction(prev_block, uid, amount, userD, userC_key) | ||
client.submit_block(operator_key) | ||
|
||
|
||
@when('userD starts to exit {amount:d} eth from plasma cash') | ||
def userD_starts_to_exit_some_eth_from_plasma_cash(context, amount): | ||
client = container.get_client() | ||
client.start_exit( | ||
userD, | ||
uid, | ||
prev_tx_blk_num=TRANSFER_TX_2_BLOCK, | ||
tx_blk_num=TRANSFER_TX_3_BLOCK | ||
) | ||
time.sleep(5) | ||
client.submit_block(operator_key) | ||
|
||
|
||
@then('root chain got the start-exit record from history challenge') | ||
def root_chain_got_the_start_exit_record_from_history_challenge(context): | ||
root_chain = container.get_root_chain() | ||
assert has_value(root_chain.functions.exits(uid).call({'from': userD})) | ||
|
||
|
||
@when('userB challenges the exit history with deposit tx') | ||
def userC_challenges_the_spent_coin_exit(context): | ||
client = container.get_client() | ||
client.challenge_exit(userB, uid, tx_blk_num=DEPOSIT_TX_BLOCK) | ||
time.sleep(5) | ||
|
||
|
||
@then('root chain got the challenge record') | ||
def then_root_chain_got_the_challenge_record(context): | ||
client = container.get_client() | ||
deposit_block = client.get_block(DEPOSIT_TX_BLOCK) | ||
deposit_tx = deposit_block.get_tx_by_uid(uid) | ||
|
||
root_chain = container.get_root_chain() | ||
assert root_chain.functions.isChallengeExisted( | ||
uid, rlp.encode(deposit_tx) | ||
).call({'from': userB}) | ||
|
||
|
||
@when('userD responds to the history challenge') | ||
def userD_responds_to_the_history_challenge(context): | ||
client = container.get_client() | ||
deposit_block = client.get_block(DEPOSIT_TX_BLOCK) | ||
deposit_tx = deposit_block.get_tx_by_uid(uid) | ||
|
||
client.respond_challenge_exit( | ||
userD, | ||
rlp.encode(deposit_tx), | ||
uid, | ||
tx_blk_num=TRANSFER_TX_1_BLOCK | ||
) | ||
time.sleep(5) | ||
|
||
|
||
@then('root chain cancels the challenge') | ||
def then_root_chain_cancels_the_challenge(context): | ||
client = container.get_client() | ||
deposit_block = client.get_block(DEPOSIT_TX_BLOCK) | ||
deposit_tx = deposit_block.get_tx_by_uid(uid) | ||
|
||
root_chain = container.get_root_chain() | ||
assert not root_chain.functions.isChallengeExisted( | ||
uid, rlp.encode(deposit_tx) | ||
).call({'from': userD}) |
75 changes: 75 additions & 0 deletions
75
integration_tests/features/steps/challenge_spent_coin_flow.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import time | ||
|
||
from behave import given, then, when | ||
|
||
from integration_tests.features.utils import has_value | ||
from plasma_cash.dependency_config import container | ||
|
||
userA = '0xb83e232458A092696bE9717045d9A605FB0FEc2b' | ||
userB = '0x08d92dcA9038eA9433254996a2D4F08D43BE8227' | ||
userC = '0xDF29cFbD5d793Fa5B22D5c730A8E8450740C6f8f' | ||
operator_key = '0xa18969817c2cefadf52b93eb20f917dce760ce13b2ac9025e0361ad1e7a1d448' | ||
userA_key = '0xe4807cf08191b310fe1821e6e5397727ee6bc694e92e25115eca40114e3a4e6b' | ||
userB_key = '0xee092298d0c0db61969cc4466d57571cf3ca36ca62db94273d5c1513312aeb30' | ||
eth_currency = '0x0000000000000000000000000000000000000000' | ||
uid = 1693390459388381052156419331572168595237271043726428428352746834777341368960 | ||
|
||
DEPOSIT_TX_BLOCK = 1 | ||
TRANSFER_TX_1_BLOCK = 2 | ||
TRANSFER_TX_2_BLOCK = 3 | ||
|
||
|
||
@given('userA deposits {amount:d} eth in plasma cash') | ||
def userA_deposits_some_amount_of_eth_in_plasma_cash(context, amount): | ||
client = container.get_client() | ||
client.deposit( | ||
amount=amount, | ||
depositor=userA, | ||
currency=eth_currency | ||
) | ||
time.sleep(5) | ||
client.submit_block(operator_key) | ||
|
||
|
||
@given('userA transfers {amount:d} eth to userB') | ||
def userA_transfers_some_eth_to_userB(context, amount): | ||
prev_block = DEPOSIT_TX_BLOCK | ||
client = container.get_client() | ||
client.send_transaction(prev_block, uid, amount, userB, userA_key) | ||
client.submit_block(operator_key) | ||
|
||
|
||
@given('userB transfers {amount:d} eth to userC') | ||
def userB_transfers_some_eth_to_userC(context, amount): | ||
prev_block = TRANSFER_TX_1_BLOCK | ||
client = container.get_client() | ||
client.send_transaction(prev_block, uid, amount, userC, userB_key) | ||
client.submit_block(operator_key) | ||
|
||
|
||
@when('userB starts to exit {amount:d} eth from plasma cash') | ||
def userB_starts_to_exit_some_eth_from_plasma_cash(context, amount): | ||
client = container.get_client() | ||
client.start_exit(userB, uid, prev_tx_blk_num=DEPOSIT_TX_BLOCK, tx_blk_num=TRANSFER_TX_1_BLOCK) | ||
time.sleep(5) | ||
client.submit_block(operator_key) | ||
|
||
|
||
@then('root chain got the start-exit record from coin spent challenge') | ||
def root_chain_got_the_start_exit_record_from_coin_spent_challenge(context): | ||
root_chain = container.get_root_chain() | ||
assert has_value(root_chain.functions.exits(uid).call({'from': userB})) | ||
|
||
|
||
@when('userC challenges the coin spent exit') | ||
def userC_challenges_the_coin_spent_exit(context): | ||
client = container.get_client() | ||
client.challenge_exit(userC, uid, tx_blk_num=TRANSFER_TX_2_BLOCK) | ||
time.sleep(5) | ||
client.submit_block(operator_key) | ||
|
||
|
||
@then('the challenge is successful and root chain cancels the coin spent exit') | ||
def the_challenge_is_successful_and_root_chain_cancels_the_spent_coin_exit(context): | ||
root_chain = container.get_root_chain() | ||
assert not has_value(root_chain.functions.exits(uid).call({'from': userC})) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from web3.auto import w3 | ||
|
||
|
||
def address_equals(address1, address2): | ||
return w3.toChecksumAddress(address1) == w3.toChecksumAddress(address2) | ||
|
||
|
||
def has_value(obj): | ||
if len(obj) > 0: | ||
return obj[0] | ||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.