Ejemplo n.º 1
0
    def test_add_non_neighbor_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=3)  # not acc1's neighbor
        acc3 = Address.create_random_account(
            full_shard_id=8)  # acc1's neighbor

        env = get_test_env(genesis_account=acc1,
                           genesis_minor_quarkash=10000000,
                           shard_size=64)
        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=0,
            gas=1000000,
        )
        self.assertFalse(state.add_tx(tx))
        self.assertEqual(len(state.tx_queue), 0)

        tx = create_transfer_transaction(
            shard_state=state,
            key=id1.get_key(),
            from_address=acc1,
            to_address=acc3,
            value=0,
            gas=1000000,
        )
        self.assertTrue(state.add_tx(tx))
        self.assertEqual(len(state.tx_queue), 1)
Ejemplo n.º 2
0
    def test_native_token_gas(self):
        """in-shard transfer QETH using native token as gas
        TODODLL: support 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.assertFalse(
            state.add_tx(tx)
        )  # warning log: Failed to add transaction: Gas token must be QKC
        return

        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, QETH),
                         10000000 - opcodes.GTXCOST)
        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.getAfterTaxReward(opcodes.GTXCOST),
        )
        # miner coinbase
        self.assertEqual(
            state.get_token_balance(acc3.recipient, self.genesis_token),
            self.getAfterTaxReward(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)
Ejemplo n.º 3
0
    def test_shard_genesis_fork_fork(self):
        """ Test shard forks at genesis blocks due to root chain fork at GENESIS.ROOT_HEIGHT"""
        acc1 = Address.create_random_account(0)
        acc2 = Address.create_random_account(1)

        with ClusterContext(2, acc1, genesis_root_heights=[0, 1]) as clusters:
            # shutdown cluster connection
            clusters[1].peer.close()

            master0 = clusters[0].master
            is_root, root0 = call_async(master0.get_next_block_to_mine(acc1))
            self.assertTrue(is_root)
            call_async(master0.add_root_block(root0))
            genesis0 = clusters[0].get_shard_state(1).db.get_minor_block_by_height(0)
            self.assertEqual(
                genesis0.header.hash_prev_root_block, root0.header.get_hash()
            )

            master1 = clusters[1].master
            is_root, root1 = call_async(master1.get_next_block_to_mine(acc2))
            self.assertTrue(is_root)
            self.assertNotEqual(root0.header.get_hash(), root1.header.get_hash())
            call_async(master1.add_root_block(root1))
            genesis1 = clusters[1].get_shard_state(1).db.get_minor_block_by_height(0)
            self.assertEqual(
                genesis1.header.hash_prev_root_block, root1.header.get_hash()
            )

            # let's make cluster1's root chain longer than cluster0's
            # expect to mine shard 0 due to proof-of-progress
            is_root, block1 = call_async(master1.get_next_block_to_mine(acc2))
            self.assertFalse(is_root)
            self.assertEqual(block1.header.branch.get_shard_id(), 0)
            result = call_async(
                master1.add_raw_minor_block(block1.header.branch, block1.serialize())
            )
            self.assertTrue(result)

            is_root, root2 = call_async(master1.get_next_block_to_mine(acc2))
            self.assertTrue(is_root)
            call_async(master1.add_root_block(root2))
            self.assertEqual(master1.root_state.tip.height, 2)

            # reestablish cluster connection
            call_async(
                clusters[1].network.connect(
                    "127.0.0.1",
                    clusters[0].master.env.cluster_config.SIMPLE_NETWORK.BOOTSTRAP_PORT,
                )
            )
            # Expect cluster0's genesis change to genesis1
            assert_true_with_timeout(
                lambda: clusters[0]
                .get_shard_state(1)
                .db.get_minor_block_by_height(0)
                .header.get_hash()
                == genesis1.header.get_hash()
            )
            self.assertTrue(clusters[0].get_shard_state(1).root_tip == root2.header)
Ejemplo n.º 4
0
    def test_shard_genesis_fork_fork(self):
        """ Test shard forks at genesis blocks due to root chain fork at GENESIS.ROOT_HEIGHT"""
        acc1 = Address.create_random_account(0)
        acc2 = Address.create_random_account(1)

        genesis_root_heights = {2: 0, 3: 1}
        with ClusterContext(
                2,
                acc1,
                chain_size=1,
                shard_size=2,
                genesis_root_heights=genesis_root_heights,
        ) as clusters:
            # shutdown cluster connection
            clusters[1].peer.close()

            master0 = clusters[0].master
            root0 = call_async(
                master0.get_next_block_to_mine(acc1, branch_value=None))
            call_async(master0.add_root_block(root0))
            genesis0 = (clusters[0].get_shard_state(
                2 | 1).db.get_minor_block_by_height(0))
            self.assertEqual(genesis0.header.hash_prev_root_block,
                             root0.header.get_hash())

            master1 = clusters[1].master
            root1 = call_async(
                master1.get_next_block_to_mine(acc2, branch_value=None))
            self.assertNotEqual(root0.header.get_hash(),
                                root1.header.get_hash())
            call_async(master1.add_root_block(root1))
            genesis1 = (clusters[1].get_shard_state(
                2 | 1).db.get_minor_block_by_height(0))
            self.assertEqual(genesis1.header.hash_prev_root_block,
                             root1.header.get_hash())

            self.assertNotEqual(genesis0.header.get_hash(),
                                genesis1.header.get_hash())

            # let's make cluster1's root chain longer than cluster0's
            root2 = call_async(
                master1.get_next_block_to_mine(acc2, branch_value=None))
            call_async(master1.add_root_block(root2))
            self.assertEqual(master1.root_state.tip.height, 2)

            # reestablish cluster connection
            call_async(clusters[1].network.connect(
                "127.0.0.1",
                clusters[0].master.env.cluster_config.SIMPLE_NETWORK.
                BOOTSTRAP_PORT,
            ))
            # Expect cluster0's genesis change to genesis1
            assert_true_with_timeout(lambda: clusters[0].get_shard_state(
                2 | 1).db.get_minor_block_by_height(0).header.get_hash() ==
                                     genesis1.header.get_hash())
            self.assertTrue(
                clusters[0].get_shard_state(2 | 1).root_tip == root2.header)
Ejemplo n.º 5
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))
Ejemplo n.º 6
0
    def test_native_token_transfer(self):
        """in-shard transfer QETH using genesis_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={
                self.GENESIS_TOKEN: 10000000,
                "QETH": 99999
            },
        )
        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=self.genesis_token,
            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(id1.recipient, self.genesis_token),
            10000000 - opcodes.GTXCOST,
        )
        self.assertEqual(state.get_token_balance(acc1.recipient, QETH),
                         99999 - 12345)
        self.assertEqual(state.get_token_balance(acc2.recipient, QETH), 12345)
        self.assertEqual(
            state.get_token_balance(acc3.recipient, self.genesis_token),
            self.getAfterTaxReward(opcodes.GTXCOST + 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, self.genesis_token)
        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, self.genesis_token)
        self.assertEqual(tx_list[0].transfer_token_id, QETH)
Ejemplo n.º 7
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)
        # Miner
        acc3 = Address.create_random_account(full_shard_key=0)

        env = get_test_env(
            genesis_account=acc1,
            genesis_minor_token_balances={"QETH": 10000000},
            charge_gas_reserve=True,
        )
        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)
        # after-tax coinbase + tx fee should only be in QKC
        self.assertEqual(
            state.get_token_balance(acc3.recipient, self.genesis_token),
            self.get_after_tax_reward(self.shard_coinbase + opcodes.GTXCOST),
        )
        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)
    def test_get_transaction_by_address(self):
        id1 = Identity.create_random_identity()
        miner_addr = Address.create_random_account(full_shard_key=0)
        acc1 = Address.create_from_identity(id1, full_shard_key=0)
        acc2 = Address.create_from_identity(id1, full_shard_key=100)
        acc3 = Address.create_random_account(full_shard_key=0)

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

        # Add a root block to have all the shards initialized
        root_block = state.root_tip.create_block_to_append().finalize()
        state.add_root_block(root_block)

        tx1 = create_transfer_transaction(
            shard_state=state,
            key=id1.get_key(),
            from_address=acc1,
            to_address=acc2,
            value=12345,
        )
        self.assertTrue(state.add_tx(tx1))
        b1 = state.create_block_to_mine(address=miner_addr)
        state.finalize_and_add_block(b1)
        self.assertEqual(state.header_tip, b1.header)

        tx2 = create_transfer_transaction(
            shard_state=state,
            key=id1.get_key(),
            from_address=acc1,
            to_address=acc3,
            value=54321,
        )
        self.assertTrue(state.add_tx(tx2))
        b2 = state.create_block_to_mine(address=miner_addr)
        state.finalize_and_add_block(b2)
        self.assertEqual(state.header_tip, b2.header)

        # acc1 and acc2 should have the same transaction history
        # while acc3 is different
        tx_list1, _ = state.db.get_transactions_by_address(acc1)
        self.assertListEqual([t.value for t in tx_list1], [12345, 54321])
        tx_list2, _ = state.db.get_transactions_by_address(acc2)
        self.assertListEqual(tx_list2, tx_list1)
        tx_list3, _ = state.db.get_transactions_by_address(acc3)
        self.assertEqual(tx_list3[0].value, 54321)
        self.assertNotEqual(tx_list3, tx_list1)
Ejemplo n.º 9
0
    def test_createTransactions(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)

        loadtest_accounts = [
            {
                "address": "b067ac9ebeeecb10bbcd1088317959d58d1e38f6b0ee10d5",
                "key": "ca0143c9aa51c3013f08e83f3b6368a4f3ba5b52c4841c6e0c22c300f7ee6827",
            },
            {
                "address": "9f2b984937ff8e3f20d2a2592f342f47257870909fffa247",
                "key": "40efdb8528de149c35fb43a572fc821d8fbdf2469dcc7fe1a9e847ef29e3c941",
            },
        ]

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

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

            send_request("createTransactions", {"numTxPerShard": 1, "xShardPercent": 0})
Ejemplo n.º 10
0
    def test_sendTransaction_with_bad_signature(self):
        """ sendTransaction validates signature """
        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

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

            request = dict(
                to="0x" + acc2.recipient.hex(),
                gasPrice="0x6",
                gas=hex(30000),
                value="0xf",
                v="0x1",
                r="0x2",
                s="0x3",
                nonce="0x0",
                fromFullShardKey="0x00000000",
                toFullShardKey="0x00000001",
            )
            self.assertEqual(send_request("sendTransaction", [request]),
                             EMPTY_TX_ID)
            self.assertEqual(len(clusters[0].get_shard_state(2 | 0).tx_queue),
                             0)
Ejemplo n.º 11
0
    def test_get_primary_account_data(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)

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

            branch = Branch.create(2, 0)
            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, block1 = call_async(master.get_next_block_to_mine(address=acc1))
            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
            )
Ejemplo n.º 12
0
    def test_sendTransaction_with_bad_signature(self):
        """ sendTransaction validates signature """
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)
        acc2 = 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

            branch = Branch.create(2, 0)
            request = dict(
                to="0x" + acc2.recipient.hex(),
                gasPrice="0x6",
                gas=hex(30000),
                value="0xf",
                v="0x1",
                r="0x2",
                s="0x3",
                nonce="0x0",
                fromFullShardId="0x00000000",
                toFullShardId="0x00000001",
            )
            self.assertIsNone(send_request("sendTransaction", request))
            self.assertEqual(len(slaves[0].shards[branch].state.tx_queue), 0)
Ejemplo n.º 13
0
    def test_proc_balance_mnt(self):
        default_addr = b"\x00" * 19 + b"\x34"
        token_id = 1234567
        token_id_bytes = token_id.to_bytes(32, byteorder="big")
        state = State()

        self.__mint(state, default_addr, token_id_bytes, encode_int32(2020))
        balance = state.get_balance(default_addr, token_id)
        self.assertEqual(balance, 2020)

        data = b"\x00" * 12 + default_addr + token_id_bytes
        # Gas not enough
        msg = Message(default_addr, default_addr, gas=399, data=data)
        ret_tuple = proc_balance_mnt(VmExtBase(state), msg)
        self.assertEqual(ret_tuple, (0, 0, []))

        # Success case
        testcases = [
            (default_addr, token_id, 2020),  # Balance already set
            (default_addr, 54321, 0),  # Non-existent token
            (Address.create_random_account(0).recipient, token_id, 0),  # Blank
        ]
        for addr, tid, bal in testcases:
            data = b"\x00" * 12 + addr + tid.to_bytes(32, byteorder="big")
            msg = Message(addr, addr, gas=500, data=data)
            result, gas_remained, ret = proc_balance_mnt(VmExtBase(state), msg)
            ret_int = int.from_bytes(ret, byteorder="big")
            self.assertEqual(result, 1)
            self.assertEqual(gas_remained, 500 - 400)
            self.assertEqual(ret_int, bal)
Ejemplo n.º 14
0
 async def go():
     nonlocal now, mock_tip
     # no current work, will generate a new one
     work, block = await miner.get_work(EMPTY_ADDR, now=now)
     self.assertEqual(len(work), 3)
     self.assertEqual(block.header.coinbase_address,
                      Address.create_empty_account())
     self.assertEqual(len(miner.work_map), 1)
     h = list(miner.work_map.keys())[0]
     self.assertEqual(work.hash, h)
     # cache hit and new block is linked to tip (by default)
     now += 1
     work, _ = await miner.get_work(EMPTY_ADDR, now=now)
     self.assertEqual(work.hash, h)
     self.assertEqual(work.height, 43)
     self.assertEqual(len(miner.work_map), 1)
     # cache hit, but current work is outdated because tip has updated
     mock_tip.height += 1
     work, _ = await miner.get_work(EMPTY_ADDR, now=now)
     h = work.hash
     self.assertEqual(len(miner.work_map), 2)
     self.assertEqual(work.height, 44)
     # new work if interval passed
     now += 11
     work, _ = await miner.get_work(EMPTY_ADDR, now=now)
     self.assertEqual(len(miner.work_map), 3)
     # height didn't change, but hash should
     self.assertNotEqual(work.hash, h)
     self.assertEqual(work.height, 44)
     # get work with specified coinbase address
     addr = Address.create_random_account(0)
     work, block = await miner.get_work(addr, now=now)
     self.assertEqual(block.header.coinbase_address, addr)
     self.assertEqual(len(miner.work_map), 4)
     self.assertEqual(len(miner.current_works), 2)
Ejemplo n.º 15
0
    def test_create_shard_at_different_height(self):
        acc1 = Address.create_random_account()
        with ClusterContext(1, acc1, genesis_root_heights=[1, 2]) as clusters:
            master = clusters[0].master
            slaves = clusters[0].slave_list

            self.assertEqual(len(slaves[0].shards), 0)
            self.assertEqual(len(slaves[1].shards), 0)

            is_root, root = call_async(master.get_next_block_to_mine(acc1))
            self.assertTrue(is_root)
            self.assertEqual(len(root.minor_block_header_list), 0)
            call_async(master.add_root_block(root))

            # shard 0 created at root height 1
            self.assertEqual(len(slaves[0].shards), 1)
            self.assertEqual(len(slaves[1].shards), 0)

            is_root, root = call_async(master.get_next_block_to_mine(acc1))
            self.assertTrue(is_root)
            self.assertEqual(len(root.minor_block_header_list), 1)
            call_async(master.add_root_block(root))

            self.assertEqual(len(slaves[0].shards), 1)
            # shard 1 created at root height 2
            self.assertEqual(len(slaves[1].shards), 1)

            # Expect to mine shard 0 due to proof of progress
            is_root, block = call_async(master.get_next_block_to_mine(acc1))
            self.assertFalse(is_root)
            self.assertEqual(block.header.branch.get_shard_id(), 0)
            self.assertEqual(block.header.height, 1)
Ejemplo n.º 16
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)
Ejemplo n.º 17
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)
Ejemplo n.º 18
0
    def test_serialization_and_deserialization(self):
        cstor_params = {
            "tx_hash": bytes(32),
            "from_address": Address.create_random_account(1),
            "to_address": Address.create_random_account(1),
            "value": 123,
            "gas_price": 456,
            "gas_token_id": 789,
            "transfer_token_id": 101,
        }
        deposit_deprecated = CrossShardTransactionDepositDeprecated(
            **cstor_params)
        deposit_v0 = CrossShardTransactionDepositV0(**cstor_params)
        deposit_v1 = CrossShardTransactionDeposit(**cstor_params)

        testcases = [
            (CrossShardTransactionDeprecatedList([deposit_deprecated]), None),
            (CrossShardTransactionListV0([deposit_v0]), None),
            (CrossShardTransactionList([deposit_v1]), 55),
        ]
        for ls, refund_rate_update in testcases:
            if refund_rate_update:
                ls.tx_list[0].refund_rate = refund_rate_update
            else:
                refund_rate_update = 100  # default refund rate, for comparison

            deserialized = CrossShardTransactionList.from_data(ls.serialize())
            self.assertIsInstance(deserialized, CrossShardTransactionList)
            self.assertEqual(len(deserialized.tx_list), 1)
            deposit = deserialized.tx_list[0]
            self.assertIsInstance(deposit, CrossShardTransactionDeposit)
            self.assertEqual(deposit.refund_rate, refund_rate_update)
            # serialize and deserialize again
            deposit_deserialized_again = CrossShardTransactionDeposit.deserialize(
                deposit.serialize())
            self.assertIsInstance(deposit_deserialized_again,
                                  CrossShardTransactionDeposit)
            self.assertEqual(deposit_deserialized_again.refund_rate,
                             refund_rate_update)
Ejemplo n.º 19
0
    def test_transaction(self):
        id1 = Identity.create_random_identity()
        acc2 = Address.create_random_account()

        tx = create_random_test_transaction(id1, acc2)

        barray = tx.serialize(bytearray())

        bb = ByteBuffer(barray)
        tx1 = Transaction.deserialize(bb)
        self.assertEqual(bb.remaining(), 0)
        self.assertEqual(tx, tx1)
        self.assertTrue(tx1.verify_signature([id1.get_recipient()]))
Ejemplo n.º 20
0
    def test_sendTransaction(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):
            slaves = clusters[0].slave_list
            master = clusters[0].master

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

            evm_tx = EvmTransaction(
                nonce=0,
                gasprice=6,
                startgas=30000,
                to=acc2.recipient,
                value=15,
                data=b"",
                from_full_shard_key=acc1.full_shard_key,
                to_full_shard_key=acc2.full_shard_key,
                network_id=slaves[0].env.quark_chain_config.NETWORK_ID,
                gas_token_id=master.env.quark_chain_config.genesis_token,
                transfer_token_id=master.env.quark_chain_config.genesis_token,
            )
            evm_tx.sign(id1.get_key())
            request = dict(
                to="0x" + acc2.recipient.hex(),
                gasPrice="0x6",
                gas=hex(30000),
                value="0xf",  # 15
                v=quantity_encoder(evm_tx.v),
                r=quantity_encoder(evm_tx.r),
                s=quantity_encoder(evm_tx.s),
                nonce="0x0",
                fromFullShardKey="0x00000000",
                toFullShardKey="0x00000001",
                network_id=hex(slaves[0].env.quark_chain_config.NETWORK_ID),
            )
            tx = TypedTransaction(SerializedEvmTransaction.from_evm_tx(evm_tx))
            response = send_request("sendTransaction", [request])

            self.assertEqual(response, "0x" + tx.get_hash().hex() + "00000000")
            state = clusters[0].get_shard_state(2 | 0)
            self.assertEqual(len(state.tx_queue), 1)
            self.assertEqual(
                state.tx_queue.pop_transaction(state.get_transaction_count),
                evm_tx)
Ejemplo n.º 21
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))
Ejemplo n.º 22
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},
        )
Ejemplo n.º 23
0
    def test_add_block_receipt_root_not_match(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1)
        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)

        b1 = state.create_block_to_mine(address=acc3)

        # Should succeed
        state.finalize_and_add_block(b1)
        b1.finalize(evm_state=state.run_block(b1))
        b1.meta.hash_evm_receipt_root = b"00" * 32
        self.assertRaises(ValueError, state.add_block(b1))
Ejemplo n.º 24
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))
Ejemplo n.º 25
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)
Ejemplo n.º 26
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"")
Ejemplo n.º 27
0
    def test_stale_block_count(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, 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)

        b1 = state.create_block_to_mine(address=acc3)
        b2 = state.create_block_to_mine(address=acc3)
        b2.header.create_time += 1

        state.finalize_and_add_block(b1)
        self.assertEqual(state.db.get_block_count_by_height(1), 1)

        state.finalize_and_add_block(b2)
        self.assertEqual(state.db.get_block_count_by_height(1), 2)
Ejemplo n.º 28
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)
Ejemplo n.º 29
0
    def test_sendTransaction(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)

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

            branch = Branch.create(2, 0)
            evm_tx = EvmTransaction(
                nonce=0,
                gasprice=6,
                startgas=30000,
                to=acc2.recipient,
                value=15,
                data=b"",
                from_full_shard_id=acc1.full_shard_id,
                to_full_shard_id=acc2.full_shard_id,
                network_id=slaves[0].env.quark_chain_config.NETWORK_ID,
            )
            evm_tx.sign(id1.get_key())
            request = dict(
                to="0x" + acc2.recipient.hex(),
                gasPrice="0x6",
                gas=hex(30000),
                value="0xf",  # 15
                v=quantity_encoder(evm_tx.v),
                r=quantity_encoder(evm_tx.r),
                s=quantity_encoder(evm_tx.s),
                nonce="0x0",
                fromFullShardId="0x00000000",
                toFullShardId="0x00000001",
                network_id=hex(slaves[0].env.quark_chain_config.NETWORK_ID),
            )
            tx = Transaction(code=Code.create_evm_code(evm_tx))
            response = send_request("sendTransaction", [request])

            self.assertEqual(response, "0x" + tx.get_hash().hex() + "00000000")
            self.assertEqual(len(slaves[0].shards[branch].state.tx_queue), 1)
            self.assertEqual(
                slaves[0].shards[branch].state.tx_queue.pop_transaction(),
                evm_tx)
Ejemplo n.º 30
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)