Author: Hiroki Gondo
Source: https://medium.com/nayuta-engineering-blog-en/understanding-taproot-assets-protocol-e2dfe3fc1e07
The Taproot Assets Protocol (formerly known as "Taro", hereafter abbreviated as "TAP") is a protocol for representing UTXO-based assets on Bitcoin. This article aims to explain how TAP creates and transfers assets.
The complete protocol is divided into many parts. This article mainly explains bip-tap and bit-tap-ms-smt.
The implementation by Lightning Labs can be found here .
What is Taproot?
“ Taproot ” is a new type of Bitcoin output that allows two types of spending conditions to be specified simultaneously: key Key Path spending and Script Path spending.

Key Path , like traditional P2PKH outputs, is spent using a signature from a public key. Schnorr signature key aggregation (multi-signature) can also be used in Taproot.
Script Path , like traditional P2SH, allows complex spending conditions to be programmed in a scripting language. And Taproot also allows multiple scripts to be specified at the same time. These scripts are not directly serialized in the Taproot output, but are constructed into a Merkle tree and compressed into a root hash value. When an output is spent using a script, only this script needs to be exposed (without exposing other scripts).
TAP embeds data (“Asset Tree”) in Script Pat . This data is unreadable and undetectable to Bitcoin nodes because it is hashed.

Asset Representation in Taproot Assets
Asset Tree
The asset tree is a two-level "sparse Merkle sum tree" structure that expresses the Taproot Assets protocol. The bottom level represents the UTXO of an asset (identified by an "asset id ( asset_id )"). The upper level aggregates the trees from the lower level.

The value of the root hash value ( asset_tree_root) of the previous Merkle tree is embedded in Script Path of a Taproot output, thereby committing to the state of the tree.
The transfer of assets also creates a new asset tree, and the old one is updated. This can be achieved by initiating a new Bitcoin transaction, spending the Taproot output of the old asset tree; transfers that do not meet the specifications (e.g. inflation, duplicate charges) are considered invalid. *
* The approach used here is a concept called “ client-side validation ”; readers familiar with Bitcoin’s prominent consensus may be curious about the basis for the correctness of the specification here, but I will ignore that question for now.
Sparse Merkle Sum Tree
"Sparse Merkle Sum Tree" (hereinafter referred to as "MS-SMT") is a variant of the Merkle tree, defined by bip-tap-ms-smt . Because its key is 256 bits, it has 2^256 leaves. Most of the leaves are empty.
Each leaf contains a quantity, and each branch node promises the sum of the quantities represented by the leaves in its subtree. Even if the contents of a subtree are unknown, the total quantity contained in the subtree can be known by simply checking the branch nodes. The root of the tree promises the total quantity represented by all leaves.
Just like a general Merkle tree, a pruned tree containing the target leaves is all that is needed to provide proof that the target leaves are in the tree (a Merkle proof). But MS-SMT also supports "non-containment proofs". This is achieved through a restriction: the number of leaves containing non-existent keywords must be explicitly set to a value indicating their non-existence (None) (so proving the existence of "None" constitutes a non-containment proof). Therefore, the default MS-SMT will have 2^256 leaves representing "None".
Asset Leaf (Asset UTXO)
The lower-level MS-MST of the asset tree uses asset_script_key as the key and asset leaves as the value. Each asset leaf represents a UTXO of the asset (for brevity, it will be directly expressed as "UTXO" below*), and the following attributes (including the optional one) will be serialized in the "type-length-value" format .
* Not Bitcoin's UTXO.
-
taproot_asset_version -
asset_genesis -
asset_id -
asset_type -
amt -
lock_time -
relative_lock_time -
prev_asset_witnesses
prev_asset_id
-asset_witness
-split_commitment_proof -
split_commitment -
asset_script_version -
asset_script_key -
asset_group_key -
canonical_universe
asset_genesis is the original image from which asset_id is derived.
asset_script_key is both a keyword for an asset leaf and a public key in Taproot form (defined in a separate tap-vm from Bitcoin) and is the condition for spending the UTXO represented by that asset leaf.
When spending a UTXO, first the (external) Bitcoin spending conditions must be satisfied, followed by the (internal) TAP spending conditions, specified by asset_script_key , which should be satisfied by asset_witness prev_asset_id and asset_script_key . For example, asset_witness is the signature of asset_script_key of the UTXO being spent.

If UTXO is split in an asset transfer, split_commitment and split_commitment_proof are also required.
split_commitment is a MS-SMT that refers to all UTXOs after the split (in this sense, the asset tree actually has three layers), and the sum in the root is the total amount transferred.
split_commitment_proof is a Merkle proof of split_commitment , proving the existence of a split.
Of all the splits, only one will have prev_asset_id , asset_witness , and split_commitment . All other splits will only have split_commitment_proof . All splits share prev_asset_id and asset_witness .
Asset Creation

Creating an asset requires embedding a new asset tree containing the UTXO of the new asset in a Taproot output of a Bitcoin transaction (this transaction becomes the genesis transaction of this asset). The ID of the asset ( asset_id ) is determined by the following formula.
asset_id := sha256(genesis_outpoint || sha256(asset_tag) || asset_meta_hash || output_index || asset_type) genesis_outpoint is the output of the previous transaction spent by this transaction, and output_index is the index number of the output containing this asset tree. This ensures that asset_id is globally unique.
Newly created asset UTXO omits prev_asset_id and asset_witness .
Asset transfer
Just like Bitcoin UTXO, asset UTXOs may be merged or split when assets are transferred. But let’s start with a simple example - there is neither splitting nor merging*.
* The following explanations are somewhat simplified. For example, the change output of Bitcoin transactions is omitted.

Alice has 10 assets, all of which are transferred to Bob.
Alice creates and broadcasts a Bitcoin transaction, spending the Taproot output of her asset UTXO. This transaction has two Taproot outputs. One output contains a new asset tree, including a new UTXO with 10 assets that Bob can control (for example, using Bob's Bitcoin public key). The other output contains an asset tree formed by removing the corresponding asset leaf from the original asset tree controlled by Alice.
The new UTXO belonging to Bob uses prev_asset_id to index Alice's previous UTXO. In asset_witness , there is the signature of the previous asset_script_key . And in asset_script_key of this new UTXO, there is a new public key given in advance by Bob.
Bob needs to verify that the spending conditions are met and that the assets have not been inflated since the transfer to confirm receipt of the payment.
- Does Bob's newly created asset tree contain a new UTXO that meets the spending conditions?
- Has the input UXTO been removed from Alice's updated asset tree?
- Are there other Taproot outputs in the transaction? Do they contain another asset tree? *
- etc.
This is all achieved by proving/verifying the inclusion/non-inclusion proofs of MS-SMT and the proofs and preimages output by Taproot.
* If another UTXO is added to another asset tree (not Bob's asset tree) and also spends the input UTXO, it constitutes a double spend.
Merging UTXOs

Alice has 3 and 7 of a certain asset in two leaves respectively, and wants to transfer all of them to Bob.
Each input UTXO can belong to a different asset tree, or a different key ( asset_script_key ) on the same asset tree. Bob's new UTXO should contain prev_asset_id and asset_witness for the two spent UTXOs.
Splitting UTXO

Alice has 7 of a certain asset and plans to transfer 3 to Bob. Therefore, Alice will keep 3 and Bob will get 7.
Alice's change UTXO will have prev_asset_id , asset_witness , and split_commitment ; Bot's new UTXO will only have split_commitment_proof *.
I will not explain how to merge and split UTXOs at the same time.
* This is slightly different from what the specification says, but it seems that this is how the latest implementations do it.
Asset transfer
Although there is no volume in front, before the asset transfer can be verified, each input UTXO must be verified to be legal. For each input UTXO, it must be proved/verified that every transaction in the entire circulation path from the creation transaction of the asset to the current input is executed correctly.

This path is a complex graph from the genesis transaction to the latest transaction. In the figure above, for Tx A , all blue transactions (its ancestor transactions) need to be verified; and for Tx B , all blue and red transactions need to be verified. This is a major scalability challenge because the history will grow quasi-exponentially.
In addition, since the original image and evidence required for verification are not published on the blockchain, how to transfer them between the sender and receiver of the asset is also a problem.
Scalability
The incremental history is a major scalability challenge. Multiple solutions have been proposed, but supporting the Lightning Network is the most promising one. Off-chain transactions do not increase the history.
The protocol is new and the specifications are incomplete. For example, I pointed out this problem before.




