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.
The API of the ckBTC Ledger will be specified at a later stage. It will offer functions to query balances and transfer funds.
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.