コード例 #1
0
    def test_xshard_tx_sent(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)
        acc2 = Address.create_from_identity(id1, full_shard_id=1)
        acc3 = Address.create_random_account(full_shard_id=0)

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

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

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

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

        self.assertEqual(state.evm_state.gas_used, 0)
        # Should succeed
        state.finalize_and_add_block(b1)
        self.assertEqual(len(state.evm_state.xshard_list), 1)
        self.assertEqual(
            state.evm_state.xshard_list[0],
            CrossShardTransactionDeposit(
                tx_hash=tx.get_hash(),
                from_address=acc1,
                to_address=acc2,
                value=888888,
                gas_price=1,
            ),
        )
        self.assertEqual(
            state.get_balance(id1.recipient, 0),
            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, 0),
                         opcodes.GTXCOST // 2)
コード例 #2
0
    def test_getTransactionReceipt_on_x_shard_transfer(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)
        acc2 = Address.create_from_identity(id1, full_shard_id=1)

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

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

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

            _, root_block = call_async(
                master.get_next_block_to_mine(address=acc1, prefer_root=True))

            call_async(master.add_root_block(root_block))

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

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

            for endpoint in ("getTransactionReceipt",
                             "eth_getTransactionReceipt"):
                resp = send_request(
                    endpoint,
                    "0x" + tx.get_hash().hex() +
                    acc2.full_shard_id.to_bytes(4, "big").hex(),
                )
                self.assertEqual(resp["transactionHash"],
                                 "0x" + tx.get_hash().hex())
                self.assertEqual(resp["status"], "0x1")
                self.assertEqual(resp["cumulativeGasUsed"], hex(30000))
                self.assertEqual(resp["gasUsed"], hex(21000))
                self.assertIsNone(resp["contractAddress"])
コード例 #3
0
    def test_getMinorBlock(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)

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

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

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

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

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

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

            resp = send_request("getMinorBlockByHeight", ["0x1", "0x2", False])
            self.assertIsNone(resp)
            resp = send_request("getMinorBlockByHeight", ["0x0", "0x4", False])
            self.assertIsNone(resp)
コード例 #4
0
    def test_add_root_block_revert_header_tip(self):
        """ block's hash_prev_root_block must be on the same chain with root_tip to update tip.

                 +--+
                 |r1|<-------------+
                /+--+              |
               /   |               |
        +--+  /  +--+    +--+     +--+
        |r0|<----|m1|<---|m2| <---|m3|
        +--+  \  +--+    +--+     +--+
               \   |       \
                \+--+.     +--+
                 |r2|<-----|r3| (r3 includes m2)
                 +--+      +--+

        Initial state: r0 <- m1 <- m2
        Adding r1, r2, m3 makes r1 the root_tip, m3 the header_tip
        Adding r3 should change the root_tip to r3, header_tip to m2
        """
        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)

        m1 = state.get_tip().create_block_to_append(address=acc1)
        state.finalize_and_add_block(m1)

        m2 = state.get_tip().create_block_to_append(address=acc1)
        state.finalize_and_add_block(m2)

        r1 = state.root_tip.create_block_to_append()
        r2 = state.root_tip.create_block_to_append()
        r1.minor_block_header_list.append(m1.header)
        r1.finalize()

        state.add_root_block(r1)

        r2.minor_block_header_list.append(m1.header)
        r2.header.create_time = r1.header.create_time + 1  # make r2, r1 different
        r2.finalize()
        self.assertNotEqual(r1.header.get_hash(), r2.header.get_hash())

        state.add_root_block(r2)

        self.assertEqual(state.root_tip, r1.header)

        m3 = state.create_block_to_mine(address=acc1)
        self.assertEqual(m3.header.hash_prev_root_block, r1.header.get_hash())
        state.finalize_and_add_block(m3)

        r3 = r2.create_block_to_append(address=acc1)
        r3.add_minor_block_header(m2.header)
        r3.finalize()
        state.add_root_block(r3)
        self.assertEqual(state.root_tip, r3.header)
        self.assertEqual(state.header_tip, m2.header)
コード例 #5
0
    def test_getWork_and_submitWork(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)

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

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

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

                header_hash_hex = resp[0]
                if shard_id is not None:  # shard 0
                    miner_address = Address.create_from(
                        master.env.quark_chain_config.shards[1].
                        COINBASE_ADDRESS)
                else:  # root
                    miner_address = Address.create_from(
                        master.env.quark_chain_config.ROOT.COINBASE_ADDRESS)
                block = call_async(
                    master.get_next_block_to_mine(address=miner_address,
                                                  branch_value=shard_id
                                                  and 0b01))
                # solve it and submit
                work = MiningWork(bytes.fromhex(header_hash_hex[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,
                        "0x" + bytes(65).hex(),
                    ],
                )
                self.assertTrue(resp)

            # show progress on shard 0
            self.assertEqual(
                clusters[0].get_shard_state(1 | 0).get_tip().header.height, 1)
コード例 #6
0
ファイル: test_jsonrpc.py プロジェクト: yoyo52/pyquarkchain
    def test_estimateGas(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("estimateGas",
                                    {"to": "0x" + acc1.serialize().hex()})
            self.assertEqual(response, "0x5208")  # 21000
コード例 #7
0
ファイル: test_jsonrpc.py プロジェクト: yoyo52/pyquarkchain
    def test_getTransactionReceipt_not_exist(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):
            resp = send_request("getTransactionReceipt",
                                "0x" + bytes(36).hex())
            self.assertIsNone(resp)
コード例 #8
0
    def test_signature(self):
        header = RootBlockHeader()
        private_key = KeyAPI.PrivateKey(Identity.create_random_identity().get_key())
        self.assertEqual(header.signature, bytes(65))
        self.assertFalse(header.is_signed())
        self.assertFalse(header.verify_signature(private_key.public_key))

        header.sign_with_private_key(private_key)
        self.assertNotEqual(header.signature, bytes(65))
        self.assertTrue(header.is_signed())
        self.assertTrue(header.verify_signature(private_key.public_key))
コード例 #9
0
    def test_getTransactionReceipt_not_exist(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):
            for endpoint in ("getTransactionReceipt",
                             "eth_getTransactionReceipt"):
                resp = send_request(endpoint, ["0x" + bytes(36).hex()])
                self.assertIsNone(resp)
コード例 #10
0
    def test_not_update_tip_on_root_fork(self):
        """ block's hash_prev_root_block must be on the same chain with root_tip to update tip.

                 +--+
              a. |r1|
                /+--+
               /   |
        +--+  /  +--+    +--+
        |r0|<----|m1|<---|m2| c.
        +--+  \  +--+    +--+
               \   |      |
                \+--+     |
              b. |r2|<----+
                 +--+

        Initial state: r0 <- m1
        Then adding r1, r2, m2 should not make m2 the tip because r1 is the root tip and r2 and r1
        are not on the same root chain.
        """
        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)

        m1 = state.get_tip().create_block_to_append(address=acc1)
        state.finalize_and_add_block(m1)

        r1 = state.root_tip.create_block_to_append()
        r2 = state.root_tip.create_block_to_append()
        r1.minor_block_header_list.append(m1.header)
        r1.finalize()

        state.add_root_block(r1)

        r2.minor_block_header_list.append(m1.header)
        r2.header.create_time = r1.header.create_time + 1  # make r2, r1 different
        r2.finalize()
        self.assertNotEqual(r1.header.get_hash(), r2.header.get_hash())

        state.add_root_block(r2)

        self.assertEqual(state.root_tip, r1.header)

        m2 = m1.create_block_to_append(address=acc1)
        m2.header.hash_prev_root_block = r2.header.get_hash()

        state.finalize_and_add_block(m2)
        # m2 is added
        self.assertEqual(
            state.db.get_minor_block_by_hash(m2.header.get_hash()), m2)
        # but m1 should still be the tip
        self.assertEqual(state.header_tip, m1.header)
コード例 #11
0
    def test_native_token_gas(self):
        """in-shard transfer QETH using native token as gas
        """
        QETH = token_id_encode("QETH")
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)
        acc2 = Address.create_random_account(full_shard_key=0)
        acc3 = Address.create_random_account(full_shard_key=0)

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

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

        self.assertTrue(state.add_tx(tx))
        b1 = state.create_block_to_mine(address=acc3)
        self.assertEqual(len(b1.tx_list), 1)
        state.finalize_and_add_block(b1)
        self.assertEqual(state.header_tip, b1.header)
        self.assertEqual(
            state.get_token_balance(acc1.recipient, QETH),
            10000000 - opcodes.GTXCOST - 12345,
        )
        self.assertEqual(state.get_token_balance(acc2.recipient, QETH), 12345)
        # tx fee
        self.assertEqual(
            state.get_token_balance(acc3.recipient, QETH),
            self.get_after_tax_reward(opcodes.GTXCOST),
        )
        # miner coinbase
        self.assertEqual(
            state.get_token_balance(acc3.recipient, self.genesis_token),
            self.get_after_tax_reward(self.shard_coinbase),
        )
        tx_list, _ = state.db.get_transactions_by_address(acc1)
        self.assertEqual(tx_list[0].value, 12345)
        self.assertEqual(tx_list[0].gas_token_id, QETH)
        self.assertEqual(tx_list[0].transfer_token_id, QETH)
        tx_list, _ = state.db.get_transactions_by_address(acc2)
        self.assertEqual(tx_list[0].value, 12345)
        self.assertEqual(tx_list[0].gas_token_id, QETH)
        self.assertEqual(tx_list[0].transfer_token_id, QETH)
コード例 #12
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))
コード例 #13
0
ファイル: test_core.py プロジェクト: techamazed/pyquarkchain
    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()]))
コード例 #14
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))
コード例 #15
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)
コード例 #16
0
ファイル: accounts.py プロジェクト: braveheart12/QuarkChain
    def new(key=None):
        """
        Create a new account.
        :param key: the private key to import, or None to generate a random one
        """
        if key is None:
            identity = Identity.create_random_identity()
        else:
            if not isinstance(key, str):
                raise Exception("Imported key must be a hexadecimal string")

            identity = Identity.create_from_key(bytes.fromhex(key))
        address = Address.create_from_identity(identity)
        return Account(identity, address)
コード例 #17
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},
        )
コード例 #18
0
    def test_getWork_and_submitWork(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)

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

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

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

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

            # show progress
            _, new_block = call_async(master.get_next_block_to_mine(address=acc1))
            self.assertIsInstance(new_block, MinorBlock)
            self.assertEqual(new_block.header.height, 2)
コード例 #19
0
    def test_fork_does_not_confirm_tx(self):
        """Tx should only be confirmed and removed from tx queue by the best chain"""
        id1 = Identity.create_random_identity()
        id2 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)
        acc2 = Address.create_from_identity(id2, full_shard_id=0)
        acc3 = Address.create_random_account(full_shard_id=0)

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

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

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

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

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

        b2 = state.create_block_to_mine(address=acc3)
        state.finalize_and_add_block(b2)
        self.assertEqual(len(state.tx_queue), 0)
コード例 #20
0
    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)
コード例 #21
0
    def test_add_minor_block_request_list(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)

        with ClusterContext(2, acc1) as clusters:
            shard_state = clusters[0].slave_list[0].shards[Branch(0b10)].state
            coinbase_amount = (
                shard_state.env.quark_chain_config.SHARD_LIST[
                    shard_state.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]
                .slave_list[1]
                .shards[Branch(0b11)]
                .state.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[1]
                .slave_list[0]
                .shards[Branch(0b10)]
                .state.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()
                )
            )
コード例 #22
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))
コード例 #23
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)
コード例 #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))
コード例 #25
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"")
コード例 #26
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)
コード例 #27
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)
コード例 #28
0
    def test_add_transaction(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_key=0)
        acc2 = Address.create_from_identity(id1, full_shard_key=1)

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

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

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

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

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

            tx_queue = clusters[1].get_shard_state(0b11).tx_queue
            assert_true_with_timeout(lambda: len(tx_queue) == 1)
            self.assertEqual(tx_queue.pop_transaction(), tx2.tx.to_evm_tx())
コード例 #29
0
ファイル: test_jsonrpc.py プロジェクト: xdagx/pyquarkchain
    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)
コード例 #30
0
ファイル: test_cluster.py プロジェクト: impe83/pyquarkchain
    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)