Merkle-Sum Sparse Merkle tree and Taproot
Taproot Assets are registered on the Bitcoin blockchain in the form of hashed metadata attached to a transaction
output. This chapter details where and how it is stored.
Everything starts with a UTXO
Taproot allows a new way to create a conditions for a transaction output. You can now
lock the UTXO with the hash of a Taproot script tree (a merkle tree). This is how it looks like that:
graph TD
%% =============================================================================================================
%% Transaction
INPUT0["Input 0"]
INPUT1["Input 1"]
OUTPUT0["Output 0"]
OUTPUT1["Output 1 (Taproot)"]
OUTPUT2["Output 2"]
TRANSACTION["Bitcoin transaction"]
INPUT0 --> TRANSACTION
INPUT1 --> TRANSACTION
TRANSACTION --> OUTPUT0
TRANSACTION --> OUTPUT1
TRANSACTION --> OUTPUT2
%% =============================================================================================================
%% =============================================================================================================
%% Taproot
OUTPUT1 --> TAPROOT_ROOT_HASH["Taproot root hash"]
TAPROOT_ROOT_HASH --> HASH12["Hash(1&2)"]
TAPROOT_ROOT_HASH --> HASH3["Hash(3)"]
HASH12 --> HASH1["Hash(1)"]
HASH12 --> HASH2["Hash(2)"]
HASH1 --> SCRIPT1["Script 1
Requires alice & bob's signatures"]
HASH2 --> SCRIPT2["Script 2
Requires alice's signature"]
HASH3 --> SCRIPT3["Script 3
Requires bob's signatures & time lock"]
When someone will want to spend it, he will only have to provide a single leaf’s script, a merkle proof to show
inclusion in the tree, and fulfillment of the spending conditions of the script. To be more clear, you could, for
example, provides the script n°2 and the proof that this script is included in the tree having the hash stored in the
UTXO.
Where is our Merkle-Sum Sparse Merkle tree?
As we’ve seen in the previous chapter, our Taproot Assets are stored in a Merkle-Sum Sparse Merkle tree. The hash of our
Taproot Assets tree will be stored in one leaf of our Taproot script as you can see here:
graph TD
TAPROOT_ROOT_HASH["Taproot root hash"]
TAPROOT_ROOT_HASH --> HASH12["Hash(1&2)"]
TAPROOT_ROOT_HASH --> HASH3["Hash(3)"]
HASH12 --> HASH1["Hash(1)"]
HASH12 --> HASH2["Hash(2)"]
HASH1 --> SCRIPT1["Script 1
Requires alice & bob's signatures"]
HASH2 --> SCRIPT2["Script 2
Requires alice's signature"]
HASH3 --> SCRIPT3["Taproot Assets Count (300)
Taproot Assets Root Hash: Hash (00, 01, null, 11)"]
%% =============================================================================================================
%% Taproot Assets
SCRIPT3 -.-> HASH00-01["123, Hash (00, 01)"]
SCRIPT3 -.-> HASH10-11["177, Hash (null, 11)"]
HASH00-01 --> HASH01["113, Hash (00)"]
HASH00-01 --> HASH02["10, Hash (01)"]
HASH10-11 --> HASH03["0, Hash (null)"]
HASH10-11 --> HASH04["177, Hash (11)"]
HASH01 --> POSITION0["Position 1
Amount: 113 USDB"]
HASH02 --> POSITION1["Position 2
Amount: 10 USDB"]
HASH03 --> POSITION2["Position 3
Amount: 0 null"]
HASH04 --> POSITION3["Position 4
Amount: 177 USDB"]
Instead of having script 3, we stored there our Taproot Assets root. As a Taproot transaction look similar to any other
bitcoin transaction, the nodes won’t even know that Taproot Assets exists.