[Feedback Wanted] Wrapped Bitcoin Ledger on the Internet Computer

Yes. I would suggest/criticize to not make the assumption like arakame that launching/growing new tokens/daos is so simple. There is an insane amount of competition for attention in both markets.

If success of the IC ecosystem/BTC adoption is the goal, why not support the team behind earthdao.co/ebtc with development, and let them support you with marketing/branding?

This looks very cool. I’m less interested in the dao side and more interested in incentivizing the btc tools so devs can work with the tech when it is ready. I am trying to find the right incentives and daos seem to be all the rage at the moment. Send me a message and tell me more about what you are thinking.

Team, come and join the community conversation with Mario Pastorelli (@mariop), Thomas Locher (@THLO)

register here: Webinar Registration - Zoom
overview of all community conversations: https://dfinity.org/conversations/


Since this is feature is now scoped, allow me to share the current feature design.

Note that the design reflects our current thinking. If the upcoming proposal to build this ledger is accepted and work on this feature is started, it is possible that some parts of the design will change as the project progresses.

NNS Proposal: Chain Key Bitcoin Ledger

The goal is to introduce a Bitcoin ledger on the Internet Computer based on the Bitcoin integration feature and Chain Key technology.

While the name is not set in stone, we call it the Chain Key Bitcoin (ckBTC) ledger in this design because it is one of the proposed names that received mostly positive feedback.

The ledger will make it possible to trade ckBTC at the speed of the Internet Computer at low cost. Moreover, it will offer mechanisms to convert BTC to ckBTC and vice versa, at a 1:1 rate.


The ckBTC functionality is introduced in the form of two new canisters:

  • The ckBTC Ledger is an instance of a ledger, handling ckBTC transfers and managing account balances.
  • The ckBTC Minter holds all Bitcoin of ckBTC holders and is in charge of issuing mint and burn calls to the ckBTC Ledger.

ckBTC Ledger

The API of the ckBTC Ledger will be specified at a later stage. It will offer functions to query balances and transfer funds.

ckBTC Minter

The ckBTC Minter will offer the following functions.

get_btc_address(subaccount: vec nat8) -> (String);

The function deterministically computes a Bitcoin address based on the ckBTC Minter’s main Bitcoin address and the caller’s principal ID and the provided subaccount.

Specifically, starting from the ckBTC Minter’s default key, BIP-32 key derivation is used to derive a key using the caller’s principal ID and the provided subaccount. The returned address is derived from this key.

Note that it is possible for a user to derive this Bitcoin address herself/himself.

update_balance(subaccount: vec nat8) -> (UpdateBalanceResult);

The function instructs the ckBTC Minter to update the ckBTC balance of the caller. Specifically, the ckBTC canister checks if there are new UTXOs associated with the Bitcoin address derived from the caller’s principal ID and the provided subaccount. If there are such UTXOs, the equivalent amount is minted in ckBTC and made available to the caller in the given subaccount.

retrieve_btc(amount: Bitcoin, fee: opt Bitcoin, address: String) -> (RetrieveBtcResult);

The function instructs the ckBTC Minter to send the given amount of Bitcoin to the provided Bitcoin address, burning the equivalent amount of ckBTC tokens. Note that at least the given amount must be transferred first, in ckBTC, to the caller’s withdrawal account. The withdrawal account is a ckBTC Ledger account under the control of the ckBTC Minter. The subaccount is derived deterministically from the user’s principal ID.

The optional fee parameter defines the fee to be used in the Bitcoin transaction that transfers the Bitcoin to the given Bitcoin address. If no fee is provided, the ckBTC Minter uses a standard fee, obtained through the Bitcoin integration fee API.

The ckBTC tokens are burned before the Bitcoin transaction is confirmed. If a transaction does not appear in a block, the user has the option to resubmit the transaction using the resubmit_retrieve_btc function below.

get_minimum_fee() -> (Bitcoin) query;

The function returns the minimum expected fee when providing a custom fee in the retrieve_btc function call.
The ckBTC Minter uses the Bitcoin integration fee API to derive this fee.

resubmit_retrieve_btc(request_id: nat64, new_fee: Bitcoin) -> (ResubmitRetrieveBtcResult);

The function instructs the ckBTC Minter to resubmit a Bitcoin transaction for a previous request, updating the fee. This function is intended to be used for transactions that are stuck because the fee was set too low.
The new fee must be higher than the last fee in the transaction associated with this request, increasing the fee according to BIP-125.


Great work! The API seems flexible for most use cases. ckBTC is very developer focused and the vast majority of retail end users are not developers, so that may reduce the number of holders.

Anyways, it will likely need to be wrapped with this implementation to be useable with other protocols (DEXs, DAOs, etc) so that should allow for other token names. These cross canister/subnet(?) calls may slow the end user experience but the flexibility is probably worth the trade off.

Any updates on the security guarantees and how the subnet will ensure BTC keys are not stolen by node operators?


Correct, the (initial) focus in on developers. We might add a frontend so that casual users can also exchange BTC and ckBTC but we will leave it mostly to the community to build cool products around this.

Correct, calls across subnets take a bit longer but it’s still only a few seconds until transactions are finalized. So it would be a vastly different experience compared to dealing with real Bitcoin.

This feature depends on the underlying Bitcoin integration feature, which in turn depends on the threshold ECDSA feature for “key management”.
There will be a single, large subnet with secret shares of a master key, which is used to derive the keys for every canister in every subnet. Since every signature request has to go to this subnet, the security largely depends on the security of this threshold ECDSA subnet. The goal is to make this subnet effectively as secure as the NNS itself.
If you’d like to learn more about the threshold ECDSA work, please ask in the corresponding channel!


Apropos names, these are Proof of Delegation transactions.

Wrapped bitcoin is “trusted to delegate” transactions. And the entrusted entity often turns out not to be trustworthy.

That’s why we want to have both the ledger and minter/custodian on the IC, in which case you only need to trust in the correct functioning of the subnet where these canisters run (and the threshold ECDSA subnet).


Agreed completely, that’s the main difference between this and classical wrapped bitcoin.

Point is, though, that not only is this fundamentally more secure, it’s also a lot less energy intensive than PoW. (and faster and many other good things). PoD is useful for bitcoin owners trying to get away from PoW. I’m proposing that we make more use of the phrase “Proof of Delegation”.

1 Like

Thanks to everyone who joined the community conversation on March 16!

For those who haven’t seen it yet, the motion proposal is now live. To all the neuron holders, please cast your vote before the deadline on March 21!


Regarding the “one Bitcoin address per transaction” question that was raised in the community conversation, we had a discussion about it internally.

From our perspective, the subaccount parameter can be used exactly for this purpose: A different subaccount will result in a different Bitcoin address.

If anybody feels that this approach does not meet the requirements for specific use cases, please let me know!

Note that the subaccount parameter can also be used for other purposes. For example, a DEX could use a subaccount to identify the owner of ckBTC on the DEX. In this scenario, the owner would transfer bitcoin to an address that will result in the minted ckBTC to be transferred to the owner’s subaccount controlled by the DEX.


what happens if a person with x amount of ckbitcoin wants to burn their ckbtc to send to an actual btc address but that x amount is greater than the amount in any single transaction address. Would that require sending from multiple transaction addresses? I’m still trying to wrap my head around this.

Good question!
In order to get bitcoin out, a user has to transfer the desired amount (from any number of accounts) to the user’s withdrawal account, which is an account controlled by the ckBTC Minter and derived from the user’s principal ID.
So, a few ckBTC transfers may be necessary (which are cheap), followed by a single Bitcoin transaction.

Wait just to make sure I’m getting this, when I send bitcoin, lets say from coinbase to this minter, you said it creates an entirely new address each time right?

I.e. get_btc_address(subaccount: vec nat8) → (String);

I send my btc to this address.

Then I mint some ckbtc.

Lets say I do this like 6 times, I’ll have 6 different addresses not on ckbtc but on actual l1 right?

Lets say I never touch this btc and theirs no other addresses to draw btc from from a withdrawl that I want to make back to coinbase. In order to aggregate a withdrawl out (i.e. unwrap) this exact amount and send back to my coinbase address wouldnt that essentially be 6 withdrawls over l1 and not ckBTC? So that would be 6 l1 btc transaction fees not over ckBTC as you say in the previous reply?

So, a few ckBTC transfers may be necessary (which are cheap), followed by a single Bitcoin transaction.

You can create a different address every time by providing a different subaccount. You are free to reuse the same subaccount, which will result in the same Bitcoin address (obviously, as long as the principal ID remains the same).

If you go through this process 6 times with different subaccounts and transfer bitcoin to these addresses, then, yes, your funds will be spread across 6 different addresses on the Bitcoin blockchain.
However, the ckBTC minter controls all of these addresses and associated UTXOs. So, if you want to transfer funds out, all you need to do is send the ckBTC to the withdrawal account and then trigger the retrieval process, which will burn the ckBTC in the withdrawal account and create a single Bitcoin transaction. The ckBTC minter is free to use any UTXOs and any number of UTXOs in the transaction to satisfy the request.

Does that answer your question?


Ohh so thats the power of chainkey cryptography? I didnt know you could make one transaction from multiple utxos of multiple bitcoin addresses that it controls to send to a whole nother bitcoin address. (I did know it was possible the other way if you were sending to multiple addresses from multiple utxos of a single address) .

But yea that answers it. I’ll have to read up more on the whitepaper again

Actually, this is just standard functionality of derived keys (see BIP-32). If you can sign for one key (= address), you can sign for derived keys (= derived addresses).
This rule applies to canisters holding bitcoin, too. :slight_smile:

ooh whoops. Thanks, youve been very helpful

The WRAPPED-Bitcoin should be called :
(∞BTC) :infinity:BTC

infinity-Bitcoin or Infinite-Bitcoin


As this topic was focused on gathering feedback, naming, and the motion proposal, I created a new topic to talk about ckBTC Chain-key Bitcoin (ckBTC): bitcoin wrapped by a smart contract.