def cross_shard_txs(): """ Fixture for 2 cross shard transaction. Returned tuple has cx from s0 -> s1 as element 0, cx from s1 -> s0 as element 1. """ s0_test_tx = { "from": "one1ue25q6jk0xk3dth4pxur9e742vcqfwulhwqh45", "to": "one1t40su52axu207vgc6ymcmwe0xmml4njrskk2vf", # erupt concert hat tree anger discover disease town gasp lemon gesture fiber spread season mixture host awake tennis issue orbit member film winter glass "amount": "1000", "from-shard": 0, "to-shard": 1, "hash": "0xc0a84ec15fc3391089f20fa6b9cc90c654eb8dd2f6815297de89eef38ce4fe2b", "nonce": "0x0", "signed-raw-tx": "0xf86e80843b9aca008252088001945d5f0e515d3714ff3118d1378dbb2f36f7face43893635c9adc5dea000008027a03b38081f3ece7725f0a7ed2e6892ec58fb906add07682b0deb3ecc1fab6643d7a050b56eef0037a135b48a2da72a93fd4ce3f32cb1e52ec01e1ab70c8888d9f10a", } s1_test_tx = { "from": "one1t40su52axu207vgc6ymcmwe0xmml4njrskk2vf", "to": "one1qljfd3pnfjwr86ll6d0s6khcqhw8969p9l7fw3", # faculty pave mad mind siren unfold invite avocado teach engine mimic mouse frown topple match thunder syrup fame material feed occur kit install clog "amount": "500", "from-shard": 1, "to-shard": 0, "hash": "0x819b0d7902134dadd07851edba0e8694e60c1aee057a96d2ceb4a9118cee0298", "nonce": "0x0", "signed-raw-tx": "0xf86e80843b9aca0082520801809407e496c4334c9c33ebffd35f0d5af805dc72e8a1891b1ae4d6e2ef5000008027a06650086393f005a04ca83fb59e228e8ebd642bc293d3698bfc46dc0ee5d872cda00cfca823a0bc32abe40a133345427b81d5382bbe0c4333227c1912dcddd89e99", } txs = [None, None] # s0 -> s1 is element 0, s1 -> s0 is element 1 in_initially_funded = False for tx in initial_funding: if tx["to"] == s0_test_tx["from"] and tx["to-shard"] == s0_test_tx["from-shard"]: in_initially_funded = True break if not in_initially_funded: raise AssertionError(f"Test transaction from address {s0_test_tx['from']} " f"not found in set of initially funded accounts.") tx_response = get_transaction(s0_test_tx["hash"], s0_test_tx["from-shard"]) txs[0] = send_and_confirm_transaction(s0_test_tx) if tx_response is None else tx_response start_time = time.time() while time.time() - start_time < tx_timeout: tx_response = get_transaction(s1_test_tx["hash"], s1_test_tx["from-shard"]) if tx_response is not None: txs[1] = tx_response return tuple(txs) elif account.get_balance(s1_test_tx["from"], endpoint=endpoints[s1_test_tx["from-shard"]]) >= 1e18: txs[1] = send_and_confirm_transaction(s1_test_tx) return tuple(txs) raise AssertionError(f"Could not confirm cross shard transaction on 'to-shard' " f"(balance not updated) for tx: {json.dumps(s0_test_tx, indent=2)}")
def pytest_sessionstart(session): """ Start the test session by sending initial test funds. Will block until transactions are confirmed on-chain. """ assert util.is_active_shard(endpoints[0], delay_tolerance=20), "Shard 0 is not making progress..." assert util.is_active_shard(endpoints[1], delay_tolerance=20), "Shard 1 is not making progress..." # Send all txs. Note that this is the only place to break the txs invariant. for tx in initial_funding: response = base_request('hmy_sendRawTransaction', params=[tx["signed-raw-tx"]], endpoint=endpoints[tx["from-shard"]]) assert is_valid_json_rpc(response), f"Invalid JSON response: {response}" # Do not check for errors since resending initial txs is fine & failed txs will be caught in confirm timeout. # Confirm all txs within 2x timeout window (since all initial txs could be in 2 blocks). start_time = time.time() while time.time() - start_time <= 2 * tx_timeout: sent_txs = [] for tx in initial_funding: tx_response = get_transaction(tx["hash"], tx["from-shard"]) if (tx_response is not None): sent_txs.append(tx_response['blockNumber'] is not None) else: sent_txs.append(tx_response is not None) if all(sent_txs): return raise AssertionError("Could not confirm initial transactions on-chain.")
def deployed_contract(): """ Fixture to deploy a smart contract. Returns the transaction information (`contract_tx`) to be used by tests in this module. Note that this contract is the Migrations contract used by truffle. """ contract_tx = { "from": "one156wkx832t0nxnaq6hxawy4c3udmnpzzddds60a", "to": None, "amount": None, "from-shard": 0, "to-shard": 0, "hash": "0xa13414dd152173395c69a11e79dea31bf029660f747a42a53744181d05571e70", "nonce": "0x8", "signed-raw-tx": "0xf9025080843b9aca008366916c80808080b901fc608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061019c806100606000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063445df0ac146100465780638da5cb5b14610064578063fdacd576146100ae575b600080fd5b61004e6100dc565b6040518082815260200191505060405180910390f35b61006c6100e2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100da600480360360208110156100c457600080fd5b8101908080359060200190929190505050610107565b005b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561016457806001819055505b5056fea265627a7a723158209b80813a158b44af65aee232b44c0ac06472c48f4abbe298852a39f0ff34a9f264736f6c6343000510003227a03a3ad2b7c2934a8325fc04d04daad740d337bb1f589482bbb1d091e1be804d29a00c46772871866a34f254e6197a526bebc2067f75edc53c488b31d84e07c3c685", "code": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c8063445df0ac146100465780638da5cb5b14610064578063fdacd576146100ae575b600080fd5b61004e6100dc565b6040518082815260200191505060405180910390f35b61006c6100e2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100da600480360360208110156100c457600080fd5b8101908080359060200190929190505050610107565b005b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561016457806001819055505b5056fea265627a7a723158209b80813a158b44af65aee232b44c0ac06472c48f4abbe298852a39f0ff34a9f264736f6c63430005100032" } in_initially_funded = False for tx in initial_funding: if tx["to"] == contract_tx["from"] and tx["to-shard"] == contract_tx["from-shard"]: in_initially_funded = True break if not in_initially_funded: raise AssertionError(f"Test transaction from address {contract_tx['from']} " f"not found in set of initially funded accounts.") if get_transaction(contract_tx["hash"], contract_tx["from-shard"]) is None: tx = send_and_confirm_transaction(contract_tx) assert tx["hash"] == contract_tx["hash"], f"Expected contract transaction hash to be {contract_tx['hash']}, " \ f"got {tx['hash']}" return contract_tx
def test_get_transaction_by_block_number_and_index_v2(): reference_response = { "blockHash": "0x08ef4c7b1d24f27be157bdf9f053d3fd2fabc81037cf87f83b000804bc2e1c9f", "blockNumber": 4, "from": "one1zksj3evekayy90xt4psrz8h6j2v3hla4qwz4ur", "timestamp": 1594802478, "gas": 21000, "gasPrice": 1000000000, "hash": "0x5718a2fda967f051611ccfaf2230dc544c9bdd388f5759a42b2fb0847fc8d759", "input": "0x", "nonce": 0, "to": "one1v92y4v2x4q27vzydf8zq62zu9g0jl6z0lx2c8q", "transactionIndex": 0, "value": 100000000000000000000000, "shardID": 0, "toShardID": 0, "v": "0x28", "r": "0x76b6130bc018cedb9f8891343fd8982e0d7f923d57ea5250b8bfec9129d4ae22", "s": "0xfbc01c988d72235b4c71b21ce033d4fc5f82c96710b84685de0578cff075a0a" } init_tx_record = initial_funding[0] tx = get_transaction(init_tx_record["hash"], init_tx_record["from-shard"]) blk = blockchain.get_block_by_hash(tx["blockHash"], endpoint=endpoints[tx["shardID"]], include_full_tx=False) index, blk_num = blk["transactions"].index(init_tx_record["hash"]), tx["blockNumber"] raw_response = base_request("hmyv2_getTransactionByBlockNumberAndIndex", params=[int(blk_num, 16), index], endpoint=endpoints[init_tx_record["from-shard"]]) response = check_and_unpack_rpc_response(raw_response, expect_error=False) assert_valid_json_structure(reference_response, response) assert response["hash"] == init_tx_record["hash"], f"Expected transaction {init_tx_record['hash']}, " \ f"got {response['hash']}"
def test_pending_transactions_v2(): tx = { "from": "one1u57rlv5q82deja6ew2l9hdy7ag3dwnw57x8s9t", "to": "one1zchjhmsxksamlxuv7h3k9h5aeury670n2jck2u", # kit attack eternal net bronze grace apple evil market spin evil tragic kid capital noble future shrimp gossip flee wonder album ahead catalog crawl "amount": "1000", "from-shard": 0, "to-shard": 0, "hash": "0x78324d91e69bdb14f4d0948bbad4ffc8bf309d4cf3e49c4c9a6871d02910c234", "nonce": "0x0", "signed-raw-tx": "0xf86e80843b9aca00825208808094162f2bee06b43bbf9b8cf5e362de9dcf064d79f3893635c9adc5dea000008028a0c6f2f65ce9dca19c50a81c3ccde8a466d3b1646d22a17184050f88bc28ea935fa0746c8b2c911bea6dce4505f2965b9ed0a4a1d04dc362395bc2ea41bd7b88fab5", } reference_response = [ { "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "blockNumber": None, "from": "one1twhzfc2wr4j5ka7gs9pmllpnrdyaskcl5lq8ye", "timestamp": 0, "gas": 21000, "gasPrice": 1000000000, "hash": "0xef8091e621745bd17133664c96842ef9d730a842f69bce6402b49490af0a17ef", "input": "0x", "nonce": 0, "to": "one13awvzpjt7n3hcrmxax3elps7a6vw46u63kc28p", "transactionIndex": 0, "value": 1000000000000000000000, "shardID": 0, "toShardID": 0, "v": "0x28", "r": "0xe876d901525a8799a8eb3ea03e2c1a43129c2ff3136ec10f6345f2899bab5026", "s": "0x5c4f1e659b9d371c2e9994aee240b966e36b6dd609747d42c9d9c9f23371d808" } ] if get_transaction(tx["hash"], tx["from-shard"]) is not None: pytest.skip(f"Test transaction (hash {tx['hash']}) already present on chain...") send_transaction(tx, confirm_submission=True) start_time = time.time() while time.time() - start_time <= tx_timeout: raw_response = base_request("hmyv2_pendingTransactions", endpoint=endpoints[tx["from-shard"]]) response = check_and_unpack_rpc_response(raw_response, expect_error=False) assert_valid_json_structure(reference_response, response) for pending_tx in response: if pending_tx["hash"] == tx["hash"]: assert pending_tx["shardID"] == tx["from-shard"], f"Pending tx has from shard {pending_tx['shardID']}, " \ f"expected shard {tx['from-shard']}" assert pending_tx["toShardID"] == tx["to-shard"], f"Pending tx has to shard {pending_tx['toShardID']}, " \ f"expected shard {tx['to-shard']}" return raise AssertionError(f"Timeout! Pending transaction not found for {json.dumps(tx, indent=2)}")
def test_send_raw_transaction_v2(): tx = { "from": "one13lu674f3jkfk2qhsngfc2vhcf372wprctdjvgu", "to": "one14jeshxg75gdr5dz8sg7fm2sjvw7snnsdw98f0y", # humor brain crouch walk focus slush material sort used refuse exist prefer obscure above grow maze scheme myself liquid lab fresh awful easily debris "amount": "1000", "from-shard": 0, "to-shard": 0, "hash": "0x99919613fce4bbc9f4a068373bbb67b3f7e5ce34a7a1eef866a32284ec70261a", "nonce": "0x0", "signed-raw-tx": "0xf86e80843b9aca00825208808094acb30b991ea21a3a3447823c9daa1263bd09ce0d893635c9adc5dea000008028a03ab9d7562ca97f7a57ccca3b691f5b7b8e75a2f0f4d38109bb818da5199d62cda02cb8180d0fed4cfe03d25f3458c7d11c91185273b6ae5e902d1debe998326997", } reference_response = { "code": -32000, "message": "transaction already finalized" } if get_transaction(tx["hash"], tx["from-shard"]) is not None: pytest.skip(f"Test transaction (hash {tx['hash']}) already present on chain...") # Submit new transaction... response = base_request('hmyv2_sendRawTransaction', params=[tx["signed-raw-tx"]], endpoint=endpoints[tx["from-shard"]]) tx_hash = check_and_unpack_rpc_response(response, expect_error=False) assert tx_hash == tx["hash"], f"Expect submitted transaction to get tx hash of {tx['hash']}, got {tx_hash}" # Test finalized transaction error... start_time = time.time() while time.time() - start_time <= tx_timeout: if get_transaction(tx["hash"], tx["from-shard"]) is not None: raw_response = base_request('hmyv2_sendRawTransaction', params=[tx["signed-raw-tx"]], endpoint=endpoints[tx["from-shard"]]) response = check_and_unpack_rpc_response(raw_response, expect_error=True) assert_valid_json_structure(reference_response, response) assert reference_response["code"] == response["code"], f"Expected error code {reference_response['code']}, " \ f"got {response['code']}" return time.sleep(0.25) raise AssertionError(f"Timeout! Finalized transaction not found for {json.dumps(tx, indent=2)}")
def test_send_raw_transaction_v1(): tx = { "from": "one1p5x4t7mvd94jn5awxmhlvgqmlazx5egzz7rveg", "to": "one1mjunf85vnhc4drv57ugsyg2fxjnsq920qzkpwq", # identify energy glimpse train script text town amused major slot armed fiction park alter dance live snow path picture desk metal voice distance good "amount": "1000", "from-shard": 0, "to-shard": 0, "hash": "0x5c5029de0c45a692265ec55d5218834c837c4c8d7cd2ed9598a858ed8ee8c811", "nonce": "0x0", "signed-raw-tx": "0xf86e80843b9aca00825208808094dcb9349e8c9df1568d94f71102214934a700154f893635c9adc5dea000008028a0e727143889e1ac8fbcaed655e186407b6b6978cbff63f79c0a6bd57bfb75ef06a07409113d6df43969d20552c9ea239e930a1ae736a6f3d2b3d4b8a3392217f99d", } reference_response = { "code": -32000, "message": "transaction already finalized" } if get_transaction(tx["hash"], tx["from-shard"]) is not None: pytest.skip(f"Test transaction (hash {tx['hash']}) already present on chain...") # Submit new transaction... response = base_request('hmy_sendRawTransaction', params=[tx["signed-raw-tx"]], endpoint=endpoints[tx["from-shard"]]) tx_hash = check_and_unpack_rpc_response(response, expect_error=False) assert tx_hash == tx["hash"], f"Expect submitted transaction to get tx hash of {tx['hash']}, got {tx_hash}" # Test finalized transaction error... start_time = time.time() while time.time() - start_time <= tx_timeout: if get_transaction(tx["hash"], tx["from-shard"]) is not None: raw_response = base_request('hmy_sendRawTransaction', params=[tx["signed-raw-tx"]], endpoint=endpoints[tx["from-shard"]]) response = check_and_unpack_rpc_response(raw_response, expect_error=True) assert_valid_json_structure(reference_response, response) assert reference_response["code"] == response["code"], f"Expected error code {reference_response['code']}, " \ f"got {response['code']}" return time.sleep(0.25) raise AssertionError(f"Timeout! Finalized transaction not found for {json.dumps(tx, indent=2)}")
def test_pending_transactions_v1(): tx = { "from": "one1twhzfc2wr4j5ka7gs9pmllpnrdyaskcl5lq8ye", "to": "one13awvzpjt7n3hcrmxax3elps7a6vw46u63kc28p", # month liar edit pull vague intact entire slab satoshi angle core unlock useless wrestle kite merry sure quiz day frame update recycle fault lecture "amount": "1000", "from-shard": 0, "to-shard": 0, "hash": "0xef8091e621745bd17133664c96842ef9d730a842f69bce6402b49490af0a17ef", "nonce": "0x0", "signed-raw-tx": "0xf86e80843b9aca008252088080948f5cc1064bf4e37c0f66e9a39f861eee98eaeb9a893635c9adc5dea000008028a0e876d901525a8799a8eb3ea03e2c1a43129c2ff3136ec10f6345f2899bab5026a05c4f1e659b9d371c2e9994aee240b966e36b6dd609747d42c9d9c9f23371d808", } reference_response = [ { "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "blockNumber": None, "from": "one1twhzfc2wr4j5ka7gs9pmllpnrdyaskcl5lq8ye", "timestamp": "0x0", "gas": "0x5208", "gasPrice": "0x3b9aca00", "hash": "0xef8091e621745bd17133664c96842ef9d730a842f69bce6402b49490af0a17ef", "input": "0x", "nonce": "0x0", "to": "one13awvzpjt7n3hcrmxax3elps7a6vw46u63kc28p", "transactionIndex": "0x0", "value": "0x3635c9adc5dea00000", "shardID": 0, "toShardID": 0, "v": "0x28", "r": "0xe876d901525a8799a8eb3ea03e2c1a43129c2ff3136ec10f6345f2899bab5026", "s": "0x5c4f1e659b9d371c2e9994aee240b966e36b6dd609747d42c9d9c9f23371d808" } ] in_initially_funded = False for init_tx in initial_funding: if init_tx["to"] == tx["from"] and init_tx["to-shard"] == tx["from-shard"]: in_initially_funded = True break if not in_initially_funded: raise AssertionError(f"Test transaction from address {tx['from']} " f"not found in set of initially funded accounts.") if get_transaction(tx["hash"], tx["from-shard"]) is not None: pytest.skip(f"Test transaction (hash {tx['hash']}) already present on chain...") send_transaction(tx, confirm_submission=True) start_time = time.time() while time.time() - start_time <= tx_timeout: raw_response = base_request("hmy_pendingTransactions", endpoint=endpoints[tx["from-shard"]]) response = check_and_unpack_rpc_response(raw_response, expect_error=False) assert_valid_json_structure(reference_response, response) for pending_tx in response: if pending_tx["hash"] == tx["hash"]: assert pending_tx["shardID"] == tx["from-shard"], f"Pending tx has from shard {pending_tx['shardID']}, " \ f"expected shard {tx['from-shard']}" assert pending_tx["toShardID"] == tx["to-shard"], f"Pending tx has to shard {pending_tx['toShardID']}, " \ f"expected shard {tx['to-shard']}" return raise AssertionError(f"Timeout! Pending transaction not found for {json.dumps(tx, indent=2)}")
def test_get_pending_cx_receipts(): """ Note that v1 & v2 have the same responses. """ cx = { "from": "one19l4hghvh40fyldxfznn0a3ss7d5gk0dmytdql4", "to": "one1ds3fayprfl6j7yd6mpwfncj9c0ajmhvmvhnmpm", # erupt concert hat tree anger discover disease town gasp lemon gesture fiber spread season mixture host awake tennis issue orbit member film winter glass "amount": "1000", "from-shard": 0, "to-shard": 1, "hash": "0x0988bcaecba9cc731245ee7ae9595d1202448413bc6e517b4c0c8da9abb1e479", "nonce": "0x0", "signed-raw-tx": "0xf86e80843b9aca008252088001946c229e90234ff52f11bad85c99e245c3fb2ddd9b893635c9adc5dea000008027a0fc7e0c3790b7c507749f4286e5b6cc59357129586fc48a326442c27886e0236ba0587c72684d05fad0c1c2111d55d810bc086cd5adf129806a89a019b539b19d26", } reference_response = [ { "receipts": [ { "txHash": "0x819b0d7902134dadd07851edba0e8694e60c1aee057a96d2ceb4a9118cee0298", "from": "one1t40su52axu207vgc6ymcmwe0xmml4njrskk2vf", "to": "one1qljfd3pnfjwr86ll6d0s6khcqhw8969p9l7fw3", "shardID": 1, "toShardID": 0, "amount": 500000000000000000000 } ], "merkleProof": { "blockNum": 35, "blockHash": "0xe07abb23824f658f452012f22e2d557a270c320058a39d6c6d5d2d53d1d7e427", "shardID": 1, "receiptHash": "0xb7f422b693a5cffd3d98b2fd4f9f833e10421bcd6d488e5cd8c2fcbcf1ecd13c", "shardIDs": [ 0 ], "shardHashes": [ "0x31db710789deaa5a1721f7bf66d3eabddfbb9e712b5ba6cdc7b183f5d9dc9b51" ] }, "header": { "shard-id": 1, "block-header-hash": "0x2e0295f760bc69cdf840576636f61602f8b13ea5172562837c10a9b6f5fa711e", "block-number": 35, "view-id": 35, "epoch": 5 }, "commitSig": "G7oQCfiRJjl8s1i7B2xxPWZefCW5muiqyNY0PwcNOFt2QQkRC95ongKIGuIKCLMAVkDpkZRdC7B0cUoe3tKceT6/9++sxcwPRQ2NBWA/u6Gkl6UneKs4Xzhpuez2MoOG", "commitBitmap": "Pw==" } ] if get_transaction(cx["hash"], cx["from-shard"]) is not None: pytest.skip(f"Test cross shard transaction (hash {cx['hash']}) already present on chain...") send_transaction(cx, confirm_submission=True) start_time = time.time() v1_success, v2_success = False, False while time.time() - start_time <= tx_timeout * 2: # Cross shards are generally slower... if not v1_success: raw_response = base_request("hmy_getPendingCXReceipts", endpoint=endpoints[cx["to-shard"]]) response = check_and_unpack_rpc_response(raw_response, expect_error=False) assert_valid_json_structure(reference_response, response) for cx_receipt in response: for r in cx_receipt["receipts"]: if r["txHash"] == cx["hash"]: v1_success = True if not v2_success: raw_response = base_request("hmyv2_getPendingCXReceipts", endpoint=endpoints[cx["to-shard"]]) response = check_and_unpack_rpc_response(raw_response, expect_error=False) assert_valid_json_structure(reference_response, response) for cx_receipt in response: for r in cx_receipt["receipts"]: if r["txHash"] == cx["hash"]: v2_success = True time.sleep(0.5) if v1_success and v2_success: return raise AssertionError(f"Timeout! Pending transaction not found for {json.dumps(cx)}")