def test_contract_create(): test_settings = settings["test_contract_create"] (node, (root_dir, external_api, top)) = setup_node_with_tokens(test_settings, "node") internal_api = common.internal_api(node) private_key = keys.new_private() public_key = keys.public_key(private_key) alice_address = keys.address(public_key) test_settings["alice"]["pubkey"] = alice_address send_tokens_to_user("alice", test_settings, external_api, internal_api) encoded_tx, contract_address = get_unsigned_contract_create( alice_address, test_settings["create_contract"], external_api) print("Unsigned encoded transaction: " + encoded_tx) print("Contract address: " + contract_address) unsigned_tx = common.base58_decode(encoded_tx) tx = common.decode_unsigned_tx(unsigned_tx) print("Unsigned decoded transaction: " + str(tx)) # make sure same tx assert_equals(tx['type'], 'contract_create_tx') assert_equals(tx['owner'], common.base58_decode(test_settings["alice"]["pubkey"])) assert_equals(tx['vm_version'], test_settings["create_contract"]["vm_version"]) assert_equals(tx['deposit'], test_settings["create_contract"]["deposit"]) assert_equals(tx['amount'], test_settings["create_contract"]["amount"]) assert_equals(tx['gas'], test_settings["create_contract"]["gas"]) assert_equals(tx['gas_price'], test_settings["create_contract"]["gas_price"]) assert_equals(tx['fee'], test_settings["create_contract"]["fee"]) signed = keys.sign_verify_encode_tx(unsigned_tx, private_key, public_key) print("Signed transaction " + signed) alice_balance0 = common.get_account_balance(external_api, internal_api, pub_key=alice_address).balance tx_object = Tx(tx=signed) external_api.post_tx(tx_object) top = external_api.get_top_block() common.wait_until_height(external_api, top.height + 3) alice_balance = common.get_account_balance(external_api, internal_api, pub_key=alice_address).balance assert_equals( alice_balance0, alice_balance + test_settings["create_contract"]["fee"] + test_settings["create_contract"]["gas_used"] + test_settings["create_contract"]["deposit"] + test_settings["create_contract"]["amount"]) print("Fee was consumed, transaction is part of the chain") cleanup(node, root_dir)
def setup_test(test): import common import keys test_settings = _test_settings_(test) node = test_settings['miner_node'] beneficiary = common.setup_beneficiary() node_root_dir = _setup_node_(node, beneficiary, test_settings['blocks_to_mine']) ext_api = common.external_api(node) int_api = common.internal_api(node) users = { k: { 'encoded_pub_key': v['key_pair']['enc_pubk'], 'pub_key': v['key_pair']['pubk'], 'priv_key': v['key_pair']['privk'] } for (k, v) in _setup_users_(beneficiary, test_settings['users'], test_settings['min_spend_tx_fee'], ext_api, int_api).items() } test.globs['epoch_node'] = { '_root_dir_': node_root_dir, 'external_api': ext_api, 'internal_api': int_api } test.globs['users'] = users
def test_send_by_name(): # Bob registers a name 'bob.aet' # Alice should be able to send tokens to Bob using that name test_settings = settings["test_send_by_name"] (node, (root_dir, ext_api, top)) = setup_node_with_tokens(test_settings, "miner") int_api = common.internal_api(node) alice_private_key = keys.new_private() alice_public_key = keys.public_key(alice_private_key) alice_address = keys.address(alice_public_key) bob_private_key = keys.new_private() bob_public_key = keys.public_key(bob_private_key) bob_address = keys.address(bob_public_key) # initial balances - amounts that the miner should send them alice_init_balance = test_settings["send_tokens"]["alice"] bob_init_balance = test_settings["send_tokens"]["bob"] # populate accounts with tokens miner_send_tokens(alice_address, alice_init_balance, int_api, ext_api) miner_send_tokens(bob_address, bob_init_balance, int_api, ext_api) # validate balances alice_balance0 = common.get_account_balance(ext_api, int_api, pub_key=alice_address).balance bob_balance0 = common.get_account_balance(ext_api, int_api, pub_key=bob_address).balance assert_equals(alice_balance0, alice_init_balance) assert_equals(bob_balance0, bob_init_balance) print("Alice balance is " + str(alice_balance0)) print("Bob balance is " + str(bob_balance0)) print("Bob address is " + bob_address) bob_name = test_settings["name_register"]["name"] register_name(bob_name, bob_address, ext_api, bob_private_key) print("Bob has registered " + bob_name) bob_balance1 = common.get_account_balance(ext_api, int_api, pub_key=bob_address).balance print("Bob balance is " + str(bob_balance1)) tokens_to_send = test_settings["spend_tx"]["amount"] print("Alice is about to send " + str(tokens_to_send) + " to " + bob_name) send_tokens_to_name(bob_name, tokens_to_send, alice_address, alice_private_key, ext_api) # validate balances alice_balance2 = common.get_account_balance(ext_api, int_api, pub_key=alice_address).balance bob_balance2 = common.get_account_balance(ext_api, int_api, pub_key=bob_address).balance print("Alice balance is " + str(alice_balance2)) print("Bob balance is " + str(bob_balance2)) # Alice's balance should be decresed by the amount being send and the fee (1) assert_equals(alice_balance2, alice_balance0 - tokens_to_send - 1) # Bob's balance should be incresed by the amount being send assert_equals(bob_balance2, bob_balance1 + tokens_to_send) # stop node common.stop_node(node) shutil.rmtree(root_dir)
def test_spend(): test_settings = settings["test_spend"] (root_dir, node, external_api, top) = setup_node_with_tokens(test_settings, "node") internal_api = common.internal_api(node) private_key = keys.new_private() public_key = keys.public_key(private_key) alice_address = keys.address(public_key) bob_address = test_settings["spend_tx"]["recipient"] test_settings["alice"]["pubkey"] = alice_address send_tokens_to_user("alice", test_settings, internal_api, external_api) spend_data_obj = SpendTx(sender=alice_address, recipient_pubkey=bob_address, amount=test_settings["spend_tx"]["amount"], fee=test_settings["spend_tx"]["fee"]) unsigned_spend_obj = external_api.post_spend(spend_data_obj) unsigned_spend_enc = unsigned_spend_obj.tx tx_hash = unsigned_spend_obj.tx_hash unsigned_tx = common.base58_decode(unsigned_spend_enc) unpacked_tx = common.unpack_tx(unsigned_tx) print("Tx " + str(common.parse_tx(unpacked_tx))) alice_balance0 = common.get_account_balance(internal_api, pub_key=alice_address).balance bob_balance0 = common.get_account_balance(internal_api, pub_key=bob_address).balance signed = keys.sign_verify_encode_tx(unsigned_tx, unpacked_tx, private_key, public_key) print("Signed transaction " + signed) print("Tx hash " + tx_hash) tx_object = Tx(tx=signed) external_api.post_tx(tx_object) top = external_api.get_top() common.wait_until_height(external_api, top.height + 3) alice_balance = common.get_account_balance(internal_api, pub_key=alice_address).balance bob_balance = common.get_account_balance(internal_api, pub_key=bob_address).balance tx = external_api.get_tx( tx_hash=tx_hash) # it is there - either in mempool or in a block print("Alice balance now is " + str(alice_balance)) print("Bob balance now is " + str(bob_balance)) print("Balances are updated, transaction has been executed") assert_equals( alice_balance0, alice_balance + test_settings["spend_tx"]["fee"] + test_settings["spend_tx"]["amount"]) assert_equals(bob_balance0, bob_balance - test_settings["spend_tx"]["amount"]) cleanup(node, root_dir)
def test_contract_create(): test_settings = settings["test_contract_create"] (root_dir, node, external_api, top) = setup_node_with_tokens(test_settings, "node") internal_api = common.internal_api(node) send_tokens_to_user("alice", test_settings, internal_api, external_api) encoded_tx = get_unsigned_contract_create(test_settings["alice"]["pubkey"], test_settings["create_contract"], external_api) print("Unsigned encoded transaction: " + encoded_tx) unsigned_tx = common.base58_decode(encoded_tx) unpacked_tx = common.unpack_tx(unsigned_tx) tx = common.parse_tx(unpacked_tx) print("Unsigned decoded transaction: " + str(tx)) # make sure same tx assert_equals(tx['type'], 'contract_create') assert_equals(tx['owner'], common.base58_decode(test_settings["alice"]["pubkey"])) assert_equals(tx['vm_version'], test_settings["create_contract"]["vm_version"]) assert_equals(tx['deposit'], test_settings["create_contract"]["deposit"]) assert_equals(tx['amount'], test_settings["create_contract"]["amount"]) assert_equals(tx['gas'], test_settings["create_contract"]["gas"]) assert_equals(tx['gas_price'], test_settings["create_contract"]["gas_price"]) assert_equals(tx['fee'], test_settings["create_contract"]["fee"]) code = bytearray.fromhex(test_settings["create_contract"]["code"][2:]) # without 0x assert_equals(tx['code'], code) call_data = bytearray.fromhex(test_settings["create_contract"]["call_data"][2:]) # without 0x assert_equals(tx['call_data'], call_data) signature = bytearray(list(map(int, test_settings["create_contract"]["signature"].split(",")))) signed = common.encode_signed_tx(unpacked_tx, [signature]) print("Signed transaction " + signed) alice_balance0 = common.get_account_balance(internal_api, pub_key=test_settings["alice"]["pubkey"]).balance tx_object = Tx(tx=signed) external_api.post_tx(tx_object) top = external_api.get_top() common.wait_until_height(external_api, top.height + 3) alice_balance = common.get_account_balance(internal_api, pub_key=test_settings["alice"]["pubkey"]).balance assert_equals(alice_balance0, alice_balance + test_settings["create_contract"]["fee"]) cleanup(node, root_dir)
def test_compile_and_call_id(): # Alice should be able to compile a sophia contract with an identity # function into bytecode and call it. test_settings = settings["test_compile_and_call_id"] (root_dir, node, external_api) = setup_node(test_settings, "alice") internal_api = common.internal_api(node) bytecode = read_id_contract(internal_api) # Call contract bytecode call_input = ContractCallInput("sophia", bytecode, "main", "42") call_result = internal_api.call_contract(call_input) assert_regexp_matches(call_result.out, '0x.*') # stop node common.stop_node(node) shutil.rmtree(root_dir)
def test_contract_on_chain_call_off_chain(): test_settings = settings["test_contract_call"] create_settings = settings["test_contract_create"] beneficiary = common.setup_beneficiary() (node, (root_dir, external_api, top)) = setup_node_with_tokens(test_settings, beneficiary, "node") internal_api = common.internal_api(node) private_key = keys.new_private() public_key = keys.public_key(private_key) alice_address = keys.address(public_key) test_settings["alice"]["pubkey"] = alice_address send_tokens_to_user(beneficiary, "alice", test_settings, external_api, internal_api) ## create contract encoded_tx, encoded_contract_id = get_unsigned_contract_create( alice_address, create_settings["create_contract"], external_api, internal_api) unsigned_tx = common.base58_decode(encoded_tx) signed = keys.sign_verify_encode_tx(unsigned_tx, private_key, public_key) alice_balance0 = common.get_account_balance(external_api, internal_api, pub_key=alice_address).balance tx_object = Tx(tx=signed) external_api.post_transaction(tx_object) top = external_api.get_top_block() common.wait_until_height(external_api, top.height + 3) call_contract = test_settings["contract_call"] call_input = ContractCallInput("sophia-address", encoded_contract_id,\ call_contract["data"]["function"],\ call_contract["data"]["argument"]) result = internal_api.call_contract(call_input) assert_equals( '0x000000000000000000000000000000000000000000000000000000000000002a', result.out) cleanup(node, root_dir)
def test_id_call(): # Alice should be able to call the id function in # an Id contract. test_settings = settings["test_id_call"] (root_dir, node, external_api) = setup_node(test_settings, "alice") internal_api = common.internal_api(node) bytecode = read_id_contract(internal_api) call_input = ContractCallInput("sophia", bytecode, "main", "42") result = internal_api.call_contract(call_input) print(result) retval = '0x000000000000000000000000000000000000000000000000000000000000002a' assert_equals(result.out, retval) # stop node common.stop_node(node) shutil.rmtree(root_dir)
def test_encode_id_call(): # Alice should be able to encode a call to a function in # a sophia contract. test_settings = settings["test_encode_id_call"] (root_dir, node, external_api) = setup_node(test_settings, "alice") internal_api = common.internal_api(node) bytecode = read_id_contract(internal_api) call_input = ContractCallInput("sophia", bytecode, "main", "42") result = internal_api.encode_calldata(call_input) calldata = '0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000046d61696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a' assert_equals(result.calldata, calldata) # stop node common.stop_node(node) shutil.rmtree(root_dir)
def test_solidity_greeter(): # Alice should be able to initialize # the gretee Solidity contract. test_settings = settings["test_id_call"] (root_dir, node, api) = setup_node(test_settings, "alice") internal_api = common.internal_api(node) bytecode = greeter_code() call_input = ContractCallInput("evm", bytecode, "", "0x00") result = internal_api.call_contract(call_input) print(result) generatedcode = greeter_generated_code() assert_equals(result.out, generatedcode) # stop node common.stop_node(node) shutil.rmtree(root_dir)
def test_call_solidity_greeter(): # Alice should be able to call the greet function in # an greete Solidity contract. test_settings = settings["test_id_call"] (root_dir, node, api) = setup_node(test_settings, "alice") internal_api = common.internal_api(node) bytecode = greeter_generated_code() setGreeting = "0xa4136862" HelloWorld = "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d48656c6c6c6f20576f726c642100000000000000000000000000000000000000" call_input = ContractCallInput("evm", bytecode, "", setGreeting + HelloWorld) result = internal_api.call_contract(call_input) print(result) generatedcode = greeter_generated_code() # assert_equals(result.out, generatedcode) # stop node common.stop_node(node) shutil.rmtree(root_dir)
def test_not_enough_tokens(): # Bob should not be able to send more tokens than he has # # Let's say Bob has 100 tokens. He should not be able to send more than # 100 tokens to Alice. # # If there's an incoming but unconfirmed deposit into Bob's account then Bob # should not be able to use the incoming tokens until the spend transaction # they are in is confirmed. test_settings = settings["test_not_enough_tokens"] coinbase_reward = common.coinbase_reward() (root_dir, bob_node, bob_api, bob_top) = setup_node_with_tokens(test_settings, "bob") bob_internal_api = common.internal_api(bob_node) def get_bob_balance(height): return common.get_account_balance_at_height(bob_api, bob_internal_api, height) def get_alice_balance(height): k = test_settings["spend_tx"]["alice_pubkey"] return common.get_account_balance_at_height(bob_api, bob_internal_api, height, pub_key=k) spend_tx_amt = test_settings["spend_tx"]["amount"] spend_tx_fee = test_settings["spend_tx"]["fee"] bob_balance = get_bob_balance(bob_top.height) bob_has_not_enough_tokens = bob_balance.balance < spend_tx_amt + spend_tx_fee assert_equals(bob_has_not_enough_tokens, True) print("Bob initial balance is " + str(bob_balance.balance) + " and he will try to spend " + str(spend_tx_amt + spend_tx_fee)) alice_balance0 = get_alice_balance(bob_top.height) # Bob tries to send some tokens to Alice spend_tx_obj = SpendTx( recipient_pubkey=test_settings["spend_tx"]["alice_pubkey"], amount=spend_tx_amt, fee=spend_tx_fee) print("Bob's spend_tx is " + str(spend_tx_obj)) bob_internal_api.post_spend_tx(spend_tx_obj) print("Transaction sent") bob_top_after_tx = bob_api.get_top() print("Waiting for a few blocks to be mined") checked_height = bob_top_after_tx.height + 3 common.wait_until_height(bob_api, checked_height) # ensure Alice balance had not changed alice_balance1 = get_alice_balance(checked_height) print("Alice's balance is now " + str(alice_balance1.balance)) assert_equals(alice_balance1.balance, alice_balance0.balance) # ensure Bob not debited # Since Bob had mined the block he is receiving the coinbase_reward blocks_mined = checked_height - bob_top.height print("Coinbase reward is " + str(coinbase_reward) + ", had mined " + str(blocks_mined) + " blocks") expected_balance = bob_balance.balance + coinbase_reward * blocks_mined bob_new_balance = get_bob_balance(checked_height) print("Bob's balance (with coinbase rewards) is now " + str(bob_new_balance.balance)) assert_equals(bob_new_balance.balance, expected_balance) # stop node common.stop_node(bob_node) shutil.rmtree(root_dir)
def test_node_discovery_from_common_friend(): """ Test node discovery (from common friend peer) Assuming Carol's node only knows about Bob upon startup and that Alice's node knows Bob, Carol's node should be able to discover Alice and sync with her node. """ test_settings = settings["test_node_discovery_from_common_friend"] alice_node = test_settings["nodes"]["alice"] bob_node = test_settings["nodes"]["bob"] carol_node = test_settings["nodes"]["carol"] # prepare a dir to hold the configs root_dir = tempfile.mkdtemp() # Alice's config: only peer is Bob alice_peers = """\ peers: - "aenode://pp$28uQUgsPcsy7TQwnRxhF8GMKU4ykFLKsgf4TwDwPMNaSCXwWV8@localhost:3025" """ alice_user_config = make_peers_user_config(root_dir, "alice_epoch.yaml", "node1", "3015", alice_peers, "true") # Bob's config: no peers bob_peers = "peers: []" bob_user_config = make_peers_user_config(root_dir, "bob_epoch.yaml", "node2", "3025", bob_peers, "false") # Carol's config: only peer is Bob carol_peers = """\ peers: - "aenode://pp$28uQUgsPcsy7TQwnRxhF8GMKU4ykFLKsgf4TwDwPMNaSCXwWV8@localhost:3025" """ carol_user_config = make_peers_user_config(root_dir, "carol_epoch.yaml", "node3", "3035", carol_peers, "false") # start Alice's node common.start_node(alice_node, alice_user_config) alice_api = common.external_api(alice_node) # Insert some blocks in Alice's chain blocks_to_mine = test_settings["blocks_to_mine"] common.wait_until_height(alice_api, blocks_to_mine) alice_top = alice_api.get_top_block() assert_true(alice_top.height >= blocks_to_mine) # Now Alice has at least blocks_to_mine blocks # start the other nodes common.start_node(bob_node, bob_user_config) common.start_node(carol_node, carol_user_config) # Check that Carol syncs with Alice's chain carol_api = common.external_api(carol_node) common.wait_until_height(carol_api, alice_top.height) assert_equals( carol_api.get_block_by_hash(alice_top.hash).height, alice_top.height) # Check that Carol discovers Alice as a peer carol_int_api = common.internal_api(carol_node) wait( lambda: 'aenode://[email protected]:3015' in get_peers(carol_int_api), timeout_seconds=20, sleep_seconds=1) # cleanup common.stop_node(alice_node) common.stop_node(bob_node) common.stop_node(carol_node) shutil.rmtree(root_dir)
def test_successful(): # Alice should be able to create a spend transaction to send tokens to # Bob. In a controlled environment, Alice should see her transaction # appear in the next block or two that are added to the blockchain. # # Once that happens, Alice should see her account debited and Bob's # account credited with the same number of tokens. # # The debit/credit should not happen until the transaction is confirmed, # e.g. included in at least one block in the chain. test_settings = settings["test_successful"] coinbase_reward = common.coinbase_reward() (root_dir, alice_node, alice_api, alice_top) = setup_node_with_tokens(test_settings, "alice") alice_internal_api = common.internal_api(alice_node) spend_tx_amt = test_settings["spend_tx"]["amount"] spend_tx_fee = test_settings["spend_tx"]["fee"] alice_balance = common.get_account_balance(alice_internal_api) alice_has_enough_tokens = alice_balance.balance >= spend_tx_amt + spend_tx_fee assert_equals(alice_has_enough_tokens, True) print("Alice initial balance is " + str(alice_balance.balance)) bob_balance0 = common.get_account_balance( alice_internal_api, pub_key=test_settings["spend_tx"]["bob_pubkey"]) # Alice sends some tokens to Bob alice_internal_api = common.internal_api(alice_node) spend_tx_obj = SpendTx( recipient_pubkey=test_settings["spend_tx"]["bob_pubkey"], amount=spend_tx_amt, fee=spend_tx_fee) print("Alice's spend_tx is " + str(spend_tx_obj)) alice_internal_api.post_spend_tx(spend_tx_obj) print("Transaction sent") # ensure Alice balance had not changed alice_balance1 = common.get_account_balance(alice_internal_api) assert_equals(alice_balance.balance, alice_balance1.balance) # ensure Bob balance had not changed bob_balance1 = common.get_account_balance( alice_internal_api, pub_key=test_settings["spend_tx"]["bob_pubkey"]) assert_equals(bob_balance1.balance, bob_balance0.balance) # wait for a block to be mined print("Waiting for a next block to be mined") common.wait_until_height(alice_api, alice_top.height + 1) alice_new_top = alice_api.get_top() alice_new_balance = common.get_account_balance(alice_internal_api) blocks_mined = alice_new_top.height - alice_top.height # Since Alice had mined the block she is receiving the fee and the # coinbase_reward # Alice should have # tokens = old_balance - spent_amt - spend_tx + spent_fee + coinbase_reward expected_balance = alice_balance.balance - spend_tx_amt + coinbase_reward * blocks_mined assert_equals(alice_new_balance.balance, expected_balance) bob_balance = common.get_account_balance( alice_internal_api, pub_key=test_settings["spend_tx"]["bob_pubkey"]) print("Coinbase reward is " + str(coinbase_reward) + ", had mined " + str(blocks_mined) + " blocks") print("Alice's balance (with a coinbase reward) is now " + str(alice_new_balance.balance)) print("Bob's balance is now " + str(bob_balance.balance)) assert_equals(bob_balance.balance, spend_tx_amt) # stop node common.stop_node(alice_node) shutil.rmtree(root_dir)
def test_node_discovery(): """ Test node discovery Assuming Carol's node only knows about Bob upon startup and that Bob's node knows Alice, Carol's node should be able to discover Alice and sync with her node. """ test_settings = settings["test_node_discovery"] alice_node = test_settings["nodes"]["alice"] bob_node = test_settings["nodes"]["bob"] carol_node = test_settings["nodes"]["carol"] alice_peer_url = node_peer_url(alice_node) bob_peer_url = node_peer_url(bob_node) carol_peer_url = node_peer_url(carol_node) # prepare a dir to hold the configs root_dir = tempfile.mkdtemp() # Alice's config: no peers alice_sys_config = make_peers_config(root_dir, "alice.config", alice_peer_url, "node1", "3015", '{peers, []},', mining=True) print("\nAlice has address " + alice_peer_url + " and no peers") # Bob's config: only peer is Alice bob_peers = ' {peers, [<<"aenode://pp$HdcpgTX2C1aZ5sjGGysFEuup67K9XiFsWqSPJs4RahEcSyF7X@localhost:3015">>]}, ' bob_sys_config = make_peers_config(root_dir, "bob.config", bob_peer_url, "node2", "3025", bob_peers, mining=False) print("Bob has address " + bob_peer_url + " and peers [" + alice_peer_url + "]") # Carol's config: only peer is Bob carol_peers = ' {peers, [<<"aenode://pp$28uQUgsPcsy7TQwnRxhF8GMKU4ykFLKsgf4TwDwPMNaSCXwWV8@localhost:3025">>]}, ' carol_sys_config = make_peers_config(root_dir, "carol.config", carol_peer_url, "node3", "3035", carol_peers, mining=False) print("Carol has address " + carol_peer_url + " and peers [" + bob_peer_url + "]") # start Alice's node common.start_node(alice_node, alice_sys_config) alice_api = common.external_api(alice_node) # Insert some blocks in Alice's chain blocks_to_mine = test_settings["blocks_to_mine"] common.wait_until_height(alice_api, blocks_to_mine) alice_top = alice_api.get_top() assert_true(alice_top.height >= blocks_to_mine) # Now Alice has at least blocks_to_mine blocks # start the other nodes common.start_node(bob_node, bob_sys_config) common.start_node(carol_node, carol_sys_config) # Check that Carol syncs with Alice's chain carol_api = common.external_api(carol_node) common.wait_until_height(carol_api, alice_top.height) assert_equals( carol_api.get_block_by_hash(alice_top.hash).height, alice_top.height) # Check that Carol discovers Alice as a peer carol_int_api = common.internal_api(carol_node) def carol_peers(): peers = carol_int_api.get_peers().peers print("Peers: " + str(peers)) return peers wait( lambda: 'aenode://pp$HdcpgTX2C1aZ5sjGGysFEuup67K9XiFsWqSPJs4RahEcSyF7X@localhost:3015' in carol_peers(), timeout_seconds=20, sleep_seconds=1) # cleanup common.stop_node(alice_node) common.stop_node(bob_node) common.stop_node(carol_node) shutil.rmtree(root_dir)
def test_spend(): # Alice should be able to create a spend transaction to send tokens to # Bob. In a controlled environment, Alice should see her transaction # appear in the next block or two that are added to the blockchain. # # Once that happens, Alice should see her account debited and Bob's # account credited with the same number of tokens. # # The debit/credit should not happen until the transaction is confirmed, # e.g. included in at least one block in the chain. # Setup test_settings = settings["test_spend"] (root_dir, node, external_api, top) = setup_node_with_tokens(test_settings, "node") internal_api = common.internal_api(node) private_key = keys.new_private() public_key = keys.public_key(private_key) alice_address = keys.address(public_key) bob_address = test_settings["spend_tx"]["recipient"] test_settings["alice"]["pubkey"] = alice_address send_tokens_to_user("alice", test_settings, external_api, internal_api) alice_balance0 = common.get_account_balance(external_api, internal_api, pub_key=alice_address).balance bob_balance0 = common.get_account_balance(external_api, internal_api, pub_key=bob_address).balance # Alice creates spend tx spend_data_obj = SpendTx( sender=alice_address, recipient_pubkey=bob_address, amount=test_settings["spend_tx"]["amount"], fee=test_settings["spend_tx"]["fee"], ttl=100, payload="foo") unsigned_spend_obj = external_api.post_spend(spend_data_obj) unsigned_spend_enc = unsigned_spend_obj.tx unsigned_tx = common.base58_decode(unsigned_spend_enc) # Alice signs spend tx signed = keys.sign_verify_encode_tx(unsigned_tx, private_key, public_key) tx_hash = keys.tx_hash_from_signed_encoded(signed) print("Tx hash " + tx_hash) print("Signed transaction " + signed) # Alice posts spend tx tx_object = Tx(tx=signed) external_api.post_tx(tx_object) _ = external_api.get_tx(tx_hash=tx_hash) # it is there - either in mempool or in a block # Wait until spend tx is mined wait(lambda: common.get_account_balance(external_api, internal_api, pub_key=alice_address).balance < alice_balance0, timeout_seconds=120, sleep_seconds=0.25) _ = external_api.get_tx(tx_hash=tx_hash) # it is there - shall be in a block print("Tx in chain ") # Check that Alice was debited and Bob was credited alice_balance = common.get_account_balance(external_api, internal_api, pub_key=alice_address).balance bob_balance = common.get_account_balance(external_api, internal_api, pub_key=bob_address).balance print("Alice balance now is " + str(alice_balance)) print("Bob balance now is " + str(bob_balance)) assert_equals(alice_balance0, alice_balance + test_settings["spend_tx"]["fee"] + test_settings["spend_tx"]["amount"]) assert_equals(bob_balance0, bob_balance - test_settings["spend_tx"]["amount"]) # Cleanup cleanup(node, root_dir)
def test_contract_call(): test_settings = settings["test_contract_call"] create_settings = settings["test_contract_create"] (root_dir, node, external_api, top) = setup_node_with_tokens(test_settings, "node") internal_api = common.internal_api(node) private_key = keys.new_private() public_key = keys.public_key(private_key) alice_address = keys.address(public_key) test_settings["alice"]["pubkey"] = alice_address send_tokens_to_user("alice", test_settings, external_api, internal_api) ## create contract encoded_tx, encoded_contract_address = get_unsigned_contract_create(alice_address, create_settings["create_contract"], external_api) unsigned_tx = common.base58_decode(encoded_tx) signed = keys.sign_verify_encode_tx(unsigned_tx, private_key, public_key) alice_balance0 = common.get_account_balance(external_api, internal_api, pub_key=alice_address).balance tx_object = Tx(tx=signed) external_api.post_tx(tx_object) top = external_api.get_top() common.wait_until_height(external_api, top.height + 3) alice_balance = common.get_account_balance(external_api, internal_api, pub_key=alice_address).balance # assert contract created: call_contract = test_settings["contract_call"] assert_equals(alice_balance0, alice_balance + create_settings["create_contract"]["fee"] + create_settings["create_contract"]["gas_used"] + create_settings["create_contract"]["deposit"] + create_settings["create_contract"]["amount"]) call_input = ContractCallInput("sophia", create_settings["create_contract"]["code"],\ call_contract["data"]["function"],\ call_contract["data"]["argument"]) result = external_api.call_contract(call_input) contract_call_obj = ContractCallData( caller=test_settings["alice"]["pubkey"], contract=encoded_contract_address, vm_version=call_contract["vm_version"], fee=call_contract["fee"], ttl=100, amount=call_contract["amount"], gas=call_contract["gas"], gas_price=call_contract["gas_price"], call_data=result.out) call_tx_obj = external_api.post_contract_call(contract_call_obj) encoded_call_tx = call_tx_obj.tx print("Unsigned encoded transaction: " + encoded_call_tx) unsigned_call_tx = common.base58_decode(encoded_call_tx) signed_call = keys.sign_verify_encode_tx(unsigned_call_tx, private_key, public_key) print("Signed transaction: " + signed_call) alice_balance0 = common.get_account_balance(external_api, internal_api, pub_key=alice_address).balance tx_object = Tx(tx=signed_call) external_api.post_tx(tx_object) top = external_api.get_top() common.wait_until_height(external_api, top.height + 3) alice_balance = common.get_account_balance(external_api, internal_api, pub_key=alice_address).balance # The call runs out of gas and all gas is consumed # assert contract called: assert_equals(alice_balance0, alice_balance + test_settings["contract_call"]["fee"] + test_settings["contract_call"]["gas"] + test_settings["contract_call"]["amount"]) print("Fee and gas was consumed, transaction is part of the chain") cleanup(node, root_dir)
def test_contract_call(): test_settings = settings["test_contract_call"] create_settings = settings["test_contract_create"] (root_dir, node, external_api, top) = setup_node_with_tokens(test_settings, "node") internal_api = common.internal_api(node) send_tokens_to_user("alice", test_settings, internal_api, external_api) ## create contract encoded_tx = get_unsigned_contract_create(test_settings["alice"]["pubkey"], create_settings["create_contract"], external_api) unsigned_tx = common.base58_decode(encoded_tx) unpacked_tx = common.unpack_tx(unsigned_tx) signature = bytearray(list(map(int, create_settings["create_contract"]["signature"].split(",")))) signed = common.encode_signed_tx(unpacked_tx,[signature]) alice_balance0 = common.get_account_balance(internal_api, pub_key=test_settings["alice"]["pubkey"]).balance tx_object = Tx(tx=signed) external_api.post_tx(tx_object) top = external_api.get_top() common.wait_until_height(external_api, top.height + 3) alice_balance = common.get_account_balance(internal_api, pub_key=test_settings["alice"]["pubkey"]).balance # assert contract created: call_contract = test_settings["contract_call"] assert_equals(alice_balance0, alice_balance + create_settings["create_contract"]["fee"]) call_input = ContractCallInput("ring", create_settings["create_contract"]["code"],\ call_contract["data"]["function"],\ call_contract["data"]["argument"]) result = external_api.call_contract(call_input) contract_call_obj = ContractCallData( caller=test_settings["alice"]["pubkey"], contract=call_contract["contract"], vm_version=call_contract["vm_version"], fee=call_contract["fee"], amount=call_contract["amount"], gas=call_contract["gas"], gas_price=call_contract["gas_price"], call_data=result.out) call_tx_obj = external_api.post_contract_call(contract_call_obj) encoded_call_tx = call_tx_obj.tx print("Unsigned encoded transaction: " + encoded_call_tx) unsigned_call_tx = common.base58_decode(encoded_call_tx) unpacked_call_tx = common.unpack_tx(unsigned_call_tx) tx = common.parse_tx(unpacked_call_tx) print("Unsigned decoded transaction: " + str(tx)) signature = bytearray(list(map(int, test_settings["contract_call"]["signature"].split(",")))) signed = common.encode_signed_tx(unpacked_call_tx,[signature]) print("Signed transaction: " + signed) alice_balance0 = common.get_account_balance(internal_api, pub_key=test_settings["alice"]["pubkey"]).balance tx_object = Tx(tx=signed) external_api.post_tx(tx_object) top = external_api.get_top() common.wait_until_height(external_api, top.height + 3) alice_balance = common.get_account_balance(internal_api, pub_key=test_settings["alice"]["pubkey"]).balance print("BALANCE0 " + str(alice_balance0)) print("BALANCE " + str(alice_balance)) # assert contract created: assert_equals(alice_balance0, alice_balance + test_settings["contract_call"]["fee"]) cleanup(node, root_dir)