ckBTC: a canister-issued bitcoin twin token on the IC, 1:1-backed by BTC

Looks like the ckBTC minter has been running for a while now on a minimum confirmation setting of 12 blocks when converting from BTC to ckBTC. A popular opinion we gathered from developers is to further lower it to have a better user experience. So we plan to submit an NNS proposal to further lower it down to 6 blocks. Would appreciate your input and support. Thanks!

6 Likes

The proposal is open for vote Proposal: 130096 - ICP Dashboard

6 Likes

I ran into a question regarding the Bitcoin address derivation used by the ckBTC minter. I found this in the ckBTC API reference:

get_btc_address(owner: opt principal, subaccount: opt blob)

The provided principal ID and subaccount are concatenated to form the derivation path for the ecdsa_public_key function, which returns the derived public key. If no principal ID is provided, then the sender’s principal ID is used. If no subaccount is provided, then the default subaccount (all zeros) is used.

This public key is encoded as a pay-to-witness-public-key-hash (P2WPKH) Bitcoin address and returned as a text.

Note that the key derivation is not BIP-32 compliant, where 31 bits are used for each derivation level. Instead, a single derivation is performed based on the full principal ID and subaccount. Since the derivation is deterministic, a canister can derive the Bitcoin address for a given principal ID and subaccount itself.

I am wondering what the last sentence refers to.

Option 1: A canister can call for example the ecdsa_public_key function on the management canister and provide as canister_id in the argument the ckBTC minter and the same derivation path.

Option 2: A canister can also obtain the root public key of the ckBTC minter once and then do the derivation in its own code without having to call the management canister every time. This option is what the last sentence refers to? Is there Motoko code available that does this derivation? I found Motoko code for BIP32 derivation but not for the non-standard derivation used here.

Option 3: Non-canister code, for example a frontend, can have the root public key of the ckBTC minter hard-coded and then can also do option 2. Is there a js library available that does this?

1 Like

I think that library makes async calls to the minter canister. I am wondering if there is something that does the derivation locally.

The last sentence simply means that, given the public key and the derivation path (comprising the principal ID and subaccount), the Bitcoin address can be derived locally, i.e., there is no need to call this (convenience) function.

This argument applies to all three options - but I’m not aware of any library support.

We should get ckBTC up and running on Eth, and as soon as the Solana integration is running, get ckBTC on there too.

Bringing the battle to the home turf of other chains should be part of our strategy! And Oisy is the perfect place for it to happen. The tvl of wBTC is enormous…

Is there any documentation at least for what I have to do to derive it? I couldn’t find documentation of it.

You can check out how the ckBTC minter itself derives the public key here.
Does this help?

1 Like

I am trying to run the ckBTC minter locally, I am getting this error:

dfx canister call ckbtc_minter update_balance '(record{ owner = opt principal "shu3y-t65bi-rhvef-c7vvy-arrzh-emws6-g2uew-hpgh2-uvjqi-7s3b2-zae"; subaccount = null})'

( variant { Err = variant { TemporarilyUnavailable = "management call \'bitcoin_get_utxos\' failed: the canister queue is full" } }, )

After deploying it with this command:

dfx deploy --specified-id ml52i-qqaaa-aaaar-qaaba-cai ckbtc_minter --argument '(variant{ Init = record { btc_network = variant { Regtest }; ledger_id = principal "mc6ru-gyaaa-aaaar-qaaaq-cai"; ecdsa_key_name = "dfx_test_key"; retrieve_btc_min_amount = 10_000; max_time_in_queue_nanos = 10_000_000_000; min_confirmations = opt 1; mode = variant { GeneralAvailability }; kyt_fee = opt 100; kyt_principal = opt principal "pvm5g-xaaaa-aaaar-qaaia-cai" } })'

What’s causing this: the canister queue is full error?

Thank you!

Hi everyone :wave: !

Summary

  • :index_pointing_at_the_viewer: Withdraw your ckTESTBTC tokens now!
  • :information_source: Rest assured, ckBTC is not impacted.

Details

Manu highlighted some proposed changes to the ICP’s bitcoin integration, one of which being

  1. Change the Bitcoin testnet canister to use Bitcoin’s testnet4, rather than the current testnet3. Testnet4 includes code changes to how the mining difficulty can be adjusted, which should avoid block storms (details can be found in BIP 94). Also testnet token availability for testnet4 is currently much better than for testnet3.

What this means, for ckTESTBTC:

  1. In the upcoming weeks, the bitcoin test canister will likely be reset to track Bitcoin testnet4 and testnet3 will no longer be available.
  2. At that point the ckTESTBTC canisters (minter, ledger, index and archive canisters) will be reset and tokens previously held by the minter will no longer be available.
  3. We therefore encourage ckTESTBTC holders to withdraw their tokens starting now.
2 Likes

Hi everyone :wave:

Some quick updates:

  1. Chainanalysis KYT has been removed and is no longer relevant for ckBTC, see this post for more details.
  2. The reason that currently only 2 out of 3 providers are not working is that there is an incompatibility between HTTP/2, which has recently been supported by HTTPs outcalls, and requests specifying the Host header. Proposal 134466 should fix that issue by removing this header from requests made by the bitcoin checker canister.
2 Likes

Proposal #134466

Vote: Adopted
Reason: Builds fine and the wasm and arguments hash match, as do both fixes.


c58e00fe22 fix(ckbtc): Drop Host header from https outcall request (#3115)
The btcscan_request function builds HTTP request for fetching raw transaction data from the BTCScan API (btcscan.org) used to set HTTP headers including Host and User-Agent now has the HOST header removed. Not sure about the errors of HTTP/2 but it matches description.
57362c30e3 fix(ckbtc): state schema upgrade (#3071)
Changes to main.rs where the init function used to initialize a canister with a configuration, now uses state::default_num_subnet_nodes() instead of a previously hardcoded constantDEFAULT_NUM_SUBNET_NODE, adding flexibility along with a centralized management for this value. Calls Config::new_and_validate to make sure input arguments are valid and stores the validated configuration into the canister state.
While the Config struct includes a default value mechanism for the num_subnet_nodes field, using serde attribute #[serde(default = "default_num_subnet_nodes")] checks that if num_subnet_nodes is missing during deserialization, it defaults to 34.

2 Likes

Proposal 134466

Vote: ADOPT

Reason: Build is successful and both code changes and hashes match.

c58e00fe22 Removed Host from request headers used for BTC API providers, since the outcalls adapter now uses HTTP/2, calls to memspace and blockstream providers would fail with a 400 error. The header was removed from btcscan too, in order to prevent possible future issues. I have been able to reproduce the issue and can confirm this commit fixes it.
On a side note I’d advise all developers who work with HTTP outcalls to update their dfx to the latest stable release, as versions <= 0.23.1 are bundled with a replica that is still using the old adapter and therefore wouldn’t experience potential issues until they deploy on mainnet.

57362c30e3 Added serde annotation to num_subnet_nodes field of Bitcoin checker’s Config struct to assign it a default value during deserialization, the config struct now also derives equality traits. A property test has been created to ensure the upgrade from an old config representation works properly, it generates config variations, which are then converted into ConfigPreviousVersion by stripping the num_subnet_nodes field, this is encoded/decoded back to Config and finally equality is checked between the original ConfigPreviousVersion and the newly decoded one converted back to ConfigPreviousVersion.

4 Likes

proposal - 134466

Vote: ADOPT

Reason:

Small fixes to BTC checker canister and all align with what is stated in the commit description. Hash and argument matches.

Hash Match: MATCH

Feedback: NONE

Proposer Check: MATCH

[c58e00fe22]
Matches description of removing Host from request_headers in btcscan_request.

[57362c30e3]
Instead of using constant DEFAULT_NUM_SUBNET_NODES for setting config in init for checker, it now invokes function default_num_subnet_nodes. This is to add backwards compatibility to state schema.

3 Likes

Hi everyone :wave:

Great news :drum:: Since the execution of proposal 134466, the bitcoin checker and ckBTC deposits seem to be working normally :tada: .

Don’t hesitate to let us know if you encounter any problem.

5 Likes