1
1
'use strict' ;
2
2
Object . defineProperty ( exports , '__esModule' , { value : true } ) ;
3
- exports . fastMerkleRoot = void 0 ;
3
+ exports . computeMastRoot = exports . fastMerkleRoot = void 0 ;
4
+ const buffer_1 = require ( 'buffer' ) ;
5
+ const bcrypto = require ( './crypto' ) ;
6
+ // todo: use varuint-bitcoin??
7
+ const varuint = require ( 'bip174/src/lib/converter/varint' ) ;
8
+ const TAP_LEAF_TAG = buffer_1 . Buffer . from ( 'TapLeaf' , 'utf8' ) ;
9
+ const TAP_BRANCH_TAG = buffer_1 . Buffer . from ( 'TapBranch' , 'utf8' ) ;
10
+ const LEAF_VERSION_TAPSCRIPT = 0xc0 ;
4
11
function fastMerkleRoot ( values , digestFn ) {
5
12
if ( ! Array . isArray ( values ) ) throw TypeError ( 'Expected values Array' ) ;
6
13
if ( typeof digestFn !== 'function' )
@@ -20,3 +27,40 @@ function fastMerkleRoot(values, digestFn) {
20
27
return results [ 0 ] ;
21
28
}
22
29
exports . fastMerkleRoot = fastMerkleRoot ;
30
+ // todo: solve any[]
31
+ function computeMastRoot ( scripts ) {
32
+ if ( scripts . length === 1 ) {
33
+ const script = scripts [ 0 ] ;
34
+ if ( Array . isArray ( script ) ) {
35
+ return computeMastRoot ( script ) ;
36
+ }
37
+ script . version = script . version || LEAF_VERSION_TAPSCRIPT ;
38
+ if ( ( script . version & 1 ) !== 0 ) throw new Error ( 'Invalid script version' ) ; // todo typedef error
39
+ // todo: if (script.output)scheck is bytes
40
+ const scriptOutput = buffer_1 . Buffer . from ( script . output , 'hex' ) ;
41
+ return bcrypto . taggedHash (
42
+ TAP_LEAF_TAG ,
43
+ buffer_1 . Buffer . concat ( [
44
+ buffer_1 . Buffer . from ( [ script . version ] ) ,
45
+ serializeScript ( scriptOutput ) ,
46
+ ] ) ,
47
+ ) ;
48
+ }
49
+ // todo: this is a binary tree, use zero an one index
50
+ const half = Math . trunc ( scripts . length / 2 ) ;
51
+ let leftHash = computeMastRoot ( scripts . slice ( 0 , half ) ) ;
52
+ let rightHash = computeMastRoot ( scripts . slice ( half ) ) ;
53
+ if ( leftHash . compare ( rightHash ) === 1 )
54
+ [ leftHash , rightHash ] = [ rightHash , leftHash ] ;
55
+ return bcrypto . taggedHash (
56
+ TAP_BRANCH_TAG ,
57
+ buffer_1 . Buffer . concat ( [ leftHash , rightHash ] ) ,
58
+ ) ;
59
+ }
60
+ exports . computeMastRoot = computeMastRoot ;
61
+ function serializeScript ( s ) {
62
+ const varintLen = varuint . encodingLength ( s . length ) ;
63
+ const buffer = buffer_1 . Buffer . allocUnsafe ( varintLen ) ; // better
64
+ varuint . encode ( s . length , buffer ) ;
65
+ return buffer_1 . Buffer . concat ( [ buffer , s ] ) ;
66
+ }
0 commit comments