Mining manufacturer tech guidelines
This page lists numerous things mining manufacturers should think about on a technical level before releasing a product to ensure it will work best with Bitcoin.
The term "core" is used here to denote the smallest logical hashing unit in a device. What this actually represents may vary from device to device, but the smaller it can be without hurting performance the better, since software can always abstract them as groups.
Things to do
- Provide a simple way for mining software to discover firmware version, features, and an overview of the hardware situation (such as number of cores, possibly arrangement of those cores, etc). Don't rely on the software making assumptions about the device: surely you plan to produce new devices in the future, so ensure everything that could change can be determined from an inquiry. One often overlooked parameter to include, is thermal expectations: what temperature is considered "normal" for this device, and at what level should the mining software default to shutting it down?
- When your connection interface supports exposing a unique identifier, make use of it. For USB devices, this generally includes at least the String descriptors for Manufacturer and Product. Be sure to make the Product string as unique as possible, and unlikely to be confused with other (possibly non-mining) devices. Software should not be expected to look at the Manufacturer string to determine if the device is for mining: you may license your design to another manufacturer in the future, who should be able to use their own Manufacturer string without breaking compatibility with mining software that works with yours.
- Each individual unit should have a unique serial number, ideally accessible from (e.g.) the USB Serial string descriptor. This is important for users who have many to keep track of them for configuration or other purposes.
- Regular status reports about work actually performed give the mining software and user a good way to tell what exactly is going on, and ability to diagnose problems. These reports should preferably include information in as much detail as possible, particularly at a per-core level. Ideal information would include, per core, at least temperature and actual number of hashes performed since the previous report. Results (nonces) should also include information about which core was responsible for finding it.
- Do report work completion independently from results. Results should be reported immediately to minimise stale shares, and there may be many (or none) for each work item.
- If you are using a "stratum-like" interface, where you generate block headers from a compressed template, be sure to properly test it. That means feeding it 1 MB blocks with 250 kB generation transactions (FIXME: is 250 kB a reasonable cutoff size? probably should have a "size after the extranonce" too...), being updated every few seconds (BFGMiner 4.8+ has a --benchmark-intense mode to simulate this). Note that a Raspberry Pi or BeagleBone Black is *not* powerful enough to satisfy this. Canaan Creative has a FPGA solution for a LM32 CPU with SHA256d acceleration which might be handy if you want to go this route.
- Avoid becoming idle during work updates. Provide a way for new jobs to be sent prior to flushing old ones out, and ensure there are sufficient queues in place to keep the cores busy at all times.
- Allow flushing the queue of pending headers independently from interrupting actual hashing, so work can be updated without a performance hit. This can occur often, even when there isn't a new block on the network.
- Some way to interrupt and clear work is a good idea to allow mining software to avoid confusion when it's being restarted; failure to do this can result in novice users getting confused by false "hardware error" reports resulting from unknown jobs.
- Implement a thermal cutoff at close to the temperature sensors as possible. The controlling computer may be busy or possibly crash right at an inopportune time, or even simply not get temperature reports quick enough, leading to chip meltdown since it isn't turned off in time. This thermal cutoff should only be at a point where impending damage is certain; below that, mining software should implement their own (user-configurable) thermal cutoff limits.
- It is likely that some miners will only cover electrical costs in certain circumstances, such as transaction fees being above a certain threshold or power costs being lower during some part of the day. When the device is idle, such as following an interrupt-and-clear work request, you should ideally avoid using any more power than necessary so mining software can automate this routine.
- Provide a user-friendly way to upgrade firmware. No software (including firmware) is perfect, and even if things work flawlessly, there may be a desire to upgrade it in the future due to unforeseeable circumstances.
- Some miners wish to lease out part of their mining units. If you can do so, it would be beneficial to allow queuing work per core so that these users can lease out specific cores within their miners.
- Disabling and enabling specific cores tends to be helpful for troubleshooting problems. Providing a way to do that is important to minimising user headaches and wasted hardware.
- If you can, equip your ASICs with an alternative proof-of-work algorithm. It can share all the same circuits as the usual SHA256d, but as long as there is some difference you can fall back on, the Bitcoin network has the option to switch to these "fall-back" PoW algorithms in the event of an "unbeatable" 51% attack. It's unlikely that the PoW algorithm will be changed at this point, but it's not completely unthinkable, and having such a fall-back algorithm shouldn't be complicated or expensive. (Obviously don't share this alternate algorithm with others unless such an event occurs)
- Smart Property ASICs. This is the future, and solves the "datacenter centralisation" problem, potentially allowing 100% of all mining to be done in the same datacenter with minimal risk to the Bitcoin network. Your ASICs should be at the very least have a tiny bit of NVRAM to store the public key of their owner, and refuse to process work unless it is signed by that key. The keyholder must also be able to sign ownership of the ASIC over to another public key. Ideally, this would be implemented in such a way that the transfer-of-ownership requires a SPV proof of a valid transaction in the Bitcoin blockchain at a certain depth, so such a sale can be performed atomically (ie, the payment and ASIC ownership are exchanged in the same Bitcoin transaction). Advanced designs may support leasing chips, or selling individual cores within a chip. It may be wise to build a microcontroller into the ASIC itself to manage all of this. In the case of a programmable chip, you should ensure there is no way to "fool" someone into thinking ownership has changed (or will change) when it does not (will not). In the case of a leasable chip, this may require a hardware "firmware attestation" feature, or an architecture capable of generating zk-SNARK proofs.
Things NOT to do
- Don't try to talk directly to mining pools. Mining protocols change, and will continue to change. Resources required to implement those mining protocols will grow, and miners are expected (and will be expected more in the future) to run their own bitcoin node for transaction selection locally. Mining will always require a PC controller, and trying to embed this logic just does Bitcoin and your customers a disfavour by limiting them going forward.
- Don't assume you can roll nonces of block headers. While in general, this is fairly safe to do, the nonce header is intended to be representative of the time a block was found, it is not an extra nonce header. Even when the ntime header is safe to change, mining software should be adjusting it to be the approximate time. In some cases, it may be wise to take advantage of ntime rolling in hardware to reduce bandwidth between the PC and controller, but ideally it should be configurable per-job and not required.
- Don't abuse the block version as an extra nonce. This is even more important than not messing with the block ntime: changing the version may cause your blocks to be rejected, delayed, or (most likely today!) trigger alarms to regular everyday bitcoin users!
- Don't require polling the device constantly for results. Get results to the mining software as quickly as possible, to minimise stale shares. An asynchronous model is ideal to ensure results don't get confused with responses to requests, and so multiple requests can be issued without waiting for a response between each.