BoB pool with configurable cycles burnt per user and lower fees

Disclaimer: This work is a private effort by the author of the post and hasn’t been reviewed and/or provided by DFINITY Foundation. All the information in this post and the functionality of the new BoB pool are provided as is without warranty of any kind.

A new BoB pool canister eclma-2yaaa-aaaas-al3bq-cai has been deployed to the ICP mainnet allowing pool users (members) to contribute cycles burned to mine BoB blocks and share the resulting BoB token rewards. The new pool improves over the “native” BoB pool in the BoB canister 6lnhz-oaaaa-aaaas-aabkq-cai by:

  • allowing users to configure their cycles burnt per BoB block;
  • charging lower fees: 5B cycles per BoB block, split across all users who burnt cycles in the respective block, e.g., 1.25B cycles per user and block if 4 users are active in the new pool; instead of at least 28.75B cycles per block charged to every user by the “native” BoB pool (see the calculation in the Appendix).

Source Code and Controllers

The source code of the new BoB pool is available in this PR in the bob-pool directory (along with PocketIC integration tests in a separate directory) against a fork of the original BoB repository. Its canister WASM hash 8fd4a1...69257a reported by dfx canister info eclma-2yaaa-aaaas-al3bq-cai --ic is reproducible via a docker build by following the readme instructions or by checking this CI run.

The controllers of the new BoB pool are q5mlb-mkhee-w4esy-qdsic-lwjvs-udgiw-i3uir-yk5zj-qkl27-muhk7-fae (the new pool’s author) and dmhsm-cyaaa-aaaal-qjrdq-cai (BoB controller; added for the sake of disaster recovery).

Pool Stats and Logs

You can check out some stats using the get_pool_state query endpoint of the pool:

dfx canister call eclma-2yaaa-aaaas-al3bq-cai get_pool_state --query --ic

You can also check out the pool’s canister logs:

dfx canister logs eclma-2yaaa-aaaas-al3bq-cai --ic

At the time of writing, the canister logs contain a single entry reporting an ICP ledger transfer from the pool to the BoB canister in order to spawn a BoB miner for the pool.

How are BoB Token Rewards Distributed

The BoB token rewards from every block mined by the pool are distributed proportionally to the amount of cycles burnt by a user since the last block mined by the pool.

How to Join the Pool

You can join the pool by sending at least 1 ICP in an ICP ledger transfer with memo 1347768404 from your identity’s default subaccount to the account: 1fbc30df20217a792691818bdf768dce82e098db3139b61e0baf58658d202a35:

$ dfx ledger transfer --icp 1 --memo 1347768404 1fbc30df20217a792691818bdf768dce82e098db3139b61e0baf58658d202a35 --ic
Transfer sent at block height <block-index>

and calling the method join_pool of the pool canister using the same identity and passing the block index of the ICP ledger transfer as argument:

$ dfx canister call eclma-2yaaa-aaaas-al3bq-cai join_pool '(<block-index>)' --ic
(variant { Ok })

How to Configure Cycles Burnt

You can configure the amount of cycles burnt per block by calling the method set_member_block_cycles of the pool canister:

dfx canister call eclma-2yaaa-aaaas-al3bq-cai set_member_block_cycles '(15000000000)' --ic

The minimum amount of cycles is 15B and the amount of cycles must be a multiple of 1M cycles.

You can also interrupt burning cycles by setting the amount of burnt cycles to zero. Your reward for the next block mined by the pool will still be calculated proportionally to the amount of cycles you burnt since the last block mined by the pool.

You can check your cycles burnt per block as well as pending cycles burnt since the last block mined by the pool and your remaining cycles to be burnt in the future by calling the get_member_cycles query endpoint of the pool:

dfx canister call eclma-2yaaa-aaaas-al3bq-cai get_member_cycles --query --ic

How to Claim BoB Tokens

You can check your BoB token rewards by calling the get_member_rewards query endpoint of the pool:

dfx canister call eclma-2yaaa-aaaas-al3bq-cai get_member_rewards '(record {start_idx=0; max_cnt=null;})' --query --ic

(passing start_idx for the sake of pagination and optionally max_cnt to limit the size of the output).

If you have pending BoB token rewards characterized by bob_block_index = null, you can claim them by calling the pay_member_rewards update endpoint of the pool:

dfx canister call eclma-2yaaa-aaaas-al3bq-cai pay_member_rewards --ic

transferring your BoB token rewards to your identity’s BoB ledger account.

You can check all BoB token rewards ever distributed by the pool using the get_pool_rewards query endpoint of the pool:

dfx canister call eclma-2yaaa-aaaas-al3bq-cai get_pool_rewards '(record {start_idx=0; max_cnt=null;})' --query --ic

(paginated analogously to get_member_rewards).

Appendix

The “native” BoB pool charges every user 1 ICP (~9.45T cycles) per day (with at most 86400s / 400s = 216 blocks per day) while the maximum amount of cycles burnt on behalf of a user per day is 15B per block * 216 blocks = 3.24T and thus the “native” BoB pool fees are at least (9.45T - 3.24T) / 216 blocks = 28.75B cycles per block (independently of how many users are active in the “native” BoB pool).

6 Likes

This is very cool and a definite improvement to the way the current pool works.

My wish list for how mining pools should ideally work is:

  • Mining pools can be spawned by users as standalone canisters (similar to how miners are currently created)
  • Mining pools will require users to stake eg; 10 - 100 ICP to create a pool
  • Mining pools must be given a unique name so people can differentiate the pool and pool owners can market their specific mining pools respectively.
  • Obviously, block rewards have to be proportionally distributed to pool members based on cycle burn contributions.
  • Mining pool owners can set a block reward fee percentage as their incentive for marketing the pool and growing it.
  • If a mining pool has no miners, the pool owner should be able to dissolve their mining pool and get their ICP stake returned.

Can you imagine the cycles that would be burnt?

1 Like

Thanks a lot, @wirelessjeano, for your suggestions!

Everybody can spawn a pool just like I did since its code is publicly available and the build is reproducible. Although I acknowledge that documentation on spawning a new pool is missing. Or do you anticipate pool spawning to be integrated into bob.fun?

What’s the motivation for this? In particular, given that you propose this to be refundable if a pool has no miners.

The pools can be distinguished based on their canister ids which are unique. If we want to have unique and human-readable pool names, then a central registry of pools would be required.

I couldn’t quite follow this question.

1 Like

It would be great if pools could be spawned and tracked from the bob.fun front-end. A paged list view with pools displaying blocks mined, total miners in pool, total cycles burnt, mining pool fees etc per pool would be valuable to users so they can make an informed decision in terms of which pool(s) to join. This would allow even the most non-technical users to create their own mining pools and well as to join others mining pools that might already be experiencing success. Command-line is trivial for devs but non-technical users will struggle. The way miners can be spawned from bob.fun works well because its frictionless. The same formula could work very well for pools too. In my opinion, the future of BOB is going to be between competing mining pools as no single miner will be able to afford the cycles required to win the block reward.

This is probably not required.

Cannister Ids would probably be sufficient in terms of identifying pools.

I was merely commenting on the fact that I believe a frictionless mining pool system / UI could really drive up the cycle burn rate.

2 Likes

@bobdotfun What do you think about the above suggestion?

1 Like