Ejemplo n.º 1
0
    def test_shard_state_recovery_from_root_block(self):
        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, shard_id=0)

        blockHeaders = []
        blockMetas = []
        for i in range(12):
            b = state.get_tip().create_block_to_append(address=acc1)
            state.finalize_and_add_block(b)
            blockHeaders.append(b.header)
            blockMetas.append(b.meta)

        # add a fork
        b1 = state.db.get_minor_block_by_height(3)
        b1.header.create_time += 1
        state.finalize_and_add_block(b1)
        self.assertEqual(
            state.db.get_minor_block_by_hash(b1.header.get_hash()), b1)

        root_block = state.root_tip.create_block_to_append()
        root_block.minor_block_header_list = blockHeaders[:5]
        root_block.finalize()

        state.add_root_block(root_block)

        recoveredState = ShardState(env=env, shard_id=0)

        recoveredState.init_from_root_block(root_block)
        # forks are pruned
        self.assertIsNone(
            recoveredState.db.get_minor_block_by_hash(b1.header.get_hash()))
        self.assertEqual(
            recoveredState.db.get_minor_block_by_hash(b1.header.get_hash(),
                                                      consistency_check=False),
            b1,
        )

        self.assertEqual(recoveredState.root_tip, root_block.header)
        self.assertEqual(recoveredState.header_tip, blockHeaders[4])
        self.assertEqual(recoveredState.confirmed_header_tip, blockHeaders[4])
        self.assertEqual(recoveredState.meta_tip, blockMetas[4])
        self.assertEqual(recoveredState.evm_state.trie.root_hash,
                         blockMetas[4].hash_evm_state_root)
Ejemplo n.º 2
0
    def test_getTransactionCount(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, jrpc_server_context(
                clusters[0].master):
            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)
            for i in range(3):
                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))

                _, block = call_async(
                    master.get_next_block_to_mine(address=acc1))
                self.assertEqual(i + 1, block.header.height)
                self.assertTrue(
                    call_async(clusters[0].get_shard(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.º 3
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.º 4
0
    def test_add_minor_block_request_list(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)

        with ClusterContext(2, acc1) as clusters:
            shard_state = clusters[0].get_shard_state(0b10)
            coinbase_amount = (
                shard_state.env.quark_chain_config.shards[
                    shard_state.full_shard_id
                ].COINBASE_AMOUNT
                // 2
            )
            b1 = shard_state.get_tip().create_block_to_append()
            evm_state = shard_state.run_block(b1)
            b1.finalize(
                evm_state=evm_state,
                coinbase_amount=evm_state.block_fee + coinbase_amount,
            )
            add_result = call_async(
                clusters[0].master.add_raw_minor_block(b1.header.branch, b1.serialize())
            )
            self.assertTrue(add_result)

            # Make sure the xshard list is not broadcasted to the other shard
            self.assertFalse(
                clusters[0]
                .get_shard_state(0b11)
                .contain_remote_minor_block_hash(b1.header.get_hash())
            )
            self.assertTrue(
                clusters[0].master.root_state.is_minor_block_validated(
                    b1.header.get_hash()
                )
            )

            # Make sure another cluster received the new block
            assert_true_with_timeout(
                lambda: clusters[0]
                .get_shard_state(0b10)
                .contain_block_by_hash(b1.header.get_hash())
            )
            assert_true_with_timeout(
                lambda: clusters[1].master.root_state.is_minor_block_validated(
                    b1.header.get_hash()
                )
            )
Ejemplo n.º 5
0
    def test_native_token_transfer_0_value(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})
        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},
        )
async def deploy_shard(endpoint, genesisId, data, network_id, shard):
    address = Address.create_from_identity(genesisId, shard)
    nonce = await endpoint.get_nonce(address)
    tx = create_transaction(address, genesisId.get_key(), nonce, data, network_id)
    tx_id = await endpoint.send_transaction(tx)
    while True:
        print(
            "shard={} tx={} contract=(waiting for tx to be confirmed)".format(
                shard, tx_id
            )
        )
        await asyncio.sleep(5)
        contract_address = await endpoint.get_contract_address(tx_id)
        if contract_address:
            break
    print("shard={} tx={} contract={}".format(shard, tx_id, contract_address))
    return tx_id, contract_address
Ejemplo n.º 7
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, 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
            _, new_block = call_async(
                master.get_next_block_to_mine(address=acc1))
            self.assertIsInstance(new_block, MinorBlock)
            self.assertEqual(new_block.header.height, 2)
Ejemplo n.º 8
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)
async def fund_shard(endpoint, genesisId, to, data, network_id, shard):
    address = Address.create_from_identity(genesisId, shard)
    nonce = await endpoint.get_nonce(address)
    tx = create_transaction(address, genesisId.get_key(), nonce, to, data,
                            network_id)
    tx_id = await endpoint.send_transaction(tx)
    while True:
        print("shard={} tx={} block=(pending)".format(shard, tx_id))
        await asyncio.sleep(5)
        resp = await endpoint.get_transaction_receipt(tx_id)
        if resp:
            break

    height = int(resp["block_height"], 16)
    status = int(resp["status"], 16)
    print("shard={} tx={} block={} status={}".format(shard, tx_id, height,
                                                     status))
    return tx_id, height
Ejemplo n.º 10
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.º 11
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.º 12
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)
Ejemplo n.º 13
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.º 14
0
def test_perf_evm():
    N = 5000
    IDN = 10
    print("Creating %d identities" % IDN)
    id_list = []
    for i in range(IDN):
        id_list.append(Identity.create_random_identity())

    acc_list = []
    for i in range(IDN):
        acc_list.append(Address.create_from_identity(id_list[i]))

    print("Creating %d transactions..." % N)
    start_time = time.time()
    tx_list = []
    from_list = []
    for i in range(N):
        from_id = id_list[random.randint(0, IDN - 1)]
        to_addr = acc_list[random.randint(0, IDN - 1)]
        evm_tx = EvmTransaction(
            nonce=0,
            gasprice=1,
            startgas=2,
            to=to_addr.recipient,
            value=3,
            data=b"",
            from_full_shard_key=0,
            to_full_shard_key=0,
            network_id=1,
        )
        evm_tx.sign(key=from_id.get_key())
        tx_list.append(evm_tx)
        from_list.append(from_id.get_recipient())
    duration = time.time() - start_time
    print("Creations PS: %.2f" % (N / duration))

    print("Verifying transactions")
    start_time = time.time()
    for i in range(N):
        tx_list[i]._sender = None
        assert tx_list[i].sender == from_list[i]
    duration = time.time() - start_time
    print("Verifications PS: %.2f" % (N / duration))
Ejemplo n.º 15
0
    def test_call_success(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):
            slaves = clusters[0].slave_list

            response = send_request(
                "call", [{"to": "0x" + acc1.serialize().hex(), "gas": hex(21000)}]
            )

            self.assertEqual(response, "0x")
            self.assertEqual(
                len(clusters[0].get_shard_state(2 | 0).tx_queue),
                0,
                "should not affect tx queue",
            )
Ejemplo n.º 16
0
    def test_getNextBlockToMine_with_shard_mask(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)

        with ClusterContext(1, acc1) as clusters, jrpc_server_context(
                clusters[0].master):
            response = send_request("getNextBlockToMine",
                                    "0x" + acc1.serialize().hex(), "0x2")
            self.assertFalse(response["isRootBlock"])
            block1 = MinorBlock.deserialize(
                bytes.fromhex(response["blockData"][2:]))
            self.assertEqual(block1.header.branch.value, 0b10)

            response = send_request("getNextBlockToMine",
                                    "0x" + acc1.serialize().hex(), "0x3")
            self.assertFalse(response["isRootBlock"])
            block1 = MinorBlock.deserialize(
                bytes.fromhex(response["blockData"][2:]))
            self.assertEqual(block1.header.branch.value, 0b11)
Ejemplo n.º 17
0
    def test_sendTransaction_missing_from_full_shard_id(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)

        with ClusterContext(1, acc1) as clusters, jrpc_server_context(
                clusters[0].master):
            request = dict(
                to="0x" + acc1.recipient.hex(),
                gasPrice="0x6",
                gas=hex(30000),
                value="0xf",
                v="0x1",
                r="0x2",
                s="0x3",
                nonce="0x0",
            )

            with self.assertRaises(Exception):
                send_request("sendTransaction", request)
Ejemplo n.º 18
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)
Ejemplo n.º 19
0
    def test_getTransactionReceipt_on_contract_creation_failure(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=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

            # Add a root block to update block gas limit for xshard tx throttling
            # so that the following tx can be processed
            is_root, root_block = call_async(
                master.get_next_block_to_mine(acc1))
            self.assertTrue(is_root)
            call_async(master.add_root_block(root_block))

            branch = Branch.create(2, 0)
            to_full_shard_id = (acc1.full_shard_id + 1
                                )  # x-shard contract creation should fail
            tx = create_contract_creation_transaction(
                shard_state=slaves[0].shards[branch].state,
                key=id1.get_key(),
                from_address=acc1,
                to_full_shard_id=to_full_shard_id,
            )
            self.assertTrue(slaves[0].add_tx(tx))

            _, block1 = call_async(master.get_next_block_to_mine(address=acc1))
            self.assertTrue(
                call_async(clusters[0].get_shard(0).add_block(block1)))

            for endpoint in ("getTransactionReceipt",
                             "eth_getTransactionReceipt"):
                resp = send_request(
                    endpoint,
                    "0x" + tx.get_hash().hex() + branch.serialize().hex())
                self.assertEqual(resp["transactionHash"],
                                 "0x" + tx.get_hash().hex())
                self.assertEqual(resp["status"], "0x0")
                self.assertEqual(resp["cumulativeGasUsed"], "0x13d6c")
                self.assertIsNone(resp["contractAddress"])
Ejemplo n.º 20
0
    def test_broadcast_cross_shard_transactions_to_neighbor_only(self):
        """ Test the broadcast is only done to the neighbors """
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)

        # create 64 shards so that the neighbor rule can kick in
        # explicitly set num_slaves to 4 so that it does not spin up 64 slaves
        with ClusterContext(1, acc1, 64, num_slaves=4) as clusters:
            master = clusters[0].master
            slaves = clusters[0].slave_list

            # Add a root block first so that later minor blocks referring to this root
            # can be broadcasted to other shards
            is_root, root_block = call_async(
                master.get_next_block_to_mine(
                    Address.create_empty_account(), prefer_root=True
                )
            )
            self.assertTrue(is_root)
            call_async(master.add_root_block(root_block))

            b1 = (
                slaves[0]
                .shards[Branch(64 | 0)]
                .state.create_block_to_mine(address=acc1)
            )
            self.assertTrue(
                call_async(master.add_raw_minor_block(b1.header.branch, b1.serialize()))
            )

            neighbor_shards = [2 ** i for i in range(6)]
            for shard_id in range(64):
                xshard_tx_list = (
                    clusters[0]
                    .get_shard_state(shard_id)
                    .db.get_minor_block_xshard_tx_list(b1.header.get_hash())
                )
                # Only neighbor should have it
                if shard_id in neighbor_shards:
                    self.assertIsNotNone(xshard_tx_list)
                else:
                    self.assertIsNone(xshard_tx_list)
Ejemplo n.º 21
0
    def test_call_failure(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):
            slaves = clusters[0].slave_list

            # insufficient gas
            response = send_request(
                "call", {"to": "0x" + acc1.serialize().hex(), "gas": "0x1"}, None
            )

            self.assertIsNone(response, "failed tx should return None")
            self.assertEqual(
                len(clusters[0].get_shard_state(2 | 0).tx_queue),
                0,
                "should not affect tx queue",
            )
Ejemplo n.º 22
0
    def test_call_success_default_gas(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)

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

            branch = Branch.create(2, 0)
            # gas is not specified in the request
            response = send_request("call",
                                    {"to": "0x" + acc1.serialize().hex()},
                                    "latest")

            self.assertEqual(response, "0x")
            self.assertEqual(
                len(slaves[0].shards[branch].state.tx_queue),
                0,
                "should not affect tx queue",
            )
Ejemplo n.º 23
0
    def test_getTransactionReceipt_on_contract_creation(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=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

            branch = Branch.create(2, 0)
            to_full_shard_id = acc1.full_shard_id + 2
            tx = create_contract_creation_transaction(
                shard_state=slaves[0].shards[branch].state,
                key=id1.get_key(),
                from_address=acc1,
                to_full_shard_id=to_full_shard_id,
            )
            self.assertTrue(slaves[0].add_tx(tx))

            _, block1 = call_async(master.get_next_block_to_mine(address=acc1))
            self.assertTrue(
                call_async(clusters[0].get_shard(0).add_block(block1)))

            for endpoint in ("getTransactionReceipt",
                             "eth_getTransactionReceipt"):
                resp = send_request(
                    endpoint,
                    "0x" + tx.get_hash().hex() + branch.serialize().hex())
                self.assertEqual(resp["transactionHash"],
                                 "0x" + tx.get_hash().hex())
                self.assertEqual(resp["status"], "0x1")
                self.assertEqual(resp["cumulativeGasUsed"], "0x213eb")

                contract_address = mk_contract_address(acc1.recipient,
                                                       to_full_shard_id, 0)
                self.assertEqual(
                    resp["contractAddress"],
                    "0x" + contract_address.hex() +
                    to_full_shard_id.to_bytes(4, "big").hex(),
                )
Ejemplo n.º 24
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)
Ejemplo n.º 25
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)
Ejemplo n.º 26
0
def create_test_transaction(
        from_id,
        from_tx_id,
        to_address,
        amount=100,
        remaining=100,
        shard_id=0,
        output_index=0,
        code=Code.get_transfer_code(),
):
    acc1 = Address.create_from_identity(from_id, shard_id)
    tx = Transaction(
        in_list=[TransactionInput(from_tx_id, output_index)],
        code=code,
        out_list=[
            TransactionOutput(acc1, remaining),
            TransactionOutput(to_address, amount),
        ],
    )
    tx.sign([from_id.get_key()])
    return tx
Ejemplo n.º 27
0
    def test_new_block_pool(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)

        with ClusterContext(1, acc1) as clusters:
            shard_state = clusters[0].get_shard_state(0b10)
            b1 = _tip_gen(shard_state)
            add_result = call_async(clusters[0].master.add_raw_minor_block(
                b1.header.branch, b1.serialize()))
            self.assertTrue(add_result)

            # Update config to force checking diff
            clusters[
                0].master.env.quark_chain_config.SKIP_MINOR_DIFFICULTY_CHECK = False
            b2 = b1.create_block_to_append(difficulty=12345)
            shard = clusters[0].slave_list[0].shards[b2.header.branch]
            with self.assertRaises(ValueError):
                call_async(shard.handle_new_block(b2))
            # Also the block should not exist in new block pool
            self.assertTrue(
                b2.header.get_hash() not in shard.state.new_block_pool)
Ejemplo n.º 28
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.º 29
0
    def test_fork_resolve(self):
        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, shard_id=0)

        b0 = state.get_tip().create_block_to_append()
        b1 = state.get_tip().create_block_to_append()

        state.finalize_and_add_block(b0)
        self.assertEqual(state.header_tip, b0.header)

        # Fork happens, first come first serve
        state.finalize_and_add_block(b1)
        self.assertEqual(state.header_tip, b0.header)

        # Longer fork happens, override existing one
        b2 = b1.create_block_to_append()
        state.finalize_and_add_block(b2)
        self.assertEqual(state.header_tip, b2.header)
Ejemplo n.º 30
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")