Пример #1
0
    def test_xshard_tx_sent(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)
        acc2 = Address.create_from_identity(id1, full_shard_id=1)
        acc3 = Address.create_random_account(full_shard_id=0)

        env = get_test_env(genesis_account=acc1,
                           genesis_minor_quarkash=10000000)
        state = create_default_shard_state(env=env, shard_id=0)
        env1 = get_test_env(genesis_account=acc1,
                            genesis_minor_quarkash=10000000)
        state1 = create_default_shard_state(env=env1, shard_id=1)

        # Add a root block to update block gas limit so that xshard tx can be included
        root_block = (
            state.root_tip.create_block_to_append().add_minor_block_header(
                state.header_tip).add_minor_block_header(
                    state1.header_tip).finalize())
        state.add_root_block(root_block)

        tx = create_transfer_transaction(
            shard_state=state,
            key=id1.get_key(),
            from_address=acc1,
            to_address=acc2,
            value=888888,
            gas=opcodes.GTXXSHARDCOST + opcodes.GTXCOST,
        )
        state.add_tx(tx)

        b1 = state.create_block_to_mine(address=acc3)
        self.assertEqual(len(b1.tx_list), 1)

        self.assertEqual(state.evm_state.gas_used, 0)
        # Should succeed
        state.finalize_and_add_block(b1)
        self.assertEqual(len(state.evm_state.xshard_list), 1)
        self.assertEqual(
            state.evm_state.xshard_list[0],
            CrossShardTransactionDeposit(
                tx_hash=tx.get_hash(),
                from_address=acc1,
                to_address=acc2,
                value=888888,
                gas_price=1,
            ),
        )
        self.assertEqual(
            state.get_balance(id1.recipient),
            10000000 - 888888 - opcodes.GTXCOST - opcodes.GTXXSHARDCOST,
        )
        # Make sure the xshard gas is not used by local block
        self.assertEqual(state.evm_state.gas_used,
                         opcodes.GTXCOST + opcodes.GTXXSHARDCOST)
        # GTXXSHARDCOST is consumed by remote shard
        self.assertEqual(state.get_balance(acc3.recipient),
                         opcodes.GTXCOST // 2)
Пример #2
0
    def test_add_transaction(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)
        acc2 = Address.create_from_identity(id1, full_shard_key=1)

        with ClusterContext(2, acc1) as clusters:
            master = clusters[0].master

            root = call_async(
                master.get_next_block_to_mine(acc1, branch_value=None))
            call_async(master.add_root_block(root))

            tx1 = create_transfer_transaction(
                shard_state=clusters[0].get_shard_state(0b10),
                key=id1.get_key(),
                from_address=acc1,
                to_address=acc1,
                value=12345,
            )
            self.assertTrue(call_async(master.add_transaction(tx1)))
            self.assertEqual(len(clusters[0].get_shard_state(0b10).tx_queue),
                             1)

            branch1 = Branch(2 | 1)
            tx2 = create_transfer_transaction(
                shard_state=clusters[0].get_shard_state(0b11),
                key=id1.get_key(),
                from_address=acc2,
                to_address=acc1,
                value=12345,
                gas=30000,
            )
            self.assertTrue(call_async(master.add_transaction(tx2)))
            self.assertEqual(len(clusters[0].get_shard_state(0b11).tx_queue),
                             1)

            # check the tx is received by the other cluster
            tx_queue = clusters[1].get_shard_state(0b10).tx_queue
            assert_true_with_timeout(lambda: len(tx_queue) == 1)
            self.assertEqual(tx_queue.pop_transaction(), tx1.tx.to_evm_tx())

            tx_queue = clusters[1].get_shard_state(0b11).tx_queue
            assert_true_with_timeout(lambda: len(tx_queue) == 1)
            self.assertEqual(tx_queue.pop_transaction(), tx2.tx.to_evm_tx())
Пример #3
0
    def test_getTransactionReceipt_on_x_shard_transfer(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)
        acc2 = Address.create_from_identity(id1, full_shard_id=1)

        with ClusterContext(1, acc1) as clusters, jrpc_server_context(
            clusters[0].master
        ):
            master = clusters[0].master
            slaves = clusters[0].slave_list

            is_root, block = call_async(master.get_next_block_to_mine(address=acc2))
            self.assertTrue(is_root)
            call_async(master.add_root_block(block))

            s1, s2 = clusters[0].get_shard_state(0), clusters[0].get_shard_state(1)
            tx_gen = lambda s, f, t: create_transfer_transaction(
                shard_state=s,
                key=id1.get_key(),
                from_address=f,
                to_address=t,
                gas=21000 if f == t else 30000,
                value=12345,
            )
            self.assertTrue(slaves[0].add_tx(tx_gen(s1, acc1, acc2)))
            _, b1 = call_async(master.get_next_block_to_mine(address=acc1))
            self.assertTrue(call_async(clusters[0].get_shard(0).add_block(b1)))
            _, b2 = call_async(master.get_next_block_to_mine(address=acc2))
            self.assertTrue(call_async(clusters[0].get_shard(1).add_block(b2)))
            _, root_block = call_async(
                master.get_next_block_to_mine(address=acc1, prefer_root=True)
            )

            call_async(master.add_root_block(root_block))

            tx = tx_gen(s2, acc2, acc2)
            self.assertTrue(slaves[1].add_tx(tx))
            _, b3 = call_async(master.get_next_block_to_mine(address=acc2))
            self.assertTrue(call_async(clusters[0].get_shard(1).add_block(b3)))

            # in-shard tx 21000 + receiving x-shard tx 9000
            self.assertEqual(s2.evm_state.gas_used, 30000)
            self.assertEqual(s2.evm_state.xshard_receive_gas_used, 9000)

            for endpoint in ("getTransactionReceipt", "eth_getTransactionReceipt"):
                resp = send_request(
                    endpoint,
                    "0x"
                    + tx.get_hash().hex()
                    + acc2.full_shard_id.to_bytes(4, "big").hex(),
                )
                self.assertEqual(resp["transactionHash"], "0x" + tx.get_hash().hex())
                self.assertEqual(resp["status"], "0x1")
                self.assertEqual(resp["cumulativeGasUsed"], hex(30000))
                self.assertEqual(resp["gasUsed"], hex(21000))
                self.assertIsNone(resp["contractAddress"])
Пример #4
0
    def test_getWork_and_submitWork(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)

        with ClusterContext(
            1, acc1, remote_mining=True, shard_size=1, small_coinbase=True
        ) as clusters, jrpc_server_context(clusters[0].master):
            master = clusters[0].master
            slaves = clusters[0].slave_list

            branch = Branch.create(1, 0)
            tx = create_transfer_transaction(
                shard_state=slaves[0].shards[branch].state,
                key=id1.get_key(),
                from_address=acc1,
                to_address=acc1,
                value=0,
                gas_price=12,
            )
            self.assertTrue(slaves[0].add_tx(tx))

            for shard_id in ["0x0", None]:  # shard, then root
                resp = send_request("getWork", shard_id)
                self.assertEqual(resp[1:], ["0x1", "0xa"])  # height and diff

                header_hash_hex = resp[0]
                if shard_id is not None:  # shard 0
                    miner_address = Address.create_from(
                        master.env.quark_chain_config.shards[1].COINBASE_ADDRESS
                    )
                else:  # root
                    miner_address = Address.create_from(
                        master.env.quark_chain_config.ROOT.COINBASE_ADDRESS
                    )
                _, block = call_async(
                    master.get_next_block_to_mine(
                        address=miner_address, prefer_root=shard_id is None
                    )
                )
                self.assertEqual(
                    header_hash_hex[2:], block.header.get_hash_for_mining().hex()
                )
                # solve it and submit
                work = MiningWork(bytes.fromhex(resp[0][2:]), 1, 10)
                solver = DoubleSHA256(work)
                nonce = solver.mine(0, 10000).nonce
                mixhash = "0x" + sha3_256(b"").hex()
                resp = send_request(
                    "submitWork", shard_id, header_hash_hex, hex(nonce), mixhash
                )
                self.assertTrue(resp)

            # show progress on shard 0
            self.assertEqual(
                clusters[0].get_shard_state(1 | 0).get_tip().header.height, 1
            )
Пример #5
0
    def test_add_transaction(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)
        acc2 = Address.create_from_identity(id1, full_shard_key=1)

        with ClusterContext(2, acc1) as clusters:
            master = clusters[0].master
            slaves = clusters[0].slave_list

            branch0 = Branch(2)
            tx1 = create_transfer_transaction(
                shard_state=slaves[0].shards[branch0].state,
                key=id1.get_key(),
                from_address=acc1,
                to_address=acc1,
                value=12345,
            )
            self.assertTrue(call_async(master.add_transaction(tx1)))
            self.assertEqual(len(slaves[0].shards[branch0].state.tx_queue), 1)

            branch1 = Branch(2 | 1)
            tx2 = create_transfer_transaction(
                shard_state=slaves[1].shards[branch1].state,
                key=id1.get_key(),
                from_address=acc2,
                to_address=acc1,
                value=12345,
                gas=30000,
            )
            self.assertTrue(call_async(master.add_transaction(tx2)))
            self.assertEqual(len(slaves[1].shards[branch1].state.tx_queue), 1)

            # check the tx is received by the other cluster
            tx_queue = clusters[1].slave_list[0].shards[branch0].state.tx_queue
            assert_true_with_timeout(lambda: len(tx_queue) == 1)
            self.assertEqual(tx_queue.pop_transaction(),
                             tx1.code.get_evm_transaction())

            tx_queue = clusters[1].slave_list[1].shards[branch1].state.tx_queue
            assert_true_with_timeout(lambda: len(tx_queue) == 1)
            self.assertEqual(tx_queue.pop_transaction(),
                             tx2.code.get_evm_transaction())
Пример #6
0
    def test_native_token_gas(self):
        """in-shard transfer QETH using native token as gas
        """
        QETH = token_id_encode("QETH")
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)
        acc2 = Address.create_random_account(full_shard_key=0)
        acc3 = Address.create_random_account(full_shard_key=0)

        env = get_test_env(
            genesis_account=acc1, genesis_minor_token_balances={"QETH": 10000000}
        )
        state = create_default_shard_state(env=env)

        tx = create_transfer_transaction(
            shard_state=state,
            key=id1.get_key(),
            from_address=acc1,
            to_address=acc2,
            value=12345,
            gas=21000,
            gas_token_id=QETH,
            transfer_token_id=QETH,
        )

        self.assertTrue(state.add_tx(tx))
        b1 = state.create_block_to_mine(address=acc3)
        self.assertEqual(len(b1.tx_list), 1)
        state.finalize_and_add_block(b1)
        self.assertEqual(state.header_tip, b1.header)
        self.assertEqual(
            state.get_token_balance(acc1.recipient, QETH),
            10000000 - opcodes.GTXCOST - 12345,
        )
        self.assertEqual(state.get_token_balance(acc2.recipient, QETH), 12345)
        # tx fee
        self.assertEqual(
            state.get_token_balance(acc3.recipient, QETH),
            self.get_after_tax_reward(opcodes.GTXCOST),
        )
        # miner coinbase
        self.assertEqual(
            state.get_token_balance(acc3.recipient, self.genesis_token),
            self.get_after_tax_reward(self.shard_coinbase),
        )
        tx_list, _ = state.db.get_transactions_by_address(acc1)
        self.assertEqual(tx_list[0].value, 12345)
        self.assertEqual(tx_list[0].gas_token_id, QETH)
        self.assertEqual(tx_list[0].transfer_token_id, QETH)
        tx_list, _ = state.db.get_transactions_by_address(acc2)
        self.assertEqual(tx_list[0].value, 12345)
        self.assertEqual(tx_list[0].gas_token_id, QETH)
        self.assertEqual(tx_list[0].transfer_token_id, QETH)
Пример #7
0
    def test_exceeding_xshard_limit(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)
        acc2 = Address.create_random_account(full_shard_id=1)
        acc3 = Address.create_random_account(full_shard_id=0)

        env = get_test_env(genesis_account=acc1,
                           genesis_minor_quarkash=10000000)
        # a huge number to make xshard tx limit become 0 so that no xshard tx can be
        # included in the block
        env.quark_chain_config.MAX_NEIGHBORS = 10**18
        state = create_default_shard_state(env=env)

        # xshard tx
        tx = create_transfer_transaction(
            shard_state=state,
            key=id1.get_key(),
            from_address=acc1,
            to_address=acc2,
            value=12345,
            gas=50000,
        )
        self.assertTrue(state.add_tx(tx))

        b1 = state.create_block_to_mine(address=acc3)
        self.assertEqual(len(b1.tx_list), 0)

        # inshard tx
        tx = create_transfer_transaction(
            shard_state=state,
            key=id1.get_key(),
            from_address=acc1,
            to_address=acc3,
            value=12345,
            gas=50000,
        )
        self.assertTrue(state.add_tx(tx))

        b1 = state.create_block_to_mine(address=acc3)
        self.assertEqual(len(b1.tx_list), 1)
Пример #8
0
    def test_duplicated_tx(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)
        acc2 = Address.create_random_account(full_shard_id=0)
        acc3 = Address.create_random_account(full_shard_id=0)

        env = get_test_env(genesis_account=acc1,
                           genesis_minor_quarkash=10000000)
        state = create_default_shard_state(env=env)

        tx = create_transfer_transaction(
            shard_state=state,
            key=id1.get_key(),
            from_address=acc1,
            to_address=acc2,
            value=12345,
        )
        self.assertTrue(state.add_tx(tx))
        self.assertFalse(state.add_tx(tx))  # already in tx_queue

        self.assertEqual(len(state.tx_queue), 1)
        self.assertEqual(len(state.tx_dict), 1)

        block, i = state.get_transaction_by_hash(tx.get_hash())
        self.assertEqual(len(block.tx_list), 1)
        self.assertEqual(block.tx_list[0], tx)
        self.assertEqual(block.header.create_time, 0)
        self.assertEqual(i, 0)

        b1 = state.create_block_to_mine(address=acc3)
        self.assertEqual(len(b1.tx_list), 1)

        # Should succeed
        state.finalize_and_add_block(b1)
        self.assertEqual(state.header_tip, b1.header)
        self.assertEqual(state.get_balance(id1.recipient),
                         10000000 - opcodes.GTXCOST - 12345)
        self.assertEqual(state.get_balance(acc2.recipient), 12345)
        self.assertEqual(state.get_balance(acc3.recipient),
                         opcodes.GTXCOST // 2)

        # Check receipts
        self.assertEqual(len(state.evm_state.receipts), 1)
        self.assertEqual(state.evm_state.receipts[0].state_root, b"\x01")
        self.assertEqual(state.evm_state.receipts[0].gas_used, 21000)
        block, i = state.get_transaction_by_hash(tx.get_hash())
        self.assertEqual(block, b1)
        self.assertEqual(i, 0)

        # tx already confirmed
        self.assertTrue(state.db.contain_transaction_hash(tx.get_hash()))
        self.assertFalse(state.add_tx(tx))
Пример #9
0
    def test_getTransactionCount(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)
        acc2 = Address.create_random_account(full_shard_key=1)

        with ClusterContext(
            1, acc1, small_coinbase=True
        ) as clusters, jrpc_server_context(clusters[0].master):
            master = clusters[0].master
            slaves = clusters[0].slave_list

            self.assertEqual(
                call_async(master.get_primary_account_data(acc1)).transaction_count, 0
            )
            for i in range(3):
                tx = create_transfer_transaction(
                    shard_state=clusters[0].get_shard_state(2 | 0),
                    key=id1.get_key(),
                    from_address=acc1,
                    to_address=acc1,
                    value=12345,
                )
                self.assertTrue(slaves[0].add_tx(tx))

                block = call_async(
                    master.get_next_block_to_mine(address=acc1, branch_value=0b10)
                )
                self.assertEqual(i + 1, block.header.height)
                self.assertTrue(
                    call_async(clusters[0].get_shard(2 | 0).add_block(block))
                )

            response = send_request(
                "getTransactionCount", "0x" + acc2.serialize().hex()
            )
            self.assertEqual(response, "0x0")

            response = send_request(
                "getTransactionCount", "0x" + acc1.serialize().hex()
            )
            self.assertEqual(response, "0x3")
            response = send_request(
                "getTransactionCount", "0x" + acc1.serialize().hex(), "latest"
            )
            self.assertEqual(response, "0x3")

            for i in range(3):
                response = send_request(
                    "getTransactionCount", "0x" + acc1.serialize().hex(), hex(i + 1)
                )
                self.assertEqual(response, hex(i + 1))
Пример #10
0
    def test_native_token_transfer_0_value_success(self):
        """to prevent storage spamming, do not delta_token_balance does not take action if value is 0
        """
        MALICIOUS0 = token_id_encode("MALICIOUS0")
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)
        acc3 = Address.create_random_account(full_shard_key=0)

        env = get_test_env(
            genesis_account=acc1,
            genesis_minor_token_balances={
                self.GENESIS_TOKEN: 10000000,
                "MALICIOUS0": 0,
            },
        )
        state = create_default_shard_state(env=env)
        tx = create_transfer_transaction(
            shard_state=state,
            key=id1.get_key(),
            from_address=acc1,
            to_address=acc1,
            value=0,
            gas=opcodes.GTXCOST,
            gas_token_id=self.genesis_token,
            transfer_token_id=MALICIOUS0,
        )
        self.assertTrue(state.add_tx(tx))

        b1 = state.create_block_to_mine(address=acc3)
        self.assertEqual(len(b1.tx_list), 1)
        state.finalize_and_add_block(b1)
        self.assertEqual(state.header_tip, b1.header)
        self.assertEqual(
            state.get_token_balance(id1.recipient, self.genesis_token),
            10000000 - opcodes.GTXCOST,
        )
        self.assertEqual(state.get_token_balance(acc1.recipient, MALICIOUS0),
                         0)
        # MALICIOUS0 shall not be in the dict
        self.assertNotEqual(
            state.get_balances(acc1.recipient),
            {
                self.genesis_token: 10000000 - opcodes.GTXCOST,
                MALICIOUS0: 0
            },
        )
        self.assertEqual(
            state.get_balances(acc1.recipient),
            {self.genesis_token: 10000000 - opcodes.GTXCOST},
        )
Пример #11
0
    def setUp(self):
        super().setUp()
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)

        env = get_test_env(genesis_account=acc1,
                           genesis_minor_quarkash=10000000)
        state = create_default_shard_state(env=env)
        tx = create_contract_creation_with_event_transaction(
            shard_state=state,
            key=id1.get_key(),
            from_address=acc1,
            to_full_shard_id=acc1.full_shard_id,
        )
        self.assertTrue(state.add_tx(tx))
        b = state.create_block_to_mine(address=acc1, gas_limit=1000000)
        hit_block = b  # will be used later
        state.finalize_and_add_block(b)
        start_height = b.header.height
        # https://hastebin.com/debezaqocu.cs
        # 1 log with 2 topics - sha3(b'Hi(address)') and msg.sender
        log = Log.create_from_eth_log(state.evm_state.receipts[0].logs[0], b,
                                      0, 0)

        # add other random blocks with normal tx
        for _ in range(10):
            tx = create_transfer_transaction(
                shard_state=state,
                key=id1.get_key(),
                from_address=acc1,
                to_address=Address.create_from_identity(
                    Identity.create_random_identity(), full_shard_id=0),
                value=1,
                gas=40000,
            )
            self.assertTrue(state.add_tx(tx))
            b = state.create_block_to_mine(address=acc1, gas_limit=100000)
            state.finalize_and_add_block(b)
        self.assertEqual(b.header.height, start_height + 10)

        self.hit_block = hit_block
        self.log = log
        self.state = state
        self.start_height = start_height

        def filter_gen_with_criteria(criteria, addresses=None):
            return Filter(state.db, addresses or [], criteria, start_height,
                          start_height + 10)

        self.filter_gen_with_criteria = filter_gen_with_criteria
Пример #12
0
    def test_disallowed_unknown_token(self):
        """do not allow tx with unknown token id
        """
        MALICIOUS0 = token_id_encode("MALICIOUS0")
        MALICIOUS1 = token_id_encode("MALICIOUS1")
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)
        acc3 = Address.create_random_account(full_shard_key=0)

        env = get_test_env(
            genesis_account=acc1,
            genesis_minor_token_balances={self.GENESIS_TOKEN: 10000000},
        )
        state = create_default_shard_state(env=env)
        tx = create_transfer_transaction(
            shard_state=state,
            key=id1.get_key(),
            from_address=acc1,
            to_address=acc1,
            value=0,
            gas=opcodes.GTXCOST,
            gas_token_id=self.genesis_token,
            transfer_token_id=MALICIOUS0,
        )
        self.assertFalse(state.add_tx(tx))

        tx1 = create_transfer_transaction(
            shard_state=state,
            key=id1.get_key(),
            from_address=acc1,
            to_address=acc1,
            value=0,
            gas=opcodes.GTXCOST,
            gas_token_id=MALICIOUS1,
            transfer_token_id=self.genesis_token,
        )
        self.assertFalse(state.add_tx(tx1))
Пример #13
0
    def test_revert_fork_put_tx_back_to_queue(self):
        """Tx in the reverted chain should be put back to the queue"""
        id1 = Identity.create_random_identity()
        id2 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)
        acc2 = Address.create_from_identity(id2, full_shard_id=0)
        acc3 = Address.create_random_account(full_shard_id=0)

        env = get_test_env(genesis_account=acc1,
                           genesis_minor_quarkash=2000000 + opcodes.GTXCOST)
        state = create_default_shard_state(env=env)

        state.add_tx(
            create_transfer_transaction(
                shard_state=state,
                key=id1.get_key(),
                from_address=acc1,
                to_address=acc2,
                value=1000000,
            ))

        b0 = state.create_block_to_mine(address=acc3)
        b1 = state.create_block_to_mine(address=acc3)
        state.finalize_and_add_block(b0)

        self.assertEqual(len(state.tx_queue), 0)

        b1.tx_list = []  # make b1 empty
        state.finalize_and_add_block(b1)
        self.assertEqual(len(state.tx_queue), 0)

        b2 = b1.create_block_to_append()
        state.finalize_and_add_block(b2)

        # now b1-b2 becomes the best chain and we expect b0 to be reverted and put the tx back to queue
        self.assertEqual(len(state.tx_queue), 1)

        b3 = b0.create_block_to_append()
        state.finalize_and_add_block(b3)
        self.assertEqual(len(state.tx_queue), 1)

        b4 = b3.create_block_to_append()
        state.finalize_and_add_block(b4)

        # b0-b3-b4 becomes the best chain
        self.assertEqual(len(state.tx_queue), 0)
Пример #14
0
 def test_add_tx_incorrect_from_shard_id(self):
     id1 = Identity.create_random_identity()
     acc1 = Address.create_from_identity(id1, full_shard_id=1)
     acc2 = Address.create_random_account(full_shard_id=1)
     env = get_test_env(genesis_account=acc1,
                        genesis_minor_quarkash=10000000)
     state = create_default_shard_state(env=env)
     # state is shard 0 but tx from shard 1
     tx = create_transfer_transaction(
         shard_state=state,
         key=id1.get_key(),
         from_address=acc1,
         to_address=acc2,
         value=12345,
     )
     self.assertFalse(state.add_tx(tx))
     self.assertIsNone(state.execute_tx(tx, acc1))
Пример #15
0
    def test_add_invalid_tx_fail(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)
        acc2 = Address.create_random_account(full_shard_id=0)

        env = get_test_env(genesis_account=acc1,
                           genesis_minor_quarkash=10000000)
        state = create_default_shard_state(env=env)

        tx = create_transfer_transaction(
            shard_state=state,
            key=id1.get_key(),
            from_address=acc1,
            to_address=acc2,
            value=999999999999999999999,  # insane
        )
        self.assertFalse(state.add_tx(tx))
        self.assertEqual(len(state.tx_queue), 0)
Пример #16
0
 def test_execute_tx(self):
     id1 = Identity.create_random_identity()
     acc1 = Address.create_from_identity(id1, full_shard_id=0)
     acc2 = Address.create_random_account(full_shard_id=0)
     env = get_test_env(genesis_account=acc1,
                        genesis_minor_quarkash=10000000)
     state = create_default_shard_state(env=env)
     tx = create_transfer_transaction(
         shard_state=state,
         key=id1.get_key(),
         from_address=acc1,
         to_address=acc2,
         value=12345,
     )
     # adding this line to make sure `execute_tx` would reset `gas_used`
     state.evm_state.gas_used = state.evm_state.gas_limit
     res = state.execute_tx(tx, acc1)
     self.assertEqual(res, b"")
Пример #17
0
    def test_get_primary_account_data(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)
        acc2 = Address.create_random_account(full_shard_key=1)

        with ClusterContext(1, acc1) as clusters:
            master = clusters[0].master
            slaves = clusters[0].slave_list

            branch = Branch(2)
            self.assertEqual(
                call_async(
                    master.get_primary_account_data(acc1)).transaction_count,
                0)
            tx = create_transfer_transaction(
                shard_state=slaves[0].shards[branch].state,
                key=id1.get_key(),
                from_address=acc1,
                to_address=acc1,
                value=12345,
            )
            self.assertTrue(slaves[0].add_tx(tx))

            is_root, root = call_async(
                master.get_next_block_to_mine(address=acc1, prefer_root=True))
            self.assertTrue(is_root)
            call_async(master.add_root_block(root))

            is_root, block1 = call_async(
                master.get_next_block_to_mine(address=acc1))
            self.assertFalse(is_root)
            self.assertTrue(
                call_async(
                    master.add_raw_minor_block(block1.header.branch,
                                               block1.serialize())))

            self.assertEqual(
                call_async(
                    master.get_primary_account_data(acc1)).transaction_count,
                1)
            self.assertEqual(
                call_async(
                    master.get_primary_account_data(acc2)).transaction_count,
                0)
Пример #18
0
    def test_getWork_and_submitWork(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)

        with ClusterContext(1, acc1, remote_mining=True,
                            shard_size=1) as clusters, jrpc_server_context(
                                clusters[0].master):
            master = clusters[0].master
            slaves = clusters[0].slave_list

            branch = Branch.create(1, 0)
            tx = create_transfer_transaction(
                shard_state=slaves[0].shards[branch].state,
                key=id1.get_key(),
                from_address=acc1,
                to_address=acc1,
                value=0,
                gas_price=12,
            )
            self.assertTrue(slaves[0].add_tx(tx))

            for shard_id in ["0x0", None]:  # shard, then root
                resp = send_request("getWork", shard_id)
                self.assertEqual(resp[1:], ["0x1", "0xa"])  # height and diff

                header_hash_hex = resp[0]
                _, block = call_async(
                    master.get_next_block_to_mine(address=acc1))
                self.assertEqual(header_hash_hex[2:],
                                 block.header.get_hash_for_mining().hex())
                # solve it and submit
                solver = DoubleSHA256(block)
                mined = solver.mine(0, 1000)
                self.assertTrue(mined)
                nonce_found = "0x" + solver.nonce_found.hex()
                mixhash = "0x" + sha3_256(b"").hex()
                resp = send_request("submitWork", shard_id, header_hash_hex,
                                    nonce_found, mixhash)
                # FIXME: also verify root chain block addition after fixing https://github.com/QuarkChain/pyquarkchain/issues/130
                if shard_id is not None:
                    self.assertTrue(resp)
Пример #19
0
 def test_estimate_gas(self):
     id1 = Identity.create_random_identity()
     acc1 = Address.create_from_identity(id1, full_shard_id=0)
     acc2 = Address.create_random_account(full_shard_id=0)
     env = get_test_env(genesis_account=acc1,
                        genesis_minor_quarkash=10000000)
     state = create_default_shard_state(env=env)
     tx_gen = lambda data: create_transfer_transaction(
         shard_state=state,
         key=id1.get_key(),
         from_address=acc1,
         to_address=acc2,
         value=12345,
         data=data,
     )
     tx = tx_gen(b"")
     estimate = state.estimate_gas(tx, acc1)
     self.assertEqual(estimate, 21000)
     tx = tx_gen(b"12123478123412348125936583475758")
     estimate = state.estimate_gas(tx, acc1)
     self.assertEqual(estimate, 23176)
Пример #20
0
    def test_gasPrice(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)

        with ClusterContext(
                1, acc1, small_coinbase=True) as clusters, jrpc_server_context(
                    clusters[0].master):
            master = clusters[0].master
            slaves = clusters[0].slave_list

            # run for multiple times
            for _ in range(3):
                tx = create_transfer_transaction(
                    shard_state=clusters[0].get_shard_state(2 | 0),
                    key=id1.get_key(),
                    from_address=acc1,
                    to_address=acc1,
                    value=0,
                    gas_price=12,
                )
                self.assertTrue(slaves[0].add_tx(tx))

                block = call_async(
                    master.get_next_block_to_mine(address=acc1,
                                                  branch_value=0b10))
                self.assertTrue(
                    call_async(clusters[0].get_shard(2 | 0).add_block(block)))

            for using_eth_endpoint in (True, False):
                if using_eth_endpoint:
                    resp = send_request("eth_gasPrice", ["0x0"])
                else:
                    resp = send_request(
                        "gasPrice",
                        ["0x0",
                         quantity_encoder(token_id_encode("QKC"))])

                self.assertEqual(resp, "0xc")
Пример #21
0
    def test_getTransactionReceipt_on_transfer(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)

        with ClusterContext(
                1, acc1, small_coinbase=True) as clusters, jrpc_server_context(
                    clusters[0].master):
            master = clusters[0].master
            slaves = clusters[0].slave_list

            tx = create_transfer_transaction(
                shard_state=clusters[0].get_shard_state(2 | 0),
                key=id1.get_key(),
                from_address=acc1,
                to_address=acc1,
                value=12345,
            )
            self.assertTrue(slaves[0].add_tx(tx))

            block1 = call_async(
                master.get_next_block_to_mine(address=acc1, branch_value=0b10))
            self.assertTrue(
                call_async(clusters[0].get_shard(2 | 0).add_block(block1)))

            for endpoint in ("getTransactionReceipt",
                             "eth_getTransactionReceipt"):
                resp = send_request(
                    endpoint,
                    [
                        "0x" + tx.get_hash().hex() +
                        acc1.full_shard_key.to_bytes(4, "big").hex()
                    ],
                )
                self.assertEqual(resp["transactionHash"],
                                 "0x" + tx.get_hash().hex())
                self.assertEqual(resp["status"], "0x1")
                self.assertEqual(resp["cumulativeGasUsed"], "0x5208")
                self.assertIsNone(resp["contractAddress"])
Пример #22
0
    def test_xshard_tx_insufficient_gas(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)
        acc2 = Address.create_from_identity(id1, full_shard_id=1)
        acc3 = Address.create_random_account(full_shard_id=0)

        env = get_test_env(genesis_account=acc1,
                           genesis_minor_quarkash=10000000)
        state = create_default_shard_state(env=env, shard_id=0)

        state.add_tx(
            create_transfer_transaction(
                shard_state=state,
                key=id1.get_key(),
                from_address=acc1,
                to_address=acc2,
                value=888888,
                gas=opcodes.GTXCOST,
            ))

        b1 = state.create_block_to_mine(address=acc3)
        self.assertEqual(len(b1.tx_list), 0)
        self.assertEqual(len(state.tx_queue), 0)
Пример #23
0
    def test_getTransactionById(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)

        with ClusterContext(
                1, acc1, small_coinbase=True) as clusters, jrpc_server_context(
                    clusters[0].master):
            master = clusters[0].master
            slaves = clusters[0].slave_list

            self.assertEqual(
                call_async(
                    master.get_primary_account_data(acc1)).transaction_count,
                0)
            tx = create_transfer_transaction(
                shard_state=clusters[0].get_shard_state(2 | 0),
                key=id1.get_key(),
                from_address=acc1,
                to_address=acc1,
                value=12345,
            )
            self.assertTrue(slaves[0].add_tx(tx))

            block1 = call_async(
                master.get_next_block_to_mine(address=acc1, branch_value=0b10))
            self.assertTrue(
                call_async(clusters[0].get_shard(2 | 0).add_block(block1)))

            resp = send_request(
                "getTransactionById",
                [
                    "0x" + tx.get_hash().hex() +
                    acc1.full_shard_key.to_bytes(4, "big").hex()
                ],
            )
            self.assertEqual(resp["hash"], "0x" + tx.get_hash().hex())
Пример #24
0
    def test_fork_does_not_confirm_tx(self):
        """Tx should only be confirmed and removed from tx queue by the best chain"""
        id1 = Identity.create_random_identity()
        id2 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)
        acc2 = Address.create_from_identity(id2, full_shard_id=0)
        acc3 = Address.create_random_account(full_shard_id=0)

        env = get_test_env(genesis_account=acc1,
                           genesis_minor_quarkash=2000000 + opcodes.GTXCOST)
        state = create_default_shard_state(env=env)

        state.add_tx(
            create_transfer_transaction(
                shard_state=state,
                key=id1.get_key(),
                from_address=acc1,
                to_address=acc2,
                value=1000000,
            ))

        b0 = state.create_block_to_mine(address=acc3)
        b1 = state.create_block_to_mine(address=acc3)
        b0.tx_list = []  # make b0 empty
        state.finalize_and_add_block(b0)

        self.assertEqual(len(state.tx_queue), 1)

        self.assertEqual(len(b1.tx_list), 1)
        state.finalize_and_add_block(b1)
        # b1 is a fork and does not remove the tx from queue
        self.assertEqual(len(state.tx_queue), 1)

        b2 = state.create_block_to_mine(address=acc3)
        state.finalize_and_add_block(b2)
        self.assertEqual(len(state.tx_queue), 0)
Пример #25
0
    def test_getRootblockConfirmationIdAndCount(self):
        # TODO test root chain forks
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)

        with ClusterContext(
                1, acc1, small_coinbase=True) as clusters, jrpc_server_context(
                    clusters[0].master):
            master = clusters[0].master
            slaves = clusters[0].slave_list

            self.assertEqual(
                call_async(
                    master.get_primary_account_data(acc1)).transaction_count,
                0)

            block = call_async(
                master.get_next_block_to_mine(address=acc1, branch_value=None))
            call_async(master.add_root_block(block))

            tx = create_transfer_transaction(
                shard_state=clusters[0].get_shard_state(2 | 0),
                key=id1.get_key(),
                from_address=acc1,
                to_address=acc1,
                value=12345,
            )
            self.assertTrue(slaves[0].add_tx(tx))

            block1 = call_async(
                master.get_next_block_to_mine(address=acc1, branch_value=0b10))
            self.assertTrue(
                call_async(clusters[0].get_shard(2 | 0).add_block(block1)))

            tx_id = ("0x" + tx.get_hash().hex() +
                     acc1.full_shard_key.to_bytes(4, "big").hex())
            resp = send_request("getTransactionById", [tx_id])
            self.assertEqual(resp["hash"], "0x" + tx.get_hash().hex())
            self.assertEqual(
                resp["blockId"],
                "0x" + block1.header.get_hash().hex() +
                block1.header.branch.get_full_shard_id().to_bytes(
                    4, byteorder="big").hex(),
            )
            minor_hash = resp["blockId"]

            # zero root block confirmation
            resp_hash = send_request("getRootHashConfirmingMinorBlockById",
                                     [minor_hash])
            self.assertIsNone(
                resp_hash, "should return None for unconfirmed minor blocks")
            resp_count = send_request(
                "getTransactionConfirmedByNumberRootBlocks", [tx_id])
            self.assertEqual(resp_count, "0x0")

            # 1 root block confirmation
            block = call_async(
                master.get_next_block_to_mine(address=acc1, branch_value=None))
            call_async(master.add_root_block(block))
            resp_hash = send_request("getRootHashConfirmingMinorBlockById",
                                     [minor_hash])
            self.assertIsNotNone(resp_hash, "confirmed by root block")
            self.assertEqual(resp_hash, "0x" + block.header.get_hash().hex())
            resp_count = send_request(
                "getTransactionConfirmedByNumberRootBlocks", [tx_id])
            self.assertEqual(resp_count, "0x1")

            # 2 root block confirmation
            block = call_async(
                master.get_next_block_to_mine(address=acc1, branch_value=None))
            call_async(master.add_root_block(block))
            resp_hash = send_request("getRootHashConfirmingMinorBlockById",
                                     [minor_hash])
            self.assertIsNotNone(resp_hash, "confirmed by root block")
            self.assertNotEqual(resp_hash,
                                "0x" + block.header.get_hash().hex())
            resp_count = send_request(
                "getTransactionConfirmedByNumberRootBlocks", [tx_id])
            self.assertEqual(resp_count, "0x2")
Пример #26
0
    def test_getMinorBlock(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)

        with ClusterContext(
                1, acc1, small_coinbase=True) as clusters, jrpc_server_context(
                    clusters[0].master):
            master = clusters[0].master
            slaves = clusters[0].slave_list

            self.assertEqual(
                call_async(
                    master.get_primary_account_data(acc1)).transaction_count,
                0)
            tx = create_transfer_transaction(
                shard_state=clusters[0].get_shard_state(2 | 0),
                key=id1.get_key(),
                from_address=acc1,
                to_address=acc1,
                value=12345,
            )
            self.assertTrue(slaves[0].add_tx(tx))

            block1 = call_async(
                master.get_next_block_to_mine(address=acc1, branch_value=0b10))
            self.assertTrue(
                call_async(clusters[0].get_shard(2 | 0).add_block(block1)))

            # By id
            for need_extra_info in [True, False]:
                resp = send_request(
                    "getMinorBlockById",
                    [
                        "0x" + block1.header.get_hash().hex() + "0" * 8,
                        False,
                        need_extra_info,
                    ],
                )
                self.assertEqual(resp["transactions"][0],
                                 "0x" + tx.get_hash().hex() + "00000002")

            resp = send_request(
                "getMinorBlockById",
                ["0x" + block1.header.get_hash().hex() + "0" * 8, True],
            )
            self.assertEqual(resp["transactions"][0]["hash"],
                             "0x" + tx.get_hash().hex())

            resp = send_request("getMinorBlockById", ["0x" + "ff" * 36, True])
            self.assertIsNone(resp)

            # By height
            for need_extra_info in [True, False]:
                resp = send_request("getMinorBlockByHeight",
                                    ["0x0", "0x1", False, need_extra_info])
                self.assertEqual(resp["transactions"][0],
                                 "0x" + tx.get_hash().hex() + "00000002")

            resp = send_request("getMinorBlockByHeight", ["0x0", "0x1", True])
            self.assertEqual(resp["transactions"][0]["hash"],
                             "0x" + tx.get_hash().hex())

            resp = send_request("getMinorBlockByHeight", ["0x1", "0x2", False])
            self.assertIsNone(resp)
            resp = send_request("getMinorBlockByHeight", ["0x0", "0x4", False])
            self.assertIsNone(resp)
Пример #27
0
    def test_getNextBlockToMine_and_addBlock(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)
        acc3 = Address.create_random_account(full_shard_id=1)

        with ClusterContext(1, acc1) as clusters, jrpc_server_context(
                clusters[0].master):
            slaves = clusters[0].slave_list

            # Expect to mine root that confirms the genesis minor blocks
            response = send_request("getNextBlockToMine",
                                    "0x" + acc1.serialize().hex(), "0x0")
            self.assertTrue(response["isRootBlock"])
            block = RootBlock.deserialize(
                bytes.fromhex(response["blockData"][2:]))

            self.assertEqual(block.header.height, 1)
            self.assertEqual(len(block.minor_block_header_list), 2)
            self.assertEqual(block.minor_block_header_list[0].height, 0)
            self.assertEqual(block.minor_block_header_list[1].height, 0)

            send_request("addBlock", "0x0", response["blockData"])

            tx = create_transfer_transaction(
                shard_state=clusters[0].get_shard_state(0),
                key=id1.get_key(),
                from_address=acc1,
                to_address=acc3,
                value=14,
                gas=opcodes.GTXXSHARDCOST + opcodes.GTXCOST,
            )
            self.assertTrue(slaves[0].add_tx(tx))

            # Expect to mine shard 0 since it has one tx
            response = send_request("getNextBlockToMine",
                                    "0x" + acc1.serialize().hex(), "0x0")
            self.assertFalse(response["isRootBlock"])
            block1 = MinorBlock.deserialize(
                bytes.fromhex(response["blockData"][2:]))
            self.assertEqual(block1.header.branch.value, 0b10)

            self.assertTrue(
                send_request("addBlock", "0x2", response["blockData"]))
            self.assertEqual(
                clusters[0].get_shard_state(1).get_balance(acc3.recipient, 0),
                0)

            # Expect to mine shard 1 due to proof-of-progress
            response = send_request("getNextBlockToMine",
                                    "0x" + acc1.serialize().hex(), "0x0")
            self.assertFalse(response["isRootBlock"])
            block2 = MinorBlock.deserialize(
                bytes.fromhex(response["blockData"][2:]))
            self.assertEqual(block2.header.branch.value, 0b11)

            self.assertTrue(
                send_request("addBlock", "0x3", response["blockData"]))

            # Expect to mine root
            response = send_request("getNextBlockToMine",
                                    "0x" + acc1.serialize().hex(), "0x0")
            self.assertTrue(response["isRootBlock"])
            block = RootBlock.deserialize(
                bytes.fromhex(response["blockData"][2:]))

            self.assertEqual(block.header.height, 2)
            self.assertEqual(len(block.minor_block_header_list), 2)
            self.assertEqual(block.minor_block_header_list[0], block1.header)
            self.assertEqual(block.minor_block_header_list[1], block2.header)

            send_request("addBlock", "0x0", response["blockData"])
            self.assertEqual(
                clusters[0].get_shard_state(1).get_balance(acc3.recipient, 0),
                0)

            # Expect to mine shard 1 for the gas on xshard tx to acc3
            response = send_request("getNextBlockToMine",
                                    "0x" + acc1.serialize().hex(), "0x0")
            self.assertFalse(response["isRootBlock"])
            block3 = MinorBlock.deserialize(
                bytes.fromhex(response["blockData"][2:]))
            self.assertEqual(block3.header.branch.value, 0b11)

            self.assertTrue(
                send_request("addBlock", "0x3", response["blockData"]))
            # Expect withdrawTo is included in acc3's balance
            resp = send_request("getBalance", "0x" + acc3.serialize().hex())
            self.assertEqual(resp["branch"], "0x3")
            self.assertEqual(resp["balance"], "0xe")
Пример #28
0
    def test_contract_suicide(self):
        """
        Kill Call Data: 0x41c0e1b5
        """
        QETH = token_id_encode("QETH")
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)
        id2 = Identity.create_random_identity()
        acc2 = Address.create_from_identity(id2, full_shard_key=0)
        acc3 = Address.create_random_account(full_shard_key=0)

        env = get_test_env(
            genesis_account=acc1,
            genesis_minor_token_balances={
                self.GENESIS_TOKEN: 200 * 10 ** 18,
                "QETH": 99999,
            },
        )
        state = create_default_shard_state(env=env)

        # 1. create contract
        BYTECODE = "6080604052348015600f57600080fd5b5060948061001e6000396000f3fe6080604052600436106039576000357c01000000000000000000000000000000000000000000000000000000009004806341c0e1b514603b575b005b348015604657600080fd5b50604d604f565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea165627a7a7230582034cc4e996685dcadcc12db798751d2913034a3e963356819f2293c3baea4a18c0029"
        """
        pragma solidity ^0.5.1;
        contract Sample {
          function () payable external{}
          function kill() external {selfdestruct(msg.sender);}
        }
        """
        CREATION_GAS = 92417
        tx = contract_creation_tx(
            shard_state=state,
            key=id1.get_key(),
            from_address=acc1,
            to_full_shard_key=acc1.full_shard_key,
            bytecode=BYTECODE,
            gas_token_id=self.genesis_token,
            transfer_token_id=self.genesis_token,
        )
        self.assertTrue(state.add_tx(tx))
        b1 = state.create_block_to_mine(address=acc3)
        self.assertEqual(len(b1.tx_list), 1)
        state.finalize_and_add_block(b1)
        self.assertEqual(state.header_tip, b1.header)
        self.assertEqual(len(state.evm_state.receipts), 1)
        self.assertEqual(state.evm_state.receipts[0].state_root, b"\x01")
        self.assertEqual(state.evm_state.receipts[0].gas_used, CREATION_GAS)
        contract_address = mk_contract_address(acc1.recipient, 0, acc1.full_shard_key)
        self.assertEqual(contract_address, state.evm_state.receipts[0].contract_address)
        self.assertEqual(
            acc1.full_shard_key, state.evm_state.receipts[0].contract_full_shard_key
        )
        self.assertEqual(
            state.get_token_balance(id1.recipient, self.genesis_token),
            200 * 10 ** 18 - CREATION_GAS,
        )
        self.assertEqual(
            state.get_token_balance(acc3.recipient, self.genesis_token),
            self.get_after_tax_reward(CREATION_GAS + self.shard_coinbase),
        )
        tx_list, _ = state.db.get_transactions_by_address(acc1)
        self.assertEqual(tx_list[0].value, 0)
        self.assertEqual(tx_list[0].gas_token_id, self.genesis_token)
        self.assertEqual(tx_list[0].transfer_token_id, self.genesis_token)

        # 2. send some default token
        tx_send = create_transfer_transaction(
            shard_state=state,
            key=id1.get_key(),
            from_address=acc1,
            to_address=Address(contract_address, acc1.full_shard_key),
            value=10 * 10 ** 18,
            gas=opcodes.GTXCOST + 40,
            gas_price=1,
            nonce=None,
            data=b"",
            gas_token_id=self.genesis_token,
            transfer_token_id=self.genesis_token,
        )
        self.assertTrue(state.add_tx(tx_send))
        b2 = state.create_block_to_mine(address=acc3)
        self.assertEqual(len(b2.tx_list), 1)
        state.finalize_and_add_block(b2)
        self.assertEqual(state.header_tip, b2.header)
        self.assertEqual(len(state.evm_state.receipts), 1)
        self.assertEqual(state.evm_state.receipts[0].state_root, b"\x01")
        self.assertEqual(state.evm_state.receipts[0].gas_used, opcodes.GTXCOST + 40)
        self.assertEqual(
            state.get_token_balance(id1.recipient, self.genesis_token),
            200 * 10 ** 18 - CREATION_GAS - (opcodes.GTXCOST + 40) - 10 * 10 ** 18,
        )
        self.assertEqual(
            state.get_token_balance(contract_address, self.genesis_token), 10 * 10 ** 18
        )

        # 3. suicide
        SUICIDE_GAS = 13199
        tx_kill = create_transfer_transaction(
            shard_state=state,
            key=id2.get_key(),
            from_address=acc2,
            to_address=Address(contract_address, acc1.full_shard_key),
            value=0,
            gas=1000000,
            gas_price=0,  # !!! acc2 has no token yet...
            nonce=None,
            data=bytes.fromhex("41c0e1b5"),
            gas_token_id=self.genesis_token,
            transfer_token_id=self.genesis_token,
        )
        self.assertTrue(state.add_tx(tx_kill))
        b3 = state.create_block_to_mine(address=acc3)
        self.assertEqual(len(b3.tx_list), 1)
        state.finalize_and_add_block(b3)
        self.assertEqual(state.header_tip, b3.header)
        self.assertEqual(len(state.evm_state.receipts), 1)
        self.assertEqual(state.evm_state.receipts[0].state_root, b"\x01")
        self.assertEqual(state.evm_state.receipts[0].gas_used, SUICIDE_GAS)
        self.assertEqual(
            state.get_token_balance(id2.recipient, self.genesis_token), 10 * 10 ** 18
        )
        self.assertEqual(
            state.get_token_balance(contract_address, self.genesis_token), 0
        )
Пример #29
0
    def test_xshard_native_token_gas_received(self):
        qeth = token_id_encode("QETHXX")
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)
        acc2 = Address.create_from_identity(id1, full_shard_key=16)
        acc3 = Address.create_random_account(full_shard_key=0)

        env0 = get_test_env(
            genesis_account=acc1,
            genesis_minor_token_balances={"QETHXX": 9999999},
            shard_size=64,
        )
        env1 = get_test_env(
            genesis_account=acc1,
            genesis_minor_token_balances={"QETHXX": 9999999},
            shard_size=64,
        )
        state0 = create_default_shard_state(env=env0, shard_id=0)
        state1 = create_default_shard_state(env=env1, shard_id=16)

        # Add a root block to allow later minor blocks referencing this root block to
        # be broadcasted
        root_block = (
            state0.root_tip.create_block_to_append()
            .add_minor_block_header(state0.header_tip)
            .add_minor_block_header(state1.header_tip)
            .finalize()
        )
        state0.add_root_block(root_block)
        state1.add_root_block(root_block)

        # Add one block in shard 0
        b0 = state0.create_block_to_mine()
        state0.finalize_and_add_block(b0)

        b1 = state1.get_tip().create_block_to_append()
        b1.header.hash_prev_root_block = root_block.header.get_hash()
        tx = create_transfer_transaction(
            shard_state=state1,
            key=id1.get_key(),
            from_address=acc2,
            to_address=acc1,
            value=8888888,
            gas=opcodes.GTXXSHARDCOST + opcodes.GTXCOST,
            gas_price=2,
            gas_token_id=qeth,
            transfer_token_id=qeth,
        )
        b1.add_tx(tx)

        # Add a x-shard tx from remote peer
        state0.add_cross_shard_tx_list_by_minor_block_hash(
            h=b1.header.get_hash(),
            tx_list=CrossShardTransactionList(
                tx_list=[
                    CrossShardTransactionDeposit(
                        tx_hash=tx.get_hash(),
                        from_address=acc2,
                        to_address=acc1,
                        value=8888888,
                        gas_price=2,
                        gas_token_id=self.genesis_token,
                        transfer_token_id=qeth,
                    )
                ]
            ),
        )

        # Create a root block containing the block with the x-shard tx
        root_block = (
            state0.root_tip.create_block_to_append()
            .add_minor_block_header(b0.header)
            .add_minor_block_header(b1.header)
            .finalize()
        )
        state0.add_root_block(root_block)

        # Add b0 and make sure all x-shard tx's are added
        b2 = state0.create_block_to_mine(address=acc3)
        state0.finalize_and_add_block(b2)

        self.assertEqual(
            state0.get_token_balance(acc1.recipient, qeth), 9999999 + 8888888
        )
        # Half coinbase collected by root + tx fee
        self.assertEqual(
            state0.get_token_balance(acc3.recipient, self.genesis_token),
            self.get_after_tax_reward(self.shard_coinbase + opcodes.GTXXSHARDCOST * 2),
        )

        # X-shard gas used
        self.assertEqual(
            state0.evm_state.xshard_receive_gas_used, opcodes.GTXXSHARDCOST
        )
Пример #30
0
    def test_xshard_native_token_gas_sent(self):
        """x-shard transfer QETH using QETH as gas
        """
        qeth = token_id_encode("QETHXX")
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)
        acc2 = Address.create_from_identity(id1, full_shard_key=1)
        acc3 = Address.create_random_account(full_shard_key=0)

        env = get_test_env(
            genesis_account=acc1,
            genesis_minor_token_balances={"QETHXX": 9999999},
            charge_gas_reserve=True,
        )
        state = create_default_shard_state(env=env, shard_id=0)
        env1 = get_test_env(genesis_account=acc1, genesis_minor_token_balances={})
        state1 = create_default_shard_state(env=env1, shard_id=1)

        # Add a root block to update block gas limit so that xshard tx can be included
        root_block = (
            state.root_tip.create_block_to_append()
            .add_minor_block_header(state.header_tip)
            .add_minor_block_header(state1.header_tip)
            .finalize()
        )
        state.add_root_block(root_block)

        tx = create_transfer_transaction(
            shard_state=state,
            key=id1.get_key(),
            from_address=acc1,
            to_address=acc2,
            value=8888888,
            gas=opcodes.GTXXSHARDCOST + opcodes.GTXCOST,
            gas_token_id=qeth,
            transfer_token_id=qeth,
        )
        state.add_tx(tx)

        b1 = state.create_block_to_mine(address=acc3)
        self.assertEqual(len(b1.tx_list), 1)

        self.assertEqual(state.evm_state.gas_used, 0)
        # Should succeed
        state.finalize_and_add_block(b1)
        self.assertEqual(len(state.evm_state.xshard_list), 1)
        self.assertEqual(
            state.evm_state.xshard_list[0],
            CrossShardTransactionDeposit(
                tx_hash=tx.get_hash(),
                from_address=acc1,
                to_address=acc2,
                value=8888888,
                gas_price=1,
                gas_token_id=self.genesis_token,
                transfer_token_id=qeth,
            ),
        )
        self.assertEqual(
            state.get_token_balance(id1.recipient, qeth),
            9999999 - 8888888 - (opcodes.GTXCOST + opcodes.GTXXSHARDCOST),
        )

        # Make sure the xshard gas is not used by local block
        self.assertEqual(state.evm_state.gas_used, opcodes.GTXCOST)
        # block coinbase for mining is still in genesis_token + xshard fee
        self.assertEqual(
            state.get_token_balance(acc3.recipient, self.genesis_token),
            self.get_after_tax_reward(self.shard_coinbase + opcodes.GTXCOST),
        )