@@ -5,6 +5,10 @@ import * as crypto from 'crypto';
55import ECPairFactory from 'ecpair' ;
66import { describe , it } from 'mocha' ;
77
8+ import { convertScriptTree } from './payments.utils' ;
9+ import { LEAF_VERSION_TAPSCRIPT } from '../src/payments/taprootutils' ;
10+ import { tapTreeToList , tapTreeFromList } from '../src/psbt/bip371' ;
11+ import { Taptree } from '../src/types' ;
812import { initEccLib } from '../src' ;
913
1014const bip32 = BIP32Factory ( ecc ) ;
@@ -13,6 +17,7 @@ const ECPair = ECPairFactory(ecc);
1317import { networks as NETWORKS , payments , Psbt , Signer , SignerAsync } from '..' ;
1418
1519import * as preFixtures from './fixtures/psbt.json' ;
20+ import * as taprootFixtures from './fixtures/p2tr.json' ;
1621
1722const validator = (
1823 pubkey : Buffer ,
@@ -1099,6 +1104,67 @@ describe(`Psbt`, () => {
10991104 } ) ;
11001105 } ) ;
11011106
1107+ describe ( 'tapTreeToList/tapTreeFromList' , ( ) => {
1108+ it ( 'Correctly converts a Taptree to a Tapleaf list and back' , ( ) => {
1109+ taprootFixtures . valid
1110+ . filter ( f => f . arguments . scriptTree )
1111+ . map ( f => f . arguments . scriptTree )
1112+ . forEach ( scriptTree => {
1113+ const originalTree = convertScriptTree (
1114+ scriptTree ,
1115+ LEAF_VERSION_TAPSCRIPT ,
1116+ ) ;
1117+ const list = tapTreeToList ( originalTree ) ;
1118+ const treeFromList = tapTreeFromList ( list ) ;
1119+
1120+ assert . deepStrictEqual ( treeFromList , originalTree ) ;
1121+ } ) ;
1122+ } ) ;
1123+ it ( 'Throws if too many leaves on a given level' , ( ) => {
1124+ const list = Array . from ( { length : 5 } ) . map ( ( ) => ( {
1125+ depth : 2 ,
1126+ leafVersion : LEAF_VERSION_TAPSCRIPT ,
1127+ script : Buffer . from ( [ ] ) ,
1128+ } ) ) ;
1129+ assert . throws ( ( ) => {
1130+ tapTreeFromList ( list ) ;
1131+ } , new RegExp ( 'No room left to insert tapleaf in tree' ) ) ;
1132+ } ) ;
1133+ it ( 'Throws if taptree depth is exceeded' , ( ) => {
1134+ let tree : Taptree = [
1135+ { output : Buffer . from ( [ ] ) } ,
1136+ { output : Buffer . from ( [ ] ) } ,
1137+ ] ;
1138+ Array . from ( { length : 129 } ) . forEach (
1139+ ( ) => ( tree = [ tree , { output : Buffer . from ( [ ] ) } ] ) ,
1140+ ) ;
1141+ assert . throws ( ( ) => {
1142+ tapTreeToList ( tree as Taptree ) ;
1143+ } , new RegExp ( 'Max taptree depth exceeded.' ) ) ;
1144+ } ) ;
1145+ it ( 'Throws if tapleaf depth is to high' , ( ) => {
1146+ const list = [
1147+ {
1148+ depth : 129 ,
1149+ leafVersion : LEAF_VERSION_TAPSCRIPT ,
1150+ script : Buffer . from ( [ ] ) ,
1151+ } ,
1152+ ] ;
1153+ assert . throws ( ( ) => {
1154+ tapTreeFromList ( list ) ;
1155+ } , new RegExp ( 'Max taptree depth exceeded.' ) ) ;
1156+ } ) ;
1157+ it ( 'Throws if not a valid taptree structure' , ( ) => {
1158+ const tree = Array . from ( { length : 3 } ) . map ( ( ) => ( {
1159+ output : Buffer . from ( [ ] ) ,
1160+ } ) ) ;
1161+
1162+ assert . throws ( ( ) => {
1163+ tapTreeToList ( tree as Taptree ) ;
1164+ } , new RegExp ( 'Cannot convert taptree to tapleaf list. Expecting a tapree structure.' ) ) ;
1165+ } ) ;
1166+ } ) ;
1167+
11021168 describe ( 'getFeeRate' , ( ) => {
11031169 it ( 'Throws error if called before inputs are finalized' , ( ) => {
11041170 const f = fixtures . getFeeRate ;
0 commit comments