Convert Circuit

Convert Circuit Description

The high-level description of Convert can be found Burn and mint.

The Convert provides a mechanism that burning and minting of assets can be enabled by adding Convert Value Commitments in transaction and ensuring the homomorphic sum of Spend, Output and Convert value commitments to be zero.

The Convert value commitment is constructed from AllowedConversion which was published earlier in AllowedConversion Tree. The AllowedConversion defines the allowed conversion assets. The AllowedConversion Tree is a merkle hash tree stored in the ledger.


An AllowedConversion is a compound asset type in essence, which contains distinct asset types and the corresponding conversion ratios.

AllowedConversion is an array of tuple {(t1,v1ratio),(t2,v2ratio)...(tn,vnratio)}\{(t_1, v_1^{ratio}),(t_2, v_2^{ratio})...(t_n, v_n^{ratio})\}

  • tt: Blt\mathbb{B}^{\mathcal{l}_t} is a bytestring representing the asset identifier of the note.
  • vratiov^{ratio}: vratiov^{ratio} is a signed 64-bit integer in the range {263,,2631}\{−2^{63} ,\dots, 2^{63} − 1\}.


  • vbi:=reprJ(PRFvcgMASP(ti))vb_i := repr_{\mathbb{J}}(PRF^{vcgMASP}(t_i))
  • vballowedconversion=Σ1n([viratio]vbi)vb^{allowedconversion} = \Sigma_1^n([v_i^{ratio}]vb_i)
  • cmallowedconversion=PedersenHashToPoint(MASP__PH,[1]6vballowedconversion)cm^{allowedconversion} = \mathsf{PedersenHashToPoint}(''MASP\_\_PH'', [1]^6||vb^{allowedconversion})

Note that PedersenHashToPoint is used the same as in NoteCommitment for now.

An AllowedConversion can be issued, removed and modified as public conversion rule by consensus authorization and stored in AllowedConversion Tree as leaf node.

An AllowedConversion can be used by proving the existence in AllowedConversion Tree(must use the latest root anchor), and then generating a Convert Value Commitment to be used in transaction.

Convert Value Commitment

Convert Value Commitment is a tuple (vballowedconversion,vconvert,rcvconvert)(vb^{allowedconversion}, v^{convert}, rcv^{convert})

  • vconvertv^{convert}: vconvertv^{convert} is an unsigned integer representing the value of conversion in range [2641][2^{64} − 1].

Choose independent uniformly random commitment trapdoors:

  • rcvconvertrcv^{convert} ValueCommit.GenTrapdoor()\leftarrow \mathsf{ValueCommit}\mathsf{.GenTrapdoor}()

Check that hJreprJ(PRFvcgMASP(vballowedconversion))h_\mathbb{J}repr_{\mathbb{J}}(PRF^{vcgMASP}(vb^{allowedconversion})) is of type KASapling.PublicPrimeOrderKA^{Sapling}.PublicPrimeOrder, i.e. it is a valid ctEdwards Curve point on the JubjubCurve (as defined in the original Sapling specification) not equal to OJO_{\mathbb{J}}. If it is equal to OJO_{\mathbb{J}}, vballowedconversionvb^{allowedconversion} is an invalid asset identifier.


  • cvconvert=[vconverthJ]vballowedconversion+[rcvconvert]GroupHashURSJ(r)(MASP__r_,r)cv^{convert} = [v^{convert} h_\mathbb{J}]vb^{allowedconversion} + [rcv^{convert}]\mathsf{GroupHash}_{\mathsf{URS}}^{\mathsf{\mathbb{J}^{(r)*}}}(''MASP\_\_r\_'',''r'')

Note that GroupHashURSJ(r)(MASP__r_,r)\mathsf{GroupHash}_{\mathsf{URS}}^{\mathsf{\mathbb{J}^{(r)*}}}(''MASP\_\_r\_'',''r'') is used the same as in NoteCommitment for now.

AllowedConversion Tree

AllowedConversion Tree has the same structure as Note Commitment Tree and is an independent tree stored in ledger.

  • MerkleDepthConvert\mathsf{MerkleDepth^{Convert}}: 32(for now)
  • leaf node: cmallowedconversioncm^{allowedconversion}

Convert Statement

The Convert circuit has 47358 constraints.

Let lMerkleSaplingl_{MerkleSapling}, lscalarl_{scalar}, ValueCommit\mathsf{ValueCommit}, PedersenHashToPoint\mathsf{PedersenHashToPoint}, GroupHashURSJ(r)\mathsf{GroupHash}_{\mathsf{URS}}^{\mathsf{\mathbb{J}^{(r)*}}}, J\mathbb{J} be as defined in the original Sapling specification.

A valid instance of πconvert\pi_{convert} assures that given a primary input:

  • rtconvert:BlMerkleSaplingrt^{convert}: \mathbb{B}^{l_{MerkleSapling}}
  • cvconvert:ValueCommit.Outputcv^{convert}: \mathsf{ValueCommit.Output}

the prover knows an auxiliary input:

  • path:B[lMerkle][MerkleDepthConvert]path: \mathbb{B}^{[l_{Merkle}][MerkleDepth^{Convert}]}
  • pos:(0..2MerkleDepthConvert1)pos: (0..2^{MerkleDepth^{Convert}}-1)
  • cmallowedconversion:BMerkleSaplingcm^{allowedconversion}: \mathbb{B}^{MerkleSapling}
  • vballowedconversion:Jvb^{allowedconversion}: \mathbb{J}
  • rcvconvert:{0..2lscalar1})rcv^{convert}: \{0..2^{l_{scalar}}-1\})
  • vconvert:{0..2lconvert_value1}v^{convert}: \{0..2^{l_{convert\_value}}-1\}

such that the following conditions hold:

  • AllowedConversion cm integrity: cmallowedconversion=PedersenHashToPoint(MASP__PH,[1]6vballowedconversion)cm^{allowedconversion} = \mathsf{PedersenHashToPoint}(''MASP\_\_PH'', [1]^6||vb^{allowedconversion})

  • Merkle path validity: Either vconvertv^{convert} is 0; or (path,pos)(path, pos) is a valid Merkle path of depth MerkleDepthConvertMerkleDepth^{Convert}, as as defined in the original Sapling specification, from cmallowedconversioncm^{allowedconversion} to the anchor rtconvertrt^{convert}

  • Small order checks: vballowedconversionvb^{allowedconversion} is not of small order, i.e.[hJ]vballowedconversionOJ[h_\mathbb{J}]vb^{allowedconversion} \neq O_\mathbb{J}.

  • Convert Value Commitment integrity: cvconvert=[vconverthJ]vballowedconversion+[rcvconvert]GroupHashURSJ(r)(MASP__r_,r)cv^{convert} = [v^{convert} h_\mathbb{J}]vb^{allowedconversion} + [rcv^{convert}]\mathsf{GroupHash}_{\mathsf{URS}}^{\mathsf{\mathbb{J}^{(r)*}}}(''MASP\_\_r\_'',''r'')

Return (cvconvert,rtconvert,πconvert)(cv^{convert}, rt^{convert},\pi_{convert})


  • Public and auxiliary inputs MUST be constrained to have the types specified. In particular, see the original Sapling specification, for required validity checks on compressed representations of Jubjub curve points. The ValueCommit.Output type also represents points, i.e. J\mathbb{J}.
  • In the Merkle path validity check, each layer does not check that its input bit sequence is a canonical encoding(in [rS1][r_{\mathbb{S}} − 1]) of the integer from the previous layer.

Incentive Description

Incentive system provide a mechanism in which the old asset(input) is burned, the new asset(output) is minted with the same quantity and incentive asset(reward) is minted with the convert ratio meanwhile.

Incentive AllowedConversion Tree

As described in Convert circuit, the AllowedConversion Tree is an independent merkle tree in the ledger and contains all the Incentive AllowedConversions.

Incentive AllowedConversion Struct

In general, there are three items in Incentive AllowedConversion Struct(but not mandatory?),i.e. input, output and reward. And each item has an asset type and a quantity(i64, for the convert ratio).

Note that the absolute value of input and output must be consistent in incentive system. The quantity of input is negative and the quantity of output is positive.

To guarantee the input and output to be open as the same asset type in future unshielding transactions, the input and output assets have the same prefix description(e.g. BTC_1, BTC_2...BTC_n). To prevent repeated shielding and unshielding and encourage long-term contribution to privacy pool, the postfix timestamp is used to distinguish the input and output assets. The timestamp depends on the update period and can be defined flexibly (e.g. date, epoch num). When a new timestamp occurs, the AllowedConversion will be updated to support all the "history asset" conversion to the latest one.

Incentive AllowedConversion Operation

Incentive AllowedConversion is governed by the incentive system, which will be in charge of issuing new incentive plan, updating(modifying) to the latest timestamp, and removing disabled conversion permissions.

  • Issue
    • Issue a new incentive plan for new asset.
    • Issue for the last latest AllowedConversion when new timestamp occurs.
  • Update
    • For every new timestamp that occurs, update the existing AllowedConversion. Keep the input but update the output to the latest asset and modify the reward quantity according to the ratio.
  • Destroy
    • Delete the AllowedConversion from the tree.
  • Query Service
    • A service for querying the latest AllowedConversion, return (anchor, path, AllowedConversion).

Workflow from User's Perspective

  • Shielding transaction
    • Query the latest timestamp for target asset(non-latest will be rejected in tx execution)
    • Construct a target shielded note and shielding tx
    • Add the note to shielded pool if tx executes successfully(check the prefix and the latest timestamp).
  • Converting transaction
    • Construct spend notes from shielded notes
    • Construct convert notes(query the latest AllowedConversion)
    • Construct output notes
    • Construct convert tx
    • Get incentive output notes with latest timestamp and rewards if tx executes successfully
  • Unshielding transaction
    • Construct unshielding transaction
    • Get unshielded note if tx executes successfully(check the prefix)