Skip to content

Instantly share code, notes, and snippets.

@jachiang
Last active July 26, 2019 12:42
Show Gist options
  • Save jachiang/d7061a363075d3725f1f2d0f94790c0b to your computer and use it in GitHub Desktop.
Save jachiang/d7061a363075d3725f1f2d0f94790c0b to your computer and use it in GitHub Desktop.
Optech Taptree

Taproot Tree Construction

Taproot Descriptors

optech_taptree_desc

Parsing a Taproot Tree from a Descriptor (Github):

tp_desc = "tp(026bf6d12e669cb96afb170daedcc0affe36fad226e9bf2b49c2ef9519361bb882,[ts(pk(026bf6d12e669cb96afb170daedcc0affe36fad226e9bf2b49c2ef9519361bb882)),[ts(pk(029f093894657d515646e23042e5ba198a11e8dd8c315deb55db62e7cbc4bab047)),[ts(pk(025a59322be1a5b2f0bfb496c7a4808baf55a9c51f4be98aa475c5592a0b915f7e)),ts(raw(0337062390b186749bd7012d75081ed5e6445fda91df0cf669dc924fd3731ad4ca))]]])"

tp = TapTree()
tp.from_desc(tp_desc)

# Internal key.
print(tp.key.get_bytes().hex())

# TODO: Access tapleafs
for ts, height in tp.tapleafs:
    print(ts.desc, height)    
> 026bf6d12e669cb96afb170daedcc0affe36fad226e9bf2b49c2ef9519361bb882
> 1 ts(pk(026bf6d12e669cb96afb170daedcc0affe36fad226e9bf2b49c2ef9519361bb882))
> 2 ts(pk(029f093894657d515646e23042e5ba198a11e8dd8c315deb55db62e7cbc4bab047))
> 3 ts(pk(025a59322be1a5b2f0bfb496c7a4808baf55a9c51f4be98aa475c5592a0b915f7e))
> 3 ts(raw(0337062390b186749bd7012d75081ed5e6445fda91df0cf669dc924fd3731ad4ca))

Constructing a Taproot Tree Node-by-Node (Github):

# Generate Tapscripts
sks = []
pks = []
for i in range(3):
    sks.append(ECKey())
    sks[i].generate()
    pks.append(sks[i].get_pubkey())
            
tss , pk_map = TapLeaf.generate_threshold_csa(2, pks)

# Build Taptree
sk = ECKey()
sk.generate()
pk = sk.get_pubkey()

tp = TapTree()
tp.key = pk
tp.root.left = tss[0]
tp.root.right = Node()
tp.root.right.left = tss[1]
tp.root.right.right = tss[2]

print(tp.desc)
> tp(022b61f89536a1bb6aea835c2ecb0d7da28ee49df5c1c839a78d129f8b299982a7,[ts(csa(027205669cd60a64c0103bd9f6051112509544c6a873d94fc2a7cf3d140c24956b,027990d93c6834116d4e67ed0b17fe950ab8d26ccd51e4eaf34a2ff05c3772a046)),[ts(csa(027205669cd60a64c0103bd9f6051112509544c6a873d94fc2a7cf3d140c24956b,02e8b6708ab17e26b3d7d42e7063261deb8c9daffc7bc7df6194a982164d38bc37)),ts(csa(027990d93c6834116d4e67ed0b17fe950ab8d26ccd51e4eaf34a2ff05c3772a046,02e8b6708ab17e26b3d7d42e7063261deb8c9daffc7bc7df6194a982164d38bc37))]])

TapTree: Compiled from Spending Policy

TODO: Description of spending policy language and compilation to future descriptors (miniscript).

  • or(EXPR)

    • Can be split across multiple tapscripts.
    • Can also be included in a single tapscript.
    • Or expressions can be weighted for probability (N).
      • or(N@EXPR, N@EXPR, N@EXPR)
  • and(EXPR)

    • Must be included in a single tapscript.
  • thresh(NUM,EXPR,EXPR,...)

    • Expands to set of and(EXPR, EXPR,...) conditions.
    • Similar to multisig to n-of-n checksigadd expansion.
  • time(NUMBER)

    • A locktime condition which applies to given expression.
  • [EXPR, EXPR, EXPR], [EXPR, EXPR] - TODO: Proposed Privacy Expression

    • Expressions which can be revealed together.

optech_taptree_huffman

Compiling a or(N@EXPR, N@EXPR, N@EXPR) policy to a Taproot Tree (Github):

# Internal Key
sk = ECKey()
sk.generate()
pk = sk.get_pubkey()

# Generate Tapscripts
sks = []
pks = []
for i in range(4):
    sks.append(ECKey())
    sks[i].generate()
    pks.append(sks[i].get_pubkey())
            
tss , pk_map = TapLeaf.generate_threshold_csa(2, pks)

# Policy Expression: or(1@tss[0], 2@tss[1], 2@tss[2], 3@tss[3])
policy = [(1, tss[0]),(2, tss[2]),(2, tss[2]),(3, tss[3])]

tp_tree = TapTree()
tp_tree.key = pk
tp_tree.from_policy(policy)

print(tp_tree.desc)
> tp(037ac0ec57b1533bea08c86838c1836801a483ea3249f787df2b7fa5c4401603bf,[ts(csa(02c365c406e731d72ca4d40916136baecb4f44e2c3ae1915c79af92704b28f7ec7,036769d0fbf3bb5b92470cacd304bfdbc33db57ae2cd00edc281a0e9d3d3753004)),[ts(csa(023f2020fd0ce7cb51d32415b4f1e8690d484f9f7418ece988fc75116beecefa28,03cae7dd02fb9f6c4945584e339f3c38038b8498e07d6a8a4b299a920dedabb5a1)),[ts(csa(023f2020fd0ce7cb51d32415b4f1e8690d484f9f7418ece988fc75116beecefa28,02c365c406e731d72ca4d40916136baecb4f44e2c3ae1915c79af92704b28f7ec7)),ts(csa(023f2020fd0ce7cb51d32415b4f1e8690d484f9f7418ece988fc75116beecefa28,03cae7dd02fb9f6c4945584e339f3c38038b8498e07d6a8a4b299a920dedabb5a1))]]])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment