<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.internetcomputer.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jamongeon</id>
	<title>Internet Computer Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.internetcomputer.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jamongeon"/>
	<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/wiki/Special:Contributions/Jamongeon"/>
	<updated>2026-04-11T02:55:28Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.17</generator>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Node_Deployment_Guide_(with_an_HSM)&amp;diff=8303</id>
		<title>Node Deployment Guide (with an HSM)</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Node_Deployment_Guide_(with_an_HSM)&amp;diff=8303"/>
		<updated>2025-03-31T17:07:35Z</updated>

		<summary type="html">&lt;p&gt;Jamongeon: typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This runbook covers all steps necessary to install the Internet Computer Operating System (IC-OS) using the legacy NitroKey HSM instructions. To use the non-HSM onboarding instructions, follow the [[IC-OS Installation Runbook]].&lt;br /&gt;
&lt;br /&gt;
The physical machine is expected to be racked and stacked according to its respective manual.&lt;br /&gt;
&lt;br /&gt;
To complete these steps, you are expected to be physically present in the data center your machine(s) reside(s). Once you successfully onboarded your first node, you can bring up the other nodes in parallel.&lt;br /&gt;
&lt;br /&gt;
If you encounter issues during any of these steps, consult the [[Troubleshooting Node Deployment Errors]] page.&lt;br /&gt;
&lt;br /&gt;
⚠️ DFINITY does &#039;&#039;&#039;not&#039;&#039;&#039; offer live support for Node Providers attempting to deploy nodes.&lt;br /&gt;
&lt;br /&gt;
==1. Choose onboarding path (HSM vs no HSM)==&lt;br /&gt;
If you chose the [[Node Provider Onboarding#5. Choose onboarding path .28HSM vs no HSM.29|HSM Node Provider Onboarding Path]], &#039;&#039;&#039;continue to the next step.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If you chose to onboard &#039;&#039;&#039;without&#039;&#039;&#039; a Nitrokey HSM, follow the [[IC-OS Installation Runbook]] to onboard your nodes.&lt;br /&gt;
&lt;br /&gt;
==2. Obtain requirements==&lt;br /&gt;
*A USB (3.0 speed that can hold at least 4GB) to put the image file on.&lt;br /&gt;
** Faster USBs will allow the process to go much faster.&lt;br /&gt;
*The NitroKey HSM for your data center.&lt;br /&gt;
*[Optional] A USB hub&lt;br /&gt;
** This is helpful at some data centers for simultaneously connecting keyboard, mouse, Nitrokey, etc.&lt;br /&gt;
*It is recommended that each server has a label with the BMC&#039;s MAC address for ease of identification in future dashboard upgrades.&lt;br /&gt;
&lt;br /&gt;
==3. Download installation image==&lt;br /&gt;
Download the latest release of the &#039;&#039;&#039;IC-OS USB Installer Image&#039;&#039;&#039; and the &#039;&#039;&#039;corresponding checksum&#039;&#039;&#039; from the [https://dashboard.internetcomputer.org/releases Internet Computer Dashboard Releases]. &lt;br /&gt;
*&#039;&#039;&#039;Note that you should always use a release from the last 6 weeks (newer is better) in order to ensure that your node can correctly connect to the network.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==4. Verify checksum and unarchive file==&lt;br /&gt;
===Mac OS X===&lt;br /&gt;
#Open the Terminal and type: &lt;br /&gt;
#:&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;shasum -a 256 ~/Downloads/disk-img.tar.zst&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
#Compare the calculated checksum with the &#039;&#039;&#039;IC-OS installation image checksum&#039;&#039;&#039; file downloaded in the previous step. &#039;&#039;&#039;Warning:&#039;&#039;&#039; Only continue if they are identical, otherwise please post your issue in the [[Node Provider Matrix channel]].&lt;br /&gt;
#:Open the Terminal and type: &amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;tar xzvf ~/Downloads/disk-img.tar.zst&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Linux / Ubuntu===&lt;br /&gt;
#Open the Terminal and type: &lt;br /&gt;
#:&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;sha256sum ~/Downloads/disk-img.tar.zst&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
#Compare the calculated checksum with the &#039;&#039;&#039;IC-OS installation image checksum&#039;&#039;&#039; file downloaded in the previous step. &#039;&#039;&#039;Warning:&#039;&#039;&#039; Only continue if they are identical, otherwise please post your issue in the [[Node Provider Matrix channel]].&lt;br /&gt;
#:Open the Terminal and type: &amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;tar xzvf ~/Downloads/disk-img.tar.zst&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Windows===&lt;br /&gt;
#Open PowerShell and type: &lt;br /&gt;
#:&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;Get-FileHash -Algorithm SHA256 .\Downloads\disk-img.tar.zst&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
#Compare the calculated checksum with the &#039;&#039;&#039;IC-OS installation image checksum&#039;&#039;&#039; file downloaded in the previous step. &#039;&#039;&#039;Warning:&#039;&#039;&#039; Only continue if they are identical, otherwise please post your issue in the [[Node Provider Matrix channel]].&lt;br /&gt;
#:Open PowerShell and type: &amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;tar xzvf .\Downloads\disk-img.tar.zst&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==5. Create Bootable USB Stick==&lt;br /&gt;
===Mac OS X===&lt;br /&gt;
#Open the Terminal and type: &lt;br /&gt;
#:&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;diskutil list&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
#All available drives should be shown. Identify which device corresponds to your USB stick. You may need to unmount the USB drive:&lt;br /&gt;
#:&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;sudo diskutil unmount /dev/YOUR_USB_DEVICE_MOUNTED_PARTITION # E.g. /dev/disk4s1&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
#Replace &#039;&#039;/dev/YOUR_USB_DEVICE&#039;&#039; with the device that corresponds to your USB stick. Additionally, replace the path to your downloaded IC-OS &#039;&#039;disk.img&#039;&#039; file. &#039;&#039;&#039;Warning:&#039;&#039;&#039; You risk losing your own data if you specify a wrong drive.  &lt;br /&gt;
#:&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;sudo dd if=/Users/YOUR_USER_NAME/Downloads/disk.img of=/dev/YOUR_USB_DEVICE bs=1M status=progress&amp;lt;/syntaxhighlight&amp;gt;If you get a “device is busy” error from the dd command, you can try running the following command to unmount all of the partitions on the disk, then re-run the dd command:&lt;br /&gt;
#:&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;sudo diskutil unmountDisk /dev/YOUR_USB_DEVICE # E.g. /dev/disk4&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Linux / Ubuntu===&lt;br /&gt;
#Open the Terminal and type &lt;br /&gt;
#:&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;blkid&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
#All available drives should be shown. Identify which device corresponds to your USB stick. You may need to unmount the USB drive:&lt;br /&gt;
#:&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;sudo umount /dev/YOUR_USB_DEVICE_MOUNTED_PARTITION # E.g. /dev/sdb1&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
#Replace &#039;&#039;/dev/YOUR_USB_DEVICE&#039;&#039; with the device that corresponds to your USB stick. Additionally, replace the path to your downloaded IC-OS &#039;&#039;disk.img&#039;&#039; file. &#039;&#039;&#039;Warning:&#039;&#039;&#039; You risk losing your own data if you specify a wrong drive.  &lt;br /&gt;
#:&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;sudo dd if=/home/YOUR_USER_NAME/Downloads/disk.img of=/dev/YOUR_USB_DEVICE bs=1M status=progress&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Windows===&lt;br /&gt;
#Download and install [https://rufus.ie/en/ Rufus Portable]&lt;br /&gt;
#Start Rufus&lt;br /&gt;
#Select the USB stick under device and select the previously downloaded IC-OS disk image and press start &lt;br /&gt;
#:[[File:05.png|480px|screenshot]]&lt;br /&gt;
#You may see some warnings. Make sure you don&#039;t have any other USBs in your computer and chose OK&lt;br /&gt;
#:[[File:06.png|480px|screenshot]]&lt;br /&gt;
#:[[File:07.png|480px|screenshot]]&lt;br /&gt;
#The &amp;quot;Ready&amp;quot; bar will go from left to right as it completes.&lt;br /&gt;
&lt;br /&gt;
==6. Add configuration ==&lt;br /&gt;
&lt;br /&gt;
===A. Open Config.ini in a text editor===&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Mac OS X&#039;&#039;&#039;====&lt;br /&gt;
&lt;br /&gt;
#Open Finder. You should now be able to see the CONFIG partition. If it&#039;s not visible, remove the USB and insert it again.&lt;br /&gt;
#:[[File:mac_01.png|580px|screenshot]]&lt;br /&gt;
#Double-click &amp;lt;code&amp;gt;config.ini&amp;lt;/code&amp;gt; to open it in TextEdit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Linux&#039;&#039;&#039;====&lt;br /&gt;
&lt;br /&gt;
#Open the File Manager. You should now be able to see the CONFIG partition. If it&#039;s not visible, remove the USB and insert it again.&lt;br /&gt;
#:[[File:linux_01.png|580px|screenshot]]&lt;br /&gt;
#Double-click &amp;lt;code&amp;gt;config.ini&amp;lt;/code&amp;gt; to open it in KWrite.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====&#039;&#039;&#039;Windows&#039;&#039;&#039;====&lt;br /&gt;
&lt;br /&gt;
#Open the Disk Management utility with a right click on the Start menu. &lt;br /&gt;
#:[[File:09-b.png|300px|screenshot]]#:&lt;br /&gt;
#Right click the CONFIG partition.&lt;br /&gt;
#Select Change drive letter or paths...&lt;br /&gt;
#:[[File:10-b.png|780px|screenshot]]&lt;br /&gt;
#Select any letter from the drop-down list. &lt;br /&gt;
#:[[File:11-b.png|480px|screenshot]]&lt;br /&gt;
# Click OK.&lt;br /&gt;
# You should now be able to see the CONFIG partition in your Windows Explorer. Select the &amp;lt;code&amp;gt;config.ini&amp;lt;/code&amp;gt; configuration file. &lt;br /&gt;
#:[[File:12-b.png|780px|screenshot]]&lt;br /&gt;
#Click on Edit to open it.&lt;br /&gt;
&lt;br /&gt;
===B. Edit Config.ini===&lt;br /&gt;
&lt;br /&gt;
Edit the config.ini file to add your network configuration.&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;&#039;all Node Providers are requested to deploy two nodes with IPv4 and a domain name for every data center they operate in&#039;&#039;&#039;. Node Providers should deploy IPv4 to the &#039;&#039;&#039;first two nodes in their first rack&#039;&#039;&#039;.&lt;br /&gt;
# Set the appropriate value for the node_reward_type.&lt;br /&gt;
#:[[File:Pasted Graphic 7.png|780px|screenshot]]&lt;br /&gt;
#:You can find the value to set by following [[Node Deployment config.ini]]&lt;br /&gt;
#:&lt;br /&gt;
#Insert your IPv6 prefix and gateway.&lt;br /&gt;
#:[[File:Pasted Graphic 8.png|780px|screenshot]]&lt;br /&gt;
#:* The IPv6 prefix should consist of four groups of hexadecimal digits, separated by colons (&#039;:&#039;). Each group can contain up to four hex digits.&lt;br /&gt;
#:*For example, a valid prefix could look like this: &amp;lt;code&amp;gt;2a00:fb01:400:200&amp;lt;/code&amp;gt;&lt;br /&gt;
#:*&#039;&#039;&#039;Important:&#039;&#039;&#039;&lt;br /&gt;
#:**The prefix should not have a trailing &#039;:&#039;&lt;br /&gt;
#:**IPv6 CIDR notation allows for a double colon (&#039;::&#039;) to represent consecutive groups of zeroes in an address. However, the  prefix configuration in this context does &#039;&#039;&#039;not&#039;&#039;&#039; support &#039;::&#039;. The &#039;::&#039; shorthand should &#039;&#039;&#039;not&#039;&#039;&#039; be used. Even if some groups are all zeros, they must be explicitly written out.&lt;br /&gt;
#[Optional] Insert your IPv4 info and domain name.&lt;br /&gt;
#:[[File:Pasted Graphic 9.png|780px|screenshot]]&lt;br /&gt;
#:*Configuring your node with IPv4 settings is optional, but if you do configure your node with IPv4 settings, you must also define the domain name for your node.&lt;br /&gt;
#:*&#039;&#039;&#039;Important:&#039;&#039;&#039;&lt;br /&gt;
#:**Please note that you &#039;&#039;&#039;must use a unique IPv4 address for each node you deploy&#039;&#039;&#039;. This means that you cannot use a single IC-OS installation image to deploy multiple nodes (like you are able to do when just configuring IPv6 nodes).  &#039;&#039;&#039;After each IPv4 node deployment, you must plug your IC-OS Installation USB stick back into your laptop and return to [[Node Deployment Guide#6. Add configuration|step 6]] in the node deployment guide to reconfigure your installation image.&#039;&#039;&#039;&lt;br /&gt;
#:**You can add, remove, or update your node’s IPv4 address and domain name after completing node deployment using dfx commands. See [[Updating your node&#039;s IPv4 and domain name|here]] for details.&lt;br /&gt;
#Save the changes. &lt;br /&gt;
#:*If you have trouble saving this file directly, you may need to save to a known location first, then copy the file into place.&lt;br /&gt;
#:*:[[File:mac_03.png|580px|screenshot]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 7. Connect Crash Cart==&lt;br /&gt;
# In order to configure the UEFI and initiate the installation of the IC-OS, please connect a crash cart to the physical machine.&lt;br /&gt;
#Plug-in the VGA/Video, keyboard and IC-OS USB stick&lt;br /&gt;
#:[[File:08.png|580px|screenshot]]&lt;br /&gt;
&lt;br /&gt;
==8. UEFI Setup and Boot Menu ==&lt;br /&gt;
Use the related page below to set up the BIOS/UEFI according to your hardware vendor.&lt;br /&gt;
&lt;br /&gt;
*[[Node Provider Machine Hardware Guide#Gen 2 Node Machine requirements|Gen2 hardware]]&lt;br /&gt;
**[[IC-OS Installation - UEFI Configuration - Gen2 Dell]]&lt;br /&gt;
**[[IC-OS Installation - UEFI Configuration - Gen2 Supermicro]]&lt;br /&gt;
**[[IC-OS Installation - UEFI Configuration - Gen2 Gigabyte]]&lt;br /&gt;
**[[IC-OS Installation - UEFI Configuration - Gen2 ASUS]]&lt;br /&gt;
*[[Node Provider Machine Hardware Guide#Gen 1 Node Machine requirements|Gen1 hardware]]&lt;br /&gt;
**[[IC-OS Installation - UEFI Configuration - Gen1 Dell|IC-OS Installation - UEFI Configuration - Gen1 Dell (Poweredge R6525)]]&lt;br /&gt;
**[[IC-OS Installation - UEFI Configuration - Gen1 Supermicro]]&lt;br /&gt;
***&lt;br /&gt;
&#039;&#039;&#039;Important:&#039;&#039;&#039; Do NOT enable the RAID bios setting. Doing so will cause issues with the IC-OS installation.&lt;br /&gt;
&lt;br /&gt;
Resume from this point when you are finished configuring the BIOS.&lt;br /&gt;
&lt;br /&gt;
==9. IC-OS Installation==&lt;br /&gt;
#Please wait while the USB Installer is booting up. This process can take up to 3 minutes.&lt;br /&gt;
#:[[File:35-sm.png|580px|screenshot]]&lt;br /&gt;
#The IC-OS installation starts. Please keep an eye on the progress. This part can take up to 10 minutes. Please remember to check the [[Troubleshooting Node Deployment Errors]] page if you encounter any errors.&lt;br /&gt;
#:[[File:36-sm.png|580px|screenshot]]&lt;br /&gt;
#Once you get asked to insert the HSM, please remove the keyboard and instead insert the HSM USB device. &lt;br /&gt;
#:[[File:37-sm.png|580px|screenshot]]&lt;br /&gt;
# If the installation finished successfully, it will initiate a reboot. 🚨 &#039;&#039;&#039;Please do not unplug the USB stick or HSM USB&#039;&#039;&#039; device at this point. 🚨 &lt;br /&gt;
#:[[File:38-sm.png|580px|screenshot]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==10. First Boot==&lt;br /&gt;
Please remember to check the [[Troubleshooting Node Deployment Errors]] page if you encounter any errors.&lt;br /&gt;
&lt;br /&gt;
# After the IC-OS installation is complete, the machine reboots and then, after a few minutes, you should see the following log:&lt;br /&gt;
#*[[File:Hostos console log.png|600x600px]]&lt;br /&gt;
#*This log does &#039;&#039;&#039;NOT yet signify a successful onboarding.&#039;&#039;&#039; Please wait at least 10 minutes for a &amp;lt;code&amp;gt;Join request successful!&amp;lt;/code&amp;gt; log signifying a successful onboarding.&lt;br /&gt;
#*If after 10 minutes, you don&#039;t see anything else logged to the screen, please &#039;&#039;&#039;leave your node running&#039;&#039;&#039; and post a message in the Matrix channel with a screenshot of you console and the additional [https://wiki.internetcomputer.org/wiki/Troubleshooting_Node_Deployment_Errors#Support_request_information_requirements Support request information requirements]&lt;br /&gt;
#Once you see the &amp;lt;code&amp;gt;Join request successful!&amp;lt;/code&amp;gt; message, you may unplug the HSM USB device, USB stick and VGA/Video.&lt;br /&gt;
#:[[File:Node join message.png|580px|screenshot]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Congratulations! Your machine successfully joined the Internet Computer! The machine has joined the IC and the Node Provider will start receiving rewards!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you do NOT see a &amp;quot;Join request successful&amp;quot; message, your node may still have successfully onboarded. Continue to the next step to attempt to verify node onboarding.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== 11. Verify node onboarding==&lt;br /&gt;
&lt;br /&gt;
#Obtain your Node ID&lt;br /&gt;
#*Your Node ID should have been outputted in the previous step. If it wasn&#039;t, &#039;&#039;&#039;please wait at least 10 minutes to see if the node ID is logged to the console.&#039;&#039;&#039;&lt;br /&gt;
#Verify that your node was successfully onboarded by checking its status on the [https://dashboard.internetcomputer.org/ dashboard] &lt;br /&gt;
#*The dashboard can be searched by your Node Provider principal. There, you should see the Node ID of your node.&lt;br /&gt;
#*If the status of your node is either “Awaiting Subnet” or “Active in Subnet,” &#039;&#039;&#039;congratulations! Your machine successfully joined the Internet Computer!&#039;&#039;&#039;&lt;br /&gt;
#*If the status of your node is NOT either “Awaiting Subnet” or “Active in Subnet”, or if it is NOT listed under your Node Provider principal, you should consult the [[Troubleshooting Node Deployment Errors]] page.&lt;br /&gt;
#*:[[File:Node onboarding verification.png|680px|screenshot]]&lt;br /&gt;
#If deploying with IPv4, verify that IPv4 was successfully configured&lt;br /&gt;
#*Ten minutes after the initial &amp;lt;code&amp;gt;Join request successful!&amp;lt;/code&amp;gt; message, you should see another log indicating a successful IPv4 deployment:&lt;br /&gt;
#*:[[File:IPv4 log.jpg|680px|screenshot]]&lt;br /&gt;
#*If your log says &amp;lt;code&amp;gt;IPv4: none configured&amp;lt;/code&amp;gt;, then your IPv4 deployment failed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you are failing to verify your node onboarding, consult the [[Troubleshooting Node Deployment Errors]] page.&lt;/div&gt;</summary>
		<author><name>Jamongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=ICP_custody_options&amp;diff=8027</id>
		<title>ICP custody options</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=ICP_custody_options&amp;diff=8027"/>
		<updated>2024-12-02T15:49:16Z</updated>

		<summary type="html">&lt;p&gt;Jamongeon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Understand the benefits and limitations of each custody option so you can choose the wallet that best suits your needs.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| style=&amp;quot;width: 33%&amp;quot; |&lt;br /&gt;
== Onchain Wallets==&lt;br /&gt;
Onchain dapps that are easily accessible with the creation of an Internet Identity. Great for daily use and small amount transfers.&lt;br /&gt;
* [https://oisy.com/ Oisy]&lt;br /&gt;
*[https://nns.ic0.app/ NNS frontend dapp] with [https://identity.ic0.app/ Internet Identity]&lt;br /&gt;
*[https://astrox.me/ AstroX ME]&lt;br /&gt;
* [https://nfid.one/ NFID Wallet]&lt;br /&gt;
*[https://orbitwallet.io/ Orbit] (private alpha)&lt;br /&gt;
*[https://www.stoicwallet.com/ Stoic wallet]&lt;br /&gt;
 | style=&amp;quot;width: 34%&amp;quot; |&lt;br /&gt;
== Mobile Wallets ==&lt;br /&gt;
Mobile apps offer easy access to crypto assets for people who use them frequently.&lt;br /&gt;
*[https://plugwallet.ooo/ Plug wallet]&lt;br /&gt;
*[https://astrox.me/ AstroX ME]&lt;br /&gt;
*[https://klever.io/en-us/crypto-wallet/icp-wallet Klever]&lt;br /&gt;
*[https://airgap.it/ AirGap]&lt;br /&gt;
*[https://trustwallet.com/ Trust Wallet]&lt;br /&gt;
 | style=&amp;quot;width: 33%&amp;quot; |&lt;br /&gt;
==Hardware Wallets==&lt;br /&gt;
Maximum security. Hardware wallets hold private keys in airgapped machines or ledger devices.&lt;br /&gt;
*[[ICP custody with Ledger Nano|Ledger Nano]] and other Ledger hardware devices&lt;br /&gt;
*[https://airgap.it/ AirGap]&lt;br /&gt;
*[https://x.com/Tangem/status/1841759127845982370 Tangem]&lt;br /&gt;
*[https://www.taurushq.com/blog/taurus-integrates-the-full-icp-value-chain-including-staking-in-its-custody-solution-taurus-protect/ Taurus]&lt;br /&gt;
*ICP Custody with [https://github.com/dfinity/quill Quill] (Minimalistic ledger and governance toolkit for cold wallets) Networked computer&lt;br /&gt;
*[[ICP custody with seed phrase and air-gapped machine]]&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| &lt;br /&gt;
==Institutional Custody==&lt;br /&gt;
For anyone managing large amounts of crypto assets. Institutional custodians offer reliability and customer support.&lt;br /&gt;
*[https://www.coinbase.com/custody Coinbase]&lt;br /&gt;
*[https://www.sygnum.com/digital-asset-banking/internet-computer-icp/ Sygnum]&lt;br /&gt;
* [https://copper.co/en/insights/company-news/copper-adds-support-for-new-token-standards-on-the-internet-computer-blockchain-as-institutional-interest-grows Copper]&lt;br /&gt;
*[https://www.crypto-finance.com/ Crypto Finance]&lt;br /&gt;
*[https://www.dfns.co/article/icp-support Dfns] (wallet-as-a-service)&lt;br /&gt;
*[https://www.primevault.com/ Primevault]&lt;br /&gt;
* [https://www.taurushq.com/blog/taurus-integrates-the-full-icp-value-chain-including-staking-in-its-custody-solution-taurus-protect/ Taurus]&lt;br /&gt;
*[https://nfid.one/ NFID Wallet]&lt;br /&gt;
*[https://orbitwallet.io/ Orbit] (private alpha)&lt;br /&gt;
|&lt;br /&gt;
==Browser-Extensions==&lt;br /&gt;
Great for users already familiar with crypto wallets from other chains.&lt;br /&gt;
*[https://plugwallet.ooo/ Plug wallet]&lt;br /&gt;
*[https://trustwallet.com/blog/beginners-guide-to-icp Trust Wallet]&lt;br /&gt;
*[https://wallet.bitfinity.network Bitfinity Wallet]&lt;br /&gt;
*[https://snaps.metamask.io/snap/npm/fort-major/msq/ Metamask] (MSQ snap)&lt;br /&gt;
*[https://www.primevault.com/ Primevault] (coupled to institutional custody)&lt;br /&gt;
|&lt;br /&gt;
==Special Use Cases ==&lt;br /&gt;
ICP staking, voting &amp;amp; governance (NNS)&lt;br /&gt;
&lt;br /&gt;
*[https://nns.ic0.app/ NNS frontend dapp]&lt;br /&gt;
*[https://www.ledger.com/coin/staking/internet-computer Ledger Nano ICP staking]&lt;br /&gt;
&lt;br /&gt;
SNS staking &amp;amp; governance&lt;br /&gt;
&lt;br /&gt;
*[https://nns.ic0.app/ NNS frontend dapp]&lt;br /&gt;
*[https://www.ledger.com/coin/staking/internet-computer Ledger Nano ICP staking]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Do you want maximum control of your keys?==&lt;br /&gt;
&lt;br /&gt;
===No? Then, use third party custody solutions:===&lt;br /&gt;
&lt;br /&gt;
Third party custody solutions allow you to trade-off ease-of-use for control. The trade-off is simple: if you do not feel comfortable managing your own keys and are willing to have a third party to have access to your keys for the sake of being hand-held through the process, then third party solutions can be the right choice for you.&lt;br /&gt;
&lt;br /&gt;
Third party custody solutions include the Institutional Custody solutions listed above, as well as any of the exchanges supporting ICP on these lists:&lt;br /&gt;
&lt;br /&gt;
*[https://coinmarketcap.com/currencies/internet-computer/#Markets CoinMarketCap list of ICP exchanges]&lt;br /&gt;
*[https://www.coingecko.com/en/coins/internet-computer CoinGecko list of ICP exchanges]&lt;br /&gt;
&lt;br /&gt;
===Yes? Then, use self-custody:===&lt;br /&gt;
All of the solutions above, except Institutional Custody, are self-custody. On ICP, Oisy and other Onchain Wallets are the preferred solution.&lt;br /&gt;
&lt;br /&gt;
==Self-custody: Maximum ease option==&lt;br /&gt;
&lt;br /&gt;
If you choose self-custody, the simplest option to consider is [https://oisy.com/ Oisy]. And if Staking is required, then [[ICP Custody with NNS frontend dapp]]. It consists of using an [https://identity.ic0.app/ Internet Identity] with the [https://nns.ic0.app/ NNS frontend dapp].&lt;br /&gt;
&lt;br /&gt;
===Traits===&lt;br /&gt;
*It&#039;s the most convenient, entirely web-based, with no need to download or install anything.&lt;br /&gt;
*The [https://nns.ic0.app/ NNS frontend dapp] has all the functionality you need.&lt;br /&gt;
*This is a very common method.&lt;br /&gt;
*This method is ideal for people who want the easiest path to control their ICP.&lt;br /&gt;
*This custody solution has staking and voting built-in if you want to participate in governance.&lt;br /&gt;
&lt;br /&gt;
==Self-custody: Maximum control option==&lt;br /&gt;
&lt;br /&gt;
If you choose self-custody, the options which maximize control are: &lt;br /&gt;
&lt;br /&gt;
*[[ICP custody with seed phrase and air-gapped machine]]&lt;br /&gt;
*[[ICP custody with Ledger Nano]]&lt;br /&gt;
&lt;br /&gt;
===Traits===&lt;br /&gt;
&lt;br /&gt;
*This option requires more technical understanding.&lt;br /&gt;
*This is the &#039;&#039;safest&#039;&#039; option from a software point of view because the user relies on less software surface area, but it is the &#039;&#039;riskiest&#039;&#039; from a human point of view in that it puts the risk of the user&#039;s [[seed phrase]] and [[private key]] custody on them.&lt;br /&gt;
*Ideal for people who want as much control over their ICP as possible.&lt;br /&gt;
*This custody solution has staking built-in if you want to stake as well.&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
*[[Tutorials for acquiring, managing, and staking ICP]]&lt;/div&gt;</summary>
		<author><name>Jamongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Troubleshooting_Failed_NNS_proposals&amp;diff=7869</id>
		<title>Troubleshooting Failed NNS proposals</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Troubleshooting_Failed_NNS_proposals&amp;diff=7869"/>
		<updated>2024-07-12T17:08:18Z</updated>

		<summary type="html">&lt;p&gt;Jamongeon: format&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Background ===&lt;br /&gt;
Occasionally, a proposal on the Network Nervous System (NNS) may be adopted but fail during execution. This usually happens due to violations of certain invariants (constraints) in the NNS Registry.&lt;br /&gt;
&lt;br /&gt;
==== Example of a Failed Proposal ====&lt;br /&gt;
An instance of such a failure can be seen in https://dashboard.internetcomputer.org/proposal/125578.&lt;br /&gt;
&lt;br /&gt;
==== Screenshot ====&lt;br /&gt;
A screenshot of the failed proposal as displayed on the dashboard, for future reference, of https://dashboard.internetcomputer.org/proposal/125578&lt;br /&gt;
[[File:Failed-nns-proposal.png|center|thumb|791x791px|Screenshot of a failed NNS proposal in the dashboard]]&lt;br /&gt;
&lt;br /&gt;
=== Identifying the Cause of Failure ===&lt;br /&gt;
As of now, the specific reasons for a proposal&#039;s failure are not directly accessible on the proposal page. To find out why a proposal failed, you need to interact with the governance canister directly.&lt;br /&gt;
&lt;br /&gt;
==== Steps to Follow ====&lt;br /&gt;
&lt;br /&gt;
# Visit the governance canister page https://dashboard.internetcomputer.org/canister/rrkah-fqaaa-aaaaa-aaaaq-cai.&lt;br /&gt;
# Scroll down to the section labeled &amp;lt;code&amp;gt;get_proposal_info&amp;lt;/code&amp;gt;&lt;br /&gt;
# Use the toggle field to input the proposal number and click &amp;quot;Call&amp;quot;.[[File:Failed-proposal-get-info.png|center|thumb|654x654px|Get info on the failed NNS proposal, on the public dashboard]]&lt;br /&gt;
# Once the result appears, select &amp;quot;JSON&amp;quot; to view it in Json format.&lt;br /&gt;
# The failure reason will be detailed in the output. &lt;br /&gt;
&lt;br /&gt;
==== Example Output ====&lt;br /&gt;
Below is an example JSON output for a failed proposal. In this case, the proposal failed because an existing Node Operator record was being duplicated. &lt;br /&gt;
&lt;br /&gt;
Example: &lt;br /&gt;
&lt;br /&gt;
Open that toggle field, enter the proposal number, and click &amp;quot;Call&amp;quot;. Once you get the result, you can click on &amp;quot;JSON&amp;quot; to get the Json format, and you can read the failure reason in the output. In this case, the same Node Operator record was already present in the registry when the proposal attempted to re-add the same record.&lt;br /&gt;
 [&lt;br /&gt;
   {&lt;br /&gt;
     &amp;quot;id&amp;quot;: [&lt;br /&gt;
       {&lt;br /&gt;
         &amp;quot;id&amp;quot;: 125578&lt;br /&gt;
       }&lt;br /&gt;
     ],&lt;br /&gt;
     &amp;quot;status&amp;quot;: 5,&lt;br /&gt;
     &amp;quot;topic&amp;quot;: 5,&lt;br /&gt;
     &amp;quot;failure_reason&amp;quot;: [&lt;br /&gt;
       {&lt;br /&gt;
         &amp;quot;error_message&amp;quot;: &amp;quot;Error executing ExecuteNnsFunction proposal. Rejection message: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: Panicked at &#039;[Registry] Verification of the mutation type failed with the following errors: [Registry Canister Error. Msg: Key already present: node_operator_record_mbnsu-w4xfc-pmdok-r2lwo-wxfr4-gigu5-4idcm-5uuuy-znvby-biiny-jqe].&#039;, rs/registry/canister/src/registry.rs:293:13&amp;quot;,&lt;br /&gt;
         &amp;quot;error_type&amp;quot;: 12&lt;br /&gt;
       }&lt;br /&gt;
     ],&lt;br /&gt;
     &amp;quot;ballots&amp;quot;: [&lt;br /&gt;
       [&lt;br /&gt;
         &amp;quot;14315117116521128082&amp;quot;,&lt;br /&gt;
         {&lt;br /&gt;
           &amp;quot;vote&amp;quot;: 0,&lt;br /&gt;
           &amp;quot;voting_power&amp;quot;: 196565756&lt;br /&gt;
         }&lt;br /&gt;
       ]&lt;br /&gt;
     ],&lt;br /&gt;
     &amp;quot;proposal_timestamp_seconds&amp;quot;: 1699617467,&lt;br /&gt;
     &amp;quot;reward_event_round&amp;quot;: 0,&lt;br /&gt;
     &amp;quot;deadline_timestamp_seconds&amp;quot;: [&lt;br /&gt;
       1699963110&lt;br /&gt;
     ],&lt;br /&gt;
     &amp;quot;failed_timestamp_seconds&amp;quot;: 1699878752,&lt;br /&gt;
     &amp;quot;reject_cost_e8s&amp;quot;: 1000000000,&lt;br /&gt;
     &amp;quot;derived_proposal_information&amp;quot;: [],&lt;br /&gt;
     &amp;quot;latest_tally&amp;quot;: [&lt;br /&gt;
       {&lt;br /&gt;
         &amp;quot;no&amp;quot;: 66258822305525,&lt;br /&gt;
         &amp;quot;yes&amp;quot;: &amp;quot;45221535235544100&amp;quot;,&lt;br /&gt;
         &amp;quot;total&amp;quot;: &amp;quot;45541158736625569&amp;quot;,&lt;br /&gt;
         &amp;quot;timestamp_seconds&amp;quot;: 1699878752&lt;br /&gt;
       }&lt;br /&gt;
     ],&lt;br /&gt;
     &amp;quot;reward_status&amp;quot;: 1,&lt;br /&gt;
     &amp;quot;decided_timestamp_seconds&amp;quot;: 1699878752,&lt;br /&gt;
     &amp;quot;proposal&amp;quot;: [&lt;br /&gt;
       {&lt;br /&gt;
         &amp;quot;url&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
         &amp;quot;title&amp;quot;: [&lt;br /&gt;
           &amp;quot;Add mbnsu as a Node Operator of Node Provider: 4jjya&amp;quot;&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;action&amp;quot;: [&lt;br /&gt;
           {&lt;br /&gt;
             &amp;quot;ExecuteNnsFunction&amp;quot;: {&lt;br /&gt;
               &amp;quot;nns_function&amp;quot;: 8,&lt;br /&gt;
               &amp;quot;payload&amp;quot;: &amp;quot;4449444c056c06a795f3ad04018af3a2b108029bf499bd0878bbf187b70c03dddfde9b0d02dba7aaae0d716e716e686d046c020071017901000001011d97289ec1b951d2eceb5cb1e1906a77881899da5298cb6a1c05086e13020a000000000000000001011d78c0a5ff79e51f8d11fa75ad5db01d3d7cee8fecd6658d81c6deb6a20203726731&amp;quot;&lt;br /&gt;
             }&lt;br /&gt;
           }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;summary&amp;quot;: &amp;quot;Node provider “MB Patrankos šūvis” is adding 10 nodes in the rg1 data center&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     ],&lt;br /&gt;
     &amp;quot;proposer&amp;quot;: [&lt;br /&gt;
       {&lt;br /&gt;
         &amp;quot;id&amp;quot;: &amp;quot;1482125923012887388&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     ],&lt;br /&gt;
     &amp;quot;executed_timestamp_seconds&amp;quot;: 0&lt;br /&gt;
   }&lt;br /&gt;
 ]&lt;/div&gt;</summary>
		<author><name>Jamongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Node_Provider_Maintenance_Guide&amp;diff=7868</id>
		<title>Node Provider Maintenance Guide</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Node_Provider_Maintenance_Guide&amp;diff=7868"/>
		<updated>2024-07-12T17:05:27Z</updated>

		<summary type="html">&lt;p&gt;Jamongeon: minor grammar fixes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Troubleshooting ==&lt;br /&gt;
See the [[Node Provider Troubleshooting]] guide for info on troubleshooting failed onboardings, unhealthy nodes, networking, and more. &lt;br /&gt;
&lt;br /&gt;
== Submitting NNS proposals ==&lt;br /&gt;
As a part of being a Node Provider, you will likely have to submit some NNS proposals. The page at the following link describes some of these proposals: [[Node Provider NNS proposals]]&lt;br /&gt;
&lt;br /&gt;
== Monitoring ==&lt;br /&gt;
You are expected to regularly monitor the health of your nodes. Node health status is available on the public dashboard. Example: [https://dashboard.internetcomputer.org/node/235hh-hmjhq-dejel-3q5oi-pdz66-dygbp-yi2sy-zmuiq-rj7r7-65hue-wae node status].&lt;br /&gt;
&lt;br /&gt;
You can also view your node&#039;s [https://internetcomputer.org/docs/current/references/node-providers/node-metrics#manually-obtaining-metrics public health metrics] and monitor it with the [https://internetcomputer.org/docs/current/references/node-providers/node-metrics IC observability stack].&lt;br /&gt;
&lt;br /&gt;
===Community Tools and Resources===&lt;br /&gt;
&lt;br /&gt;
Several node providers have generously shared tools to facilitate monitoring node health. These tools can provide notifications in case of node issues.&lt;br /&gt;
&lt;br /&gt;
====Aviate Labs Node Monitor====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Turnkey Solution&#039;&#039;&#039;: Receive email alerts for unhealthy nodes.&lt;br /&gt;
*&#039;&#039;&#039;Link&#039;&#039;&#039;: [https://www.aviatelabs.co/node-monitor AviateLabs Node Monitor]&lt;br /&gt;
&lt;br /&gt;
====DIY Node Monitoring====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;GitHub Repository&#039;&#039;&#039;: Run your own node monitoring system.&lt;br /&gt;
*&#039;&#039;&#039;Link&#039;&#039;&#039;: [https://github.com/aviate-labs/node-monitor Aviate Labs GitHub]&lt;br /&gt;
&lt;br /&gt;
====Prometheus Exporter for Node Status====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;GitHub Repository&#039;&#039;&#039;: A tool for exporting node status to a Prometheus-compatible format.&lt;br /&gt;
*&#039;&#039;&#039;Link&#039;&#039;&#039;: [https://github.com/virtualhive/ic-node-status-prometheus-exporter IC Node Status Prometheus Exporter]&lt;br /&gt;
&lt;br /&gt;
== Common maintenance tasks ==&lt;br /&gt;
*[[Removing a Node From the Registry]]&lt;br /&gt;
*[[Adding additional node machines to existing Node Allowance]]&lt;br /&gt;
*[[Updating your node&#039;s IPv4 and domain name]]&lt;br /&gt;
*[[Moving a node from one DC to another]]&lt;br /&gt;
*[[iDRAC access and TSR logs]]&lt;br /&gt;
*[[Checking node CPU and memory speed]]&lt;br /&gt;
*For changing your Node Provider or DC principal, please refer to [[Node Provider NNS proposals]]&lt;br /&gt;
*[[Updating Firmware]]&lt;br /&gt;
==Permitted tools==&lt;br /&gt;
For security and confidentiality reasons, other tools are not allowed to run on the same machine in parallel with the replica. In case you need to troubleshoot an issue, it is recommended to either boot the machine from a USB drive that has a live Linux distribution (e.g. [https://ubuntu.com/tutorials/try-ubuntu-before-you-install#3-boot-from-usb-flash-drive Ubuntu]) or to debug from an auxiliary machine in the same rack on which you have complete control, as described in [[Troubleshooting Unhealthy Nodes#Setting Up an Auxiliary Machine for Network Diagnostics|Unhealthy Nodes#Setting Up an Auxiliary Machine for Network Diagnostics]]&lt;br /&gt;
&lt;br /&gt;
==Scheduled data center outages==&lt;br /&gt;
When your data center notifies you of a scheduled outage, you must:&lt;br /&gt;
&lt;br /&gt;
*Notify DFINITY on the [[Node Provider Matrix channel]]&lt;br /&gt;
*Make sure your nodes return to one of the healthy statuses when the outage is resolved:&lt;br /&gt;
**Active in Subnet - The node is healthy and actively functioning within a subnet.&lt;br /&gt;
**Awaiting Subnet - The node is operational and prepared to join a subnet when necessary.&lt;br /&gt;
*If a node is degraded at first, give it a little bit of time in case it needs to catch up, but make sure that it does return to one of the two healthy statuses.&lt;br /&gt;
&lt;br /&gt;
==Node rewards based on useful work==&lt;br /&gt;
The Internet Computer protocol can tolerate up to 1/3 of nodes misbehaving. There is an ongoing activity to automatically issue node rewards based on useful work, and also to automatically reduce node remuneration in case nodes are misbehaving. This will provide a financial incentive for honest behavior. Please follow the forum and the Matrix channel to stay informed about these activities.&lt;br /&gt;
&lt;br /&gt;
In the meantime, the recommendation is to prepare for this by making sure that your nodes are online and healthy at all times, otherwise you risk penalties even before the automatic node rewards based on useful work become active.&lt;br /&gt;
&lt;br /&gt;
== Subnet recovery==&lt;br /&gt;
In case subnet recovery is needed, we may have to reach out to you for assistance. Please make sure you closely follow activities in the Matrix Channel, and enable notifications on new messages -- especially direct mentions.&lt;br /&gt;
&lt;br /&gt;
==General best practices==&lt;br /&gt;
&lt;br /&gt;
# Keep a separate machine in the same rack with appropriate tools for network diagnostics and troubleshooting&lt;br /&gt;
# Engage with the node provider community for support and to share effective troubleshooting techniques&lt;br /&gt;
===Setting Up an Auxiliary Machine for Network Diagnostics===&lt;br /&gt;
Robust Internet connectivity is essential. Without access to internal node logs and metrics, troubleshooting requires alternative strategies, including the use of an auxiliary machine within the same rack. Here&#039;s a brief outline for setting up an auxiliary machine in the same rack while following best security practices:&lt;br /&gt;
&lt;br /&gt;
# Hardware Setup:&lt;br /&gt;
#* Choose a server with sufficient resources to run diagnostic tools without impacting its performance. There is no need to follow the gen1/gen2 hardware requirements for this server (since this node would not be joining the IC network), but make sure the server is performant enough to run network tests.&lt;br /&gt;
#* Ensure that physical security measures are in place to prevent unauthorized access.&lt;br /&gt;
# Operating System and Software:&lt;br /&gt;
#* Install a secure operating system, like a minimal installation of Linux (we prefer Ubuntu 22.04), which reduces the attack surface.&lt;br /&gt;
#* Keep the system updated with the latest security patches and firmware updates.&lt;br /&gt;
# Network Configuration:&lt;br /&gt;
#* Configure the machine with an IPv6 address in the same range as the IC nodes for accurate testing.&lt;br /&gt;
#* Set up a restrictive firewall on the machine to allow &#039;&#039;only the necessary&#039;&#039; inbound and outbound traffic. Consider allowing Internet access for this machine only during troubleshooting sessions and keeping the machine behind a VPN at other times.&lt;br /&gt;
# Diagnostic Tools:&lt;br /&gt;
#* Install network diagnostic tools such as &amp;lt;code&amp;gt;ping&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;traceroute&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;nmap&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;tcpdump&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;iperf&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* Configure monitoring tools to simulate node activities and track responsiveness.&lt;br /&gt;
# Security Measures:&lt;br /&gt;
#* Use strong, unique passwords for all accounts, and change them regularly. Or, preferably, do not use passwords at all and use key-based access instead.&lt;br /&gt;
#* Implement key-based SSH authentication and disable root login over SSH.&lt;br /&gt;
#* Regularly review logs for any unusual activities that might indicate a security breach.&lt;br /&gt;
# Maintenance and Updates:&lt;br /&gt;
#* Regularly update all software to the latest versions.&lt;br /&gt;
#* Periodically test your network diagnostic tools to ensure they are functioning as expected.&lt;br /&gt;
&lt;br /&gt;
==Peer-support and bug reports / resolution: Node Provider Matrix Channel==&lt;br /&gt;
&lt;br /&gt;
Node Providers are encouraged to join the dedicated [[Node Provider Matrix channel]]. This platform can be used for discussing maintenance-related queries and sharing insights, report issues, and search for previous resolutions for operations.&lt;br /&gt;
&lt;br /&gt;
Please consult the Matrix channel for troubleshooting issues &#039;&#039;&#039;&amp;lt;u&amp;gt;only after consulting the [[Node Provider Troubleshooting]] guide&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Communication Guidelines on the Matrix Channel&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As a Node Provider, ensure your notifications are enabled to receive new messages promptly. Your input or intervention might be crucial, especially in urgent situations.&lt;br /&gt;
&lt;br /&gt;
It is recommended to add the node provider name to your alias (handle) on the communication platform, to facilitate communication and enable others to quickly and easily mention you.&lt;/div&gt;</summary>
		<author><name>Jamongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Node_Provider_Troubleshooting&amp;diff=7867</id>
		<title>Node Provider Troubleshooting</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Node_Provider_Troubleshooting&amp;diff=7867"/>
		<updated>2024-07-12T16:10:51Z</updated>

		<summary type="html">&lt;p&gt;Jamongeon: add missing period&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Specific troubleshooting guides==&lt;br /&gt;
&lt;br /&gt;
* [[Troubleshooting Node Deployment Errors]]&lt;br /&gt;
* [[Troubleshooting Unhealthy Nodes]]&lt;br /&gt;
* [[Troubleshooting Networking Issues]]&lt;br /&gt;
* [[Troubleshooting Failed NNS proposals]]&lt;br /&gt;
&lt;br /&gt;
==Getting the node ID from a node==&lt;br /&gt;
&lt;br /&gt;
# Hook up a console to the node.&lt;br /&gt;
# The node ID will print to the screen upon a fresh boot and every 10 minutes thereafter.&lt;br /&gt;
# If a node does not show its principal, consult the [[Troubleshooting Node Deployment Errors]] page.&lt;br /&gt;
&lt;br /&gt;
==Node Provider Matrix channel ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;After first consulting relevant documentation&amp;lt;/u&amp;gt;&#039;&#039;&#039;, discuss your issue with other Node Providers in the [[Node Provider Matrix channel]].&lt;/div&gt;</summary>
		<author><name>Jamongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Node_Provider_Reward_Configuration_Guide&amp;diff=7866</id>
		<title>Node Provider Reward Configuration Guide</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Node_Provider_Reward_Configuration_Guide&amp;diff=7866"/>
		<updated>2024-07-12T16:08:56Z</updated>

		<summary type="html">&lt;p&gt;Jamongeon: minor grammar/format&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;After onboarding all your nodes, you must submit a reward configuration proposal in order to start receiving node rewards. If you do not do this, you will not receive node rewards.&lt;br /&gt;
&lt;br /&gt;
In the next code block:&lt;br /&gt;
&lt;br /&gt;
*Replace the &amp;lt;code&amp;gt;NEURON_ID&amp;lt;/code&amp;gt; value with your neuron ID from the NNS Frontend Dapp (step 3.6 from the [[Node Provider Onboarding]]).&lt;br /&gt;
*Replace the &amp;lt;code&amp;gt;NODE_OPERATOR_PRINCIPAL&amp;lt;/code&amp;gt; value with your node operator principal (step 7.1 from the [[Node Provider Onboarding]]).&lt;br /&gt;
*Replace &amp;lt;code&amp;gt;NODE_1_MACHINE_ID&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NODE_2_MACHINE_ID&amp;lt;/code&amp;gt; ... &amp;lt;code&amp;gt;NODE_N_MACHINE_ID&amp;lt;/code&amp;gt; with the node machine IDs for all N of your node machines (found on the [https://dashboard.internetcomputer.org/ dashboard])&lt;br /&gt;
*Replace &amp;lt;code&amp;gt;NODE_COUNT&amp;lt;/code&amp;gt; with the number of nodes you are setting a reward configuration for.  *Important : &#039;&#039;If you adding nodes to a previous node allocation or updating a previous node operator record, you have to make sure the total node count should be accounted for&#039;&#039; &#039;&#039;in the&#039;&#039; &amp;lt;code&amp;gt;NODE_COUNT&amp;lt;/code&amp;gt; &#039;&#039;parameter.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== 1. Create the proposal ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ NEURON_ID = XXXXXXXXXXXXXXXXXXXX&lt;br /&gt;
$ NODE_OPERATOR_PRINCIPAL = xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxx&lt;br /&gt;
$ ./ic-admin \&lt;br /&gt;
        --nns-url https://ic0.app \&lt;br /&gt;
        -s ~/.config/dfx/identity/node-provider-hotkey/identity.pem \&lt;br /&gt;
    propose-to-update-node-operator-config \&lt;br /&gt;
        --proposer $NEURON_ID \&lt;br /&gt;
        --summary &amp;quot;Set rewards for the following nodes:&lt;br /&gt;
&lt;br /&gt;
        * NODE_1_MACHINE_ID&lt;br /&gt;
        * NODE_2_MACHINE_ID&lt;br /&gt;
        * ...&lt;br /&gt;
        * NODE_N_MACHINE_ID&lt;br /&gt;
        &amp;quot; \&lt;br /&gt;
        --node-operator-id $NODE_OPERATOR_PRINCIPAL \&lt;br /&gt;
        --rewardable-nodes &#039;{&amp;quot;type3.1&amp;quot;: NODE_COUNT}&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default reward configuration for Gen2 nodes is &amp;lt;code&amp;gt;type3.1&amp;lt;/code&amp;gt;. If a different node configuration is applicable to your node models, replace this value. &lt;br /&gt;
&lt;br /&gt;
Example reward configuration proposal for 3 Gen2 nodes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ NEURON_ID = 13419667327548602649&lt;br /&gt;
$ NODE_OPERATOR_PRINCIPAL = uqquy-76uhn-2mys5-dh54e-85ntr-sr953-redif-zkte3-94ndi-st2i1-93t&lt;br /&gt;
$ ./ic-admin \&lt;br /&gt;
        --nns-url https://ic0.app \&lt;br /&gt;
        -s ~/.config/dfx/identity/node-provider-hotkey/identity.pem \&lt;br /&gt;
    propose-to-update-node-operator-config \&lt;br /&gt;
        --proposer $NEURON_ID \&lt;br /&gt;
        --summary &amp;quot;Set rewards for the following nodes:&lt;br /&gt;
&lt;br /&gt;
        * sed94-atzdo-rltqy-tmnhr-fvspg-fat3p-sdbjp-7q3jg-dgfcq-zrlap-cqe&lt;br /&gt;
        * uq4uy-76uhn-2mys5-dh54e-85ntr-sr953-redif-zkte3-94ndi-st2i1-93t-sdjsl-vjlfn-6duch-vskdu-26pf5-cwibg-zooqk-sdn2e-cgugm-tae&lt;br /&gt;
        * 39esy-hmrb2-nfvao-t42co-tqfed-y3i7c-xqxyp-idt2w-wgmgr-l4x7l-gae&lt;br /&gt;
        &amp;quot; \&lt;br /&gt;
        --node-operator-id $NODE_OPERATOR_PRINCIPAL \&lt;br /&gt;
        --rewardable-nodes &#039;{&amp;quot;type3.1&amp;quot;: 3}&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 2. Find the proposal on https://dashboard.internetcomputer.org/governance and wait until it has been executed. ====&lt;/div&gt;</summary>
		<author><name>Jamongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Validation_of_Candidate_Node_Machines&amp;diff=7865</id>
		<title>Validation of Candidate Node Machines</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Validation_of_Candidate_Node_Machines&amp;diff=7865"/>
		<updated>2024-07-12T16:03:13Z</updated>

		<summary type="html">&lt;p&gt;Jamongeon: minor grammar fixes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Background ==&lt;br /&gt;
In order to improve the decentralization network, an optimization model has been proposed on the forum (see [https://forum.dfinity.org/t/ic-topology-series-node-diversification-part-i/23402 node diversification part 1] and [https://forum.dfinity.org/t/ic-topology-node-diversification-part-ii/23553 node diversification part 2]) and also approved (see [https://dashboard.internetcomputer.org/proposal/125367 proposal 125367]). Given a certain target topology, the model optimizes between node rewards (onboarding of additional new nodes and rewards for existing nodes) and decentralization, calculating the minimum number of additional node machines required in order to achieve specific decentralization targets.&lt;br /&gt;
&lt;br /&gt;
The basis for the optimization model is a target IC topology for the next 6 to 12 months which may extend into Q1 2025 for contracts ending for Gen1 node machines. This target topology has been proposed on the forum in [https://forum.dfinity.org/t/ic-topology-node-diversification-part-ii/23553 node diversification part 2], and approved by the community in [https://dashboard.internetcomputer.org/proposal/125549 proposal 125549] on 12th November 2023. This model sets targets for the number of Gen1 nodes and Gen2 nodes per subnet and the decentralization coefficients (Nakamato coefficients) per subnet. &lt;br /&gt;
[[File:Validation Candidate Nodes - figure 1.png|center|thumb|800x800px|Validation of Candidate Node Machines - figure 1|alt=]] &lt;br /&gt;
&lt;br /&gt;
Running the optimization tool with the current topology will produce a graph like above, with the red blocks showing the number of additional required node machines in order to reach the decentralization targets set in the IC Target Topology. The number of additional node machines required to reach the decentralization targets is visible in the &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt; example graph is 68 additional Gen 2 node machines. &lt;br /&gt;
&lt;br /&gt;
With the optimization model and the IC Target Topology, the goal is to implement a transparent, objective and reproducible approach for node provider onboarding. Running the model with the existing IC topology and the number of new node machines intended to be onboarded, the model allows the proposer:&lt;br /&gt;
&lt;br /&gt;
* to verify whether adding additional nodes actually improves the decentralization, and &lt;br /&gt;
* allows the community to verify this improvement and vote on the proposal to add additional nodes.&lt;br /&gt;
&lt;br /&gt;
Below the steps are described to run the optimization model and verify any new proposal. An example is also given for a specific (fictional) proposal. &lt;br /&gt;
&lt;br /&gt;
== Basic starting points ==&lt;br /&gt;
There are a few basic starting points that everybody should be aware of when using the optimization tool and the IC Target Topology. First of all, using the model requires some basic knowledge of Python and Github, so please make sure to familiarize yourself with these before starting.&lt;br /&gt;
&lt;br /&gt;
In addition, it is important to note that the IC Target Topology is not fixed. It is voted in by the community as the target to be achieved within a certain timeframe. [https://dashboard.internetcomputer.org/proposal/125549 Proposal 125549] describes the target topology for the next half year/year, estimated on the current growth of the IC network. If expected growth should change, the community can decide to vote on an updated IC Target Topology with either more node machines or less node machines. Note that the Target IC Topology is intended to assess effectiveness of adding additional nodes, and identify potential nodes that are not relevant from a decentralization perspective. It does not assess or propose any changes in node rewards, which is a topic that the community discusses and votes upon separately. &lt;br /&gt;
&lt;br /&gt;
If target IC Topology is reached - meaning the &amp;lt;code&amp;gt;Objective Value&amp;lt;/code&amp;gt; in the optimization model has reached the value of zero, no new node machines should be onboarded. Hence, NNS proposals for increasing the Node Allowance or defining a new Node Allowance should be rejected by the community. Once a new IC Target topology is defined or (other) Node Providers have reduced their Node Allowance, the &amp;lt;code&amp;gt;Objective Value&amp;lt;/code&amp;gt; might increase again which would allow for new proposals to be submitted and approved. &lt;br /&gt;
== Steps to follow to assess node relevance ==&lt;br /&gt;
Assessing the relevance of adding new node machines using the optimization tool requires you to follow four basic steps:&lt;br /&gt;
&lt;br /&gt;
# Installing and running the latest version of the optimization tool.&lt;br /&gt;
# Determining your candidate node configuration.&lt;br /&gt;
# Updating your candidate nodes in the optimization tooling.&lt;br /&gt;
# If adding new node machines is relevant, submitting the Node Operator proposal with the necessary background description.&lt;br /&gt;
&lt;br /&gt;
Each of these steps is discussed in detail below. &lt;br /&gt;
&lt;br /&gt;
=== Step 1: Downloading and installing the optimization tool ===&lt;br /&gt;
The optimization tool can be found in the following Github repository: https://github.com/dfinity/decentralization/. The repository is open sourced to allow the community to help improve the tooling with additional functionality and visualizations. &lt;br /&gt;
&lt;br /&gt;
To run the model. Please follow the following steps:&lt;br /&gt;
&lt;br /&gt;
* Find the repository on https://github.com/dfinity/decentralization/&lt;br /&gt;
* Either follow one of the following two approaches:&lt;br /&gt;
** Command Line approach - Follow the instructions as described in the README file, i.e.:&lt;br /&gt;
*** Clone the repository to you computer&lt;br /&gt;
*** Install [https://python-poetry.org/ Python Poetry]&lt;br /&gt;
*** Run the model in the command line as described in the README file&lt;br /&gt;
** Jupyter Notebook approach - Frequent Python users might have a preference for using [https://jupyter.org/ Jupyter Notebook]. If you want to use Jupyter notebook, you can follow the following steps:&lt;br /&gt;
*** Copy the code from the repository files and delete the import commands and main() sections from the separate python files (&amp;lt;code&amp;gt;data_preparation.py&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;helper_functions.py&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;linear_solver.py&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;visualization.py&amp;lt;/code&amp;gt;) &lt;br /&gt;
*** Run each file in subsequent cells in Jupyter notebook&lt;br /&gt;
*** You can subsequently rerun the model and adjust parameters using the interface of Jupyter notebook.&lt;br /&gt;
* Carefully read the forum posts on [https://forum.dfinity.org/t/ic-topology-series-node-diversification-part-i/23402 node diversification part 1] and [https://forum.dfinity.org/t/ic-topology-node-diversification-part-ii/23553 node diversification part 2] to understand the working of the tooling.&lt;br /&gt;
* Check the outcome of the model without making any updates to the model, in particular the &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt; as described above. As per 23 November 2023, the Objective Value should be similar to the graph shown above, with an additional 72 nodes needed to reach the target topology.&lt;br /&gt;
&lt;br /&gt;
=== Step 2 : Determine your candidate node configuration ===&lt;br /&gt;
The Internet Computer dashboard shows the worldwide distribution of node machines. Based on this distribution, as a potential new Node Provider you can identify potential locations and data center providers for new node machines.&lt;br /&gt;
&lt;br /&gt;
For the Node Provider economics and understanding the costs and rewards for running a node machine, please look at the detailed NP documentation on the Internet Computer wiki pages, in particular those on [[Node Provider Machine Hardware Guide|hardware configuration]], [[Node Provider Data Center and ISP Guide|data center requirements]], and [[Node Provider Remuneration|node rewards]]. &lt;br /&gt;
&lt;br /&gt;
Once you have decided on potential data center locations and a potential number of new node machines that have viable economics, you can follow the following steps to add this candidate configuration to the optimization tool:&lt;br /&gt;
&lt;br /&gt;
* Collect the following information:&lt;br /&gt;
** The node provider name (if you are an existing node provider, use your existing Node Provider name)&lt;br /&gt;
** The data center name (if you are intending to add node machines to an existing data center, use the existing data center name)&lt;br /&gt;
** The data center provider name (if you are intending to use an existing data center provider, use the existing data center provider name)&lt;br /&gt;
** The country name (if you are intending to add node machines to an existing country, use the existing country name)&lt;br /&gt;
** The number of nodes you intend to onboard&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Update the candidate node configuration in the optimization tooling ===&lt;br /&gt;
The optimization tool includes a function that allows candidate nodes to be added to the node configuration, and to run the optimization with including these candidate nodes. With the information collected in step 2, the following steps allow for the optimization tool to be run including the candidate nodes:&lt;br /&gt;
&lt;br /&gt;
* Updated the latest topology in the optimization tooling&lt;br /&gt;
** Find the &amp;lt;code&amp;gt;df_candidate_nodes&amp;lt;/code&amp;gt; function in the &amp;lt;code&amp;gt;main.py&amp;lt;/code&amp;gt; of the &amp;lt;code&amp;gt;ic_topology&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
** You will see the following example entry: &amp;lt;code&amp;gt;df_candidate_nodes = create_candidate_node_dataframe(node_provider =&#039;Lionel Messi&#039;,data_center =&#039;Buenos Aires&#039;,data_center_provider =&#039;Perron Corporation&#039;,country = &#039;AR&#039;,is_sev = True,no_nodes = 0)&amp;lt;/code&amp;gt;&lt;br /&gt;
** Replace ‘Lionel Messi’ with the Node Provider name.&lt;br /&gt;
** Replace ‘Buenos Aires’ with the data center name.&lt;br /&gt;
** Replace ‘Perron Corporation’ with the data center provider name.&lt;br /&gt;
** Replace ‘AR’ with the country name.&lt;br /&gt;
** Replace “0” in no_nodes with the number of nodes intended to be onboarded.&lt;br /&gt;
* Run the model and determine the &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt;:&lt;br /&gt;
** If the &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt; is lower compared to the &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt; without making changes to the df_candidate_nodes, it means that adding one or more new nodes is increasing the decentralization of the IC. It is important to note that every single node machine should help 1:1 to reduce the &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt;. For, if the &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt; without adding any candidate nodes is 68, and 6 candidate nodes are added, the &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt; should reduce to 68 minus 6 is 62. If the &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt; is reduced to for example 66, only 2 candidate node machines will support further decentralization of the IC network, and no more than 2 candidate nodes should be added.&lt;br /&gt;
** If the ObjectiveValue is the same compared to the &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt; without making changes to the df_candidate_nodes, it means that adding one or more new nodes does not improve  the decentralization of the IC. &lt;br /&gt;
&lt;br /&gt;
=== Step 4: Submitting a Node Operator proposal ===&lt;br /&gt;
If the conclusion from step 3 is that adding node machines helps decentralization of the IC network, the final step is to prepare to submit a proposal for onboarding these nodes. Following are the steps to take in order to submit this proposal:&lt;br /&gt;
&lt;br /&gt;
* If you are not yet a Node Provider, please follow the steps on the [[Node Provider Onboarding|NP onboarding wiki page]] to submit a Node Provider Proposal. Please make sure to submit the self-declaration form and the identity-document as part of the proposal, as described in the instructions. &lt;br /&gt;
* If you are intending to onboard node machines in a new data center, follow the subsequent steps on the same [[Node Provider Onboarding|NP onboarding wiki page]] to submit a Data Center Proposal.&lt;br /&gt;
* Follow the steps on the same [[Node Provider Onboarding|NP onboarding wiki page]] to submit a Node Operator Proposal. The Node Operator Proposal should include the following input in the summary text:&lt;br /&gt;
** The number of nodes planned to be onboarded.&lt;br /&gt;
** Node provider name (as per the public dashboard).&lt;br /&gt;
** The data center and country where nodes are to be onboarded.&lt;br /&gt;
** Evidence of running the optimization model and providing reproducible feedback on decrease in &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt;. This can be done in the following way:&lt;br /&gt;
*** Upload a pdf with screenshots of running the optimization model to the wiki, on the page of your specific Node Provider self-declaration documentation.&lt;br /&gt;
*** Include the link to this pdf document and the hash of this document in the Node Operator Proposal.&lt;br /&gt;
*** Include/describe exactly the used input data and config the optimization model was run with.&lt;br /&gt;
*** Clearly state the &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt; before adding the candidate nodes.&lt;br /&gt;
*** Clearly state the &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt; after adding the candidate nodes.&lt;br /&gt;
* Complete the steps of the [[Node Provider Onboarding|NP onboarding wiki page]].&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
The example below shows how to use the optimization model to validate whether candidate nodes improve the decentralization of the IC network. In the optimization model code in the Github library, you will find a function &amp;lt;code&amp;gt;df_candidate_nodes&amp;lt;/code&amp;gt; that is defined as follows:&lt;br /&gt;
 df_candidate_nodes = create_candidate_node_dataframe(node_provider =&#039;Lionel Messi&#039;, data_center =&#039;Buenos Aires&#039;, data_center_provider =&#039;Perron Corporation&#039;, country = &#039;AR&#039;, is_sev = True, no_nodes = 0)&lt;br /&gt;
This function uses a hypothetical new Node Provider, called Lionel Messi, that is interested in setting up new node machines in the Buenos Aires data center. Lionel Messi uses the data center entity Perron Corporation as the data center name. Note that all nodes are marked as  &amp;lt;code&amp;gt;is_sev = True&amp;lt;/code&amp;gt; which means that Gen2 node machines (with SEV SNP enabled) will be set up, and that  &amp;lt;code&amp;gt;no_nodes = 0&amp;lt;/code&amp;gt; so when running the current optimization tooling zero nodes will be added; the optimization tool will only use the existing IC topology to calculate the number of required Gen2 Nodes, defined as &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now let’s add one node machine to the candidate node list of Lionel Messi. For this, the function is updated as follows:&lt;br /&gt;
 df_candidate_nodes = create_candidate_node_dataframe(node_provider =&#039;Lionel Messi&#039;, data_center =&#039;Buenos Aires&#039;, data_center_provider =&#039;Perron Corporation&#039;, country = &#039;AR&#039;, is_sev = True, no_nodes = 1)&lt;br /&gt;
Re-running the optimization model will generate (amongst others) the following output. As can be seen from the Node Provider topology Matrix, Lionel Messi is added as a node Provider with one node (which is the top orange block in the graph, and the bottom name in the Node Provider legend on the right). &lt;br /&gt;
[[File:Validation of Candidate Node Machines - figure 2.png|alt=Validation of Candidate Node Machines - figure 2|center|thumb|800x800px|Validation of Candidate Node Machines - figure 2]]  &lt;br /&gt;
&lt;br /&gt;
The output also shows the data center being added to the Data Center topology. Again, the node is shown on the top (as the block block on second to the top) and the data center name is shown at the bottom of the data center legend as Perron Corporation.  &lt;br /&gt;
&lt;br /&gt;
 [[File:Candidate Node Machine Validation - figure 3.png|center|thumb|800x800px|Validation of Candidate Node Machines - figure 3|alt=]]&lt;br /&gt;
More importantly, the node allocation per subnet is now showing an updated &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt; with a value of 67, hence 67 more Gen2 node machines are required to reach the IC target topology. Compared to running the model without Lionel Messi’s candidate node machine, the &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt; is reduced from 68 (see beginning of this article) to 67, hence adding one extra node machine in Buenos Aires support the decentralization of the IC network. &lt;br /&gt;
&lt;br /&gt;
[[File:Validation of Canidate Node Machines - figure 4.png|center|thumb|800x800px|Validation of Candidate Node Machines - figure 4|alt=]]&lt;br /&gt;
&lt;br /&gt;
It would be interesting to validate whether adding additional node machines in Buenos Aires further support the decentralization of the IC. Let’s increase the number of candidate nodes from 1 to 4 by updating the &amp;lt;code&amp;gt;df_candidate_nodes&amp;lt;/code&amp;gt; function as follows:&lt;br /&gt;
 df_candidate_nodes = create_candidate_node_dataframe(node_provider =&#039;Lionel Messi&#039;, data_center =&#039;Buenos Aires&#039;, data_center_provider =&#039;Perron Corporation&#039;, country = &#039;AR&#039;, is_sev = True, no_nodes = 4)&lt;br /&gt;
The node allocation per subnet now shows an &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt; with a value of 64, hence 64 more Gen2 node machines are required to reach the decentralization targets of the IC network. This is a reduction from the original 68 required node machines with 4 nodes. Hence, the model shows that adding 4 candidate nodes in Buenos Aires still adds to the decentralization of the IC network. &lt;br /&gt;
&lt;br /&gt;
Further increasing the number of candidate nodes to 6 shows that decentralization of the IC network still improves. By adding 6 candidate nodes through the updated &amp;lt;code&amp;gt;df_candidate_nodes&amp;lt;/code&amp;gt; function, the &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt; reduces to 62 from 68. &lt;br /&gt;
[[File:Validation of Candidate node Machines - figure 5.png|center|thumb|800x800px|Validation of Candidate Node Machines - figure 5]]&lt;br /&gt;
&lt;br /&gt;
Similarly, adding 8 candidate node machines still improves decentralization, as the &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt; reduced to 60. &lt;br /&gt;
 df_candidate_nodes = create_candidate_node_dataframe(node_provider =&#039;Lionel Messi&#039;, data_center =&#039;Buenos Aires&#039;, data_center_provider =&#039;Perron Corporation&#039;, country = &#039;AR&#039;, is_sev = True, no_nodes = 8)&lt;br /&gt;
&lt;br /&gt;
 [[File:Validation of Candidate node Machines - figure 6.png|center|thumb|800x800px|Validation of Candidate Node Machines - figure 6]]&lt;br /&gt;
&lt;br /&gt;
However, if we increase the number of candidate node machines in Buenos Aires from 8 to 9, we notice that the &amp;lt;code&amp;gt;ObjectiveValue&amp;lt;/code&amp;gt; does not reduce anymore. Hence, adding 8 node machines in Buenos Aires is the optimal solution for improving the decentralization targets. &lt;br /&gt;
 df_candidate_nodes = create_candidate_node_dataframe(node_provider =&#039;Lionel Messi&#039;, data_center =&#039;Buenos Aires&#039;, data_center_provider =&#039;Perron Corporation&#039;, country = &#039;AR&#039;, is_sev = True, no_nodes = 9)&lt;br /&gt;
[[File:Validation of Candidate Node Machines - figure 7.png|center|thumb|800x800px|Validation of Candidate Node Machines - figure 7]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This can be explained by the fact that most subnets (marked in blue in the Node Allocation subnet graph) are already optimized in terms of country limit, node provider limit, and data center limit. Only the subnets with blocks marked in red need additional node machines from unique countries, unique data centers and unique node providers. Adding 8 nodes achieves this. An additional ninth node machine cannot be added to any of the existing subnets in order to improve any of the country limits, data center limits and node provider limits.&lt;br /&gt;
&lt;br /&gt;
== Q&amp;amp;A ==&lt;br /&gt;
&lt;br /&gt;
* What is the maximum number of nodes for one country ?&lt;br /&gt;
** As per the agreed target topology  ([https://dashboard.internetcomputer.org/proposal/125549 proposal] link) the country subnet limit ranges between 2 and 3. Given that there are currently 40 subnets, once the proposed topology is fully implemented, each country will have the capacity to host between 80 and 120 nodes in total. This range is calculated by multiplying the number of subnets (40) by the per-subnet country limit (2 to 3).&lt;/div&gt;</summary>
		<author><name>Jamongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Node_Provider_Self-declaration&amp;diff=7864</id>
		<title>Node Provider Self-declaration</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Node_Provider_Self-declaration&amp;diff=7864"/>
		<updated>2024-07-12T15:53:30Z</updated>

		<summary type="html">&lt;p&gt;Jamongeon: fix format and add forum post link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page describes the Node Provider self-declaration process and provides templates. This process and templates are currently in a draft state and discussed by the community (see [https://forum.dfinity.org/t/proposal-for-node-provider-self-declaration/16501 forum post]). Once the NNS has decided on the expected format, the post and this page will be updated to reflect the NNS decision.&lt;br /&gt;
&lt;br /&gt;
== Motivation ==&lt;br /&gt;
&lt;br /&gt;
In a fully decentralized network, the onboarding of a Node Provider is managed entirely by the Network Nervous Systems (NNS). This means that anybody who wants to become a Node Provider needs to submit a proposal that will be voted upon by the community. The main question for the community is: how to decide whether to accept or reject a new Node Provider into the network?&lt;br /&gt;
&lt;br /&gt;
Ultimately, it’s the Node Provider&#039;s responsibility to convince the community to adopt their proposal to be added as a new Node Provider. With the self-declaration, the Node Provider shall:&lt;br /&gt;
&lt;br /&gt;
* Establish their identity.&lt;br /&gt;
* Make a statement of good intent.&lt;br /&gt;
&lt;br /&gt;
This way, the community will have sufficient information to vote on the Node Provider&#039;s onboarding proposal.&lt;br /&gt;
&lt;br /&gt;
== Documents and Templates ==&lt;br /&gt;
&lt;br /&gt;
Before submitting a proposal to become a new Node Provider, the Node Provider shall prepare two kinds of documents. The documents should be delivered as a PDF file that is digitally signed.&lt;br /&gt;
&lt;br /&gt;
=== (1) Self-declaration ===&lt;br /&gt;
&lt;br /&gt;
(A) Statement of identity&lt;br /&gt;
&lt;br /&gt;
Entity name: __________________________________________________&lt;br /&gt;
&lt;br /&gt;
Representative name: __________________________________________&lt;br /&gt;
&lt;br /&gt;
Position within entity: ___________________________________________&lt;br /&gt;
&lt;br /&gt;
Entity address and location: ______________________________________&lt;br /&gt;
&lt;br /&gt;
Country: ______________________________________________________&lt;br /&gt;
&lt;br /&gt;
Chamber of Commerce Nr: _______________________________________&lt;br /&gt;
&lt;br /&gt;
(B) Statement of provision of node machines&lt;br /&gt;
&lt;br /&gt;
I hereby guarantee that I shall provide node machines in accordance with the required Hardware Configuration for running the IC Network, as described on the IC wiki (see [[Node Provider Machine Hardware Guide]]).&lt;br /&gt;
&lt;br /&gt;
(C) Statement of good intent&lt;br /&gt;
&lt;br /&gt;
I guarantee to the world that I shall honestly operate the node machines I provide, and that should I behave dishonestly, for example by deliberately interfering with my node machine(s) to prevent them correctly processing ICP protocol messages, in collusion with others or alone, that I will be liable to users of the network, and to other node providers, for any damages caused.&lt;br /&gt;
&lt;br /&gt;
I further declare I am aware that any deliberate interference with a node machine, which causes it to incorrectly process ICP protocol messages, represents a misuse of that hardware, and of any hardware it interacts with, and that in some jurisdictions, that may constitute a crime.&lt;br /&gt;
&lt;br /&gt;
Signature of representatives&lt;br /&gt;
&lt;br /&gt;
___________________&lt;br /&gt;
&lt;br /&gt;
___________________&lt;br /&gt;
&lt;br /&gt;
___________________&lt;br /&gt;
&lt;br /&gt;
=== (2) Identity Proof ===&lt;br /&gt;
&lt;br /&gt;
The Node Provider shall provide proof that the identity(ies) listed in the self-declaration exist in the real world. The proof can be any document that sufficiently proves the identity of the signers of the self-declaration to the community.&lt;br /&gt;
&lt;br /&gt;
== Process ==&lt;br /&gt;
&lt;br /&gt;
Initially, the process is quite manual. Over time, it shall be automated and for convenience be incorporated into dApps running on the IC. For now:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Preparation:&#039;&#039;&#039; The Node Provider prepares:&lt;br /&gt;
## The two kinds of documents listed above in a format that is widely available, e.g. PDF. .zip files are not recommended.&lt;br /&gt;
### Compute the sha256 hash of each document.&lt;br /&gt;
# &#039;&#039;&#039;Publication:&#039;&#039;&#039; The Node Provider uploads the documents including the sha256 hashes to the wiki page [[Node Provider Self Declarations|Node Provider Self Declarations.]]&lt;br /&gt;
# &#039;&#039;&#039;Proposal submission:&#039;&#039;&#039; The Node Provider submits a proposal to the NNS asking to be accepted to the network.&lt;br /&gt;
## The technical instructions are provided on the [[Node Provider Onboarding]] page.&lt;br /&gt;
## The summary of the proposal shall point to the published file (step 2) and list the hash (step 1).&lt;br /&gt;
# &#039;&#039;&#039;NNS vote:&#039;&#039;&#039; It’s now up to the NNS community to check whether the provided information matches the community’s expectations and to vote on the proposal.&lt;/div&gt;</summary>
		<author><name>Jamongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Node_Provider_Onboarding&amp;diff=7863</id>
		<title>Node Provider Onboarding</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Node_Provider_Onboarding&amp;diff=7863"/>
		<updated>2024-07-12T15:45:59Z</updated>

		<summary type="html">&lt;p&gt;Jamongeon: Update instructions for downloading ic-admin&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Learn how to be accepted by the NNS as a Node Provider and onboard your nodes to the IC.&lt;br /&gt;
&lt;br /&gt;
Please allocate up to a week to complete this guide, as it may take several days for a proposal to be accepted by the NNS, and you may have to submit multiple NNS proposals. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that the following steps do not need to be performed on the node machine itself.&#039;&#039;&#039; You can complete them on your personal laptop.&lt;br /&gt;
&lt;br /&gt;
If you encounter issues through any of these steps, check the [[Node Provider Troubleshooting]] page. If that does not solve your problem, you are encouraged to ask for assistance in the [[Node Provider Matrix channel]].&lt;br /&gt;
&lt;br /&gt;
For regular operations after onboarding, please refer to [[Node Provider Maintenance Guide|Node Provider Maintenance Guide.]]&lt;br /&gt;
&lt;br /&gt;
==== ⚠️ DFINITY does &#039;&#039;&#039;not&#039;&#039;&#039; offer live support for Node Providers attempting to onboard nodes. ====&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;&amp;lt;big&amp;gt;Requirements&amp;lt;/big&amp;gt;&#039;&#039;&#039; ==&lt;br /&gt;
* Assure your node(s) meet the [[Node Provider Machine Hardware Guide|Node Provider Machine Hardware requirements.]]&lt;br /&gt;
* View the [[Node Provider Networking Guide|Node Provider Networking Guide.]]&lt;br /&gt;
* Setup a [https://www.ledger.com/ hardware wallet].&lt;br /&gt;
*[https://shop.nitrokey.com/shop/product/nkhs2-nitrokey-hsm-2-7/ NitroKey HSM] (Optional, legacy—not recommended).&lt;br /&gt;
* 11 ICP (10 of which are to be staked for the NNS proposal deposit).&lt;br /&gt;
* Basic understanding of [[Neurons 101|neurons]], [https://internetcomputer.org/docs/current/tokenomics/nns/nns-staking-voting-rewards staking], and [[Governance of the Internet Computer|governance]] proposals, such as understanding what it means to stake a neuron for 8 years.&lt;br /&gt;
&lt;br /&gt;
== 1. Install the required tools ==&lt;br /&gt;
===&#039;&#039;&#039; A. Install ic-admin &#039;&#039;&#039;===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ic-admin&amp;lt;/code&amp;gt; is the tool used to create and submit NNS proposals.&lt;br /&gt;
&lt;br /&gt;
==== MacOS ====&lt;br /&gt;
# To install &amp;lt;code&amp;gt;ic-admin&amp;lt;/code&amp;gt;, view the latest release version in the [https://github.com/dfinity/ic/releases/latest DFINITY/ic repo]. Then, use the following URL &amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ curl -L &amp;quot;https://github.com/dfinity/ic/releases/download/[latest-release]/ic-admin-x86_64-darwin.gz&amp;quot; -o - | gunzip &amp;gt; ./ic-admin&lt;br /&gt;
$ chmod +x ./ic-admin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Replace &amp;lt;code&amp;gt;[latest-release]&amp;lt;/code&amp;gt; with the most recent IC version, such as &amp;lt;code&amp;gt;release-2024-07-10_23-01-base&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Verify the binary &amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ diff &amp;lt;(shasum -a 256 ./ic-admin | cut -d&#039; &#039; -f1) &amp;lt;(echo 035abf8925bf54e067d13eee0a6205e883507d6138bcd232ec8069301a9b190a) &amp;amp;&amp;amp; echo &amp;quot;ic-admin checksum matches&amp;quot; || echo &amp;quot;***ERROR***: ic-admin checksum does not match&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Linux ====&lt;br /&gt;
NOTE: The instructions below have been tested with the Ubuntu 20.04 release.&lt;br /&gt;
# To install &amp;lt;code&amp;gt;ic-admin&amp;lt;/code&amp;gt;, view the latest release version in the [https://github.com/dfinity/ic/releases/latest DFINITY/ic repo]. Then, use the following URL &amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ curl -L &amp;quot;https://github.com/dfinity/ic/releases/download/[latest-release]/ic-admin-x86_64-linux.gz&amp;quot; -o - | gunzip &amp;gt; ./ic-admin&lt;br /&gt;
$ chmod +x ./ic-admin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Replace &amp;lt;code&amp;gt;[latest-release]&amp;lt;/code&amp;gt; with the most recent IC version, such as &amp;lt;code&amp;gt;release-2024-07-10_23-01-base&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Verify the binary &amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ diff &amp;lt;(shasum -a 256 ./ic-admin | cut -d&#039; &#039; -f1) &amp;lt;(echo e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855) &amp;amp;&amp;amp; echo &amp;quot;ic-admin checksum matches&amp;quot; || echo &amp;quot;***ERROR***: ic-admin checksum does not match&amp;quot; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===&#039;&#039;&#039; B. Install dfx &#039;&#039;&#039;===&lt;br /&gt;
&lt;br /&gt;
#&amp;lt;code&amp;gt;dfx&amp;lt;/code&amp;gt; is a CLI tool used to generate neuron hotkeys, among other things such as canister deployment and management. &amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ sh -ci &amp;quot;$(curl -fsSL https://internetcomputer.org/install.sh)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
#Verify that &amp;lt;code&amp;gt;dfx&amp;lt;/code&amp;gt; is up to date. &amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ export PATH=$HOME/bin:$PATH&lt;br /&gt;
$ dfx upgrade&lt;br /&gt;
$ dfx --version&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==2. Create Node Provider hotkey ==&lt;br /&gt;
&lt;br /&gt;
#Create an identity for the Node Provider h&#039;&#039;&#039;otkey&#039;&#039;&#039; &amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ dfx identity new --storage-mode=plaintext node-provider-hotkey&lt;br /&gt;
&lt;br /&gt;
Created identity: &amp;quot;node-provider-hotkey&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$ dfx --identity node-provider-hotkey identity get-principal&lt;br /&gt;
&lt;br /&gt;
xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxx&lt;br /&gt;
# example node-provider-hotkey: wuyst-x5tpn-g5wri-mp3ps-vjtba-de3xs-w5xgb-crvek-tucbe-o5rqi-mae&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;You will need the Node Provider hotkey in the next steps.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: The Node Provider hotkey is NOT the Node Provider principal. This is the hotkey that is used for the NNS proposal submissions only.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: You may be prompted to enter a passphrase when creating your identity and accessing your identity principal. Take note of the passphrase you choose.&lt;br /&gt;
&lt;br /&gt;
==3. Create and Manage Neuron via NNS Frontend Dapp and Internet Identity==&lt;br /&gt;
&lt;br /&gt;
#Send at least 11 ICP tokens to your hardware wallet address.&lt;br /&gt;
#Navigate to the Neurons tab and create a Neuron by staking at least 10 ICP from your hardware wallet. Staking more ICP is acceptable, but 10 is the minimum needed for this process, and you must have a little more for transaction fees.&lt;br /&gt;
#&amp;lt;u&amp;gt;IMPORTANT!&amp;lt;/u&amp;gt; Confirm the transaction on your hardware wallet. &lt;br /&gt;
#:[[File:-docs-stake_neuron_1.png|1024px|stake neuron]]&lt;br /&gt;
#After the Neuron has been created successfully, confirm to &amp;quot;Add NNS Dapp as hotkey&amp;quot; in the dialogue and on your hardware wallet, and close the dialog after the action completes.&lt;br /&gt;
#:[[File:-docs-stake_neuron_2.png|1024px|neuron id]]&lt;br /&gt;
#Set the dissolve delay to at least 6 months, and confirm the choice in the dialogue and on your hardware wallet. After the action completes, you can close the &amp;quot;Follow Neurons&amp;quot;.&lt;br /&gt;
#:[[File:dissolve_delay.png|480px|neuron id]]&lt;br /&gt;
#You will now see a Neuron listed with its ID. Copy the Neuron ID, since you will need it in the next steps to place the necessary proposals.&lt;br /&gt;
#:[[File:Neuron id.png|1024px]]&lt;br /&gt;
&lt;br /&gt;
==4. Add hotkeys==&lt;br /&gt;
&lt;br /&gt;
#Select the Neuron you just created to open Neuron management view and press “Add hotkey” button.&lt;br /&gt;
#:[[File:Hotkey 1.png|873x873px]]&lt;br /&gt;
# A dialog will pop up where you can enter the hotkey you generated in step 2.1 (output from command &amp;lt;code&amp;gt;dfx --identity node-provider-hotkey identity get-principal&amp;lt;/code&amp;gt;). This will allow you to submit NNS proposals using &amp;lt;code&amp;gt;ic-admin&amp;lt;/code&amp;gt; and will not be used for anything else.&amp;lt;br&amp;gt;&lt;br /&gt;
#:Press the &#039;&#039;&#039;confirm&#039;&#039;&#039; button and confirm the transactions on your hardware wallet.&amp;lt;br&amp;gt;&lt;br /&gt;
#:[[File:Hotkey 2.png|899x899px]]&lt;br /&gt;
#Get the Ledger Hardware Wallet Principal Id: Navigate back to ICP page and select your Ledger hardware wallet account. You will need to use this Ledger Hardware Wallet principal as the Node Provider principal in order to get the rewards directly into the secure hardware wallet.&lt;br /&gt;
#:[[File:Node provider principal 1.png|1024px]]&lt;br /&gt;
#:[[File:Node provider principal 2.png|800px]]&lt;br /&gt;
#Copy and save this Node Provider principal by clicking on the copy icon after the principal id. You&#039;ll need it in the next steps. &amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ NODE_PROVIDER_PRINCIPAL=xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxx   &lt;br /&gt;
# Input ledger Hardware Wallet principal, from the NNS FrontEnd dapp https://nns.ic0.app/&lt;br /&gt;
&lt;br /&gt;
# example: $ NODE_PROVIDER_PRINCIPAL=fharn-5vyi2-4xb4a-64yyi-3jpmj-pga23-mxy25-d5uim-fqcro-eoefh-tae&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==5. Choose onboarding path (HSM vs no HSM)==&lt;br /&gt;
Onboarding &#039;&#039;&#039;without&#039;&#039;&#039; a NitroKey HSM is the recommended onboarding path. In particular, node providers onboarding [[Node Provider Machine Hardware Guide|Gen 2 hardware]] must onboard &#039;&#039;&#039;without&#039;&#039;&#039; a NitroKey HSM. If you will be onboarding &#039;&#039;&#039;without&#039;&#039;&#039; a NitroKey HSM, continue to the next step.  &lt;br /&gt;
&lt;br /&gt;
If the legacy procedure is necessary, follow the [[NitroKey HSM onboarding instructions]] and &#039;&#039;&#039;return to step 8.&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
==6. Setup the Node Operator keys ==&lt;br /&gt;
#&#039;&#039;&#039;&#039;&#039;Ensure dfx is at least version 0.14.&#039;&#039;&#039;&#039;&#039; Node Operator keys created with older versions of dfx &#039;&#039;&#039;will fail to join the IC&#039;&#039;&#039;.  Run:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ dfxvm update&lt;br /&gt;
$ dfx --version&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
#Create a new principal with dfx:&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ dfx identity new --storage-mode=plaintext node_operator&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
#Confirm &amp;lt;code&amp;gt;node_operator&amp;lt;/code&amp;gt; identity was created successfully:&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ dfx identity list&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;This list &#039;&#039;should&#039;&#039; contain &amp;lt;code&amp;gt;node_operator&amp;lt;/code&amp;gt;.&lt;br /&gt;
#Copy new key to a known location:&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ cp ~/.config/dfx/identity/node_operator/identity.pem ./node_operator_private_key.pem&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
#Check the contents of the &amp;lt;code&amp;gt;node_operator_private_key.pem&amp;lt;/code&amp;gt; file and double check that it contains the following contents. It is imperative that the first line has &amp;lt;code&amp;gt;-----BEGIN EC PRIVATE KEY-----&amp;lt;/code&amp;gt;. If it does not, make sure you use the latest &amp;lt;code&amp;gt;dfx&amp;lt;/code&amp;gt; version and that you followed the instructions precisely.&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
❯ cat ./node_operator_private_key.pem&lt;br /&gt;
-----BEGIN EC PRIVATE KEY-----&lt;br /&gt;
[3 lines of base64 encoded private key, e.g. n2Nhp68YcQpuS0u96r...]&lt;br /&gt;
-----END EC PRIVATE KEY-----&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Note: you must retain access to the &amp;lt;code&amp;gt;node_operator_private_key.pem&amp;lt;/code&amp;gt; file for when you onboard nodes in &#039;&#039;&#039;[https://wiki.internetcomputer.org/wiki/Node_Provider_Roadmap#Milestone_Five:_Node_Machine_Onboarding roadmap milestone five.]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==7. Get the node operator principal==&lt;br /&gt;
&lt;br /&gt;
#Get the principal:&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ NODE_OPERATOR_PRINCIPAL=$(dfx --identity node_operator identity get-principal)&lt;br /&gt;
$ echo $NODE_OPERATOR_PRINCIPAL&lt;br /&gt;
&lt;br /&gt;
uqquy-76uhn-2mys5-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxx&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;You will need the node operator principal in the next steps.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==8. Register your Node Provider principal to the network==&lt;br /&gt;
In the next codeblock: &lt;br /&gt;
*Replace the &amp;lt;code&amp;gt;NODE_PROVIDER_NAME&amp;lt;/code&amp;gt; value with the name of the entity that will provide the nodes.&lt;br /&gt;
*Replace the &amp;lt;code&amp;gt;NODE_PROVIDER_PRINCIPAL&amp;lt;/code&amp;gt; value with the Ledger Hardware Wallet principal that you got from the NNS Frontend Dapp (step 4.4)&lt;br /&gt;
*Replace the &amp;lt;code&amp;gt;NEURON_ID&amp;lt;/code&amp;gt; value with your neuron ID from the NNS Frontend Dapp (step 3.6)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;IMPORTANT:&#039;&#039;&#039;&#039;&#039; Please make sure that you also update the &amp;lt;code&amp;gt;--summary&amp;lt;/code&amp;gt; and include a link to the forum discussion, your company&#039;s web page, and/or to another place that can convince the voting community that you are making a legitimate request. You must also include the file hash for the [[Node Provider Self-declaration|self declaration and proof of identity documents]], or the proposal will be rejected. This way you will avoid the community voting NO to your proposal and you losing your staked ICPs.&lt;br /&gt;
&lt;br /&gt;
##Create the Proposal &amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ NODE_PROVIDER_NAME=&amp;quot;My Company&amp;quot;&lt;br /&gt;
$ NODE_PROVIDER_PRINCIPAL=xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxx&lt;br /&gt;
$ NEURON_ID=XXXXXXXXXXXXXXXXXXXX&lt;br /&gt;
$ ./ic-admin \&lt;br /&gt;
        --nns-url https://ic0.app \&lt;br /&gt;
        -s ~/.config/dfx/identity/node-provider-hotkey/identity.pem \&lt;br /&gt;
    propose-to-add-or-remove-node-provider add \&lt;br /&gt;
        --proposer $NEURON_ID \&lt;br /&gt;
        --proposal-title &amp;quot;Register a node provider &#039;${NODE_PROVIDER_NAME}&#039;&amp;quot; \&lt;br /&gt;
        --summary &amp;quot;Register a node provider &#039;${NODE_PROVIDER_NAME}&#039;, in line with the announcement and discussion at &amp;lt;https://forum.dfinity.org/t/...&amp;gt;. The self-declaration documentation is available at &amp;lt;https://wiki.internetcomputer.org/wiki/...&amp;gt; with SHA256 hash &amp;lt;SHA256&amp;gt;. The proof of identity is available at &amp;lt;https://wiki.internetcomputer.org/wiki/...&amp;gt; with SHA256 hash &amp;lt;SHA256&amp;gt;.&amp;quot; \&lt;br /&gt;
        --node-provider-pid &amp;quot;$NODE_PROVIDER_PRINCIPAL&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Note: make sure &amp;lt;code&amp;gt;${NODE_PROVIDER_NAME}&amp;lt;/code&amp;gt; is presented in single quotes, so the IC dashboard can pick up and display the correct Node Provider name.&lt;br /&gt;
#Find the proposal on https://dashboard.internetcomputer.org/governance and &#039;&#039;&#039;wait until it is executed before proceeding to next step.&#039;&#039;&#039;&lt;br /&gt;
#In order to expedite the speed of your proposal&#039;s approval, it is best to create a post in this [https://forum.dfinity.org/t/new-node-provider-proposals/16643/69 forum thread] to raise awareness of your proposal. You can use this as a [https://docs.google.com/document/d/1nKy5hKiF72a4NCHvpgij-Np9pbtR5KOBbF1W6qr-nds/edit?usp=sharing template] for the post.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;See guide for [[Troubleshooting Failed NNS proposals]]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==9. Register your datacenter to the network (if necessary)==&lt;br /&gt;
#Search for your data center on https://dashboard.internetcomputer.org/centers. &lt;br /&gt;
#*If you found the datacenter that is hosting your nodes, remember its ID, and skip the following section. Otherwise, proceed with the registration of a new DC record.&lt;br /&gt;
#:[[File:dc_id.png|1041x1041px|alt=]]&lt;br /&gt;
===Create a data center record for a new DC===&lt;br /&gt;
In the next block of code:&lt;br /&gt;
*Replace the &amp;lt;code&amp;gt;NEURON_ID&amp;lt;/code&amp;gt; value with your neuron ID from the NNS Frontend Dapp (step 3.6)&lt;br /&gt;
*Replace the JSON fields from the &amp;lt;code&amp;gt;–data-centers-to-add&amp;lt;/code&amp;gt; argument and their corresponding values in &amp;lt;code&amp;gt;--summary&amp;lt;/code&amp;gt;:&lt;br /&gt;
**&amp;lt;code&amp;gt;&amp;amp;quot;id&amp;amp;quot;&amp;lt;/code&amp;gt; represents the city that your datacenter is in and is formulated as a combination of two letters representing the city and an incrementing number. Search data center IDs on https://dashboard.internetcomputer.org, and find a combination of two letters and a number that’s not yet registered. Examples:&lt;br /&gt;
***dl1 (Dallas, no IDs with “dl” prefix)&lt;br /&gt;
***zh10 (Zurich, numbers 0-9 are already registered)&lt;br /&gt;
**:[[File:dc_id.png|1024px]]&lt;br /&gt;
**&amp;lt;code&amp;gt;&amp;amp;quot;region&amp;amp;quot;&amp;lt;/code&amp;gt; represents the local region of a datacenter and is formulated as a three-part string divided by commas. The three parts making the string are continent, country code, and region, in the given order. Examples:&lt;br /&gt;
***North America,US,Florida&lt;br /&gt;
***Europe,DE,Bavaria&lt;br /&gt;
***Asia,SG,Singapore&lt;br /&gt;
**:[[File:datacenter_region.png|1024px]]&lt;br /&gt;
**&amp;lt;code&amp;gt;&amp;amp;quot;owner&amp;amp;quot;&amp;lt;/code&amp;gt; The entity that provides your datacenter facilities. &lt;br /&gt;
***Search https://dashboard.internetcomputer.org for existing data center providers.&lt;br /&gt;
*** If there’s match, make sure you use the same exact some name for your datacenter.&lt;br /&gt;
***Otherwise, name the data center owner to your best knowledge.&lt;br /&gt;
**:[[File:datacenter_owner.png|1024px]]&lt;br /&gt;
**&amp;lt;code&amp;gt;&amp;amp;quot;gps&amp;amp;quot;&amp;lt;/code&amp;gt; GPS coordinates. &lt;br /&gt;
***Find your datacenter on https://www.google.com/maps/.&lt;br /&gt;
***Right click on location, and select the GPS coordinates (first item in the menu) in order to copy them.&lt;br /&gt;
**:[[File:maps.png|310x310px|alt=Getting GPS coordinates|Getting GPS coordinates]]&lt;br /&gt;
&lt;br /&gt;
#Create the proposal: &amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ NEURON_ID=XXXXXXXXXXXXXXXXXXXX&lt;br /&gt;
$ ./ic-admin \&lt;br /&gt;
        --nns-url https://ic0.app \&lt;br /&gt;
        -s ~/.config/dfx/identity/node-provider-hotkey/identity.pem \&lt;br /&gt;
    propose-to-add-or-remove-data-centers \&lt;br /&gt;
        --summary &amp;quot;Register a Flexential datacenter as dl1 in North America,US,Texas&amp;quot; \&lt;br /&gt;
        --skip-confirmation \&lt;br /&gt;
        --proposer $NEURON_ID \&lt;br /&gt;
        --data-centers-to-add &#039;{&lt;br /&gt;
            &amp;quot;id&amp;quot;: &amp;quot;dl1&amp;quot;,&lt;br /&gt;
            &amp;quot;region&amp;quot;: &amp;quot;North America,US,Texas&amp;quot;,&lt;br /&gt;
            &amp;quot;owner&amp;quot;: &amp;quot;Flexential&amp;quot;,&lt;br /&gt;
            &amp;quot;gps&amp;quot;: [&lt;br /&gt;
                33.00803, -96.66614&lt;br /&gt;
            ]&lt;br /&gt;
        }&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;Remember to replace all the values of both the arguments &amp;lt;code&amp;gt;–data-centers-to-add&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;--summary&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
#Find the proposal on https://dashboard.internetcomputer.org/governance and wait until it&#039;s executed before proceeding to next step.&lt;br /&gt;
#In order to expedite the speed of your proposal&#039;s approval, it is best to create a post in this [https://forum.dfinity.org/t/new-node-provider-proposals/16643/69 forum thread] to raise awareness of your proposal. You can use this as a [https://docs.google.com/document/d/1Hg0tI9O5__Tp4qKrNKuTADsQT7Z47I6aAFXbiDimG_U/edit?usp=sharing template] for the post.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;See guide for [[Troubleshooting Failed NNS proposals]]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==10. Create a node operator record==&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;IMPORTANT&#039;&#039;&#039;:&#039;&#039; Before submitting the Node Operator record, please go through the description of [[Validation of Candidate Node Machines]] to validate whether additional node machines are needed for decentralization of the IC-network. &lt;br /&gt;
&lt;br /&gt;
* Create a pdf with the outcome of running the optimization model and the steps that allow the community to reproduce the validation check. &lt;br /&gt;
* Include the pdf in the wiki page that includes the NP documents (self-declaration and proof-of-identity document)&lt;br /&gt;
* Include a link to the pdf as well as the hash of the document in the Node Operator record proosal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the next codeblock:&lt;br /&gt;
*Replace the &amp;lt;code&amp;gt;NEURON_ID&amp;lt;/code&amp;gt; value with your neuron ID from the NNS Frontend Dapp (step 3.6).&lt;br /&gt;
*Replace the &amp;lt;code&amp;gt;NODE_PROVIDER_PRINCIPAL&amp;lt;/code&amp;gt; value with the Ledger Hardware Wallet principal that you got from the NNS Frontend Dapp (step 4.4).&lt;br /&gt;
*Replace the &amp;lt;code&amp;gt;NODE_OPERATOR_PRINCIPAL&amp;lt;/code&amp;gt; value with your node operator principal (step 7.1). &#039;&#039;&#039;Important&#039;&#039;&#039;: if you are adding an additional node operator record because you will deploy nodes in another data center, please make sure to create a new node operator principal first (steps 6 and 7). A node operator principal can only be tied to 1 data center.&lt;br /&gt;
*Replace the &amp;lt;code&amp;gt;NODE_PROVIDER_NAME&amp;lt;/code&amp;gt; value with the name of the entity that will provide the nodes.&lt;br /&gt;
*Replace the &amp;lt;code&amp;gt;NODE_ALLOWANCE&amp;lt;/code&amp;gt; variable value with number of nodes you are providing.&lt;br /&gt;
* Replace the &amp;lt;code&amp;gt;DC_ID&amp;lt;/code&amp;gt; variable value with id of your datacenter.&lt;br /&gt;
&lt;br /&gt;
# Create the proposal: &amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
$ NEURON_ID=XXXXXXXXXXXXXXXXXXXX&lt;br /&gt;
$ NODE_PROVIDER_PRINCIPAL=xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxx&lt;br /&gt;
$ NODE_OPERATOR_PRINCIPAL=xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxx&lt;br /&gt;
$ NODE_PROVIDER_NAME=&amp;quot;My Company&amp;quot;&lt;br /&gt;
$ NODE_ALLOWANCE=8&lt;br /&gt;
$ DC_ID=dl1&lt;br /&gt;
&lt;br /&gt;
$ ./ic-admin \&lt;br /&gt;
        --nns-url https://ic0.app \&lt;br /&gt;
        -s ~/.config/dfx/identity/node-provider-hotkey/identity.pem \&lt;br /&gt;
    propose-to-add-node-operator \&lt;br /&gt;
        $NODE_PROVIDER_PRINCIPAL \&lt;br /&gt;
        --summary &amp;quot;Node provider &#039;$NODE_PROVIDER_NAME&#039; is adding $NODE_ALLOWANCE nodes in the $DC_ID data center. The result of the canidate node machine validation and exact configuration run is available at &amp;lt;https://wiki.internetcomputer.org/wiki/...&amp;gt; with SHA256 hash &amp;lt;SHA256&amp;gt;.&amp;quot; \&lt;br /&gt;
        --proposer $NEURON_ID \&lt;br /&gt;
        --node-operator-principal-id $NODE_OPERATOR_PRINCIPAL \&lt;br /&gt;
        --node-allowance $NODE_ALLOWANCE \&lt;br /&gt;
        --dc-id $DC_ID&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
#Find the proposal on https://dashboard.internetcomputer.org/governance and wait until it&#039;s executed before proceeding to next step.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;See guide for [[Troubleshooting Failed NNS proposals]]&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Jamongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Node_Provider_Documentation&amp;diff=7862</id>
		<title>Node Provider Documentation</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Node_Provider_Documentation&amp;diff=7862"/>
		<updated>2024-07-12T13:51:21Z</updated>

		<summary type="html">&lt;p&gt;Jamongeon: Revise node provider homepage&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
The Internet Computer is a decentralized network of nodes running an instance of the network&#039;s protocol software. These nodes are owned by Node Providers who invest in and operate the node hardware that powers the network. Running these nodes in data centers provides the high performance and cost-effectiveness of the Internet Computer.&lt;br /&gt;
&lt;br /&gt;
Each Node Provider receives rewards for their nodes&#039; [[Proof of Useful Work|useful work]]. Individuals or organizations can become Node Providers by submitting a proposal to the Network Nervous System (NNS), the Decentralized Autonomous Organization (DAO) that governs the Internet Computer. The ICP community then votes on whether or not to include the Node Provider.&lt;br /&gt;
&lt;br /&gt;
The more diverse the set of Node Providers who supply node machines, the more resilient the Internet Computer is. You can support the Internet Computer and the ICP community by becoming a Node Provider and increasing its decentralization.&lt;br /&gt;
&lt;br /&gt;
== ⚠️ No new node machines being onboarded: Target topology reached  ==&lt;br /&gt;
Last year, the community voted on an ICP target topology with a maximum number of node machines, as well as on an optimization model to validate candidate node machines against this ICP target topology. The ICP target topology has been reached as of December 2023; see more information in this [https://forum.dfinity.org/t/new-node-provider-proposals/16643/322?u=svenf forum post]. &lt;br /&gt;
&lt;br /&gt;
This means that the &#039;&#039;&#039;ICP network currently does not require any additional node machines&#039;&#039;&#039; in order to reach its decentralization targets. Therefore, DFINITY will not vote to adopt any proposals for new node machines being added to the IC network. Once the subnets are reaching capacity and more subnets are required to run all applications, the community may decide to increase the target topology again and allow additional node machines to join the network.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
To become a Node Provider, follow the [[Node Provider Roadmap]], which explain the costs, rewards, responsibilities, and steps required to become a Node Provider.&lt;br /&gt;
&lt;br /&gt;
== Resources ==&lt;br /&gt;
*Node deployment guides:&lt;br /&gt;
**[[Node Deployment Guide (with an HSM)|Legacy (Gen-1) Node Deployment Guide (with an HSM)]]&lt;br /&gt;
**[[Node Deployment Guide|Current (Gen-2) Node Deployment Guide (without an HSM)]]&lt;br /&gt;
*Node Provider onboarding&lt;br /&gt;
**[[Node Provider Onboarding]]&lt;br /&gt;
**[[Node Provider Self-declaration]]&lt;br /&gt;
**[[Validation of Candidate Node Machines]]&lt;br /&gt;
**[[Node Provider Reward Configuration Guide]]&lt;br /&gt;
**[[Troubleshooting Failed NNS proposals]]&lt;br /&gt;
*Troubleshooting and maintenance:&lt;br /&gt;
**[[Node Provider Maintenance Guide]]&lt;br /&gt;
**[[Node Provider Troubleshooting|Node Provider Troubleshooting Guide]]&lt;br /&gt;
**[[Node Provider Matrix channel]]&lt;br /&gt;
*Guides and resources&lt;br /&gt;
**[[Node Provider Machine Hardware Guide]]&lt;br /&gt;
**[[Node Provider Networking Guide]]&lt;br /&gt;
**[[Node Provider Alerting Options]]&lt;br /&gt;
**[[Node Provider Data Center and ISP Guide]]&lt;br /&gt;
**[[Node Provider Decentralization and Security Guide]]&lt;br /&gt;
**[[Node Provider Legal Guide]]&lt;br /&gt;
**[[Node Provider Remuneration]]&lt;br /&gt;
**[[Node Provider Domain Name Guide]]&lt;br /&gt;
**[[BMC Password Reset Guide]]&lt;br /&gt;
**[[Gen1 Node Provider onboarding Gen2 node machines]]&lt;br /&gt;
**[[RMU build Gen-1.5|Guide for Gen-1 to Gen-1.5 RMU build]]&lt;br /&gt;
*Other resources:&lt;br /&gt;
**[[Node Provider FAQ]]&lt;/div&gt;</summary>
		<author><name>Jamongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Chain-key_Bitcoin&amp;diff=6005</id>
		<title>Chain-key Bitcoin</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Chain-key_Bitcoin&amp;diff=6005"/>
		<updated>2023-07-19T14:52:10Z</updated>

		<summary type="html">&lt;p&gt;Jamongeon: Removing `track_balance` API endpoint and all mentions of it; fixing bitcoin capitalization&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Chain-key Bitcoin (ckBTC) is a token on the Internet Computer that is backed 1:1 by bitcoin (BTC) such that 1 ckBTC can always be redeemed for 1 BTC and vice versa.&lt;br /&gt;
&lt;br /&gt;
Unlike other tokens pegged to bitcoin, the ckBTC token does not rely on a third-party bridge for the conversion between BTC and ckBTC, making it a substantially more secure alternative to “wrapped” tokens.&lt;br /&gt;
&lt;br /&gt;
While chain-key bitcoin and regular bitcoin have the same value, the advantage of chain-key bitcoin is fast and cheap transfers: A transfer is finalized within a few seconds (a speed-up of roughly three orders of magnitude compared to transfers on the Bitcoin blockchain) and only costs 0.0000001 ckBTC (approximately two orders of magnitude lower than the Bitcoin miner fees). &lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
The ckBTC functionality is built upon the [[Bitcoin integration]] of the Internet Computer, which makes it possible for canisters to receive, hold, and send bitcoin.&lt;br /&gt;
&lt;br /&gt;
There are two canisters, the ckBTC minter and ckBTC ledger, that together provide the ckBTC functionality. The ckBTC minter mints new ckBTC tokens whenever it receives bitcoin. Likewise, it burns ckBTC tokens whenever an owner of ckBTC tokens requests a withdrawal of bitcoin. The ckBTC minter needs to receive BTC, based on a large number of confirmations due to the lack of finality in Bitcoin, before it mints the same amount in ckBTC and it burns ckBTC before it transfers BTC back to the users.&lt;br /&gt;
&lt;br /&gt;
A best-effort approach is used for the transfer of BTC to the users, i.e., the user cannot get the burned ckBTC back. Rather, the ckBTC minter repeatedly attempts to transfer BTC out. Note that “user” refers to the caller of the functions exposed by the ckBTC minter and ckBTC ledger in the following. A human user or another canister may be behind the function invocations.&lt;br /&gt;
&lt;br /&gt;
The ckBTC ledger is [https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/README.md ICRC-1 compliant], updating the balance accounts when ckBTC tokens are transferred and executing the mint and burn operations coming from the ckBTC minter. &lt;br /&gt;
&lt;br /&gt;
An overview of the basic architecture is depicted in the following figure.&lt;br /&gt;
[[File:CkBTC Specification - Overview (Version 2).png|alt=|center|thumb|600x600px|High-level overview of chain-key Bitcoin.]]&lt;br /&gt;
The figure shows the main flow at a high level of abstraction: Users interact with the ckBTC minter and the ckBTC ledger to convert ckBTC/BTC and transfer ckBTC, respectively. The ckBTC minter interacts with the Bitcoin canister to retrieve information about the Bitcoin network state and send Bitcoin transactions.&lt;br /&gt;
&lt;br /&gt;
The ckBTC minter further interacts with the [[Know-Your-Transaction (KYT) Canister|KYT canister]] for &amp;quot;know-your-transaction&amp;quot; (KYT) checks. These checks are meant to ensure that the ckBTC minter only uses &amp;quot;clean&amp;quot; bitcoins to back the issued ckBTC tokens and to prevent transferring bitcoins to Bitcoin addresses that are considered to be associated with illicit activity. As such, these KYT checks provide an additional layer of security to ckBTC users.&lt;br /&gt;
&lt;br /&gt;
== Technical Details ==&lt;br /&gt;
&lt;br /&gt;
=== Bitcoin Addresses ===&lt;br /&gt;
Within this page, Bitcoin addresses are implicitly understood to be of type P2WPKH (“pay to witness public key hash”) as defined in [https://en.bitcoin.it/wiki/BIP_0141 BIP-141]. All addresses are rendered in the Bech32 format as defined in [https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki BIP-173]. The main advantage of P2WPKH over the legacy P2PKH address type is that its use results in lower transaction fees.&lt;br /&gt;
&lt;br /&gt;
For this reason, it is the default address type in most wallets for standard transactions.&lt;br /&gt;
&lt;br /&gt;
=== ckBTC Ledger ===&lt;br /&gt;
The ckBTC ledger is a [https://dashboard.internetcomputer.org/canister/mxzaz-hqaaa-aaaar-qaada-cai canister], controlled by the NNS (specifically, the [https://dashboard.internetcomputer.org/canister/r7inp-6aaaa-aaaaa-aaabq-cai NNS root canister]), running on the [https://dashboard.internetcomputer.org/subnet/pzp6e-ekpqk-3c5x7-2h6so-njoeq-mt45d-h3h6c-q3mxf-vpeq5-fk5o7-yae pzp6e] subnet. Since it is ICRC-1 compliant, it offers [https://github.com/dfinity/ICRC-1/blob/aa82e52aaa74cc7c5f6a141e30b708bf42ede1e3/standards/ICRC-1/README.md#methods all functions] defined in the ICRC-1 standard. In particular, it provides the functionality to transfer ckBTC between accounts. &lt;br /&gt;
&lt;br /&gt;
The ckBTC ledger is responsible for keeping account balances and for transferring ckBTC between accounts. It provides the following functionality:&lt;br /&gt;
&lt;br /&gt;
* It enables the ckBTC minter to mint and burn ckBTC.&lt;br /&gt;
* It enables the transfer of ckBTC among users.&lt;br /&gt;
&lt;br /&gt;
As mentioned above, the transfer fee is 0.0000001 ckBTC, the equivalent of 10 Satoshi. Since the fee in ckBTC is burned, every transaction leads to a growing surplus in BTC controlled by the ckBTC minter. The surplus will eventually be used to cover the cycle cost of the ckBTC minter. &lt;br /&gt;
&lt;br /&gt;
The minting account is the ckBTC minter’s default account; that is, the account derived from the ckBTC minter’s principal ID and the all-zero subaccount.&lt;br /&gt;
&lt;br /&gt;
The initial supply of the ckBTC ledger is 0. ckBTC tokens are minted only when the ckBTC minter receives bitcoin, ensuring that the ckBTC supply managed by the ckBTC ledger is upper bounded by the amount of bitcoin held by the ckBTC minter.&lt;br /&gt;
&lt;br /&gt;
=== ckBTC Minter ===&lt;br /&gt;
&lt;br /&gt;
The ckBTC minter is a [https://dashboard.internetcomputer.org/canister/mqygn-kiaaa-aaaar-qaadq-cai canister] that is controlled by the NNS and running on the [https://dashboard.internetcomputer.org/subnet/pzp6e-ekpqk-3c5x7-2h6so-njoeq-mt45d-h3h6c-q3mxf-vpeq5-fk5o7-yae pzp6e] subnet as well. &lt;br /&gt;
&lt;br /&gt;
The ckBTC minter is the canister responsible for managing deposited BTC and minting/burning ckBTC based on the amount of deposited BTC. It provides the following functionality:&lt;br /&gt;
&lt;br /&gt;
* For a certain principal ID and an optional subaccount, it returns a specific Bitcoin address under the ckBTC minter’s control.&lt;br /&gt;
* Users can inform the ckBTC minter about bitcoins that were sent to an address controlled by the ckBTC minter. If the balance has increased, the ckBTC minter mints the same amount in ckBTC for the user associated with the Bitcoin address.&lt;br /&gt;
* Users can ask the ckBTC minter to track the balance of a Bitcoin address until new funds are received, which then automatically triggers the minting of the equivalent amount of ckBTC.&lt;br /&gt;
* Users can request to get bitcoins back. The ckBTC minter burns the same amount of ckBTC and transfers the bitcoins to the address provided by the user.&lt;br /&gt;
&lt;br /&gt;
The ckBTC minter canister has a few important configuration parameters including:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;retrieve_btc_min_amount&amp;lt;/code&amp;gt;: This is the minimum ckBTC amount that can be burned and, correspondingly, the minimum BTC amount that can be withdrawn. The parameter is set to 0.001 BTC, or 100,000 satoshi.&lt;br /&gt;
* &amp;lt;code&amp;gt;max_time_in_queue_nanos&amp;lt;/code&amp;gt;: Any BTC retrieval request should be kept in a queue for at most this time. Caching requests rather than handling them right away has the advantage that multiple requests can be served in a single transaction, saving Bitcoin miner fees. The parameter is set to 10 minutes, which corresponds to the expected time between Bitcoin blocks.&lt;br /&gt;
* &amp;lt;code&amp;gt;min_confirmations&amp;lt;/code&amp;gt;:  The number of confirmations required for the ckBTC minter to accept a Bitcoin transaction. In particular, the ckBTC minter does not mint ckBTC before a transaction transferring BTC to a Bitcoin address managed by the ckBTC minter reaches this number of transactions. The parameter was initially set to 72 but has been reduced to 12 in the meantime.&lt;br /&gt;
* &amp;lt;code&amp;gt;kyt_fee&amp;lt;/code&amp;gt;: The fee that must be paid for KYT checks. It is currently set to 2000 satoshi.&lt;br /&gt;
The other parameters are self-explanatory and can be found in the [https://github.com/dfinity/ic/blob/master/rs/bitcoin/ckbtc/minter/ckbtc_minter.did ckBTC minter Candid file].&lt;br /&gt;
&lt;br /&gt;
=== State Management ===&lt;br /&gt;
&lt;br /&gt;
==== Managed Addresses ====&lt;br /&gt;
A Bitcoin address that is controlled by the ckBTC minter and has a positive balance is called a managed address. If the balance of a managed address reduces to zero, the address is no longer managed and can be removed from the state.&lt;br /&gt;
&lt;br /&gt;
Note that it is possible to increase the balance again, in which case the address becomes managed again.&lt;br /&gt;
&lt;br /&gt;
==== Unspent Transaction Outputs ====&lt;br /&gt;
Once a new Unspent Transaction Output (UTXO) under the control of the ckBTC minter is discovered (using the &amp;lt;code&amp;gt;update_balance&amp;lt;/code&amp;gt; function), it is stored internally in a set called &amp;lt;code&amp;gt;available_utxos&amp;lt;/code&amp;gt; (defined [https://github.com/dfinity/ic/blob/2348b094d3d27616ee3f049d3048baa1da8d625a/rs/bitcoin/ckbtc/minter/src/state.rs#L305C14-L305C14 here] in the source code).&lt;br /&gt;
&lt;br /&gt;
All discovered UTXOs remain in this set until a Bitcoin transaction is created to spend one or more of them when retrieving bitcoins. When a transaction is created spending some UTXOs, these UTXOs are removed from the set &amp;lt;code&amp;gt;available_utxos&amp;lt;/code&amp;gt; and inserted in the &amp;lt;code&amp;gt;used_utxos&amp;lt;/code&amp;gt; field of the &amp;lt;code&amp;gt;SubmittedBtcTransaction&amp;lt;/code&amp;gt; struct (defined [https://github.com/dfinity/ic/blob/70d19f16c17f8f42987a46d473ba27705927cdb7/rs/bitcoin/ckbtc/minter/src/state.rs#L87 here] in the source code), which is the internal representation of a Bitcoin transaction.&lt;br /&gt;
&lt;br /&gt;
A UTXO is removed from the ckBTC state when the &amp;lt;code&amp;gt;SubmittedBtcTransaction&amp;lt;/code&amp;gt; struct that contains the UTXO is removed from the state. &lt;br /&gt;
&lt;br /&gt;
==== Transactions ====&lt;br /&gt;
To provide information about current transactions, outgoing transactions must be cached. A transaction is cached until its inputs are no longer considered unspent based on a large number of confirmations.&lt;br /&gt;
&lt;br /&gt;
Every transaction that the ckBTC minter creates has an output that sends the ckBTC minter fee plus the transaction change back to its main BTC address (P2WPKH address derived from its public key with an empty derivation path) using the Bitcoin integration’s &amp;lt;code&amp;gt;get_utxos&amp;lt;/code&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
A transaction can be removed from the cache if the transaction output that belongs to the ckBTC minter appears in the returned list when calling &amp;lt;code&amp;gt;get_utxos&amp;lt;/code&amp;gt; with sufficient confirmations for the ckBTC minter’s main BTC address.&lt;br /&gt;
&lt;br /&gt;
The ckBTC minter may resubmit transactions, making use of Bitcoin’s request by fee (RBF) mechanism as defined in [https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki BIP-125]. In the case of ckBTC, a resubmission adds a transaction to the cache that spends exactly the same UTXOs as the transaction it replaces. The only difference is that the BTC amount sent to the user is reduced in order to increase the fee.&lt;br /&gt;
&lt;br /&gt;
BIP-125 states that at most 100 transactions may be evicted from the mempool, i.e., the fee cannot be increased more than 100 times. Moreover, the fee must be increased at least by the minimum relay fee (see minrelaytxfee [https://en.bitcoin.it/wiki/Miner_fees#Relaying here]) of 1 Satoshi/vbyte.&lt;br /&gt;
&lt;br /&gt;
For example, if we assume a minimum increase of 200 Satoshi (the minimum fee for a basic &amp;lt;code&amp;gt;segwit&amp;lt;/code&amp;gt; transaction with one input and one output is 192 Satoshi and the number per output is always lower than 200 if there are at least as many outputs as inputs), the minimum transfer amount should be at least 20,000 Satoshi which equals 0.0002 BTC. When adding a base fee at a large fee rate of 100 Satoshi/vbyte and assuming a virtual transaction size of 200 vbyte per output, we get a minimum transfer amount of 0.0004 BTC. Adding a security margin, we define the minimum retrieval amount to be &amp;lt;code&amp;gt;MIN_RETRIEVAL_AMOUNT = 0.001 BTC&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;To ensure that every transaction can potentially be updated, the RBF flag must be set on every transaction.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Know Your Transaction &amp;amp; Fees====&lt;br /&gt;
Before UTXOs are accepted, they undergo a know-your-transaction (KYT) check where information about the UTXO is sent to a “KYT canister”, which interacts with KYT service providers, such as Chainalysis, to check if the UTXO is “clean” using HTTPS outcalls.&lt;br /&gt;
&lt;br /&gt;
In a similar fashion, there is a KYT check of the destination address when attempting to transfer bitcoins out of the ckBTC minter.&lt;br /&gt;
&lt;br /&gt;
Both of these KYT checks incur fees, charged in ckBTC:&lt;br /&gt;
&lt;br /&gt;
*The KYT fee is subtracted from the amount to be minted and the amount transferred out.&lt;br /&gt;
*The KYT fee is 2000 satoshi per KYT check.&lt;br /&gt;
&lt;br /&gt;
The KYT canister supports multiple KYT access key providers, called maintainers, each having a principal ID and (secret) access key to the external KYT service. Since the maintainers pay for their subscriptions, they must be remunerated. To this end, the ckBTC minter maintains a mapping of maintainers to the owed amount, which is the number of KYT checks that were performed with the respective maintainer’s credentials times the KYT fee of 2000 Satoshi.&lt;br /&gt;
&lt;br /&gt;
Each successful response from the KYT canister contains the principal ID of the maintainer so that the ckBTC minter can update the owed amount correctly. Once every 24 hours, the ckBTC minter pays out the owed amounts in ckBTC to all maintainers.&lt;br /&gt;
&lt;br /&gt;
==Converting BTC to ckBTC==&lt;br /&gt;
&lt;br /&gt;
In this section, the process to convert BTC to ckBTC is explained, making use of the ckBTC minter and ckBTC ledger endpoints.&lt;br /&gt;
&lt;br /&gt;
The first step is for the user to determine the Bitcoin address where the user is supposed to transfer bitcoin for the minting process by calling the &amp;lt;code&amp;gt;get_btc_address&amp;lt;/code&amp;gt; endpoint. Next, the user transfers the desired BTC amount to this Bitcoin address. &lt;br /&gt;
&lt;br /&gt;
Internally, the tracking works as follows. Since the expected time between Bitcoin blocks is 10 minutes, the ckBTC minter first checks if new unspent transaction outputs (UTXOs) are available for that address with at least the required number of confirmations after &amp;lt;code&amp;gt;10*min_confirmations&amp;lt;/code&amp;gt; minutes. If there is at least one new UTXO, tracking stops and the ckBTC minter instructs the ckBTC ledger to mint the same amount of ckBTC tokens into the account derived from the principal ID and the subaccount.&lt;br /&gt;
&lt;br /&gt;
If no new UTXOs are discovered with sufficiently many confirmations, the ckBTC ledger checks if there are new UTXOs with at least one confirmation. If this is not the case, tracking stops as well. Otherwise, the expected time until the first new UTXO reaches the desired number of confirmations is computed, which is 10 minutes times the difference between the desired number of confirmations and the current number of confirmations. The same process then repeats until ckBTC tokens are minted or tracking stops.&lt;br /&gt;
&lt;br /&gt;
It is evident from this description that it’s possible that tracking may stop before ckBTC tokens are minted, for example, if it takes an unusually long time until the transaction appears in a block. In this case, the endpoint can be invoked again. Alternatively, the user can wait until the transaction has the required number of confirmations and call the &amp;lt;code&amp;gt;update_balance&amp;lt;/code&amp;gt; endpoint.&lt;br /&gt;
&lt;br /&gt;
===Technical Details===&lt;br /&gt;
As mentioned above, a call to the &amp;lt;code&amp;gt;update_balance&amp;lt;/code&amp;gt; endpoint triggers a call to the Bitcoin canister to get UTXOs for the Bitcoin address associated with the given &amp;lt;code&amp;gt;principal-subaccount&amp;lt;/code&amp;gt; pair. Let &#039;&#039;&#039;&#039;&#039;R&#039;&#039;&#039;&#039;&#039; denote the set of returned UTXOs. The following pseudo-code illustrates how the UTXOs are processed:&amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
for utxo in new_utxos(R):        // R = set of received UTXOs in the get_utxos call&lt;br /&gt;
    if utxo.value &amp;gt;= KYT_FEE:&lt;br /&gt;
        if utxo in checked_utxos: &lt;br /&gt;
            (uuid, state) = checked_utxos.get(utxo)&lt;br /&gt;
        else:&lt;br /&gt;
            (uuid, state, kyt_provider) = kyt_canister.check(utxo).await?&lt;br /&gt;
            if state == clean:&lt;br /&gt;
                D = D \ {utxo}&lt;br /&gt;
                P = P ∪ {utxo}&lt;br /&gt;
                checked_utxos.set(utxo, (uuid, clean))&lt;br /&gt;
                owed_kyt_fee[kyt_provider] += KYT_FEE&lt;br /&gt;
        if state == clean:&lt;br /&gt;
            ckbtc_ledger.mint(utxo.value-KYT_FEE, recipient_account, uuid).await? &lt;br /&gt;
            checked_utxos.remove(utxo) &lt;br /&gt;
        else:&lt;br /&gt;
            add_to_quarantine_list(utxo)&lt;br /&gt;
    else:&lt;br /&gt;
        add_to_ignore_list(utxo)&lt;br /&gt;
return response with UTXO statuses&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;A UTXO is considered if its value is at least the KYT fee, which is a configuration parameter of the ckBTC minter. UTXOs whose value lie below the KYT fee are added to an ignore list. The additional state &amp;lt;code&amp;gt;checked_utxos&amp;lt;/code&amp;gt; is maintained to remember that a UTXO was checked if the state is clean. Once the corresponding amount of ckBTC has been minted, this state can be removed again. If the UTXO is tainted, it is moved to a quarantine list instead. UTXOs in the ignore list and quarantine list remain there.&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;new_utxos&amp;lt;/code&amp;gt; filters out all UTXOs on the ignore list, the quarantine list, and the sets &#039;&#039;&#039;&#039;&#039;P&#039;&#039;&#039;&#039;&#039; and &#039;&#039;&#039;&#039;&#039;S&#039;&#039;&#039;&#039;&#039;. On the other hand, the &amp;lt;code&amp;gt;checked_utxos&amp;lt;/code&amp;gt; data structure is not considered.&lt;br /&gt;
&lt;br /&gt;
==Converting ckBTC to BTC==&lt;br /&gt;
&lt;br /&gt;
The process to convert ckBTC to BTC consists of the following steps: &lt;br /&gt;
&lt;br /&gt;
#Transfer request: The user moves the ckBTC that he/she wants to convert to BTC to a special ckBTC withdrawal account under the control of the ckBTC minter and requests a transfer. The destination Bitcoin address undergoes a KYT check. If the check is successful, the request is accepted and put into a queue.&lt;br /&gt;
#Submission: On a heartbeat, the ckBTC minter attempts to submit transactions for validated transfer requests.&lt;br /&gt;
#Finalization: On a heartbeat, the ckBTC minter checks which transactions went through and finalizes these transactions.&lt;br /&gt;
#Resubmission: The ckBTC minter can resubmit a transaction that has been pending at least for a specific amount of time with a higher fee.&lt;br /&gt;
&lt;br /&gt;
The individual parts are discussed in greater detail in the following sections.&lt;br /&gt;
&lt;br /&gt;
The first step to convert ckBTC to BTC is to transfer the amount to be retrieved to the owner-specific withdrawal account under the ckBTC minter’s control. This step is required because only the ckBTC minter can burn tokens and it can only burn those tokens in one of its accounts. The withdrawal account can be obtained by calling the &amp;lt;code&amp;gt;get_withdrawal_account&amp;lt;/code&amp;gt; endpoint.&lt;br /&gt;
&lt;br /&gt;
After the user has transferred the desired ckBTC amount to the withdrawal account, the user can call the &amp;lt;code&amp;gt;retrieve_btc&amp;lt;/code&amp;gt; endpoint to inform the ckBTC minter about the withdrawal intent. In addition to specifying the withdrawal amount, the Bitcoin address where the withdrawn funds are to be sent must be specified as well.&lt;br /&gt;
&lt;br /&gt;
The ckBTC minter first performs a KYT check against the targeted Bitcoin address. If the check is successful, the ckBTC minter instructs the ckBTC ledger to burn the ckBTC in the withdrawal account. Lastly, the ckBTC minter deducts the KYT fee from the amount to be retrieved and puts the corresponding retrieval request into a queue and checks the status of the queue on a heartbeat.&lt;br /&gt;
&lt;br /&gt;
If the oldest request has been in the queue for at least 10 minutes or at least 20 retrieval requests have been accumulated at the time of the heartbeat, the ckBTC minter creates a single Bitcoin transaction to serve up to 100 retrieval requests as follows:&lt;br /&gt;
&lt;br /&gt;
#It selects available UTXOs with a total sum of at least the sum in the retrieval requests.&lt;br /&gt;
#It constructs a Bitcoin transaction with the selected UTXOs as inputs and an output for each retrieval request plus an additional output for the ckBTC minter’s fee.&lt;br /&gt;
# It uses the Bitcoin canister’s fee API to determine an appropriate fee for the transaction, using the median fee rate.&lt;br /&gt;
#It distributes the fee evenly among all outputs other than the output for the ckBTC minter’s fee.&lt;br /&gt;
#For each input of the transaction, the ckBTC minter invokes the threshold ECDSA functionality (calling the &amp;lt;code&amp;gt;sign_with_ecdsa&amp;lt;/code&amp;gt; function) to obtain the required signatures and puts them into the transaction.&lt;br /&gt;
#Lastly, it sends the Bitcoin transaction by invoking the &amp;lt;code&amp;gt;send_transaction&amp;lt;/code&amp;gt; function of the Bitcoin integration API.&lt;br /&gt;
&lt;br /&gt;
The BTC retrieval process is depicted in the following figure.&lt;br /&gt;
[[File:CkBTC Specification - Withdrawal (simplified)- Version 2.png|alt=|center|thumb|600x600px|Process of converting ckBTC to BTC.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that the amounts in the transfer to the withdrawal account and the retrieval request need not be the same. The &amp;lt;code&amp;gt;retrieve_btc_status&amp;lt;/code&amp;gt; endpoint can be used to query the current status of a retrieval request.&lt;br /&gt;
&lt;br /&gt;
===Technical Details===&lt;br /&gt;
&lt;br /&gt;
====Transfer Request====&lt;br /&gt;
The ckBTC minter can only burn ckBTC under its control. Therefore, the first step is to transfer ckBTC to the ckBTC withdrawal account controlled by the ckBTC minter and associated with the owner of the ckBTC that are to be burned. Specifically, the withdrawal account is a ckBTC ledger account where the principal ID is the ckBTC minter and the subaccount is derived deterministically from the owner’s principal ID.&lt;br /&gt;
&lt;br /&gt;
After this transfer, the user sends a &amp;lt;code&amp;gt;retrieve_btc&amp;lt;/code&amp;gt; request, specifying the amount that they would like to retrieve, the Bitcoin address where the funds are to be transferred, and, optionally, a fee level (which have yet to be defined).&lt;br /&gt;
&lt;br /&gt;
Upon receiving such a request, the ckBTC minter first performs a KYT check against the Bitcoin address where funds are supposed to be sent. If the check is successful, the ckBTC minter issues a burn request to the ckBTC ledger, burning the amount in the received request in the user’s ckBTC withdrawal account. If the burn operation is successful, the ckBTC minter creates a transfer request, removing the &amp;lt;code&amp;gt;KYT_FEE&amp;lt;/code&amp;gt; from the transfer amount, and appends it to its pending-requests queue.&lt;br /&gt;
&lt;br /&gt;
Alternatively, if the destination address does not pass the KYT check, a burn request is sent to the ckBTC ledger, burning the &amp;lt;code&amp;gt;KYT_FEE&amp;lt;/code&amp;gt; amount.&lt;br /&gt;
&lt;br /&gt;
Recall that the ckBTC ledger uses the ckBTC minter default account as the minting account. Withdrawal accounts should never resolve to the default minting account because the ckBTC ledger considers the minting account for minting only.&lt;br /&gt;
&lt;br /&gt;
The following pseudo-code illustrates how the &amp;lt;code&amp;gt;retrieve_btc&amp;lt;/code&amp;gt; endpoint works, given the parameters &amp;lt;code&amp;gt;amount&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;btc_address&amp;lt;/code&amp;gt;.&amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
assert(amount &amp;gt;= max(MIN_RETRIEVAL_AMOUNT, KYT_FEE))&lt;br /&gt;
    assert(ckbtc_ledger.balance_of(withdrawal_account).await? &amp;gt;= amount)&lt;br /&gt;
  (uuid, state, kyt_provider) = kyt_canister.check(btc_address).await? &lt;br /&gt;
&lt;br /&gt;
if state == clean:&lt;br /&gt;
    index = ckbtc_ledger.burn(amount, withdrawal_account).await?&lt;br /&gt;
    owed_kyt_fee[kyt_provider] += KYT_FEE&lt;br /&gt;
    create_request(amount-KYT_FEE, index, btc_address, uuid)&lt;br /&gt;
 else:&lt;br /&gt;
    index = ckbtc_ledger.burn(KYT_FEE, withdrawal_account).await? &lt;br /&gt;
    owed_kyt_fee[kyt_provider] += KYT_FEE&lt;br /&gt;
    return Error(&amp;quot;Failed KYT check&amp;quot;, index)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Note that a failure to perform the KYT check results in a rejected request. Further note that if the KYT check succeeds but the burn transaction fails (regardless of the state of the KYT response), no KYT fee is charged and the request is rejected. A subsequent request with the same parameters will result in another call to the KYT canister again, which is acceptable because multiple identical calls to the KYT service provider do not result in increased fees.&lt;br /&gt;
&lt;br /&gt;
For each retrieval request, the ckBTC minter stores the following data:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;block_index&amp;lt;/code&amp;gt;: The block index of the burn operation used to burn the ckBTC. Since the block index is unique, it is used as the request ID.&lt;br /&gt;
*&amp;lt;code&amp;gt;amount&amp;lt;/code&amp;gt;: The total amount of tokens to retrieve. This amount must be at least the minimum retrieval amount as defined above.&lt;br /&gt;
*&amp;lt;code&amp;gt;address&amp;lt;/code&amp;gt;: The address where the bitcoins will be sent.&lt;br /&gt;
*&amp;lt;code&amp;gt;received_at&amp;lt;/code&amp;gt;: The timestamp when the request was received.&lt;br /&gt;
*&amp;lt;code&amp;gt;fee_level&amp;lt;/code&amp;gt;: If no fee level is provided, a medium fee level is used.&lt;br /&gt;
&lt;br /&gt;
====Submission====&lt;br /&gt;
The ckBTC minter uses the heartbeat mechanism to initiate Bitcoin transfers. On a heartbeat, the following steps are carried out:&lt;br /&gt;
&lt;br /&gt;
#Check if there is at least one request that is 10 minutes old or there are at least 20 requests in the pending-requests queue. If not, stop.&lt;br /&gt;
#Update the balance of the ckBTC minter’s main BTC address (the P2WPKH address derived from its public key with an empty derivation path) using the Bitcoin integration’s &amp;lt;code&amp;gt;get_utxos&amp;lt;/code&amp;gt; function.&lt;br /&gt;
#Determine the total amount of bitcoins available, which is the sum of all bitcoins in processed UTXOs, plus bitcoins under the ckBTC minter’s main BTC address.&lt;br /&gt;
#Call the transfer function with the next batch of requests with the same fee level that can be served given the total amount of available bitcoins. A transaction is created, setting the transaction ID for each request in the batch, and sent to the Bitcoin network.&lt;br /&gt;
#Every request in this batch is then moved to the unconfirmed-transfers queue.&lt;br /&gt;
&lt;br /&gt;
As evident from the steps outlined above, the transfer function can handle multiple requests at the same time. Handling multiple requests in a single transaction has several advantages over sending individual transactions:&lt;br /&gt;
&lt;br /&gt;
#Requests can possibly be served more quickly, especially if the ckBTC minter must wait for change to return to its main BTC address.&lt;br /&gt;
#As the fee for the non-input bytes is shared, the fee per request is slightly lower.&lt;br /&gt;
#Serving multiple requests at the same time makes denial-of-service attacks where an attacker attempts to keep the pool of usable UTXOs empty with many small requests harder.&lt;br /&gt;
&lt;br /&gt;
Given this set of requests, the next step is to select UTXOs for the transaction.&lt;br /&gt;
&lt;br /&gt;
Since UTXOs are always spent entirely, the difference between the sum of bitcoins in the spent UTXOs and the requested amount must be transferred to a new UTXO as well. The ckBTC minter uses its main BTC address to accumulate “change”.&lt;br /&gt;
&lt;br /&gt;
All UTXOs of its main BTC address are immediately transferred to the corresponding set &#039;&#039;&#039;&#039;&#039;P&#039;&#039;&#039;&#039;&#039; of processed UTXOs. The reason is that there is no minting for the balances in these UTXOs.&lt;br /&gt;
&lt;br /&gt;
The transfer function performs the following steps:&lt;br /&gt;
&lt;br /&gt;
#First, the transfer function determines the “target”, the total number t (≤ T) of bitcoins that must be transferred out to handle all requests in the given batch.&lt;br /&gt;
# Then, the function selects UTXOs for the transaction from one or more sets &#039;&#039;&#039;&#039;&#039;P&#039;&#039;&#039;&#039;&#039; of its managed addresses. The selected UTXOs are moved from the sets &#039;&#039;&#039;&#039;&#039;P&#039;&#039;&#039;&#039;&#039; to the corresponding sets &#039;&#039;&#039;&#039;&#039;S&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
# Next, the Bitcoin transaction is built and computes the fee based on current Bitcoin fees (using the &amp;lt;code&amp;gt;get_current_fee_percentiles&amp;lt;/code&amp;gt; Bitcoin integration endpoint) and the size of the transaction. The fee rate in Satoshi/vbyte is determined by the fee level. Note that the fee is deducted by splitting it evenly among the handled retrieval requests, deducting the same fraction of the total fee from each output that is not returning change and the ckBTC minter fee to the ckBTC minter. The ckBTC minter fee is &amp;lt;code&amp;gt;246*in + 7*out + 52 Satoshi&amp;lt;/code&amp;gt;, where in and out denote the number of transaction inputs and outputs, respectively (as specified here).&lt;br /&gt;
#Every input is signed using the threshold ECDSA interface.&lt;br /&gt;
#Finally, the transaction is submitted using the &amp;lt;code&amp;gt;send_transaction&amp;lt;/code&amp;gt; Bitcoin integration endpoint.&lt;br /&gt;
&lt;br /&gt;
The following UTXO selection algorithm, in pseudo-code, is used:&amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
// t = target (satoshis), P = Union of all sets of processed UTXOs&lt;br /&gt;
// Pre-condition: sum(P) &amp;gt;= t&lt;br /&gt;
select_utxos(t, P):&lt;br /&gt;
    return greedy(t, P)&lt;br /&gt;
&lt;br /&gt;
greedy(t, A):	               // t = target, A = Available UTXOs&lt;br /&gt;
    if t ≤ 0 or |A| = 0: return {}&lt;br /&gt;
    m := max(A)             // The UTXO with the largest value&lt;br /&gt;
    if m.value &amp;lt; t:&lt;br /&gt;
        return {m} ∪ greedy(t-m.value, A \ {m})&lt;br /&gt;
    else:&lt;br /&gt;
        return min({p ∊ A | p.value ≥ t})&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;The algorithm has the following properties:&lt;br /&gt;
&lt;br /&gt;
*It uses the smallest number of UTXOs possible for the given target.&lt;br /&gt;
*If a single UTXO suffices, it uses the UTXO that results in the smallest change.&lt;br /&gt;
&lt;br /&gt;
Once the transaction is sent, the requests are moved to the unconfirmed-transfers queue. &lt;br /&gt;
&lt;br /&gt;
====Finalization====&lt;br /&gt;
The ckBTC minter uses the heartbeat mechanism to determine the status of sent transactions as well. Specifically, the ckBTC minter periodically wakes up and checks the state of the requests in the unconfirmed-transfers queue.The  ckBTC minter checks the UTXOs of its main account to determine which transactions have sufficiently many confirmations.&lt;br /&gt;
&lt;br /&gt;
Such requests can then be stored in a confirmed-transfers queue for some time in order to enable a more long-term look-up of the transaction status.&lt;br /&gt;
&lt;br /&gt;
====Resubmission====&lt;br /&gt;
It is possible that it takes a long time for a transaction to be included in a block. If fees increase significantly for some time, a transaction may even be stuck for a long time or dropped entirely. While the ckBTC minter enforces a reasonable fee through its fee levels, it may still be necessary to issue a transaction again because burned ckBTC are never returned and UTXOs are never freed and are thus stuck when the transaction spending these UTXOs is stuck.&lt;br /&gt;
&lt;br /&gt;
The ckBTC minter resubmits a transaction that has not been confirmed within a certain number of hours. Given that the ckBTC minter always waits for many confirmations, the waiting time will likely be multiple hours up to one day, though this parameter has not been defined yet. &lt;br /&gt;
&lt;br /&gt;
The new transaction will use the UTXOs reserved for the requests. The transaction will be identical except that the outputs for each user will be reduced due to the increased fee. The new fee is the sum of the old transaction fee plus the size of the transaction (in vbytes) times the minimum relay fee of 1 Satoshi/vbyte plus the ckBTC minter fee again because it must acquire new signatures and send the new transaction to the Bitcoin canister.&lt;br /&gt;
&lt;br /&gt;
==Fees==&lt;br /&gt;
&lt;br /&gt;
The ckBTC canisters run on an application subnet and must be self-sustainable. Rather than charging cycles for the endpoints, the ckBTC minter accumulates a surplus of BTC over time. In the future, the ckBTC minter will mint ckBTC to get the total ckBTC supply and the BTC amount under the ckBTC minter&#039;s control to match. The ckBTC minter can then trade these extra ckBTC tokens for cycles to charge both the ckBTC minter and ckBTC ledger.&lt;br /&gt;
&lt;br /&gt;
There is a growing surplus of BTC because there is a ckBTC transfer fee of 0.0000001 ckBTC, which is burned, and a ckBTC minter fee when retrieving BTC. The latter is determined as follows:&lt;br /&gt;
&lt;br /&gt;
*Under the conservative assumption that 1 BTC = 10,000 XDR, 1 billion cycles corresponds to 10 Satoshi (because 1 trillion cycles corresponds to 1 XDR).&lt;br /&gt;
* The [https://internetcomputer.org/docs/current/developer-docs/deploy/computation-and-storage-costs/ cost] to obtain a single EDCSA signature is approximately 21.54 billion cycles on a 28-node subnet, whereas sending a Bitcoin transaction costs 5 billion cycles plus 20 million cycles per byte.&lt;br /&gt;
&lt;br /&gt;
Given these numbers, the cost to sign and send a transaction with &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; inputs and &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; outputs is&lt;br /&gt;
&lt;br /&gt;
 21.54b*in + 5b + tx_size*20m cycles&lt;br /&gt;
 &amp;lt; 21.54b*in + 5b + (149*in + 35*out + 10)*20m cycles&lt;br /&gt;
 &amp;lt; 24.52b*in +0.7b*out + 5.2b cycles&lt;br /&gt;
 &amp;lt; 246*in + 7*out + 52 satoshi.&lt;br /&gt;
&lt;br /&gt;
The formula &amp;lt;code&amp;gt;246*in + 7*out + 52&amp;lt;/code&amp;gt; is used to determine the ckBTC minter’s fee in satoshi. Since every transaction has at least one input and one output, the fee is at least 305 Satoshi.&lt;br /&gt;
&lt;br /&gt;
This conservative pricing strategy is used to subsidize the other endpoints, which are free of charge. Moreover, while the &amp;lt;code&amp;gt;retrieve_btc&amp;lt;/code&amp;gt; endpoint is relatively expensive, the fee is typically still lower than the Bitcoin miner fee.&lt;br /&gt;
&lt;br /&gt;
As mentioned above, there is also a KYT fee (currently 2000 Satoshi) when converting BTC to ckBTC and vice versa.&lt;br /&gt;
&lt;br /&gt;
==ckBTC Minter API==&lt;br /&gt;
&lt;br /&gt;
The ckBTC minter provides the following endpoints:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;get_btc_address&amp;lt;/code&amp;gt;: Returns a specific Bitcoin address that the caller can use to obtain ckBTC by sending BTC to this address.&lt;br /&gt;
*&amp;lt;code&amp;gt;update_balance&amp;lt;/code&amp;gt;: Instructs the ckBTC minter to check the balance of a Bitcoin address and mint ckBTC into the account of the owner.&lt;br /&gt;
*&amp;lt;code&amp;gt;estimate_withdrawal_fee&amp;lt;/code&amp;gt;: Returns a current estimate for the fee to be paid when retrieving a certain BTC amount.&lt;br /&gt;
* &amp;lt;code&amp;gt;get_deposit_fee&amp;lt;/code&amp;gt;: Returns the fee charged when minting ckBTC.&lt;br /&gt;
*&amp;lt;code&amp;gt;get_withdrawal_account&amp;lt;/code&amp;gt;: Returns a specific ckBTC account where the owner must transfer ckBTC before being able to retrieve BTC.&lt;br /&gt;
*&amp;lt;code&amp;gt;retrieve_btc&amp;lt;/code&amp;gt;: Instructs the ckBTC minter to burn a certain ckBTC amount and send the corresponding BTC amount, minus fees, to a provided Bitcoin address.&lt;br /&gt;
* &amp;lt;code&amp;gt;retrieve_btc_status&amp;lt;/code&amp;gt;: Returns the status of a previous &amp;lt;code&amp;gt;retrieve_btc&amp;lt;/code&amp;gt; call.&lt;br /&gt;
*&amp;lt;code&amp;gt;get_minter_info&amp;lt;/code&amp;gt;: Returns information about the ckBTC minter itself.&lt;br /&gt;
*&amp;lt;code&amp;gt;get_events&amp;lt;/code&amp;gt;: Returns a set of events at the ckBTC minter.&lt;br /&gt;
&lt;br /&gt;
The endpoints are discussed in more detail in the [https://internetcomputer.org/docs/current/developer-docs/integrations/bitcoin/ckbtc ckBTC developer documentation.]&lt;br /&gt;
&lt;br /&gt;
== See also==&lt;br /&gt;
&lt;br /&gt;
*Code Bitcoin on the Internet Computer: https://internetcomputer.org/bitcoin-integration&lt;br /&gt;
* Chain-key tokens: https://internetcomputer.org/how-it-works/chain-key-tokens/&lt;br /&gt;
*Chain-key Bitcoin developer documents: https://internetcomputer.org/docs/current/developer-docs/integrations/bitcoin/ckbtc&lt;/div&gt;</summary>
		<author><name>Jamongeon</name></author>
	</entry>
	<entry>
		<id>https://wiki.internetcomputer.org/w/index.php?title=Chain-key_Bitcoin&amp;diff=6004</id>
		<title>Chain-key Bitcoin</title>
		<link rel="alternate" type="text/html" href="https://wiki.internetcomputer.org/w/index.php?title=Chain-key_Bitcoin&amp;diff=6004"/>
		<updated>2023-07-17T17:19:34Z</updated>

		<summary type="html">&lt;p&gt;Jamongeon: Editing and adding information from the ckBTC design document (https://docs.google.com/document/d/18n33mTyvZaaisN8KU4FeliITbrL8zrUCKxv6tVfXPH0/edit?pli=1#heading=h.kknwh0c6ltfe) as requested and discussed with @Thomas Locher&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Chain-key Bitcoin (ckBTC) is a token on the Internet Computer that is backed 1:1 by Bitcoin (BTC) such that 1 ckBTC can always be redeemed for 1 BTC and vice versa.&lt;br /&gt;
&lt;br /&gt;
Unlike other tokens pegged to Bitcoin, the ckBTC token does not rely on a third-party bridge for the conversion between BTC and ckBTC, making it a substantially more secure alternative to “wrapped” tokens.&lt;br /&gt;
&lt;br /&gt;
While chain-key Bitcoin and regular Bitcoin have the same value, the advantage of chain-key Bitcoin is fast and cheap transfers: A transfer is finalized within a few seconds (a speed-up of roughly three orders of magnitude compared to transfers on the Bitcoin blockchain) and only costs 0.0000001 ckBTC (approximately two orders of magnitude lower than the Bitcoin miner fees). &lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
The ckBTC functionality is built upon the [[Bitcoin integration]] of the Internet Computer, which makes it possible for canisters to receive, hold, and send bitcoin.&lt;br /&gt;
&lt;br /&gt;
There are two canisters, the ckBTC minter and ckBTC ledger, that together provide the ckBTC functionality. The ckBTC minter mints new ckBTC tokens whenever it receives Bitcoin. Likewise, it burns ckBTC tokens whenever an owner of ckBTC tokens requests a withdrawal of Bitcoin. The ckBTC minter needs to receive BTC, based on a large number of confirmations due to the lack of finality in Bitcoin, before it mints the same amount in ckBTC and it burns ckBTC before it transfers BTC back to the users.&lt;br /&gt;
&lt;br /&gt;
A best-effort approach is used for the transfer of BTC to the users, i.e., the user cannot get the burned ckBTC back. Rather, the ckBTC minter repeatedly attempts to transfer BTC out. Note that “user” refers to the caller of the functions exposed by the ckBTC minter and ckBTC ledger in the following. A human user or another canister may be behind the function invocations.&lt;br /&gt;
&lt;br /&gt;
The ckBTC ledger is [https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/README.md ICRC-1 compliant], updating the balance accounts when ckBTC tokens are transferred and executing the mint and burn operations coming from the ckBTC minter. &lt;br /&gt;
&lt;br /&gt;
An overview of the basic architecture is depicted in the following figure.&lt;br /&gt;
[[File:CkBTC Specification - Overview (Version 2).png|alt=|center|thumb|600x600px|High-level overview of chain-key Bitcoin.]]&lt;br /&gt;
The figure shows the main flow at a high level of abstraction: Users interact with the ckBTC minter and the ckBTC ledger to convert ckBTC/BTC and transfer ckBTC, respectively. The ckBTC minter interacts with the Bitcoin canister to retrieve information about the Bitcoin network state and send Bitcoin transactions.&lt;br /&gt;
&lt;br /&gt;
The ckBTC minter further interacts with the [[Know-Your-Transaction (KYT) Canister|KYT canister]] for &amp;quot;know-your-transaction&amp;quot; (KYT) checks. These checks are meant to ensure that the ckBTC minter only uses &amp;quot;clean&amp;quot; Bitcoins to back the issued ckBTC tokens and to prevent transferring Bitcoins to Bitcoin addresses that are considered to be associated with illicit activity. As such, these KYT checks provide an additional layer of security to ckBTC users.&lt;br /&gt;
&lt;br /&gt;
== Technical Details ==&lt;br /&gt;
&lt;br /&gt;
=== Bitcoin Addresses ===&lt;br /&gt;
Within this page, Bitcoin addresses are implicitly understood to be of type P2WPKH (“pay to witness public key hash”) as defined in [https://en.bitcoin.it/wiki/BIP_0141 BIP-141]. All addresses are rendered in the Bech32 format as defined in [https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki BIP-173]. The main advantage of P2WPKH over the legacy P2PKH address type is that its use results in lower transaction fees.&lt;br /&gt;
&lt;br /&gt;
For this reason, it is the default address type in most wallets for standard transactions.&lt;br /&gt;
&lt;br /&gt;
=== ckBTC Ledger ===&lt;br /&gt;
The ckBTC ledger is a [https://dashboard.internetcomputer.org/canister/mxzaz-hqaaa-aaaar-qaada-cai canister], controlled by the NNS (specifically, the [https://dashboard.internetcomputer.org/canister/r7inp-6aaaa-aaaaa-aaabq-cai NNS root canister]), running on the [https://dashboard.internetcomputer.org/subnet/pzp6e-ekpqk-3c5x7-2h6so-njoeq-mt45d-h3h6c-q3mxf-vpeq5-fk5o7-yae pzp6e] subnet. Since it is ICRC-1 compliant, it offers [https://github.com/dfinity/ICRC-1/blob/aa82e52aaa74cc7c5f6a141e30b708bf42ede1e3/standards/ICRC-1/README.md#methods all functions] defined in the ICRC-1 standard. In particular, it provides the functionality to transfer ckBTC between accounts. &lt;br /&gt;
&lt;br /&gt;
The ckBTC ledger is responsible for keeping account balances and for transferring ckBTC between accounts. It provides the following functionality:&lt;br /&gt;
&lt;br /&gt;
* It enables the ckBTC minter to mint and burn ckBTC.&lt;br /&gt;
* It enables the transfer of ckBTC among users.&lt;br /&gt;
&lt;br /&gt;
As mentioned above, the transfer fee is 0.0000001 ckBTC, the equivalent of 10 Satoshi. Since the fee in ckBTC is burned, every transaction leads to a growing surplus in BTC controlled by the ckBTC minter. The surplus will eventually be used to cover the cycle cost of the ckBTC minter. &lt;br /&gt;
&lt;br /&gt;
The minting account is the ckBTC minter’s default account; that is, the account derived from the ckBTC minter’s principal ID and the all-zero subaccount.&lt;br /&gt;
&lt;br /&gt;
The initial supply of the ckBTC ledger is 0. ckBTC tokens are minted only when the ckBTC minter receives Bitcoin, ensuring that the ckBTC supply managed by the ckBTC ledger is upper bounded by the amount of Bitcoin held by the ckBTC minter.&lt;br /&gt;
&lt;br /&gt;
=== ckBTC Minter ===&lt;br /&gt;
&lt;br /&gt;
The ckBTC minter is a [https://dashboard.internetcomputer.org/canister/mqygn-kiaaa-aaaar-qaadq-cai canister] that is controlled by the NNS and running on the [https://dashboard.internetcomputer.org/subnet/pzp6e-ekpqk-3c5x7-2h6so-njoeq-mt45d-h3h6c-q3mxf-vpeq5-fk5o7-yae pzp6e] subnet as well. &lt;br /&gt;
&lt;br /&gt;
The ckBTC minter is the canister responsible for managing deposited BTC and minting/burning ckBTC based on the amount of deposited BTC. It provides the following functionality:&lt;br /&gt;
&lt;br /&gt;
* For a certain principal ID and an optional subaccount, it returns a specific Bitcoin address under the ckBTC minter’s control.&lt;br /&gt;
* Users can inform the ckBTC minter about Bitcoins that were sent to an address controlled by the ckBTC minter. If the balance has increased, the ckBTC minter mints the same amount in ckBTC for the user associated with the Bitcoin address.&lt;br /&gt;
* Users can ask the ckBTC minter to track the balance of a Bitcoin address until new funds are received, which then automatically triggers the minting of the equivalent amount of ckBTC.&lt;br /&gt;
* Users can request to get bitcoins back. The ckBTC minter burns the same amount of ckBTC and transfers the Bitcoins to the address provided by the user.&lt;br /&gt;
&lt;br /&gt;
The ckBTC minter canister has a few important configuration parameters including:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;retrieve_btc_min_amount&amp;lt;/code&amp;gt;: This is the minimum ckBTC amount that can be burned and, correspondingly, the minimum BTC amount that can be withdrawn. The parameter is set to 0.001 BTC, or 100,000 satoshi.&lt;br /&gt;
* &amp;lt;code&amp;gt;max_time_in_queue_nanos&amp;lt;/code&amp;gt;: Any BTC retrieval request should be kept in a queue for at most this time. Caching requests rather than handling them right away has the advantage that multiple requests can be served in a single transaction, saving Bitcoin miner fees. The parameter is set to 10 minutes, which corresponds to the expected time between Bitcoin blocks.&lt;br /&gt;
* &amp;lt;code&amp;gt;min_confirmations&amp;lt;/code&amp;gt;:  The number of confirmations required for the ckBTC minter to accept a Bitcoin transaction. In particular, the ckBTC minter does not mint ckBTC before a transaction transferring BTC to a Bitcoin address managed by the ckBTC minter reaches this number of transactions. The parameter was initially set to 72 but has been reduced to 12 in the meantime.&lt;br /&gt;
* &amp;lt;code&amp;gt;kyt_fee&amp;lt;/code&amp;gt;: The fee that must be paid for KYT checks. It is currently set to 2000 satoshi.&lt;br /&gt;
The other parameters are self-explanatory and can be found in the [https://github.com/dfinity/ic/blob/master/rs/bitcoin/ckbtc/minter/ckbtc_minter.did ckBTC minter Candid file].&lt;br /&gt;
&lt;br /&gt;
=== State Management ===&lt;br /&gt;
&lt;br /&gt;
==== Managed Addresses ====&lt;br /&gt;
A Bitcoin address that is controlled by the ckBTC minter and has a positive balance is called a managed address. If the balance of a managed address reduces to zero, the address is no longer managed and can be removed from the state.&lt;br /&gt;
&lt;br /&gt;
Note that it is possible to increase the balance again, in which case the address becomes managed again.&lt;br /&gt;
&lt;br /&gt;
==== Unspent Transaction Outputs ====&lt;br /&gt;
Once a new Unspent Transaction Output (UTXO) under the control of the ckBTC minter is discovered (using the &amp;lt;code&amp;gt;update_balance&amp;lt;/code&amp;gt; function), it is stored internally in a set called &amp;lt;code&amp;gt;available_utxos&amp;lt;/code&amp;gt; (defined [https://github.com/dfinity/ic/blob/2348b094d3d27616ee3f049d3048baa1da8d625a/rs/bitcoin/ckbtc/minter/src/state.rs#L305C14-L305C14 here] in the source code).&lt;br /&gt;
&lt;br /&gt;
All discovered UTXOs remain in this set until a Bitcoin transaction is created to spend one or more of them when retrieving Bitcoins. When a transaction is created spending some UTXOs, these UTXOs are removed from the set &amp;lt;code&amp;gt;available_utxos&amp;lt;/code&amp;gt; and inserted in the &amp;lt;code&amp;gt;used_utxos&amp;lt;/code&amp;gt; field of the &amp;lt;code&amp;gt;SubmittedBtcTransaction&amp;lt;/code&amp;gt; struct (defined [https://github.com/dfinity/ic/blob/70d19f16c17f8f42987a46d473ba27705927cdb7/rs/bitcoin/ckbtc/minter/src/state.rs#L87 here] in the source code), which is the internal representation of a Bitcoin transaction.&lt;br /&gt;
&lt;br /&gt;
A UTXO is removed from the ckBTC state when the &amp;lt;code&amp;gt;SubmittedBtcTransaction&amp;lt;/code&amp;gt; struct that contains the UTXO is removed from the state. &lt;br /&gt;
&lt;br /&gt;
==== Transactions ====&lt;br /&gt;
To provide information about current transactions, outgoing transactions must be cached. A transaction is cached until its inputs are no longer considered unspent based on a large number of confirmations.&lt;br /&gt;
&lt;br /&gt;
Every transaction that the ckBTC minter creates has an output that sends the ckBTC minter fee plus the transaction change back to its main BTC address (P2WPKH address derived from its public key with an empty derivation path) using the Bitcoin integration’s &amp;lt;code&amp;gt;get_utxos&amp;lt;/code&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
A transaction can be removed from the cache if the transaction output that belongs to the ckBTC minter appears in the returned list when calling &amp;lt;code&amp;gt;get_utxos&amp;lt;/code&amp;gt; with sufficient confirmations for the ckBTC minter’s main BTC address.&lt;br /&gt;
&lt;br /&gt;
The ckBTC minter may resubmit transactions, making use of Bitcoin’s request by fee (RBF) mechanism as defined in [https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki BIP-125]. In the case of ckBTC, a resubmission adds a transaction to the cache that spends exactly the same UTXOs as the transaction it replaces. The only difference is that the BTC amount sent to the user is reduced in order to increase the fee.&lt;br /&gt;
&lt;br /&gt;
BIP-125 states that at most 100 transactions may be evicted from the mempool, i.e., the fee cannot be increased more than 100 times. Moreover, the fee must be increased at least by the minimum relay fee (see minrelaytxfee [https://en.bitcoin.it/wiki/Miner_fees#Relaying here]) of 1 Satoshi/vbyte.&lt;br /&gt;
&lt;br /&gt;
For example, if we assume a minimum increase of 200 Satoshi (the minimum fee for a basic segwit transaction with one input and one output is 192 Satoshi and the number per output is always lower than 200 if there are at least as many outputs as inputs), the minimum transfer amount should be at least 20,000 Satoshi which equals 0.0002 BTC. When adding a base fee at a large fee rate of 100 Satoshi/vbyte and assuming a virtual transaction size of 200 vbyte per output, we get a minimum transfer amount of 0.0004 BTC. Adding a security margin, we define the minimum retrieval amount to be &amp;lt;code&amp;gt;MIN_RETRIEVAL_AMOUNT = 0.001 BTC&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;To ensure that every transaction can potentially be updated, the RBF flag must be set on every transaction.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Know Your Transaction &amp;amp; Fees ====&lt;br /&gt;
Before UTXOs are accepted, they undergo a know-your-transaction (KYT) check where information about the UTXO is sent to a “KYT canister”, which interacts with KYT service providers, such as Chainalysis, to check if the UTXO is “clean” using HTTPS outcalls.&lt;br /&gt;
&lt;br /&gt;
In a similar fashion, there is a KYT check of the destination address when attempting to transfer Bitcoins out of the ckBTC minter.&lt;br /&gt;
&lt;br /&gt;
Both of these KYT checks incur fees, charged in ckBTC:&lt;br /&gt;
&lt;br /&gt;
* The KYT fee is subtracted from the amount to be minted and the amount transferred out. &lt;br /&gt;
* The KYT fee is 2000 satoshi per KYT check.&lt;br /&gt;
&lt;br /&gt;
The KYT canister supports multiple KYT access key providers, called maintainers, each having a principal ID and (secret) access key to the external KYT service. Since the maintainers pay for their subscriptions, they must be remunerated. To this end, the ckBTC minter maintains a mapping of maintainers to the owed amount, which is the number of KYT checks that were performed with the respective maintainer’s credentials times the KYT fee of 2000 Satoshi.&lt;br /&gt;
&lt;br /&gt;
Each successful response from the KYT canister contains the principal ID of the maintainer so that the ckBTC minter can update the owed amount correctly. Once every 24 hours, the ckBTC minter pays out the owed amounts in ckBTC to all maintainers.&lt;br /&gt;
&lt;br /&gt;
== Converting BTC to ckBTC ==&lt;br /&gt;
&lt;br /&gt;
In this section, the process to convert BTC to ckBTC is explained, making use of the ckBTC minter and ckBTC ledger endpoints.&lt;br /&gt;
&lt;br /&gt;
The first step is for the user to determine the Bitcoin address where the user is supposed to transfer Bitcoin for the minting process by calling the &amp;lt;code&amp;gt;get_btc_address&amp;lt;/code&amp;gt; endpoint. Next, the user transfers the desired BTC amount to this Bitcoin address. Subsequently, the user calls the &amp;lt;code&amp;gt;track_balance&amp;lt;/code&amp;gt; endpoint to inform the ckBTC minter that it is about to receive Bitcoins at the given address.&lt;br /&gt;
&lt;br /&gt;
Internally, the tracking works as follows. Since the expected time between Bitcoin blocks is 10 minutes, the ckBTC minter first checks if new unspent transaction outputs (UTXOs) are available for that address with at least the required number of confirmations after &amp;lt;code&amp;gt;10*min_confirmations&amp;lt;/code&amp;gt; minutes. If there is at least one new UTXO, tracking stops and the ckBTC minter instructs the ckBTC ledger to mint the same amount of ckBTC tokens into the account derived from the principal ID and the subaccount.&lt;br /&gt;
&lt;br /&gt;
If no new UTXOs are discovered with sufficiently many confirmations, the ckBTC ledger checks if there are new UTXOs with at least one confirmation. If this is not the case, tracking stops as well. Otherwise, the expected time until the first new UTXO reaches the desired number of confirmations is computed, which is 10 minutes times the difference between the desired number of confirmations and the current number of confirmations. The same process then repeats until ckBTC tokens are minted or tracking stops.&lt;br /&gt;
&lt;br /&gt;
It is evident from this description that it’s possible that tracking may stop before ckBTC tokens are minted, for example, if it takes an unusually long time until the transaction appears in a block. In this case, the endpoint can be invoked again. Alternatively, the user can wait until the transaction has the required number of confirmations and call the &amp;lt;code&amp;gt;update_balance&amp;lt;/code&amp;gt; endpoint.&lt;br /&gt;
&lt;br /&gt;
The following figure depicts the conversion flow using the &amp;lt;code&amp;gt;track_balance&amp;lt;/code&amp;gt; endpoint.&lt;br /&gt;
[[File:CkBTC Specification - Submission (simplified) - Version 2.png|alt=|center|thumb|600x600px|Process of converting BTC to ckBTC.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In this figure, the ckBTC minter discovers the new UTXO after the waiting period by calling &amp;lt;code&amp;gt;get_utxos&amp;lt;/code&amp;gt; on the Bitcoin canister. As mentioned above, it is possible that it may take several interactions with the Bitcoin canister until the transaction has received sufficiently many confirmations before the ckBTC minter issues the mint transaction to the ckBTC ledger. After a successful KYT check, the ckBTC ledger is instructed to mint ckBTC tokens for the user. The minted amount corresponds to the value of the UTXO minus the KYT fee.&lt;br /&gt;
&lt;br /&gt;
=== Technical Details ===&lt;br /&gt;
As mentioned above, a call to the &amp;lt;code&amp;gt;update_balance&amp;lt;/code&amp;gt; endpoint triggers a call to the Bitcoin canister to get UTXOs for the Bitcoin address associated with the given &amp;lt;code&amp;gt;principal-subaccount&amp;lt;/code&amp;gt; pair. Let &#039;&#039;&#039;&#039;&#039;R&#039;&#039;&#039;&#039;&#039; denote the set of returned UTXOs. The following pseudo-code illustrates how the UTXOs are processed:&amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
for utxo in new_utxos(R):        // R = set of received UTXOs in the get_utxos call&lt;br /&gt;
    if utxo.value &amp;gt;= KYT_FEE:&lt;br /&gt;
        if utxo in checked_utxos: &lt;br /&gt;
            (uuid, state) = checked_utxos.get(utxo)&lt;br /&gt;
        else:&lt;br /&gt;
            (uuid, state, kyt_provider) = kyt_canister.check(utxo).await?&lt;br /&gt;
            if state == clean:&lt;br /&gt;
                D = D \ {utxo}&lt;br /&gt;
                P = P ∪ {utxo}&lt;br /&gt;
                checked_utxos.set(utxo, (uuid, clean))&lt;br /&gt;
                owed_kyt_fee[kyt_provider] += KYT_FEE&lt;br /&gt;
        if state == clean:&lt;br /&gt;
            ckbtc_ledger.mint(utxo.value-KYT_FEE, recipient_account, uuid).await? &lt;br /&gt;
            checked_utxos.remove(utxo) &lt;br /&gt;
        else:&lt;br /&gt;
            add_to_quarantine_list(utxo)&lt;br /&gt;
    else:&lt;br /&gt;
        add_to_ignore_list(utxo)&lt;br /&gt;
return response with UTXO statuses&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;A UTXO is considered if its value is at least the KYT fee, which is a configuration parameter of the ckBTC minter. UTXOs whose value lie below the KYT fee are added to an ignore list. The additional state &amp;lt;code&amp;gt;checked_utxos&amp;lt;/code&amp;gt; is maintained to remember that a UTXO was checked if the state is clean. Once the corresponding amount of ckBTC has been minted, this state can be removed again. If the UTXO is tainted, it is moved to a quarantine list instead. UTXOs in the ignore list and quarantine list remain there.&lt;br /&gt;
&lt;br /&gt;
The function &amp;lt;code&amp;gt;new_utxos&amp;lt;/code&amp;gt; filters out all UTXOs on the ignore list, the quarantine list, and the sets &#039;&#039;&#039;&#039;&#039;P&#039;&#039;&#039;&#039;&#039; and &#039;&#039;&#039;&#039;&#039;S&#039;&#039;&#039;&#039;&#039;. On the other hand, the &amp;lt;code&amp;gt;checked_utxos&amp;lt;/code&amp;gt; data structure is not considered.&lt;br /&gt;
&lt;br /&gt;
=== Automated Tracking ===&lt;br /&gt;
The &amp;lt;code&amp;gt;update_balance&amp;lt;/code&amp;gt; function only triggers a minting operation if the corresponding Bitcoin transaction has sufficient confirmations, which implies that it is the user’s responsibility to check the number of confirmations before making the &amp;lt;code&amp;gt;update_balance&amp;lt;/code&amp;gt; call.&lt;br /&gt;
&lt;br /&gt;
In order to improve the user experience, the additional endpoint &amp;lt;code&amp;gt;track_balance&amp;lt;/code&amp;gt;, with the same parameters as &amp;lt;code&amp;gt;update_balance&amp;lt;/code&amp;gt;, is provided. When invoked instead of &amp;lt;code&amp;gt;update_balance&amp;lt;/code&amp;gt;, the ckBTC minter starts tracking the Bitcoin address derived from the provided principal ID and subaccount using the &amp;lt;code&amp;gt;get_btc_address&amp;lt;/code&amp;gt; endpoint. 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.&lt;br /&gt;
&lt;br /&gt;
The balance of the Bitcoin address is not tracked indefinitely. Tracking is stopped if either at least one new unspent transaction output (UTXO) is discovered or there is no new UTXO within a certain time interval as defined in the following:&lt;br /&gt;
&lt;br /&gt;
* Since the expected time between Bitcoin blocks is 10 minutes, the ckBTC minter first checks if new UTXOs are available for that address with at least the required number of confirmations after &amp;lt;code&amp;gt;10*MIN_CONFIRMATIONS&amp;lt;/code&amp;gt; minutes.&lt;br /&gt;
* If there is at least one new UTXO, tracking stops and the same flow as for &amp;lt;code&amp;gt;update_balance&amp;lt;/code&amp;gt; is triggered. If the KYT check is successful, the ckBTC minter instructs the ckBTC ledger to mint the same amount of ckBTC tokens minus the KYT fee into the account derived from the principal ID and the subaccount.&lt;br /&gt;
* If no new UTXOs are discovered with sufficiently many confirmations, the ckBTC ledger checks if there are new UTXOs with at least one confirmation. If this is not the case, tracking stops as well. Otherwise, the expected time until the first new UTXO reaches the desired number of confirmations is computed, which is 10 minutes times the difference between the desired number of confirmations and the current number of confirmations. The next check is scheduled after this many minutes and the process repeats until a new UTXO is discovered or tracking stops.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It is evident from this description that it is possible that tracking may stop before ckBTC tokens are minted, for example, if it takes an unusually long time until the transaction appears in a block. In this case, the endpoint can be invoked again. Alternatively, the user can wait until the transaction has the required number of confirmations and call the &amp;lt;code&amp;gt;update_balance&amp;lt;/code&amp;gt; endpoint.&lt;br /&gt;
&lt;br /&gt;
== Converting ckBTC to BTC ==&lt;br /&gt;
&lt;br /&gt;
The process to convert ckBTC to BTC consists of the following steps: &lt;br /&gt;
&lt;br /&gt;
# Transfer request: The user moves the ckBTC that he/she wants to convert to BTC to a special ckBTC withdrawal account under the control of the ckBTC minter and requests a transfer. The destination Bitcoin address undergoes a KYT check. If the check is successful, the request is accepted and put into a queue.&lt;br /&gt;
# Submission: On a heartbeat, the ckBTC minter attempts to submit transactions for validated transfer requests.&lt;br /&gt;
# Finalization: On a heartbeat, the ckBTC minter checks which transactions went through and finalizes these transactions.&lt;br /&gt;
# Resubmission: The ckBTC minter can resubmit a transaction that has been pending at least for a specific amount of time with a higher fee.&lt;br /&gt;
&lt;br /&gt;
The individual parts are discussed in greater detail in the following sections.&lt;br /&gt;
&lt;br /&gt;
The first step to convert ckBTC to BTC is to transfer the amount to be retrieved to the owner-specific withdrawal account under the ckBTC minter’s control. This step is required because only the ckBTC minter can burn tokens and it can only burn those tokens in one of its accounts. The withdrawal account can be obtained by calling the &amp;lt;code&amp;gt;get_withdrawal_account&amp;lt;/code&amp;gt; endpoint.&lt;br /&gt;
&lt;br /&gt;
After the user has transferred the desired ckBTC amount to the withdrawal account, the user can call the &amp;lt;code&amp;gt;retrieve_btc&amp;lt;/code&amp;gt; endpoint to inform the ckBTC minter about the withdrawal intent. In addition to specifying the withdrawal amount, the Bitcoin address where the withdrawn funds are to be sent must be specified as well.&lt;br /&gt;
&lt;br /&gt;
The ckBTC minter first performs a KYT check against the targeted Bitcoin address. If the check is successful, the ckBTC minter instructs the ckBTC ledger to burn the ckBTC in the withdrawal account. Lastly, the ckBTC minter deducts the KYT fee from the amount to be retrieved and puts the corresponding retrieval request into a queue and checks the status of the queue on a heartbeat.&lt;br /&gt;
&lt;br /&gt;
If the oldest request has been in the queue for at least 10 minutes or at least 20 retrieval requests have been accumulated at the time of the heartbeat, the ckBTC minter creates a single Bitcoin transaction to serve up to 100 retrieval requests as follows:&lt;br /&gt;
&lt;br /&gt;
# It selects available UTXOs with a total sum of at least the sum in the retrieval requests.&lt;br /&gt;
# It constructs a Bitcoin transaction with the selected UTXOs as inputs and an output for each retrieval request plus an additional output for the ckBTC minter’s fee.&lt;br /&gt;
# It uses the Bitcoin canister’s fee API to determine an appropriate fee for the transaction, using the median fee rate.&lt;br /&gt;
# It distributes the fee evenly among all outputs other than the output for the ckBTC minter’s fee.&lt;br /&gt;
# For each input of the transaction, the ckBTC minter invokes the threshold ECDSA functionality (calling the &amp;lt;code&amp;gt;sign_with_ecdsa&amp;lt;/code&amp;gt; function) to obtain the required signatures and puts them into the transaction.&lt;br /&gt;
# Lastly, it sends the Bitcoin transaction by invoking the &amp;lt;code&amp;gt;send_transaction&amp;lt;/code&amp;gt; function of the Bitcoin integration API.&lt;br /&gt;
&lt;br /&gt;
The BTC retrieval process is depicted in the following figure.&lt;br /&gt;
[[File:CkBTC Specification - Withdrawal (simplified)- Version 2.png|alt=|center|thumb|600x600px|Process of converting ckBTC to BTC.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that the amounts in the transfer to the withdrawal account and the retrieval request need not be the same. The &amp;lt;code&amp;gt;retrieve_btc_status&amp;lt;/code&amp;gt; endpoint can be used to query the current status of a retrieval request.&lt;br /&gt;
&lt;br /&gt;
=== Technical Details ===&lt;br /&gt;
&lt;br /&gt;
==== Transfer Request ====&lt;br /&gt;
The ckBTC minter can only burn ckBTC under its control. Therefore, the first step is to transfer ckBTC to the ckBTC withdrawal account controlled by the ckBTC minter and associated with the owner of the ckBTC that are to be burned. Specifically, the withdrawal account is a ckBTC ledger account where the principal ID is the ckBTC minter and the subaccount is derived deterministically from the owner’s principal ID.&lt;br /&gt;
&lt;br /&gt;
After this transfer, the user sends a &amp;lt;code&amp;gt;retrieve_btc&amp;lt;/code&amp;gt; request, specifying the amount that they would like to retrieve, the Bitcoin address where the funds are to be transferred, and, optionally, a fee level (which have yet to be defined).&lt;br /&gt;
&lt;br /&gt;
Upon receiving such a request, the ckBTC minter first performs a KYT check against the Bitcoin address where funds are supposed to be sent. If the check is successful, the ckBTC minter issues a burn request to the ckBTC ledger, burning the amount in the received request in the user’s ckBTC withdrawal account. If the burn operation is successful, the ckBTC minter creates a transfer request, removing the &amp;lt;code&amp;gt;KYT_FEE&amp;lt;/code&amp;gt; from the transfer amount, and appends it to its pending-requests queue.&lt;br /&gt;
&lt;br /&gt;
Alternatively, if the destination address does not pass the KYT check, a burn request is sent to the ckBTC ledger, burning the &amp;lt;code&amp;gt;KYT_FEE&amp;lt;/code&amp;gt; amount.&lt;br /&gt;
&lt;br /&gt;
The steps of a successful request are illustrated in the following figure.&lt;br /&gt;
&lt;br /&gt;
Recall that the ckBTC ledger uses the ckBTC minter default account as the minting account. Withdrawal accounts should never resolve to the default minting account because the ckBTC ledger considers the minting account for minting only.&lt;br /&gt;
&lt;br /&gt;
The following pseudo-code illustrates how the &amp;lt;code&amp;gt;retrieve_btc&amp;lt;/code&amp;gt; endpoint works, given the parameters &amp;lt;code&amp;gt;amount&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;btc_address&amp;lt;/code&amp;gt;.&amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
assert(amount &amp;gt;= max(MIN_RETRIEVAL_AMOUNT, KYT_FEE))&lt;br /&gt;
    assert(ckbtc_ledger.balance_of(withdrawal_account).await? &amp;gt;= amount)&lt;br /&gt;
  (uuid, state, kyt_provider) = kyt_canister.check(btc_address).await? &lt;br /&gt;
&lt;br /&gt;
if state == clean:&lt;br /&gt;
    index = ckbtc_ledger.burn(amount, withdrawal_account).await?&lt;br /&gt;
    owed_kyt_fee[kyt_provider] += KYT_FEE&lt;br /&gt;
    create_request(amount-KYT_FEE, index, btc_address, uuid)&lt;br /&gt;
 else:&lt;br /&gt;
    index = ckbtc_ledger.burn(KYT_FEE, withdrawal_account).await? &lt;br /&gt;
    owed_kyt_fee[kyt_provider] += KYT_FEE&lt;br /&gt;
    return Error(&amp;quot;Failed KYT check&amp;quot;, index)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Note that a failure to perform the KYT check results in a rejected request. Further note that if the KYT check succeeds but the burn transaction fails (regardless of the state of the KYT response), no KYT fee is charged and the request is rejected. A subsequent request with the same parameters will result in another call to the KYT canister again, which is acceptable because multiple identical calls to the KYT service provider do not result in increased fees.&lt;br /&gt;
&lt;br /&gt;
For each retrieval request, the ckBTC minter stores the following data:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;block_index&amp;lt;/code&amp;gt;: The block index of the burn operation used to burn the ckBTC. Since the block index is unique, it is used as the request ID.&lt;br /&gt;
* &amp;lt;code&amp;gt;amount&amp;lt;/code&amp;gt;: The total amount of tokens to retrieve. This amount must be at least the minimum retrieval amount as defined above.&lt;br /&gt;
* &amp;lt;code&amp;gt;address&amp;lt;/code&amp;gt;: The address where the Bitcoins will be sent.&lt;br /&gt;
* &amp;lt;code&amp;gt;received_at&amp;lt;/code&amp;gt;: The timestamp when the request was received.&lt;br /&gt;
* &amp;lt;code&amp;gt;fee_level&amp;lt;/code&amp;gt;: If no fee level is provided, a medium fee level is used.&lt;br /&gt;
&lt;br /&gt;
==== Submission ====&lt;br /&gt;
The ckBTC minter uses the heartbeat mechanism to initiate Bitcoin transfers. On a heartbeat, the following steps are carried out:&lt;br /&gt;
&lt;br /&gt;
# Check if there is at least one request that is 10 minutes old or there are at least 20 requests in the pending-requests queue. If not, stop.&lt;br /&gt;
# Update the balance of the ckBTC minter’s main BTC address (the P2WPKH address derived from its public key with an empty derivation path) using the Bitcoin integration’s &amp;lt;code&amp;gt;get_utxos&amp;lt;/code&amp;gt; function.&lt;br /&gt;
# Determine the total amount of Bitcoins available, which is the sum of all Bitcoins in processed UTXOs, plus Bitcoins under the ckBTC minter’s main BTC address.&lt;br /&gt;
# Call the transfer function with the next batch of requests with the same fee level that can be served given the total amount of available Bitcoins. A transaction is created, setting the transaction ID for each request in the batch, and sent to the Bitcoin network.&lt;br /&gt;
# Every request in this batch is then moved to the unconfirmed-transfers queue.&lt;br /&gt;
&lt;br /&gt;
As evident from the steps outlined above, the transfer function can handle multiple requests at the same time. Handling multiple requests in a single transaction has several advantages over sending individual transactions:&lt;br /&gt;
&lt;br /&gt;
# Requests can possibly be served more quickly, especially if the ckBTC minter must wait for change to return to its main BTC address.&lt;br /&gt;
# As the fee for the non-input bytes is shared, the fee per request is slightly lower.&lt;br /&gt;
# Serving multiple requests at the same time makes denial-of-service attacks where an attacker attempts to keep the pool of usable UTXOs empty with many small requests harder.&lt;br /&gt;
&lt;br /&gt;
Given this set of requests, the next step is to select UTXOs for the transaction.&lt;br /&gt;
&lt;br /&gt;
Since UTXOs are always spent entirely, the difference between the sum of Bitcoins in the spent UTXOs and the requested amount must be transferred to a new UTXO as well. The ckBTC minter uses its main BTC address to accumulate “change”.&lt;br /&gt;
&lt;br /&gt;
All UTXOs of its main BTC address are immediately transferred to the corresponding set &#039;&#039;&#039;&#039;&#039;P&#039;&#039;&#039;&#039;&#039; of processed UTXOs. The reason is that there is no minting for the balances in these UTXOs.&lt;br /&gt;
&lt;br /&gt;
The transfer function performs the following steps:&lt;br /&gt;
&lt;br /&gt;
# First, the transfer function determines the “target”, the total number t (≤ T) of Bitcoins that must be transferred out to handle all requests in the given batch.&lt;br /&gt;
# Then, the function selects UTXOs for the transaction from one or more sets &#039;&#039;&#039;&#039;&#039;P&#039;&#039;&#039;&#039;&#039; of its managed addresses. The selected UTXOs are moved from the sets &#039;&#039;&#039;&#039;&#039;P&#039;&#039;&#039;&#039;&#039; to the corresponding sets &#039;&#039;&#039;&#039;&#039;S&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
# Next, the Bitcoin transaction is built and computes the fee based on current Bitcoin fees (using the &amp;lt;code&amp;gt;get_current_fee_percentiles&amp;lt;/code&amp;gt; Bitcoin integration endpoint) and the size of the transaction. The fee rate in Satoshi/vbyte is determined by the fee level. Note that the fee is deducted by splitting it evenly among the handled retrieval requests, deducting the same fraction of the total fee from each output that is not returning change and the ckBTC minter fee to the ckBTC minter. The ckBTC minter fee is &amp;lt;code&amp;gt;246*in + 7*out + 52 Satoshi&amp;lt;/code&amp;gt;, where in and out denote the number of transaction inputs and outputs, respectively (as specified here).&lt;br /&gt;
# Every input is signed using the threshold ECDSA interface.&lt;br /&gt;
# Finally, the transaction is submitted using the &amp;lt;code&amp;gt;send_transaction&amp;lt;/code&amp;gt; Bitcoin integration endpoint.&lt;br /&gt;
&lt;br /&gt;
The following UTXO selection algorithm, in pseudo-code, is used:&amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot;&amp;gt;&lt;br /&gt;
// t = target (satoshis), P = Union of all sets of processed UTXOs&lt;br /&gt;
// Pre-condition: sum(P) &amp;gt;= t&lt;br /&gt;
select_utxos(t, P):&lt;br /&gt;
    return greedy(t, P)&lt;br /&gt;
&lt;br /&gt;
greedy(t, A):	               // t = target, A = Available UTXOs&lt;br /&gt;
    if t ≤ 0 or |A| = 0: return {}&lt;br /&gt;
    m := max(A)             // The UTXO with the largest value&lt;br /&gt;
    if m.value &amp;lt; t:&lt;br /&gt;
        return {m} ∪ greedy(t-m.value, A \ {m})&lt;br /&gt;
    else:&lt;br /&gt;
        return min({p ∊ A | p.value ≥ t})&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;The algorithm has the following properties:&lt;br /&gt;
&lt;br /&gt;
* It uses the smallest number of UTXOs possible for the given target.&lt;br /&gt;
* If a single UTXO suffices, it uses the UTXO that results in the smallest change.&lt;br /&gt;
&lt;br /&gt;
Once the transaction is sent, the requests are moved to the unconfirmed-transfers queue. &lt;br /&gt;
&lt;br /&gt;
==== Finalization ====&lt;br /&gt;
The ckBTC minter uses the heartbeat mechanism to determine the status of sent transactions as well. Specifically, the ckBTC minter periodically wakes up and checks the state of the requests in the unconfirmed-transfers queue.The  ckBTC minter checks the UTXOs of its main account to determine which transactions have sufficiently many confirmations.&lt;br /&gt;
&lt;br /&gt;
Such requests can then be stored in a confirmed-transfers queue for some time in order to enable a more long-term look-up of the transaction status.&lt;br /&gt;
&lt;br /&gt;
==== Resubmission ====&lt;br /&gt;
It is possible that it takes a long time for a transaction to be included in a block. If fees increase significantly for some time, a transaction may even be stuck for a long time or dropped entirely. While the ckBTC minter enforces a reasonable fee through its fee levels, it may still be necessary to issue a transaction again because burned ckBTC are never returned and UTXOs are never freed and are thus stuck when the transaction spending these UTXOs is stuck.&lt;br /&gt;
&lt;br /&gt;
The ckBTC minter resubmits a transaction that has not been confirmed within a certain number of hours. Given that the ckBTC minter always waits for many confirmations, the waiting time will likely be multiple hours up to one day, though this parameter has not been defined yet. &lt;br /&gt;
&lt;br /&gt;
The new transaction will use the UTXOs reserved for the requests. The transaction will be identical except that the outputs for each user will be reduced due to the increased fee. The new fee is the sum of the old transaction fee plus the size of the transaction (in vbytes) times the minimum relay fee of 1 Satoshi/vbyte plus the ckBTC minter fee again because it must acquire new signatures and send the new transaction to the Bitcoin canister.&lt;br /&gt;
&lt;br /&gt;
== Fees ==&lt;br /&gt;
&lt;br /&gt;
The ckBTC canisters run on an application subnet and must be self-sustainable. Rather than charging cycles for the endpoints, the ckBTC minter accumulates a surplus of BTC over time. In the future, the ckBTC minter will mint ckBTC to get the total ckBTC supply and the BTC amount under the ckBTC minter&#039;s control to match. The ckBTC minter can then trade these extra ckBTC tokens for cycles to charge both the ckBTC minter and ckBTC ledger.&lt;br /&gt;
&lt;br /&gt;
There is a growing surplus of BTC because there is a ckBTC transfer fee of 0.0000001 ckBTC, which is burned, and a ckBTC minter fee when retrieving BTC. The latter is determined as follows:&lt;br /&gt;
&lt;br /&gt;
* Under the conservative assumption that 1 BTC = 10,000 XDR, 1 billion cycles corresponds to 10 Satoshi (because 1 trillion cycles corresponds to 1 XDR). &lt;br /&gt;
* The [https://internetcomputer.org/docs/current/developer-docs/deploy/computation-and-storage-costs/ cost] to obtain a single EDCSA signature is approximately 21.54 billion cycles on a 28-node subnet, whereas sending a Bitcoin transaction costs 5 billion cycles plus 20 million cycles per byte.&lt;br /&gt;
&lt;br /&gt;
Given these numbers, the cost to sign and send a transaction with &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; inputs and &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; outputs is&lt;br /&gt;
&lt;br /&gt;
 21.54b*in + 5b + tx_size*20m cycles&lt;br /&gt;
 &amp;lt; 21.54b*in + 5b + (149*in + 35*out + 10)*20m cycles&lt;br /&gt;
 &amp;lt; 24.52b*in +0.7b*out + 5.2b cycles&lt;br /&gt;
 &amp;lt; 246*in + 7*out + 52 satoshi.&lt;br /&gt;
&lt;br /&gt;
The formula &amp;lt;code&amp;gt;246*in + 7*out + 52&amp;lt;/code&amp;gt; is used to determine the ckBTC minter’s fee in satoshi. Since every transaction has at least one input and one output, the fee is at least 305 Satoshi.&lt;br /&gt;
&lt;br /&gt;
This conservative pricing strategy is used to subsidize the other endpoints, which are free of charge. Moreover, while the &amp;lt;code&amp;gt;retrieve_btc&amp;lt;/code&amp;gt; endpoint is relatively expensive, the fee is typically still lower than the Bitcoin miner fee.&lt;br /&gt;
&lt;br /&gt;
As mentioned above, there is also a KYT fee (currently 2000 Satoshi) when converting BTC to ckBTC and vice versa.&lt;br /&gt;
&lt;br /&gt;
== ckBTC Minter API ==&lt;br /&gt;
&lt;br /&gt;
The ckBTC minter provides the following endpoints:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;get_btc_address&amp;lt;/code&amp;gt;: Returns a specific Bitcoin address that the caller can use to obtain ckBTC by sending BTC to this address.&lt;br /&gt;
* &amp;lt;code&amp;gt;track_balance&amp;lt;/code&amp;gt;: Instructs the ckBTC minter to track a certain Bitcoin address until funds are added, which will trigger the minting of ckBTC. &#039;&#039;&#039;NOTE: This endpoint is work-in-progress and not available yet.&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;update_balance&amp;lt;/code&amp;gt;: Instructs the ckBTC minter to check the balance of a Bitcoin address and mint ckBTC into the account of the owner.&lt;br /&gt;
* &amp;lt;code&amp;gt;estimate_withdrawal_fee&amp;lt;/code&amp;gt;: Returns a current estimate for the fee to be paid when retrieving a certain BTC amount.&lt;br /&gt;
* &amp;lt;code&amp;gt;get_deposit_fee&amp;lt;/code&amp;gt;: Returns the fee charged when minting ckBTC.&lt;br /&gt;
* &amp;lt;code&amp;gt;get_withdrawal_account&amp;lt;/code&amp;gt;: Returns a specific ckBTC account where the owner must transfer ckBTC before being able to retrieve BTC.&lt;br /&gt;
* &amp;lt;code&amp;gt;retrieve_btc&amp;lt;/code&amp;gt;: Instructs the ckBTC minter to burn a certain ckBTC amount and send the corresponding BTC amount, minus fees, to a provided Bitcoin address.&lt;br /&gt;
* &amp;lt;code&amp;gt;retrieve_btc_status&amp;lt;/code&amp;gt;: Returns the status of a previous &amp;lt;code&amp;gt;retrieve_btc&amp;lt;/code&amp;gt; call.&lt;br /&gt;
* &amp;lt;code&amp;gt;get_minter_info&amp;lt;/code&amp;gt;: Returns information about the ckBTC minter itself.&lt;br /&gt;
* &amp;lt;code&amp;gt;get_events&amp;lt;/code&amp;gt;: Returns a set of events at the ckBTC minter.&lt;br /&gt;
&lt;br /&gt;
The endpoints are discussed in more detail in the following sections.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;get_btc_address(owner: opt principal, subaccount: opt blob)&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
The provided principal ID and subaccount are concatenated to form the derivation path for the [https://internetcomputer.org/docs/current/references/ic-interface-spec#ic-ecdsa_public_key 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.&lt;br /&gt;
&lt;br /&gt;
This public key is encoded as a pay-to-witness-public-key-hash (P2WPKH) Bitcoin address and returned as a text.&lt;br /&gt;
&lt;br /&gt;
Note that the key derivation is not [https://en.bitcoin.it/wiki/BIP_0032 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.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;track_balance(owner: opt principal, subaccount: opt blob)&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&#039;&#039;&#039;NOTE: This endpoint is work-in-progress and not available yet.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The ckBTC minter starts tracking the Bitcoin address derived from the provided principal ID and subaccount using the &amp;lt;code&amp;gt;get_btc_address&amp;lt;/code&amp;gt; endpoint. 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.&lt;br /&gt;
&lt;br /&gt;
The balance of the Bitcoin address is not tracked indefinitely. Tracking is stopped if either at least one new unspent transaction output (UTXO) is discovered or there is no new UTXO within a certain time interval (details about balance tracking are provided below).&lt;br /&gt;
&lt;br /&gt;
If at least one new UTXO is discovered, the same amount of ckBTC tokens minus the KYT fee are minted and made available to the owner.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;update_balance(owner: opt principal, subaccount: opt blob)&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Instead of having the ckBTC minter track the balance of a Bitcoin address, the &amp;lt;code&amp;gt;update_balance&amp;lt;/code&amp;gt; function can be invoked to instruct the ckBTC minter to check if there are new UTXOs for a particular Bitcoin address.&lt;br /&gt;
&lt;br /&gt;
If there is at least one new UTXO, the corresponding ckBTC amount is minted, otherwise an error is returned.&lt;br /&gt;
&lt;br /&gt;
The ckBTC minter effectively invokes this endpoint itself on a timer when the &amp;lt;code&amp;gt;track_balance&amp;lt;/code&amp;gt; function is used.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;estimate_withdrawal_fee(amount: opt nat64)&amp;lt;/code&amp;gt; ====&lt;br /&gt;
The endpoint returns an estimate for the fee that must be paid when retrieving the given BTC amount. Internally, a transaction is built (without valid signatures) to determine the fee, which consists of the Bitcoin miner fee, the ckBTC minter fee, and the KYT fee. If no amount is provided, it is assumed that three inputs are required to build the transaction.&lt;br /&gt;
&lt;br /&gt;
If there is no change to the internal state of the ckBTC minter and the [https://github.com/dfinity/bitcoin-canister Bitcoin canister] before issuing the request to retrieve bitcoins, the fee will be exactly the returned estimate.&lt;br /&gt;
&lt;br /&gt;
The fee can change when a) a new Bitcoin block is mined in the meantime, which causes the Bitcoin canister to update the Bitcoin miner fees or b) another retrieval request is handled first, spending some of the outputs that were used when estimating the fee.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;get_deposit_fee&amp;lt;/code&amp;gt; ====&lt;br /&gt;
The endpoint returns the fee that the ckBTC minter charges for minting ckBTC when receiving new UTXOs. Currently, this fee is simply the KYT fee.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;get_withdrawal_account&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
The function returns the caller’s withdrawal account, which is the account derived from the ckBTC minter’s principal ID and the subaccount derived from the caller’s principal ID.&lt;br /&gt;
&lt;br /&gt;
A user can only retrieve BTC by first transferring ckBTC to this particular account.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;retrieve_btc(address: text, amount: nat64)&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
The function instructs the ckBTC minter to burn the specified amount. Once the request is picked up from the queue, a Bitcoin transaction is created containing an output that transfers the requested amount (minus fees as discussed below) to the specified Bitcoin address.&lt;br /&gt;
&lt;br /&gt;
Since Bitcoin retrieval is handled asynchronously, the function returns the block index of the transaction burning the ckBTC tokens.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;retrieve_btc_status(block_index: nat64)&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
The status of a BTC retrieval request can be checked using this function. The different possible statuses are:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Unknown&amp;lt;/code&amp;gt;: There is no information available on the ckBTC minter because there is no retrieval request associated with the given block index or the retrieval request is old and the corresponding information has already been removed.&lt;br /&gt;
* &amp;lt;code&amp;gt;Pending&amp;lt;/code&amp;gt;: The BTC retrieval request is queued.&lt;br /&gt;
* &amp;lt;code&amp;gt;Signing&amp;lt;/code&amp;gt;: The BTC retrieval request is acquiring all signatures to serve the BTC retrieval request.&lt;br /&gt;
* &amp;lt;code&amp;gt;Sending&amp;lt;/code&amp;gt;: The Bitcoin transaction serving the BTC retrieval request is being sent.&lt;br /&gt;
* &amp;lt;code&amp;gt;Submitted&amp;lt;/code&amp;gt;: The Bitcoin transaction has been transmitted. The transaction ID is returned.&lt;br /&gt;
* &amp;lt;code&amp;gt;AmountTooLow&amp;lt;/code&amp;gt;: The BTC retrieval request could not be served because the Bitcoin miner fees are prohibitively high.&lt;br /&gt;
* &amp;lt;code&amp;gt;Confirmed&amp;lt;/code&amp;gt;: The Bitcoin transaction serving the BTC retrieval request is confirmed inside the ckBTC minter, which happens when the transaction has at least the minimum required number of confirmations specified in the min_confirmations parameter above.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;get_minter_info&amp;lt;/code&amp;gt; ====&lt;br /&gt;
The function returns the following parameters internal to the ckBTC minter:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;kyt_fee&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;min_confirmations&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;retrieve_btc_min_amount&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;get_events(start: nat64, length: nat64)&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
The ckBTC minter tracks the events that change its internal state. Given a start index and a length parameter, the ckBTC minter returns all events sequentially from the event at the given start index up to the event at index start+length-1.&lt;br /&gt;
&lt;br /&gt;
Note that this endpoint is used for debugging purposes and there is no guarantee that the endpoint will continue to exist in this form.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* Code Bitcoin on the Internet Computer: https://internetcomputer.org/bitcoin-integration&lt;br /&gt;
* Chain-key tokens: https://internetcomputer.org/how-it-works/chain-key-tokens/ &lt;br /&gt;
* Chain-key Bitcoin developer documents: https://internetcomputer.org/docs/current/developer-docs/integrations/bitcoin/ckbtc&lt;/div&gt;</summary>
		<author><name>Jamongeon</name></author>
	</entry>
</feed>