Beispiel #1
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())
        mblock, coinbase_amount_map = shard_state.init_genesis_state(
            r_state.get_tip_block())
        block_hash = mblock.header.get_hash()
        r_state.add_validated_minor_block_hash(block_hash,
                                               coinbase_amount_map.balance_map)
        s_state_list[full_shard_id] = shard_state

    # add a root block so that later minor blocks will be broadcasted to neighbor shards
    minor_header_list = []
    for state in s_state_list.values():
        minor_header_list.append(state.header_tip)

    root_block = r_state.create_block_to_mine(minor_header_list)
    assert r_state.add_block(root_block)
    for state in s_state_list.values():
        assert state.add_root_block(root_block)

    return r_state, s_state_list
Beispiel #2
0
def handle_root_print_by_height(env, args):
    root_state = RootState(env)
    header = root_state.db.get_root_block_header_by_height(args.height)
    if header is None:
        print("header not found")
        return 1
    pprint(header.to_dict())
    print("hash: {}".format(header.get_hash().hex()))
    return 0
Beispiel #3
0
def handle_root_print_block(env, args):
    root_state = RootState(env)
    block = root_state.db.get_root_block_by_hash(bytes.fromhex(args.hash))
    if block is None:
        print("header not found")
        return 1
    pprint(block.to_dict())
    print("hash: {}".format(block.header.get_hash().hex()))
    return 0
def main():
    os.chdir(
        os.path.join(os.path.dirname(os.path.abspath(__file__)), "../cluster"))

    env, args = parse_args()

    rs = RootState(env)
    rb = rs.get_tip_block()
    print("Root block height: %d" % rb.header.height)

    if args.all_shards:
        print_all_shard_balances(env, rb, args)
    elif args.recipient:
        print_recipient_balance(env, rb, args)
    elif args.full_shard_id:
        print_shard_balance(env, rb, args.full_shard_id)
    elif args.minor_block_height:
        print_balance_by_block_height(env, rb, args.minor_block_height)
Beispiel #5
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)
Beispiel #6
0
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)
Beispiel #7
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

    # add a root block so that later minor blocks will be broadcasted to neighbor shards
    root_block = r_state.tip.create_block_to_append()
    for state in s_state_list.values():
        root_block.add_minor_block_header(state.header_tip)
        block_hash = state.header_tip.get_hash()
        r_state.add_validated_minor_block_hash(block_hash)

    root_block.finalize()
    assert r_state.add_block(root_block)
    for state in s_state_list.values():
        assert state.add_root_block(root_block)

    return (r_state, s_state_list)
Beispiel #8
0
def create_test_clusters(
    num_cluster,
    genesis_account,
    chain_size,
    shard_size,
    num_slaves,
    genesis_root_heights,
    genesis_minor_quarkash,
    remote_mining=False,
    small_coinbase=False,
    loadtest_accounts=None,
    connect=True,  # connect the bootstrap node by default
    should_set_gas_price_limit=False,
    mblock_coinbase_amount=None,
):
    # so we can have lower minimum diff
    easy_diff_calc = EthDifficultyCalculator(
        cutoff=45, diff_factor=2048, minimum_diff=10
    )

    bootstrap_port = get_next_port()  # first cluster will listen on this port
    cluster_list = []
    loop = asyncio.get_event_loop()

    for i in range(num_cluster):
        env = get_test_env(
            genesis_account,
            genesis_minor_quarkash=genesis_minor_quarkash,
            chain_size=chain_size,
            shard_size=shard_size,
            genesis_root_heights=genesis_root_heights,
            remote_mining=remote_mining,
        )
        env.cluster_config.P2P_PORT = bootstrap_port if i == 0 else get_next_port()
        env.cluster_config.JSON_RPC_PORT = get_next_port()
        env.cluster_config.PRIVATE_JSON_RPC_PORT = get_next_port()
        env.cluster_config.SIMPLE_NETWORK = SimpleNetworkConfig()
        env.cluster_config.SIMPLE_NETWORK.BOOTSTRAP_PORT = bootstrap_port
        env.quark_chain_config.loadtest_accounts = loadtest_accounts or []
        if should_set_gas_price_limit:
            env.quark_chain_config.MIN_TX_POOL_GAS_PRICE = 10
            env.quark_chain_config.MIN_MINING_GAS_PRICE = 10

        if small_coinbase:
            # prevent breaking previous tests after tweaking default rewards
            env.quark_chain_config.ROOT.COINBASE_AMOUNT = 5
            for c in env.quark_chain_config.shards.values():
                c.COINBASE_AMOUNT = 5
        if mblock_coinbase_amount is not None:
            for c in env.quark_chain_config.shards.values():
                c.COINBASE_AMOUNT = mblock_coinbase_amount

        env.cluster_config.SLAVE_LIST = []
        check(is_p2(num_slaves))

        for j in range(num_slaves):
            slave_config = SlaveConfig()
            slave_config.ID = "S{}".format(j)
            slave_config.PORT = get_next_port()
            slave_config.FULL_SHARD_ID_LIST = []
            env.cluster_config.SLAVE_LIST.append(slave_config)

        full_shard_ids = [
            (i << 16) + shard_size + j
            for i in range(chain_size)
            for j in range(shard_size)
        ]
        for i, full_shard_id in enumerate(full_shard_ids):
            slave = env.cluster_config.SLAVE_LIST[i % num_slaves]
            slave.FULL_SHARD_ID_LIST.append(full_shard_id)

        slave_server_list = []
        for j in range(num_slaves):
            slave_env = env.copy()
            slave_env.db = InMemoryDb()
            slave_env.slave_config = env.cluster_config.get_slave_config(
                "S{}".format(j)
            )
            slave_server = SlaveServer(slave_env, name="cluster{}_slave{}".format(i, j))
            slave_server.start()
            slave_server_list.append(slave_server)

        root_state = RootState(env, diff_calc=easy_diff_calc)
        master_server = MasterServer(env, root_state, name="cluster{}_master".format(i))
        master_server.start()

        # Wait until the cluster is ready
        loop.run_until_complete(master_server.cluster_active_future)

        # Substitute diff calculate with an easier one
        for slave in slave_server_list:
            for shard in slave.shards.values():
                shard.state.diff_calc = easy_diff_calc

        # Start simple network and connect to seed host
        network = SimpleNetwork(env, master_server, loop)
        network.start_server()
        if connect and i != 0:
            peer = call_async(network.connect("127.0.0.1", bootstrap_port))
        else:
            peer = None

        cluster_list.append(Cluster(master_server, slave_server_list, network, peer))

    return cluster_list
Beispiel #9
0
 def test_root_state_simple(self):
     env = get_test_env()
     state = RootState(env=env)
     self.assertEqual(state.tip.height, 0)
Beispiel #10
0
    def test_root_state_recovery(self):
        env = get_test_env()
        r_state, s_states = create_default_state(env)

        s_state0 = s_states[2 | 0]
        s_state1 = s_states[2 | 1]
        b0 = s_state0.create_block_to_mine()
        add_minor_block_to_cluster(s_states, b0)
        b1 = s_state1.create_block_to_mine()
        add_minor_block_to_cluster(s_states, b1)

        r_state.add_validated_minor_block_hash(
            b0.header.get_hash(), b0.header.coinbase_amount_map.balance_map)
        r_state.add_validated_minor_block_hash(
            b1.header.get_hash(), b1.header.coinbase_amount_map.balance_map)
        root_block0 = r_state.create_block_to_mine([b0.header, b1.header])

        root_block00 = r_state.create_block_to_mine([b0.header, b1.header])

        self.assertTrue(r_state.add_block(root_block0))

        # create a fork
        root_block00.header.create_time += 1
        root_block00.finalize(
            coinbase_tokens=r_state._calculate_root_block_coinbase(
                [
                    header.get_hash()
                    for header in root_block00.minor_block_header_list
                ],
                root_block00.header.height,
            ))
        self.assertNotEqual(root_block0.header.get_hash(),
                            root_block00.header.get_hash())

        self.assertFalse(r_state.add_block(root_block00))
        self.assertEqual(
            r_state.db.get_root_block_by_hash(root_block00.header.get_hash()),
            root_block00,
        )

        b2 = s_state0.create_block_to_mine()
        add_minor_block_to_cluster(s_states, b2)
        b3 = s_state1.create_block_to_mine()
        add_minor_block_to_cluster(s_states, b3)

        r_state.add_validated_minor_block_hash(
            b2.header.get_hash(), b2.header.coinbase_amount_map.balance_map)
        r_state.add_validated_minor_block_hash(
            b3.header.get_hash(), b3.header.coinbase_amount_map.balance_map)
        root_block1 = r_state.create_block_to_mine([b2.header, b3.header])

        self.assertTrue(r_state.add_block(root_block1))

        # now the longest chain is root_block0 <-- root_block1
        # but root_block0 will become the new tip after recovery

        recovered_state = RootState(env=env)
        self.assertEqual(recovered_state.tip, root_block0.header)
        self.assertEqual(recovered_state.db.get_root_block_by_height(2),
                         root_block0)
        tip_height = recovered_state.tip.height
        self.assertEqual(
            recovered_state.db.get_root_block_by_height(tip_height),
            root_block0)

        # fork is pruned from recovered state
        self.assertIsNone(
            recovered_state.db.get_root_block_by_hash(
                root_block00.header.get_hash()))
        self.assertEqual(
            recovered_state.db.get_root_block_by_hash(
                root_block00.header.get_hash(), consistency_check=False),
            root_block00,
        )
Beispiel #11
0
def create_test_clusters(
    num_cluster,
    genesis_account,
    shard_size,
    num_slaves,
    genesis_root_heights,
    remote_mining=False,
):
    # so we can have lower minimum diff
    easy_diff_calc = EthDifficultyCalculator(cutoff=45,
                                             diff_factor=2048,
                                             minimum_diff=10)

    bootstrap_port = get_next_port()  # first cluster will listen on this port
    cluster_list = []
    loop = asyncio.get_event_loop()

    for i in range(num_cluster):
        env = get_test_env(
            genesis_account,
            genesis_minor_quarkash=1000000,
            shard_size=shard_size,
            genesis_root_heights=genesis_root_heights,
            remote_mining=remote_mining,
        )
        env.cluster_config.P2P_PORT = bootstrap_port if i == 0 else get_next_port(
        )
        env.cluster_config.JSON_RPC_PORT = get_next_port()
        env.cluster_config.PRIVATE_JSON_RPC_PORT = get_next_port()
        env.cluster_config.SIMPLE_NETWORK = SimpleNetworkConfig()
        env.cluster_config.SIMPLE_NETWORK.BOOTSTRAP_PORT = bootstrap_port

        env.cluster_config.SLAVE_LIST = []
        for j in range(num_slaves):
            slave_config = SlaveConfig()
            slave_config.ID = "S{}".format(j)
            slave_config.PORT = get_next_port()
            slave_config.SHARD_MASK_LIST = [ShardMask(num_slaves | j)]
            slave_config.DB_PATH_ROOT = None  # TODO: fix the db in config
            env.cluster_config.SLAVE_LIST.append(slave_config)

        slave_server_list = []
        for j in range(num_slaves):
            slave_env = env.copy()
            slave_env.db = InMemoryDb()
            slave_env.slave_config = env.cluster_config.get_slave_config(
                "S{}".format(j))
            slave_server = SlaveServer(slave_env,
                                       name="cluster{}_slave{}".format(i, j))
            slave_server.start()
            slave_server_list.append(slave_server)

        root_state = RootState(env, diff_calc=easy_diff_calc)
        master_server = MasterServer(env,
                                     root_state,
                                     name="cluster{}_master".format(i))
        master_server.start()

        # Wait until the cluster is ready
        loop.run_until_complete(master_server.cluster_active_future)

        # Substitute diff calculate with an easier one
        for slave in slave_server_list:
            for shard in slave.shards.values():
                shard.state.diff_calc = easy_diff_calc

        # Start simple network and connect to seed host
        network = SimpleNetwork(env, master_server)
        network.start_server()
        if i != 0:
            peer = call_async(network.connect("127.0.0.1", bootstrap_port))
        else:
            peer = None

        cluster_list.append(
            Cluster(master_server, slave_server_list, network, peer))

    return cluster_list
Beispiel #12
0
    def test_root_state_recovery(self):
        env = get_test_env()
        r_state, s_states = create_default_state(env)

        s_state0 = s_states[2 | 0]
        s_state1 = s_states[2 | 1]
        b0 = s_state0.get_tip().create_block_to_append()
        add_minor_block_to_cluster(s_states, b0)
        b1 = s_state1.get_tip().create_block_to_append()
        add_minor_block_to_cluster(s_states, b1)

        r_state.add_validated_minor_block_hash(b0.header.get_hash())
        r_state.add_validated_minor_block_hash(b1.header.get_hash())
        root_block0 = (
            r_state.tip.create_block_to_append().add_minor_block_header(
                s_state0.db.get_minor_block_by_height(0).header
            ).add_minor_block_header(b0.header).add_minor_block_header(
                s_state1.db.get_minor_block_by_height(
                    0).header).add_minor_block_header(b1.header).finalize())

        root_block00 = (
            r_state.tip.create_block_to_append().add_minor_block_header(
                s_state0.db.get_minor_block_by_height(0).header
            ).add_minor_block_header(b0.header).add_minor_block_header(
                s_state1.db.get_minor_block_by_height(
                    0).header).add_minor_block_header(b1.header).finalize())

        self.assertTrue(r_state.add_block(root_block0))

        # create a fork
        root_block00.header.create_time += 1
        root_block00.finalize()
        self.assertNotEqual(root_block0.header.get_hash(),
                            root_block00.header.get_hash())

        self.assertFalse(r_state.add_block(root_block00))
        self.assertEqual(
            r_state.db.get_root_block_by_hash(root_block00.header.get_hash()),
            root_block00,
        )

        b2 = s_state0.get_tip().create_block_to_append()
        add_minor_block_to_cluster(s_states, b2)
        b3 = s_state1.get_tip().create_block_to_append()
        add_minor_block_to_cluster(s_states, b3)

        r_state.add_validated_minor_block_hash(b2.header.get_hash())
        r_state.add_validated_minor_block_hash(b3.header.get_hash())
        root_block1 = (
            r_state.tip.create_block_to_append().add_minor_block_header(
                b2.header).add_minor_block_header(b3.header).finalize())

        self.assertTrue(r_state.add_block(root_block1))

        # now the longest chain is root_block0 <-- root_block1
        # but root_block0 will become the new tip after recovery

        recovered_state = RootState(env=env)
        self.assertEqual(recovered_state.tip, root_block0.header)
        self.assertEqual(recovered_state.db.get_root_block_by_height(1),
                         root_block0)
        self.assertEqual(recovered_state.get_root_block_by_height(None),
                         root_block0)

        # fork is pruned from recovered state
        self.assertIsNone(
            recovered_state.db.get_root_block_by_hash(
                root_block00.header.get_hash()))
        self.assertEqual(
            recovered_state.db.get_root_block_by_hash(
                root_block00.header.get_hash(), consistency_check=False),
            root_block00,
        )
Beispiel #13
0
def handle_root_print_tip(env, args):
    root_state = RootState(env)
    pprint(root_state.tip.to_dict())
    print("hash: {}".format(root_state.tip.get_hash().hex()))
    return 0
Beispiel #14
0
def get_root_state():
    env, args = parse_args()
    return RootState(env)
Beispiel #15
0
def create_test_clusters(num_cluster, genesis_account, shard_size, num_slaves,
                         genesis_root_heights):
    bootstrap_port = get_next_port()  # first cluster will listen on this port
    cluster_list = []
    loop = asyncio.get_event_loop()

    for i in range(num_cluster):
        env = get_test_env(
            genesis_account,
            genesis_minor_quarkash=1000000,
            shard_size=shard_size,
            genesis_root_heights=genesis_root_heights,
        )
        env.cluster_config.P2P_PORT = bootstrap_port if i == 0 else get_next_port(
        )
        env.cluster_config.JSON_RPC_PORT = get_next_port()
        env.cluster_config.PRIVATE_JSON_RPC_PORT = get_next_port()
        env.cluster_config.SIMPLE_NETWORK = SimpleNetworkConfig()
        env.cluster_config.SIMPLE_NETWORK.BOOTSTRAP_PORT = bootstrap_port

        env.cluster_config.SLAVE_LIST = []
        for j in range(num_slaves):
            slave_config = SlaveConfig()
            slave_config.ID = "S{}".format(j)
            slave_config.PORT = get_next_port()
            slave_config.SHARD_MASK_LIST = [ShardMask(num_slaves | j)]
            slave_config.DB_PATH_ROOT = None  # TODO: fix the db in config
            env.cluster_config.SLAVE_LIST.append(slave_config)

        slave_server_list = []
        for j in range(num_slaves):
            slave_env = env.copy()
            slave_env.db = InMemoryDb()
            slave_env.slave_config = env.cluster_config.get_slave_config(
                "S{}".format(j))
            slave_server = SlaveServer(slave_env,
                                       name="cluster{}_slave{}".format(i, j))
            slave_server.start()
            slave_server_list.append(slave_server)

        root_state = RootState(env)
        master_server = MasterServer(env,
                                     root_state,
                                     name="cluster{}_master".format(i))
        master_server.start()

        # Wait until the cluster is ready
        loop.run_until_complete(master_server.cluster_active_future)

        # Start simple network and connect to seed host
        network = SimpleNetwork(env, master_server)
        network.start_server()
        if i != 0:
            peer = call_async(network.connect("127.0.0.1", bootstrap_port))
        else:
            peer = None

        cluster_list.append(
            Cluster(master_server, slave_server_list, network, peer))

    return cluster_list