@vbyte/btc-dev 1.1.8 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/README.md +260 -3
  3. package/dist/const.d.ts +3 -0
  4. package/dist/const.js +23 -22
  5. package/dist/index.d.ts +11 -11
  6. package/dist/index.js +10 -10
  7. package/dist/lib/address/api.d.ts +2 -2
  8. package/dist/lib/address/api.js +12 -12
  9. package/dist/lib/address/encode.d.ts +1 -1
  10. package/dist/lib/address/encode.js +24 -24
  11. package/dist/lib/address/index.d.ts +6 -6
  12. package/dist/lib/address/index.js +6 -6
  13. package/dist/lib/address/p2pkh.d.ts +2 -2
  14. package/dist/lib/address/p2pkh.js +14 -14
  15. package/dist/lib/address/p2sh.d.ts +2 -2
  16. package/dist/lib/address/p2sh.js +13 -13
  17. package/dist/lib/address/p2tr.d.ts +2 -2
  18. package/dist/lib/address/p2tr.js +13 -13
  19. package/dist/lib/address/p2wpkh.d.ts +2 -2
  20. package/dist/lib/address/p2wpkh.js +14 -14
  21. package/dist/lib/address/p2wsh.d.ts +2 -2
  22. package/dist/lib/address/p2wsh.js +13 -13
  23. package/dist/lib/address/script.d.ts +1 -1
  24. package/dist/lib/address/script.js +16 -16
  25. package/dist/lib/address/util.d.ts +1 -1
  26. package/dist/lib/address/util.js +22 -22
  27. package/dist/lib/meta/index.d.ts +4 -4
  28. package/dist/lib/meta/index.js +4 -4
  29. package/dist/lib/meta/locktime.d.ts +1 -1
  30. package/dist/lib/meta/locktime.js +12 -12
  31. package/dist/lib/meta/ref.js +9 -6
  32. package/dist/lib/meta/scribe.d.ts +2 -2
  33. package/dist/lib/meta/scribe.js +48 -53
  34. package/dist/lib/meta/sequence.d.ts +1 -1
  35. package/dist/lib/meta/sequence.js +16 -15
  36. package/dist/lib/script/decode.d.ts +2 -2
  37. package/dist/lib/script/decode.js +50 -15
  38. package/dist/lib/script/encode.d.ts +1 -1
  39. package/dist/lib/script/encode.js +20 -16
  40. package/dist/lib/script/index.d.ts +5 -13
  41. package/dist/lib/script/index.js +5 -14
  42. package/dist/lib/script/lock.d.ts +2 -2
  43. package/dist/lib/script/lock.js +15 -12
  44. package/dist/lib/script/util.js +4 -4
  45. package/dist/lib/script/words.js +129 -129
  46. package/dist/lib/sighash/index.d.ts +3 -3
  47. package/dist/lib/sighash/index.js +3 -3
  48. package/dist/lib/sighash/segwit.d.ts +2 -2
  49. package/dist/lib/sighash/segwit.js +15 -14
  50. package/dist/lib/sighash/taproot.d.ts +2 -2
  51. package/dist/lib/sighash/taproot.js +24 -23
  52. package/dist/lib/sighash/util.d.ts +2 -2
  53. package/dist/lib/sighash/util.js +7 -7
  54. package/dist/lib/signer/index.d.ts +2 -2
  55. package/dist/lib/signer/index.js +2 -2
  56. package/dist/lib/signer/sign.d.ts +1 -1
  57. package/dist/lib/signer/sign.js +42 -7
  58. package/dist/lib/signer/verify.d.ts +17 -3
  59. package/dist/lib/signer/verify.js +233 -3
  60. package/dist/lib/taproot/cblock.d.ts +1 -1
  61. package/dist/lib/taproot/cblock.js +14 -16
  62. package/dist/lib/taproot/encode.d.ts +1 -1
  63. package/dist/lib/taproot/encode.js +7 -7
  64. package/dist/lib/taproot/index.d.ts +4 -4
  65. package/dist/lib/taproot/index.js +4 -4
  66. package/dist/lib/taproot/parse.d.ts +1 -1
  67. package/dist/lib/taproot/parse.js +12 -14
  68. package/dist/lib/taproot/tree.d.ts +2 -2
  69. package/dist/lib/taproot/tree.js +11 -7
  70. package/dist/lib/tx/create.d.ts +1 -1
  71. package/dist/lib/tx/create.js +28 -12
  72. package/dist/lib/tx/decode.d.ts +2 -2
  73. package/dist/lib/tx/decode.js +50 -17
  74. package/dist/lib/tx/encode.d.ts +2 -2
  75. package/dist/lib/tx/encode.js +13 -16
  76. package/dist/lib/tx/index.d.ts +7 -7
  77. package/dist/lib/tx/index.js +7 -7
  78. package/dist/lib/tx/parse.d.ts +1 -1
  79. package/dist/lib/tx/parse.js +9 -9
  80. package/dist/lib/tx/size.d.ts +2 -2
  81. package/dist/lib/tx/size.js +9 -9
  82. package/dist/lib/tx/util.d.ts +2 -2
  83. package/dist/lib/tx/util.js +23 -20
  84. package/dist/lib/tx/validate.d.ts +1 -1
  85. package/dist/lib/tx/validate.js +3 -3
  86. package/dist/lib/witness/index.d.ts +2 -2
  87. package/dist/lib/witness/index.js +2 -2
  88. package/dist/lib/witness/parse.d.ts +2 -2
  89. package/dist/lib/witness/parse.js +24 -23
  90. package/dist/lib/witness/util.d.ts +2 -2
  91. package/dist/lib/witness/util.js +5 -5
  92. package/dist/main.cjs +2308 -1005
  93. package/dist/main.cjs.map +1 -1
  94. package/dist/module.mjs +2308 -1005
  95. package/dist/module.mjs.map +1 -1
  96. package/dist/package.json +20 -17
  97. package/dist/schema/base.d.ts +1 -1
  98. package/dist/schema/base.js +17 -13
  99. package/dist/schema/index.d.ts +2 -2
  100. package/dist/schema/index.js +2 -2
  101. package/dist/schema/taproot.d.ts +1 -1
  102. package/dist/schema/taproot.js +2 -2
  103. package/dist/schema/tx.d.ts +1 -1
  104. package/dist/schema/tx.js +4 -4
  105. package/dist/script.js +8 -8
  106. package/dist/script.js.map +1 -1
  107. package/dist/types/address.d.ts +4 -4
  108. package/dist/types/index.d.ts +8 -8
  109. package/dist/types/index.js +8 -8
  110. package/dist/types/meta.d.ts +4 -4
  111. package/dist/types/psbt.d.ts +2 -2
  112. package/dist/types/script.d.ts +2 -2
  113. package/dist/types/sighash.d.ts +2 -2
  114. package/dist/types/witness.d.ts +5 -5
  115. package/package.json +20 -17
  116. package/src/const.ts +0 -61
  117. package/src/index.ts +0 -13
  118. package/src/lib/address/api.ts +0 -50
  119. package/src/lib/address/encode.ts +0 -183
  120. package/src/lib/address/index.ts +0 -7
  121. package/src/lib/address/p2pkh.ts +0 -94
  122. package/src/lib/address/p2sh.ts +0 -96
  123. package/src/lib/address/p2tr.ts +0 -91
  124. package/src/lib/address/p2wpkh.ts +0 -94
  125. package/src/lib/address/p2wsh.ts +0 -92
  126. package/src/lib/address/script.ts +0 -63
  127. package/src/lib/address/util.ts +0 -87
  128. package/src/lib/meta/index.ts +0 -4
  129. package/src/lib/meta/locktime.ts +0 -57
  130. package/src/lib/meta/ref.ts +0 -107
  131. package/src/lib/meta/scribe.ts +0 -256
  132. package/src/lib/meta/sequence.ts +0 -146
  133. package/src/lib/script/decode.ts +0 -85
  134. package/src/lib/script/encode.ts +0 -129
  135. package/src/lib/script/index.ts +0 -20
  136. package/src/lib/script/lock.ts +0 -73
  137. package/src/lib/script/util.ts +0 -78
  138. package/src/lib/script/words.ts +0 -182
  139. package/src/lib/sighash/index.ts +0 -3
  140. package/src/lib/sighash/segwit.ts +0 -152
  141. package/src/lib/sighash/taproot.ts +0 -206
  142. package/src/lib/sighash/util.ts +0 -51
  143. package/src/lib/signer/index.ts +0 -2
  144. package/src/lib/signer/sign.ts +0 -39
  145. package/src/lib/signer/verify.ts +0 -88
  146. package/src/lib/taproot/cblock.ts +0 -96
  147. package/src/lib/taproot/encode.ts +0 -49
  148. package/src/lib/taproot/index.ts +0 -4
  149. package/src/lib/taproot/parse.ts +0 -65
  150. package/src/lib/taproot/tree.ts +0 -94
  151. package/src/lib/tx/create.ts +0 -90
  152. package/src/lib/tx/decode.ts +0 -123
  153. package/src/lib/tx/encode.ts +0 -155
  154. package/src/lib/tx/index.ts +0 -7
  155. package/src/lib/tx/parse.ts +0 -69
  156. package/src/lib/tx/size.ts +0 -68
  157. package/src/lib/tx/util.ts +0 -111
  158. package/src/lib/tx/validate.ts +0 -49
  159. package/src/lib/witness/index.ts +0 -2
  160. package/src/lib/witness/parse.ts +0 -127
  161. package/src/lib/witness/util.ts +0 -18
  162. package/src/schema/base.ts +0 -57
  163. package/src/schema/index.ts +0 -2
  164. package/src/schema/taproot.ts +0 -12
  165. package/src/schema/tx.ts +0 -48
  166. package/src/types/address.ts +0 -35
  167. package/src/types/index.ts +0 -8
  168. package/src/types/meta.ts +0 -48
  169. package/src/types/psbt.ts +0 -15
  170. package/src/types/script.ts +0 -18
  171. package/src/types/sighash.ts +0 -16
  172. package/src/types/taproot.ts +0 -41
  173. package/src/types/txdata.ts +0 -85
  174. package/src/types/witness.ts +0 -42
@@ -1,39 +0,0 @@
1
- import { Buff } from '@vbyte/buff'
2
- import { ECC } from '@vbyte/micro-lib'
3
- import { parse_tx } from '@/lib/tx/parse.js'
4
- import { SIGHASH_DEFAULT } from '@/const.js'
5
- import { hash_segwit_tx } from '@/lib/sighash/segwit.js'
6
- import { hash_taproot_tx } from '@/lib/sighash/taproot.js'
7
-
8
- import type {
9
- SigHashOptions,
10
- TxData
11
- } from '@/types/index.js'
12
-
13
- export function sign_segwit_tx (
14
- seckey : string,
15
- txdata : TxData,
16
- options : SigHashOptions,
17
- ) {
18
- const tx = parse_tx(txdata)
19
- const msg = hash_segwit_tx(tx, options)
20
- const sig = ECC.sign_ecdsa(seckey, msg).hex
21
- const flag = format_sigflag(options.sigflag ?? SIGHASH_DEFAULT)
22
- return sig + flag
23
- }
24
-
25
- export function sign_taproot_tx (
26
- seckey : string,
27
- txdata : TxData,
28
- options : SigHashOptions,
29
- ) {
30
- const tx = parse_tx(txdata)
31
- const msg = hash_taproot_tx(tx, options)
32
- const sig = ECC.sign_bip340(seckey, msg).hex
33
- const flag = format_sigflag(options.sigflag ?? 0)
34
- return sig + flag
35
- }
36
-
37
- function format_sigflag (flag : number) {
38
- return (flag !== 0) ? Buff.num(flag, 1).hex : ''
39
- }
@@ -1,88 +0,0 @@
1
- import { Bytes } from '@vbyte/buff'
2
-
3
- import type {
4
- SigHashOptions,
5
- TxData
6
- } from '@/types/index.js'
7
-
8
- export function verify_tx (
9
- _txdata : TxData | Bytes,
10
- _config : SigHashOptions = {}
11
- ) : boolean {
12
- console.warn('verify_segwit_tx is not implemented')
13
- return true
14
- }
15
-
16
- // export function verify_signature (
17
- // txdata : TxData | Bytes,
18
- // index : number,
19
- // config : HashConfig = {}
20
- // ) : boolean {
21
- // const tx = Tx.fmt.toJson(txdata)
22
- // const { throws = false } = config
23
- // const { prevout, witness = [] } = tx.vin[index]
24
- // const witnessData = Tx.util.readWitness(witness)
25
- // const { cblock, script, params } = witnessData
26
-
27
- // let pub : Buff
28
-
29
- // if (params.length < 1) {
30
- // return safeThrow('Invalid witness data: ' + String(witness), throws)
31
- // }
32
-
33
- // const { scriptPubKey } = prevout ?? {}
34
-
35
- // if (scriptPubKey === undefined) {
36
- // return safeThrow('Prevout scriptPubKey is empty!', throws)
37
- // }
38
-
39
- // const { type, data: tapkey } = Tx.util.readScriptPubKey(scriptPubKey)
40
-
41
- // if (type !== 'p2tr') {
42
- // return safeThrow('Prevout script is not a valid taproot output:' + tapkey.hex, throws)
43
- // }
44
-
45
- // if (tapkey.length !== 32) {
46
- // return safeThrow('Invalid tapkey length: ' + String(tapkey.length), throws)
47
- // }
48
-
49
- // if (
50
- // cblock !== null &&
51
- // script !== null
52
- // ) {
53
- // const version = cblock[0] & 0xfe
54
- // const target = getTapLeaf(script, version)
55
- // config.extension = target
56
-
57
- // if (!checkPath(tapkey, target, cblock, { throws })) {
58
- // return safeThrow('cblock verification failed!', throws)
59
- // }
60
- // }
61
-
62
- // if (config.pubkey !== undefined) {
63
- // pub = Buff.bytes(config.pubkey)
64
- // } else if (params.length > 1 && params[1].length === 32) {
65
- // pub = Buff.bytes(params[1])
66
- // } else {
67
- // pub = Buff.bytes(tapkey)
68
- // }
69
-
70
- // const rawsig = Script.fmt.toParam(params[0])
71
- // const stream = new Stream(rawsig)
72
- // const signature = stream.read(64).raw
73
-
74
- // if (stream.size === 1) {
75
- // config.sigflag = stream.read(1).num
76
- // if (config.sigflag === 0x00) {
77
- // return safeThrow('0x00 is not a valid appended sigflag!', throws)
78
- // }
79
- // }
80
-
81
- // const hash = hashTx(tx, index, config)
82
-
83
- // if (!verify(signature, hash, pub, throws)) {
84
- // return safeThrow('Invalid signature!', throws)
85
- // }
86
-
87
- // return true
88
- // }
@@ -1,96 +0,0 @@
1
- import { Buff, Bytes } from '@vbyte/buff'
2
- import { Assert, ECC } from '@vbyte/micro-lib'
3
- import { merkleize } from './tree.js'
4
- import { TAPLEAF_DEFAULT_VERSION } from '@/const.js'
5
- import * as Schema from '@/schema/index.js'
6
-
7
- import {
8
- encode_tapbranch,
9
- encode_taptweak
10
- } from './encode.js'
11
-
12
- import {
13
- parse_pubkey_parity,
14
- parse_cblock
15
- } from './parse.js'
16
-
17
- import {
18
- TaprootConfig,
19
- TaprootContext
20
- } from '@/types/index.js'
21
-
22
- const DEFAULT_VERSION = TAPLEAF_DEFAULT_VERSION
23
-
24
- export function create_taproot (config : TaprootConfig) : TaprootContext {
25
- Schema.taproot.config.parse(config)
26
-
27
- const { pubkey, version = DEFAULT_VERSION } = config
28
-
29
- const leaves = config.leaves ?? []
30
-
31
- const target = (config.target !== undefined)
32
- ? Buff.bytes(config.target).hex
33
- : undefined
34
-
35
- let path : string[] = [],
36
- taproot : string | undefined
37
-
38
- if (leaves.length > 0) {
39
- // Merkelize the leaves into a root hash (with proof).
40
- const [ root, _, proofs ] = merkleize(leaves, target)
41
- // Get the control path from the merkelized output.
42
- path = proofs
43
- // Get the tapped key from the internal key.
44
- taproot = root
45
- } else {
46
- // Get the tapped key from the single tapleaf.
47
- taproot = target
48
- }
49
-
50
- const taptweak = encode_taptweak(pubkey, taproot)
51
- const twk_key = ECC.tweak_pubkey(pubkey, taptweak, 'ecdsa')
52
- const parity = parse_pubkey_parity(twk_key)
53
- const tapkey = ECC.serialize_pubkey(twk_key, 'bip340')
54
- // Get the block version / parity bit.
55
- const cbit = Buff.num(version + parity)
56
- // Stack the initial control block data.
57
- const block : Bytes[] = [ cbit, Buff.bytes(pubkey) ]
58
- // If there is more than one path, add to block.
59
- if (path.length > 0) {
60
- path.forEach(e => block.push(e))
61
- }
62
- // Merge the data together into one array.
63
- const cblock = Buff.join(block)
64
-
65
- return {
66
- int_key : Buff.bytes(pubkey).hex,
67
- path,
68
- parity,
69
- taproot : taproot ?? null,
70
- cblock : cblock.hex,
71
- tapkey : tapkey.hex,
72
- taptweak : taptweak.hex
73
- }
74
- }
75
-
76
- export function verify_taproot (
77
- tapkey : string,
78
- target : string,
79
- cblock : string
80
- ) : boolean {
81
- Assert.size(tapkey, 32)
82
- const { parity, path, int_key } = parse_cblock(cblock)
83
-
84
- const ext_key = Buff.join([ parity, tapkey ])
85
-
86
- let branch = Buff.bytes(target).hex
87
-
88
- for (const leaf of path) {
89
- branch = encode_tapbranch(branch, leaf).hex
90
- }
91
-
92
- const tap_tweak = encode_taptweak(int_key, branch)
93
- const tweaked_key = ECC.tweak_pubkey(int_key, tap_tweak, 'ecdsa')
94
-
95
- return (ext_key.hex === tweaked_key.hex)
96
- }
@@ -1,49 +0,0 @@
1
- import { Buff } from '@vbyte/buff'
2
- import { hash340 } from '@vbyte/micro-lib/hash'
3
- import { Assert } from '@vbyte/micro-lib'
4
- import { prefix_script_size } from '@/lib/script/index.js'
5
-
6
- import { TAPLEAF_DEFAULT_VERSION } from '@/const.js'
7
-
8
- const DEFAULT_VERSION = TAPLEAF_DEFAULT_VERSION
9
-
10
- export function encode_tapscript (
11
- script : string | Uint8Array,
12
- version = DEFAULT_VERSION
13
- ) : Buff {
14
- const preimg = prefix_script_size(script)
15
- return encode_tapleaf(preimg, version)
16
- }
17
-
18
- export function encode_tapleaf (
19
- data : string | Uint8Array,
20
- version = DEFAULT_VERSION
21
- ) : Buff {
22
- const vbyte = encode_leaf_version(version)
23
- return hash340('TapLeaf', vbyte, data)
24
- }
25
-
26
- export function encode_tapbranch (
27
- leaf_a : string,
28
- leaf_b : string
29
- ) : Buff {
30
- // Compare leaves in lexical order.
31
- if (leaf_b < leaf_a) {
32
- // Swap leaves if needed.
33
- [ leaf_a, leaf_b ] = [ leaf_b, leaf_a ]
34
- }
35
- // Return digest of leaves as a branch hash.
36
- return hash340('TapBranch', leaf_a, leaf_b)
37
- }
38
-
39
- export function encode_leaf_version (version = 0xc0) : number {
40
- return version & 0xfe
41
- }
42
-
43
- export function encode_taptweak (
44
- pubkey : string | Uint8Array,
45
- data : string | Uint8Array = new Uint8Array()
46
- ) : Buff {
47
- Assert.size(pubkey, 32)
48
- return hash340('TapTweak', pubkey, data)
49
- }
@@ -1,4 +0,0 @@
1
- export * from './cblock.js'
2
- export * from './encode.js'
3
- export * from './parse.js'
4
- export * from './tree.js'
@@ -1,65 +0,0 @@
1
- import { Buff, Stream } from '@vbyte/buff'
2
- import { Assert, ECC } from '@vbyte/micro-lib'
3
- import { parse_witness } from '@/lib/witness/parse.js'
4
-
5
- import {
6
- encode_tapbranch,
7
- encode_tapscript,
8
- encode_taptweak,
9
- } from './encode.js'
10
-
11
- import type { ControlBlock } from '@/types/index.js'
12
-
13
- export function parse_taproot_witness (witness : string[]) {
14
- const { cblock, params, script } = parse_witness(witness)
15
-
16
- Assert.exists(cblock, 'cblock is null')
17
- Assert.exists(script, 'script is null')
18
-
19
- const cblk = parse_cblock(cblock)
20
- const target = encode_tapscript(script, cblk.version)
21
-
22
- let branch = target.hex
23
-
24
- for (const leaf of cblk.path) {
25
- branch = encode_tapbranch(branch, leaf).hex
26
- }
27
-
28
- const tweak = encode_taptweak(cblk.int_key, branch)
29
- const tapkey = ECC.tweak_pubkey(cblk.int_key, tweak, 'bip340')
30
-
31
- params.map(e => Buff.bytes(e).hex)
32
-
33
- return { cblock: cblk, params, script, tapkey: tapkey.hex, tweak: tweak.hex }
34
- }
35
-
36
- export function parse_cblock (cblock : string | Uint8Array) : ControlBlock {
37
- const buffer = new Stream(cblock)
38
- const cbyte = buffer.read(1).num
39
- const int_key = buffer.read(32).hex
40
- const [ version, parity ] = parse_cblock_parity(cbyte)
41
- const path = []
42
- while (buffer.size >= 32) {
43
- path.push(buffer.read(32).hex)
44
- }
45
- if (buffer.size !== 0) {
46
- throw new Error('Non-empty buffer on control block: ' + String(buffer))
47
- }
48
- return { int_key, path, parity, version }
49
- }
50
-
51
- export function parse_cblock_parity (cbits : number) {
52
- return (cbits % 2 === 0)
53
- ? [ cbits - 0, 0x02 ]
54
- : [ cbits - 1, 0x03 ]
55
- }
56
-
57
- export function parse_pubkey_parity (
58
- pubkey : string | Uint8Array
59
- ) : number {
60
- Assert.size(pubkey, 33, 'invalid pubkey size')
61
- const [ parity ] = Buff.bytes(pubkey)
62
- if (parity === 0x02) return 0
63
- if (parity === 0x03) return 1
64
- throw new Error('Invalid parity bit: ' + String(parity))
65
- }
@@ -1,94 +0,0 @@
1
- import { Buff } from '@vbyte/buff'
2
- import { encode_tapbranch } from './encode.js'
3
-
4
- import type { TapTree, MerkleProof } from '@/types/index.js'
5
-
6
- /**
7
- * Get the root of a taproot tree.
8
- * @param leaves - The leaves of the tree.
9
- * @returns The root of the tree.
10
- */
11
- export function get_merkle_root (leaves : TapTree) {
12
- // Process the merkle tree, and return the root.
13
- return merkleize(leaves)[0]
14
- }
15
-
16
- /**
17
- * Process a taproot tree into a merkle proof.
18
- * @param taptree - The leaves of the tree.
19
- * @param target - The target leaf of the tree.
20
- * @param path - The recursive path of the tree.
21
- * @returns The root of the tree.
22
- */
23
- export function merkleize (
24
- taptree : TapTree,
25
- target ?: string,
26
- path : string[] = []
27
- ) : MerkleProof {
28
- // Initialize the leaves and tree arrays.
29
- const leaves : string[] = []
30
- const tree : string[] = []
31
- // If there are no leaves, throw an error.
32
- if (taptree.length < 1) {
33
- throw new Error('Tree is empty!')
34
- }
35
- // Crawl through the tree, and find each leaf.
36
- for (let i = 0; i < taptree.length; i++) {
37
- // Get the current leaf as bytes.
38
- const bytes = taptree[i]
39
- // If the leaf is an array,
40
- if (Array.isArray(bytes)) {
41
- // Recursively process the nested tree.
42
- let [ tapleaf, new_target, branches ] = merkleize(bytes, target)
43
- // Update the target leaf.
44
- target = new_target
45
- // Add the nested tapleaf to the leaves array.
46
- leaves.push(tapleaf)
47
- // For each branch node,
48
- for (const branch of branches) {
49
- // Add the branch to the path.
50
- path.push(branch)
51
- }
52
- } else {
53
- // Convert the leaf to a hex string.
54
- const leaf = Buff.bytes(bytes).hex
55
- // Add the leaf to the leaves array.
56
- leaves.push(leaf)
57
- }
58
- }
59
-
60
- // If there is only one leaf,
61
- if (leaves.length === 1) {
62
- // Return the leaf as the root.
63
- return [ leaves[0], target, path ]
64
- }
65
- // Ensure the tree is sorted at this point.
66
- leaves.sort()
67
- // Ensure the tree is balanced evenly.
68
- if (leaves.length % 2 !== 0) {
69
- // If uneven, duplicate the last leaf.
70
- leaves.push(leaves[leaves.length - 1])
71
- }
72
- // Sort through the leaves (two at a time).
73
- for (let i = 0; i < leaves.length - 1; i += 2) {
74
- // Compute two leaves into a branch.
75
- const branch = encode_tapbranch(leaves[i], leaves[i + 1]).hex
76
- // Push our branch to the tree.
77
- tree.push(branch)
78
- // Check if a proof target is specified.
79
- if (typeof target === 'string') {
80
- // Check if this branch is part of our proofs.
81
- if (target === leaves[i]) {
82
- // If so, include right-side of branch.
83
- path.push(leaves[i + 1])
84
- target = branch
85
- } else if (target === leaves[i + 1]) {
86
- // If so, include left-side of branch.
87
- path.push(leaves[i])
88
- target = branch
89
- }
90
- }
91
- }
92
- // Recursively process the tree.
93
- return merkleize(tree, target, path)
94
- }
@@ -1,90 +0,0 @@
1
- import { Assert } from '@vbyte/micro-lib'
2
- import { COINBASE, DEFAULT } from '@/const.js'
3
-
4
- import {
5
- normalize_prevout,
6
- normalize_sequence,
7
- normalize_value
8
- } from './util.js'
9
-
10
- import {
11
- assert_tx_template,
12
- assert_vin_template,
13
- assert_vout_template
14
- } from './validate.js'
15
-
16
- import type {
17
- TxData,
18
- TxInput,
19
- TxOutput,
20
- TxTemplate,
21
- TxSpendInput,
22
- TxCoinbaseInput,
23
- TxOutputTemplate,
24
- TxVirtualInput,
25
- TxInputTemplate
26
- } from '@/types/index.js'
27
-
28
- export function create_coinbase_input (
29
- config : TxInputTemplate
30
- ) : TxCoinbaseInput {
31
- assert_vin_template(config)
32
- Assert.exists(config.coinbase, 'coinbase is required')
33
- const txid = COINBASE.TXID
34
- const vout = COINBASE.VOUT
35
- const coinbase = config.coinbase
36
- const witness = config.witness ?? []
37
- const sequence = normalize_sequence(config.sequence)
38
- return { coinbase, prevout: null, script_sig: null, sequence, witness, txid, vout }
39
- }
40
-
41
- export function create_virtual_input (
42
- config : TxInputTemplate
43
- ) : TxVirtualInput {
44
- assert_vin_template(config)
45
- Assert.is_empty(config.coinbase, 'coinbase is not allowed')
46
- Assert.is_empty(config.prevout, 'prevout is not allowed')
47
- const { txid, vout, script_sig = null, witness = [] } = config
48
- const sequence = normalize_sequence(config.sequence)
49
- return { txid, vout, coinbase: null, prevout: null, script_sig, sequence, witness }
50
- }
51
-
52
- export function create_spend_input (
53
- config : TxInputTemplate
54
- ) : TxSpendInput {
55
- assert_vin_template(config)
56
- Assert.exists(config.prevout, 'prevout is required')
57
- const { txid, vout, script_sig = null, witness = [] } = config
58
- const prevout = normalize_prevout(config.prevout)
59
- const sequence = normalize_sequence(config.sequence)
60
- return { txid, vout, coinbase: null, prevout, script_sig, sequence, witness }
61
- }
62
-
63
- export function create_tx_input (
64
- config : TxInputTemplate
65
- ) : TxInput {
66
- if (config.coinbase) return create_coinbase_input(config)
67
- if (config.prevout) return create_spend_input(config)
68
- return create_virtual_input(config)
69
- }
70
-
71
- export function create_tx_output (
72
- config : TxOutputTemplate
73
- ) : TxOutput {
74
- assert_vout_template(config)
75
- const script_pk = config.script_pk
76
- const value = normalize_value(config.value)
77
- return { script_pk, value }
78
- }
79
-
80
- export function create_tx (
81
- config? : Partial<TxTemplate>
82
- ) : TxData {
83
- assert_tx_template(config)
84
- const { vin = [], vout = [] } = config ?? { vin: [], vout: [] }
85
- const locktime = config.locktime ?? DEFAULT.LOCKTIME
86
- const version = config.version ?? DEFAULT.VERSION
87
- const inputs = vin.map(txin => create_tx_input(txin))
88
- const outputs = vout.map(txout => create_tx_output(txout))
89
- return { locktime, vin : inputs, vout : outputs, version }
90
- }
@@ -1,123 +0,0 @@
1
- import { Stream } from '@vbyte/buff'
2
- import { Assert } from '@vbyte/micro-lib/assert'
3
- import { parse_error } from '@vbyte/micro-lib/util'
4
- import { COINBASE } from '@/const.js'
5
-
6
- import {
7
- TxInput,
8
- TxOutput,
9
- TxCoinbaseInput,
10
- TxVirtualInput,
11
- TxDecodedData
12
- } from '@/types/index.js'
13
-
14
- export function decode_tx (
15
- txdata : string | Uint8Array,
16
- use_segwit = true
17
- ) : TxDecodedData {
18
- // Assert the txdata is a bytes object.
19
- Assert.is_bytes(txdata, 'txdata must be hex or bytes')
20
- // Setup a byte-stream.
21
- const stream = new Stream(txdata)
22
- // Parse tx version.
23
- const version = read_version(stream)
24
- // Check and enable any flags that are set.
25
- let has_witness = check_witness_flag(stream)
26
- // If use_segwit is false, set has_witness to false.
27
- has_witness = (use_segwit) ? has_witness : false
28
- // Parse our inputs and outputs.
29
- const vin = read_inputs(stream)
30
- const vout = read_outputs(stream)
31
- // If witness flag is set, parse witness data.
32
- if (has_witness) {
33
- for (const txin of vin) {
34
- txin.witness = read_witness(stream)
35
- }
36
- }
37
- // Parse locktime.
38
- const locktime = read_locktime(stream)
39
- // Return transaction object with calculated fields.
40
- return { version, vin, vout, locktime }
41
- }
42
-
43
- function read_version (stream : Stream) : number {
44
- return stream.read(4).reverse().to_num()
45
- }
46
-
47
- function check_witness_flag (stream : Stream) : boolean {
48
- const [ marker, flag ] : number[] = [ ...stream.peek(2) ]
49
- if (marker === 0) {
50
- stream.read(2)
51
- if (flag === 1) {
52
- return true
53
- } else {
54
- throw new Error(`Invalid witness flag: ${flag}`)
55
- }
56
- }
57
- return false
58
- }
59
-
60
- function read_inputs (stream : Stream) : TxInput[] {
61
- const inputs = []
62
- const vinCount = stream.varint()
63
- for (let i = 0; i < vinCount; i++) {
64
- const txinput = read_vin(stream)
65
- inputs.push(txinput)
66
- }
67
- return inputs
68
- }
69
-
70
- function read_vin (stream : Stream) : TxInput {
71
- const txid = stream.read(32).reverse().hex
72
- const vout = stream.read(4).reverse().num
73
- const script_sig = read_payload(stream)
74
- const sequence = stream.read(4).reverse().num
75
- const witness : string[] = []
76
- if (txid === COINBASE.TXID && vout === COINBASE.VOUT) {
77
- return { coinbase : script_sig, prevout: null, script_sig : null, sequence, txid, vout, witness } as TxCoinbaseInput
78
- } else {
79
- return { coinbase : null, prevout: null, script_sig, sequence, txid, vout, witness } as TxVirtualInput
80
- }
81
- }
82
-
83
- function read_outputs (stream : Stream) : TxOutput[] {
84
- const outputs = []
85
- const vcount = stream.varint()
86
- for (let i = 0; i < vcount; i++) {
87
- try {
88
- outputs.push(read_vout(stream))
89
- } catch (error) {
90
- throw new Error(`failed to decode output: ${i}: ${parse_error(error)}`)
91
- }
92
- }
93
- return outputs
94
- }
95
-
96
- function read_vout (stream : Stream) : TxOutput {
97
- const value = stream.read(8).reverse().big
98
- const script_pk = read_payload(stream)
99
- Assert.exists(script_pk, 'failed to decode script_pk')
100
- return { value, script_pk }
101
- }
102
-
103
- function read_witness (stream : Stream) : string[] {
104
- const stack = []
105
- const count = stream.varint()
106
- for (let i = 0; i < count; i++) {
107
- const element = read_payload(stream)
108
- if (element === null) {
109
- throw new Error('failed to decode witness element: ' + i)
110
- }
111
- stack.push(element)
112
- }
113
- return stack
114
- }
115
-
116
- export function read_payload (stream : Stream) : string | null {
117
- const size = stream.varint('le')
118
- return (size > 0) ? stream.read(size).hex : null
119
- }
120
-
121
- function read_locktime (stream : Stream) : number {
122
- return stream.read(4).reverse().to_num()
123
- }