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"] beneficiary = common.setup_beneficiary() (node, (root_dir, external_api, internal_api, top)) = setup_node_with_tokens(test_settings, beneficiary, "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 bob_address = test_settings["spend_tx"]["recipient"] send_tokens_to_user(beneficiary, "alice", test_settings, external_api, internal_api) alice_balance0 = common.get_account_balance(external_api, alice_address) bob_balance0 = common.get_account_balance(external_api, bob_address) print("Alice balance at start is " + str(alice_balance0)) print("Bob balance at start is " + str(bob_balance0)) # Alice creates spend tx print("Tx amount " + str(test_settings["spend_tx"]["amount"])) print("Tx fee " + str(test_settings["spend_tx"]["fee"])) spend_data_obj = SpendTx(sender_id=alice_address, recipient_id=bob_address, amount=test_settings["spend_tx"]["amount"], fee=test_settings["spend_tx"]["fee"], ttl=100, payload="foo") unsigned_spend_obj = internal_api.post_spend(spend_data_obj) unsigned_spend_enc = unsigned_spend_obj.tx unsigned_tx = common.api_decode(unsigned_spend_enc) # Alice signs spend tx signed = keys.sign_verify_encode_tx(unsigned_tx, private_key, public_key) # Alice posts spend tx common.ensure_transaction_posted(external_api, signed) # Check that Alice was debited and Bob was credited alice_balance = common.get_account_balance(external_api, alice_address) bob_balance = common.get_account_balance(external_api, bob_address) 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_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) 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"]) 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) 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() 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"]) print("Fee 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) 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, 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"]) 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=contract_address, 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) 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_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"] (root_dir, node, 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(): # 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"]) 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) print("Tx hash " + tx_hash) # Alice signs spend tx signed = keys.sign_verify_encode_tx(unsigned_tx, private_key, public_key) 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 key_pair(): import keys priv = keys.new_private() pub = keys.public_key(priv) return {'privk': priv, 'pubk': pub, 'enc_pubk': keys.address(pub)}
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"] beneficiary = common.setup_beneficiary() (node, (root_dir, ext_api, int_api, top)) = setup_node_with_tokens(test_settings, beneficiary, "miner") alice_private_key = keys.new_private() alice_public_key = keys.public_key(alice_private_key) alice_address = keys.address(alice_public_key) alice = {'privk': alice_private_key, 'enc_pubk': alice_address} 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 common.send_tokens_to_unchanging_user_and_wait_balance( beneficiary, alice_address, alice_init_balance, 1, ext_api, int_api) common.send_tokens_to_unchanging_user_and_wait_balance( beneficiary, bob_address, bob_init_balance, 1, ext_api, int_api) # validate balances alice_balance0 = common.get_account_balance(ext_api, alice_address) bob_balance0 = common.get_account_balance(ext_api, bob_address) 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, int_api, bob_private_key) print("Bob has registered " + bob_name) bob_balance1 = common.get_account_balance(ext_api, bob_address) 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) resolved_address = get_address_by_name(bob_name, ext_api) common.send_tokens_to_unchanging_user_and_wait_balance( alice, resolved_address, tokens_to_send, 1, ext_api, int_api) # validate balances alice_balance2 = common.get_account_balance(ext_api, alice_address) bob_balance2 = common.get_account_balance(ext_api, bob_address) 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_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"] beneficiary = common.setup_beneficiary() (node, (root_dir, ext_api, int_api, top)) = setup_node_with_tokens(test_settings, beneficiary, "miner") alice_address = keys.address(keys.public_key(keys.new_private())) bob_private_key = keys.new_private() bob_public_key = keys.public_key(bob_private_key) bob_address = keys.address(bob_public_key) bob = {'privk': bob_private_key, 'enc_pubk': bob_address} # 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, and validate balances common.send_tokens_to_unchanging_user_and_wait_balance( beneficiary, alice_address, alice_init_balance, 1, ext_api, int_api) common.send_tokens_to_unchanging_user_and_wait_balance( beneficiary, bob_address, bob_init_balance, 1, ext_api, int_api) alice_balance0 = common.get_account_balance(ext_api, alice_address) bob_balance0 = common.get_account_balance(ext_api, bob_address) print("Alice balance is " + str(alice_balance0)) print("Bob balance is " + str(bob_balance0)) assert_equals(alice_balance0, alice_init_balance) assert_equals(bob_balance0, bob_init_balance) # check that Bob is able to send less tokens than he has spend_tx_fee = test_settings["spend_tx"]["fee"] few_tokens_to_send = test_settings["spend_tx"]["small_amount"] print("Bob is about to send " + str(few_tokens_to_send) + " to Alice") common.send_tokens_to_unchanging_user_and_wait_balance( bob, alice_address, few_tokens_to_send, spend_tx_fee, ext_api, int_api) alice_balance1 = common.get_account_balance(ext_api, pub_key=alice_address) bob_balance1 = common.get_account_balance(ext_api, pub_key=bob_address) print("Alice balance is " + str(alice_balance1)) print("Bob balance is " + str(bob_balance1)) assert_equals(alice_balance1, alice_balance0 + few_tokens_to_send) assert_equals(bob_balance1, bob_balance0 - (few_tokens_to_send + spend_tx_fee)) # check that Bob is unable to send less tokens than he has many_tokens_to_send = test_settings["spend_tx"]["large_amount"] print("Bob is about to send " + str(many_tokens_to_send) + " to Alice") common.send_tokens_to_unchanging_user(bob, alice_address, many_tokens_to_send, spend_tx_fee, ext_api, int_api) common.wait_until_height(ext_api, ext_api.get_current_key_block().height + 3) alice_balance2 = common.get_account_balance(ext_api, pub_key=alice_address) bob_balance2 = common.get_account_balance(ext_api, pub_key=bob_address) print("Alice balance is " + str(alice_balance2)) print("Bob balance is " + str(bob_balance2)) assert_equals(alice_balance2, alice_balance1) assert_equals(bob_balance2, bob_balance1) # stop node common.stop_node(node) shutil.rmtree(root_dir)
def test_contract_call(): test_settings = settings["test_contract_call"] create_settings = settings["test_contract_create"] beneficiary = common.setup_beneficiary() (node, (root_dir, external_api, internal_api, top)) = setup_node_with_tokens(test_settings, beneficiary, "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, alice_address) common.ensure_transaction_posted(external_api, signed) alice_balance = common.get_account_balance(external_api, pub_key=alice_address) # 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"]) bytecode = read_id_contract(internal_api) call_input = ContractCallInput("sophia", bytecode, call_contract["data"]["function"], call_contract["data"]["argument"]) result = internal_api.call_contract(call_input) contract_call_obj = ContractCallTx( caller_id=test_settings["alice"]["pubkey"], contract_id=encoded_contract_id, 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 = internal_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, alice_address) common.ensure_transaction_posted(external_api, signed_call) alice_balance = common.get_account_balance(external_api, alice_address) # 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"] beneficiary = common.setup_beneficiary() (node, (root_dir, external_api, internal_api, top)) = setup_node_with_tokens(test_settings, beneficiary, "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.api_decode(encoded_tx) signed = keys.sign_verify_encode_tx(unsigned_tx, private_key, public_key) alice_balance0 = common.get_account_balance(external_api, alice_address) common.ensure_transaction_posted(external_api, signed) alice_balance = common.get_account_balance(external_api, pub_key=alice_address) # 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"]["gas_price"] + create_settings["create_contract"]["deposit"] + create_settings["create_contract"]["amount"]) bytecode = common.compile_contract(id_contract()) calldata = common.encode_calldata(id_contract(), call_contract["data"]["function"], call_contract["data"]["argument"]) ContractCallTx = internal_api.get_model('ContractCallTx') contract_call_obj = ContractCallTx( caller_id=test_settings["alice"]["pubkey"], contract_id=encoded_contract_id, abi_version=call_contract["abi_version"], fee=call_contract["fee"], ttl=100, amount=call_contract["amount"], gas=call_contract["gas"], gas_price=call_contract["gas_price"], call_data=calldata) call_tx_obj = internal_api.PostContractCall( body=contract_call_obj).response().result encoded_call_tx = call_tx_obj.tx print("Unsigned encoded transaction: " + encoded_call_tx) unsigned_call_tx = common.api_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, alice_address) common.ensure_transaction_posted(external_api, signed_call) alice_balance = common.get_account_balance(external_api, alice_address) assert_equals( alice_balance0, alice_balance + test_settings["contract_call"]["fee"] + test_settings["contract_call"]["amount"] + test_settings["contract_call"]["gas_used"] * test_settings["contract_call"]["gas_price"]) print("Fee and gas was consumed, transaction is part of the chain") cleanup(node, root_dir)