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_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 miner_send_tokens(address, amount, internal_api, external_api): spend_tx_obj = SpendTx(recipient_pubkey=address, amount=amount, fee=1) # populate account internal_api.post_spend_tx(spend_tx_obj) top = external_api.get_top() common.wait_until_height(external_api, top.height + 3)
def send_tokens_to_user_(address, tokens, fee, internal_api): def get_balance(k): return common.get_account_balance(internal_api, k).balance bal0 = get_balance(address) spend_tx_obj = SpendTx(recipient_pubkey=address, amount=tokens, fee=fee) internal_api.post_spend_tx(spend_tx_obj) wait(lambda: get_balance(address) == (bal0 + tokens), timeout_seconds=120, sleep_seconds=0.25)
def send_tokens(sender, address, tokens, fee, ext_api, int_api): spend_tx_obj = SpendTx(sender_id=sender['enc_pubk'], recipient_id=address, amount=tokens, fee=fee, ttl=100, payload="sending tokens") spend_tx = int_api.post_spend(spend_tx_obj).tx unsigned_tx = api_decode(spend_tx) signed_tx = integration.keys.sign_encode_tx(unsigned_tx, sender['privk']) return post_transaction(ext_api, signed_tx)
def send_tokens_to_unchanging_user(sender, address, tokens, fee, external_api, internal_api): spend_tx_obj = SpendTx(sender_id=sender['enc_pubk'], recipient_id=address, amount=tokens, fee=fee, ttl=100, payload="sending tokens") spend_tx = internal_api.post_spend(spend_tx_obj).tx unsigned_tx = base58_decode(spend_tx) signed_tx = integration.keys.sign_encode_tx(unsigned_tx, sender['privk']) external_api.post_transaction(Tx(tx=signed_tx))
def miner_send_tokens(address, amount, internal_api, external_api): spend_tx_obj = SpendTx( recipient_id=address, amount=amount, fee=1, ttl=100, payload="sending tokens") # populate account internal_api.post_spend_tx(spend_tx_obj) top = external_api.get_top_block() common.wait_until_height(external_api, top.height + 3)
def send_tokens_to_user(user, test_settings, internal_api, external_api): spend_tx_obj = SpendTx( recipient_pubkey=test_settings[user]["pubkey"], amount=test_settings[user]["amount"], fee=test_settings[user]["fee"]) # populate Alice's account internal_api.post_spend_tx(spend_tx_obj) top = external_api.get_top() common.wait_until_height(external_api, top.height + 3) balance_obj = common.get_account_balance(internal_api, pub_key=test_settings[user]["pubkey"]) print(user.capitalize() + "'s balance is now " + str(balance_obj.balance))
def send_tokens_to_name(name, tokens, sender_address, private_key, external_api): name_entry = external_api.get_name(name) resolved_address = json.loads(name_entry.pointers)['account_pubkey'] print("Name " + name + " resolved to address " + resolved_address) unsigned_spend = common.base58_decode(\ external_api.post_spend(\ SpendTx(sender=sender_address, recipient_pubkey=resolved_address, amount=tokens, fee=1)).tx) signed_spend = keys.sign_encode_tx(unsigned_spend, private_key) external_api.post_tx(Tx(tx=signed_spend)) top = external_api.get_top() common.wait_until_height(external_api, top.height + 3)
def test_spend_tx_creation(self): """ Very dummy spend transaction creation test, Checking only that the API does not throw an error now. TODO: Rewrite to proper user story, when created transaction is propagated to peers etc.. """ api = self.INT_API['dev1'] spend_tx_obj = SpendTx( recipient_pubkey= "BAAggMEhrC3ODBqlYeQ6dk00F87AKMkV6kkyhgfJ/luOzGUC+4APxFkVgAYPai3TjSyLRObv0GeDACg1ZxwnfHY=", amount=0, fee=0) api.post_spend_tx(spend_tx_obj)
def send_tokens_to_name(name, tokens, sender_address, private_key, external_api): name_entry = external_api.get_name(name) resolved_address = name_entry.pointers[0].id print("Name " + name + " resolved to address " + resolved_address) unsigned_spend = common.base58_decode(\ external_api.post_spend(\ SpendTx(sender_id=sender_address, recipient_id=resolved_address, amount=tokens, fee=1,\ ttl=100, payload="foo")).tx) signed_spend = keys.sign_encode_tx(unsigned_spend, private_key) external_api.post_tx(Tx(tx=signed_spend)) top = external_api.get_top_block() common.wait_until_height(external_api, top.height + 3)
def send_tokens_to_unchanging_user(address, tokens, fee, external_api, internal_api): def get_balance(k): return get_account_balance(external_api, internal_api, k).balance bal0 = get_balance(address) spend_tx_obj = SpendTx(recipient_pubkey=address, amount=tokens, fee=fee, ttl=100, payload="sending tokens") internal_api.post_spend_tx(spend_tx_obj) wait(lambda: get_balance(address) == (bal0 + tokens), timeout_seconds=120, sleep_seconds=0.25)
def send_tokens_to_unchanging_user(beneficiary, address, tokens, fee, external_api, internal_api): import keys def get_balance(k): return get_account_balance(external_api, internal_api, k).balance bal0 = get_balance(address) spend_tx_obj = SpendTx(sender_id=beneficiary['enc_pubk'], recipient_id=address, amount=tokens, fee=fee, ttl=100, payload="sending tokens") spend_tx = internal_api.post_spend(spend_tx_obj).tx unsigned_tx = base58_decode(spend_tx) signed_tx = keys.sign_encode_tx(unsigned_tx, beneficiary['privk']) external_api.post_transaction(Tx(tx=signed_tx)) wait(lambda: get_balance(address) == (bal0 + tokens), timeout_seconds=20, sleep_seconds=0.25)
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_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_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)