def put_confirmed_cross_shard_transaction_deposit_list(
            self, minor_block_hash, cross_shard_transaction_deposit_list):
        """Stores a mapping from minor block to the list of CrossShardTransactionDeposit confirmed"""
        if not self.env.cluster_config.ENABLE_TRANSACTION_HISTORY:
            return

        l = CrossShardTransactionList(cross_shard_transaction_deposit_list)
        self.db.put(b"xr_" + minor_block_hash, l.serialize())
Exemple #2
0
    def __get_branch_to_add_xshard_tx_list_request(self, block_hash,
                                                   xshard_tx_list,
                                                   prev_root_height):
        xshard_map = dict(
        )  # type: Dict[Branch, List[CrossShardTransactionDeposit]]

        # only broadcast to the shards that have been initialized
        initialized_shard_ids = self.env.quark_chain_config.get_initialized_shard_ids_before_root_height(
            prev_root_height)
        for shard_id in initialized_shard_ids:
            branch = Branch.create(self.__get_shard_size(), shard_id)
            xshard_map[branch] = []

        for xshard_tx in xshard_tx_list:
            shard_id = xshard_tx.to_address.get_shard_id(
                self.__get_shard_size())
            branch = Branch.create(self.__get_shard_size(), shard_id)
            check(branch in xshard_map)
            xshard_map[branch].append(xshard_tx)

        branch_to_add_xshard_tx_list_request = (
            dict())  # type: Dict[Branch, AddXshardTxListRequest]
        for branch, tx_list in xshard_map.items():
            cross_shard_tx_list = CrossShardTransactionList(tx_list)

            request = AddXshardTxListRequest(branch, block_hash,
                                             cross_shard_tx_list)
            branch_to_add_xshard_tx_list_request[branch] = request

        return branch_to_add_xshard_tx_list_request
Exemple #3
0
def add_minor_block_to_cluster(s_states, block):
    full_shard_id = block.header.branch.get_full_shard_id()
    s_states[full_shard_id].finalize_and_add_block(block)
    block_hash = block.header.get_hash()
    for dst_full_shard_id, state in s_states.items():
        if dst_full_shard_id == full_shard_id:
            continue
        state.add_cross_shard_tx_list_by_minor_block_hash(
            block_hash, CrossShardTransactionList(tx_list=[]))
def add_minor_block_to_cluster(s_states, block):
    shard_id = block.header.branch.get_shard_id()
    s_states[shard_id].finalize_and_add_block(block)
    block_hash = block.header.get_hash()
    for i in range(block.header.branch.get_shard_size()):
        if i == shard_id:
            continue
        s_states[i].add_cross_shard_tx_list_by_minor_block_hash(
            block_hash, CrossShardTransactionList(tx_list=[]))
Exemple #5
0
def add_minor_block_to_cluster(s_states, block):
    """Add block to corresponding shard state and broadcast xshard list to other shards"""
    full_shard_id = block.header.branch.get_full_shard_id()
    s_states[full_shard_id].finalize_and_add_block(block)
    block_hash = block.header.get_hash()
    for dst_full_shard_id, state in s_states.items():
        if dst_full_shard_id == full_shard_id:
            continue
        state.add_cross_shard_tx_list_by_minor_block_hash(
            block_hash, CrossShardTransactionList(tx_list=[]))
Exemple #6
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)
Exemple #7
0
    def test_root_chain_first_consensus(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)

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

        # Add one block and prepare a fork
        b0 = state0.get_tip().create_block_to_append(address=acc1)
        b2 = state0.get_tip().create_block_to_append(
            address=Address.create_empty_account())

        state0.finalize_and_add_block(b0)
        state0.finalize_and_add_block(b2)

        b1 = state1.get_tip().create_block_to_append()
        b1.finalize(evm_state=state1.run_block(b1))

        # Create a root block containing the block with the x-shard tx
        state0.add_cross_shard_tx_list_by_minor_block_hash(
            h=b1.header.get_hash(),
            tx_list=CrossShardTransactionList(tx_list=[]))
        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)

        b00 = b0.create_block_to_append()
        state0.finalize_and_add_block(b00)
        self.assertEqual(state0.header_tip, b00.header)

        # Create another fork that is much longer (however not confirmed by root_block)
        b3 = b2.create_block_to_append()
        state0.finalize_and_add_block(b3)
        b4 = b3.create_block_to_append()
        state0.finalize_and_add_block(b4)
        self.assertGreater(b4.header.height, b00.header.height)
        self.assertEqual(state0.header_tip, b00.header)
Exemple #8
0
def create_default_state(env, diff_calc=None):
    r_state = RootState(env=env, diff_calc=diff_calc)
    s_state_list = dict()
    for full_shard_id in env.quark_chain_config.get_full_shard_ids():
        shard_state = ShardState(env=env,
                                 full_shard_id=full_shard_id,
                                 db=quarkchain.db.InMemoryDb())
        shard_state.init_genesis_state(r_state.get_tip_block())
        s_state_list[full_shard_id] = shard_state

    for state in s_state_list.values():
        block_hash = state.header_tip.get_hash()
        for dst_state in s_state_list.values():
            if state == dst_state:
                continue
            dst_state.add_cross_shard_tx_list_by_minor_block_hash(
                block_hash, CrossShardTransactionList(tx_list=[]))
        r_state.add_validated_minor_block_hash(block_hash)

    return (r_state, s_state_list)
def create_default_state(env, diff_calc=None):
    r_state = RootState(env=env, diff_calc=diff_calc)
    s_state_list = []
    for shard_id in range(env.quark_chain_config.SHARD_SIZE):
        shard_state = ShardState(env=env,
                                 shard_id=shard_id,
                                 db=quarkchain.db.InMemoryDb())
        shard_state.init_genesis_state(r_state.get_tip_block())
        s_state_list.append(shard_state)

    for state in s_state_list:
        block_hash = state.header_tip.get_hash()
        for dst_state in s_state_list:
            if state == dst_state:
                continue
            dst_state.add_cross_shard_tx_list_by_minor_block_hash(
                block_hash, CrossShardTransactionList(tx_list=[]))
        r_state.add_validated_minor_block_hash(block_hash)

    return (r_state, s_state_list)
Exemple #10
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
        )
 def __get_confirmed_cross_shard_transaction_deposit_list(
         self, minor_block_hash):
     data = self.db.get(b"xr_" + minor_block_hash, None)
     if not data:
         return []
     return CrossShardTransactionList.from_data(data).tx_list
 def get_minor_block_xshard_tx_list(self, h) -> CrossShardTransactionList:
     key = b"xShard_" + h
     if key not in self.db:
         return None
     return CrossShardTransactionList.from_data(self.db.get(key))
 def put_minor_block_xshard_tx_list(self, h,
                                    tx_list: CrossShardTransactionList):
     self.db.put(b"xShard_" + h, tx_list.serialize())
Exemple #14
0
    def test_xshard_for_two_root_blocks(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)

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

        # 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=888888,
            gas=opcodes.GTXXSHARDCOST + opcodes.GTXCOST,
        )
        b1.add_tx(tx)

        # Add a x-shard tx from state1
        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=888888,
                    gas_price=2,
                )
            ]),
        )

        # Create a root block containing the block with the x-shard tx
        root_block0 = (
            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_block0)

        b2 = state0.get_tip().create_block_to_append()
        state0.finalize_and_add_block(b2)

        b3 = b1.create_block_to_append()
        b3.header.hash_prev_root_block = root_block.header.get_hash()

        # Add a x-shard tx from state1
        state0.add_cross_shard_tx_list_by_minor_block_hash(
            h=b3.header.get_hash(),
            tx_list=CrossShardTransactionList(tx_list=[
                CrossShardTransactionDeposit(
                    tx_hash=bytes(32),
                    from_address=acc2,
                    to_address=acc1,
                    value=385723,
                    gas_price=3,
                )
            ]),
        )

        root_block1 = (
            state0.root_tip.create_block_to_append().add_minor_block_header(
                b2.header).add_minor_block_header(b3.header).finalize())
        state0.add_root_block(root_block1)

        # Test x-shard gas limit when create_block_to_mine
        b5 = state0.create_block_to_mine(address=acc3, gas_limit=0)
        # Current algorithm allows at least one root block to be included
        self.assertEqual(b5.header.hash_prev_root_block,
                         root_block0.header.get_hash())
        b6 = state0.create_block_to_mine(address=acc3,
                                         gas_limit=opcodes.GTXXSHARDCOST)
        self.assertEqual(b6.header.hash_prev_root_block,
                         root_block0.header.get_hash())
        # There are two x-shard txs: one is root block coinbase with zero gas, and anonther is from shard 1
        b7 = state0.create_block_to_mine(address=acc3,
                                         gas_limit=2 * opcodes.GTXXSHARDCOST)
        self.assertEqual(b7.header.hash_prev_root_block,
                         root_block1.header.get_hash())
        b8 = state0.create_block_to_mine(address=acc3,
                                         gas_limit=3 * opcodes.GTXXSHARDCOST)
        self.assertEqual(b8.header.hash_prev_root_block,
                         root_block1.header.get_hash())

        # Add b0 and make sure all x-shard tx's are added
        b4 = state0.create_block_to_mine(address=acc3)
        self.assertEqual(b4.header.hash_prev_root_block,
                         root_block1.header.get_hash())
        state0.finalize_and_add_block(b4)

        self.assertEqual(state0.get_balance(acc1.recipient),
                         10000000 + 888888 + 385723)
        # Half collected by root
        self.assertEqual(state0.get_balance(acc3.recipient),
                         opcodes.GTXXSHARDCOST * (2 + 3) // 2)

        # Check gas used for receiving x-shard tx
        self.assertEqual(state0.evm_state.gas_used, 18000)
        self.assertEqual(state0.evm_state.xshard_receive_gas_used, 18000)
Exemple #15
0
    def test_xshard_tx_received_exclude_non_neighbor(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=3)
        acc3 = Address.create_random_account(full_shard_id=0)

        env0 = get_test_env(genesis_account=acc1,
                            genesis_minor_quarkash=10000000,
                            shard_size=64)
        env1 = get_test_env(genesis_account=acc1,
                            genesis_minor_quarkash=10000000,
                            shard_size=64)
        state0 = create_default_shard_state(env=env0, shard_id=0)
        state1 = create_default_shard_state(env=env1, shard_id=3)

        # 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()
        tx = create_transfer_transaction(
            shard_state=state1,
            key=id1.get_key(),
            from_address=acc2,
            to_address=acc1,
            value=888888,
            gas=opcodes.GTXXSHARDCOST + opcodes.GTXCOST,
            gas_price=2,
        )
        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=888888,
                    gas_price=2,
                )
            ]),
        )

        # 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_balance(acc1.recipient), 10000000)
        # Half collected by root
        self.assertEqual(state0.get_balance(acc3.recipient), 0)

        # X-shard gas used
        evmState0 = state0.evm_state
        self.assertEqual(evmState0.xshard_receive_gas_used, 0)