CHIP Number | 0020 |
---|---|
Title | Wallet Hinted Coin Discovery |
Description | Standardizes the method of discovering coins whose puzzles contain the wallet's inner puzzles. |
Author | Brandon Haggstrom |
Editor | Dan Perry |
Comments-URI | CHIPs repo, PR #81 |
Status | Final |
Category | Informational |
Sub-Category | Guideline |
Created | 2023-08-21 |
Requires | None |
Replaces | None |
Superseded-By | None |
Chia's coin set model sometimes makes it difficult for wallets to know which coins they have the ability to spend. The wallet needs to know either the puzzle hash or the parent id of the coins to find them on-chain. This is straightforward to do when the puzzles can be derived from the public key directly (such as the standard transaction). Often however, puzzles are composed together or contain state which changes their puzzle hash. The number of puzzle hash combinations increase exponentially with the assets the wallet has to check for. It's also possible for the wallet to be sent an asset which has a puzzle hash that it isn't familiar with, but that it can spend (for example, a Chia Asset Token with an unknown TAIL).
On the other hand, the number of inner puzzle hashes scales linearly and the wallet can easily calculate them. By including the inner puzzle hash as the first memo in the CREATE_COIN
condition (referred to as a hint), full nodes can perform a quick search for that inner puzzle hash and find each coin that matches it.
Coin hinting pre-dates the CHIP process and is already part of the Chia blockchain and reference wallet. The purpose of this CHIP is to document what hints are and standardize their use in wallets going forward.
Hints were originally implemented as a way to make it possible for wallets to discover assets which were previously unknown. For example, CATs are identified by a unique TAIL, and the wallet needs the TAIL before hand to calculate puzzle hashes and look up coins. Therefore, if someone were to send an unknown CAT to the wallet, it would have no idea that the coin was created.
With hints on the other hand, full nodes can notify the wallet of new coins that match each of the wallet's inner puzzle hashes. You can then check the puzzle reveal of the parent coin to find information about the TAIL. This same idea applies to any other coin with an outer puzzle.
As well as this, it's important to standardize how coins are discovered so that different wallet implementations are compatible with one another and can find coins created by other wallets. If every wallet used its own puzzles or coin discovery methods, coins would essentially be lost when switching between different apps.
Wallets which do not support hints will not be affected by the introduction of hints. The created coins are the same, and there is no change to the puzzles used. However, unhinted coins will not be visible to wallets which require hints and don't manually calculate puzzle hashes.
Versions of the full node prior to 1.2.8 do not track hints, and wallets which are connected to these older nodes will not find hinted coins.
In versions of Chia prior to 1.8.2, coin change produced as a result of CAT spends were not hinted. Because of this, wallets must find these older coins in one of two other ways:
- Request the children of every hinted CAT coin that has been spent, to find any potential change.
- Or, manually calculate each CAT puzzle for a given TAIL (by currying each inner puzzle), then fetch the coin records matching these puzzle hashes.
Since the release of 1.8.2, all created CAT coins are hinted in the Chia reference wallet. However, the wallet still looks for unhinted coins created by previous versions, in order to preserve backwards compatibility.
The CREATE_COIN
condition denotes the puzzle hash and amount of created coins. As such, it is a convenient place to store metadata about the coin, such as the hint. By using a list to store this value, it leaves the potential for adding more memos or new arguments to the condition in the future if needed.
This information could be stored off-chain instead, but this would create a dependency on a centralized external service and a single point of failure. Even though this information doesn't need to be trusted and can be validated on-chain, relying on a server to remain online in order to find hinted coins isn't ideal.
When a coin is spent, its puzzle is run with the solution as its input. The puzzle's output is a list of conditions, which must be satisfied in order for the spend to be valid.
Notably, the CREATE_COIN
condition is used to create new transaction outputs. It's defined as follows:
(51 puzzle_hash amount (...memos)?)
- The opcode for the
CREATE_COIN
condition is51
. - The first parameter,
puzzle_hash
, is the hash of the puzzle with which the new coin must be spent. - The second parameter,
amount
, is the value locked up in the coin, in mojos. - The third parameter,
memos
, is an optional list, which must be null terminated.
The first value in the memos
list (if present) is considered a hint in addition to a memo if it's exactly 32 bytes in length.
As an example, the following inner solution for the standard transaction would create an unhinted coin:
(() (q . ((51 target_puzzle_hash amount))) ())
The following solution would instead create a coin with the hint matching the inner puzzle hash:
(() (q . ((51 target_puzzle_hash amount (target_puzzle_hash)))) ())
This CREATE_COIN
condition creates the same coin as before, but now it specifies the hint with which the receiving wallet can look up to find this coin.
Hints are only necessary for outer puzzles where the inner puzzle's hash matches the hint. As an example, a coin whose puzzle is the standard transaction itself with no outer puzzle does not need a hint in order to be discovered by a wallet.
It is worth nothing that including a hint in the solution adds an additional CLVM cost of 384,000 (32 bytes * 12,000 cost per byte).
The following are links to test cases for coin hinting:
- Implementation of conditions in
chia_rs
, including tests for coin hinting. - CAT wallet tests for CAT hinting.
The following are links to the existing implementations of coin hinting in the reference client:
- The full node RPC
get_coin_records_by_hint
command for looking up coins by hint. - The official Chia reference wallet implements hinting for various primitives (such as CATs, NFTs, and DIDs).
There is no on-chain validation for memos. This means that the wallet can't know with absolute certainty that the hinted inner puzzle hash actually matches the inner puzzle of the coin until the puzzle reveal is constructed. Since this requires some computational work, it would be theoretically possible to spam a wallet by creating a bunch of incorrectly hinted coins. However, this is unlikely to be a real issue as long as the validation logic isn't excessively slow. It's a good idea to filter out extremely small coins (dust) early to make all forms of spam require more effort.
It is possible to use a very large memo in the CREATE_COIN
condition. However, if the first memo is not exactly 32 bytes, it will not be considered a hint, and as such won't be included in the full node's hint store.
It's also worth noting that a full node which keeps track of hints is technically using resources that are not strictly required by the blockchain. A hint is essentially 32 bytes of additional storage in the blockchain database that is only paid for once in the CLVM program, upsetting the carefully calculated resource usage to clvm cost ratio, which leads to slightly larger database sizes in the long term.
None
Copyright and related rights waived via CC0.