11'use strict' ;
2+ /**
3+ * Script tools module for working with Bitcoin scripts.
4+ * Provides utilities such as decompiling, compiling, converting to/from ASM, stack manipulation,
5+ * and script validation functions.
6+ *
7+ * @packageDocumentation
8+ */
29var __createBinding =
310 ( this && this . __createBinding ) ||
411 ( Object . create
@@ -55,10 +62,6 @@ exports.toStack = toStack;
5562exports . isCanonicalPubKey = isCanonicalPubKey ;
5663exports . isDefinedHashType = isDefinedHashType ;
5764exports . isCanonicalScriptSignature = isCanonicalScriptSignature ;
58- /**
59- * Script tools, including decompile, compile, toASM, fromASM, toStack, isCanonicalPubKey, isCanonicalScriptSignature
60- * @packageDocumentation
61- */
6265const bip66 = __importStar ( require ( './bip66.cjs' ) ) ;
6366const ops_js_1 = require ( './ops.cjs' ) ;
6467Object . defineProperty ( exports , 'OPS' , {
@@ -73,8 +76,16 @@ const scriptSignature = __importStar(require('./script_signature.cjs'));
7376const types = __importStar ( require ( './types.cjs' ) ) ;
7477const tools = __importStar ( require ( 'uint8array-tools' ) ) ;
7578const v = __importStar ( require ( 'valibot' ) ) ;
79+ /** Base opcode for OP_INT values. */
7680const OP_INT_BASE = ops_js_1 . OPS . OP_RESERVED ; // OP_1 - 1
81+ /** Validation schema for a Bitcoin script stack. */
7782const StackSchema = v . array ( v . union ( [ v . instance ( Uint8Array ) , v . number ( ) ] ) ) ;
83+ /**
84+ * Determines if a value corresponds to an OP_INT opcode.
85+ *
86+ * @param value - The opcode to check.
87+ * @returns True if the value is an OP_INT, false otherwise.
88+ */
7889function isOPInt ( value ) {
7990 return (
8091 v . is ( v . number ( ) , value ) &&
@@ -83,57 +94,95 @@ function isOPInt(value) {
8394 value === ops_js_1 . OPS . OP_1NEGATE )
8495 ) ;
8596}
97+ /**
98+ * Checks if a script chunk is push-only (contains only data or OP_INT opcodes).
99+ *
100+ * @param value - The chunk to check.
101+ * @returns True if the chunk is push-only, false otherwise.
102+ */
86103function isPushOnlyChunk ( value ) {
87104 return v . is ( types . BufferSchema , value ) || isOPInt ( value ) ;
88105}
106+ /**
107+ * Determines if a stack consists of only push operations.
108+ *
109+ * @param value - The stack to check.
110+ * @returns True if all elements in the stack are push-only, false otherwise.
111+ */
89112function isPushOnly ( value ) {
90113 return v . is ( v . pipe ( v . any ( ) , v . everyItem ( isPushOnlyChunk ) ) , value ) ;
91114}
115+ /**
116+ * Counts the number of non-push-only opcodes in a stack.
117+ *
118+ * @param value - The stack to analyze.
119+ * @returns The count of non-push-only opcodes.
120+ */
92121function countNonPushOnlyOPs ( value ) {
93122 return value . length - value . filter ( isPushOnlyChunk ) . length ;
94123}
124+ /**
125+ * Converts a minimal script buffer to its corresponding opcode, if applicable.
126+ *
127+ * @param buffer - The buffer to check.
128+ * @returns The corresponding opcode or undefined if not minimal.
129+ */
95130function asMinimalOP ( buffer ) {
96131 if ( buffer . length === 0 ) return ops_js_1 . OPS . OP_0 ;
97132 if ( buffer . length !== 1 ) return ;
98133 if ( buffer [ 0 ] >= 1 && buffer [ 0 ] <= 16 ) return OP_INT_BASE + buffer [ 0 ] ;
99134 if ( buffer [ 0 ] === 0x81 ) return ops_js_1 . OPS . OP_1NEGATE ;
100135}
136+ /**
137+ * Determines if a buffer or stack is a Uint8Array.
138+ *
139+ * @param buf - The buffer or stack to check.
140+ * @returns True if the input is a Uint8Array, false otherwise.
141+ */
101142function chunksIsBuffer ( buf ) {
102143 return buf instanceof Uint8Array ;
103144}
145+ /**
146+ * Determines if a buffer or stack is a valid stack.
147+ *
148+ * @param buf - The buffer or stack to check.
149+ * @returns True if the input is a stack, false otherwise.
150+ */
104151function chunksIsArray ( buf ) {
105152 return v . is ( StackSchema , buf ) ;
106153}
154+ /**
155+ * Determines if a single chunk is a Uint8Array.
156+ *
157+ * @param buf - The chunk to check.
158+ * @returns True if the chunk is a Uint8Array, false otherwise.
159+ */
107160function singleChunkIsBuffer ( buf ) {
108161 return buf instanceof Uint8Array ;
109162}
110163/**
111- * Compiles an array of chunks into a Buffer .
164+ * Compiles an array of script chunks into a Uint8Array .
112165 *
113- * @param chunks - The array of chunks to compile.
114- * @returns The compiled Buffer .
115- * @throws Error if the compilation fails.
166+ * @param chunks - The chunks to compile.
167+ * @returns The compiled script as a Uint8Array .
168+ * @throws Error if compilation fails.
116169 */
117170function compile ( chunks ) {
118- // TODO: remove me
119171 if ( chunksIsBuffer ( chunks ) ) return chunks ;
120172 v . parse ( StackSchema , chunks ) ;
121173 const bufferSize = chunks . reduce ( ( accum , chunk ) => {
122- // data chunk
123174 if ( singleChunkIsBuffer ( chunk ) ) {
124175 // adhere to BIP62.3, minimal push policy
125176 if ( chunk . length === 1 && asMinimalOP ( chunk ) !== undefined ) {
126177 return accum + 1 ;
127178 }
128179 return accum + pushdata . encodingLength ( chunk . length ) + chunk . length ;
129180 }
130- // opcode
131181 return accum + 1 ;
132- } , 0.0 ) ;
182+ } , 0 ) ;
133183 const buffer = new Uint8Array ( bufferSize ) ;
134184 let offset = 0 ;
135185 chunks . forEach ( chunk => {
136- // data chunk
137186 if ( singleChunkIsBuffer ( chunk ) ) {
138187 // adhere to BIP62.3, minimal push policy
139188 const opcode = asMinimalOP ( chunk ) ;
@@ -154,15 +203,19 @@ function compile(chunks) {
154203 if ( offset !== buffer . length ) throw new Error ( 'Could not decode chunks' ) ;
155204 return buffer ;
156205}
206+ /**
207+ * Decompiles a script buffer into an array of chunks.
208+ *
209+ * @param buffer - The script buffer to decompile.
210+ * @returns The decompiled chunks or null if decompilation fails.
211+ */
157212function decompile ( buffer ) {
158- // TODO: remove me
159213 if ( chunksIsArray ( buffer ) ) return buffer ;
160214 v . parse ( types . BufferSchema , buffer ) ;
161215 const chunks = [ ] ;
162216 let i = 0 ;
163217 while ( i < buffer . length ) {
164218 const opcode = buffer [ i ] ;
165- // data chunk
166219 if ( opcode > ops_js_1 . OPS . OP_0 && opcode <= ops_js_1 . OPS . OP_PUSHDATA4 ) {
167220 const d = pushdata . decode ( buffer , i ) ;
168221 // did reading a pushDataInt fail?
@@ -179,7 +232,6 @@ function decompile(buffer) {
179232 } else {
180233 chunks . push ( data ) ;
181234 }
182- // opcode
183235 } else {
184236 chunks . push ( opcode ) ;
185237 i += 1 ;
@@ -202,7 +254,6 @@ function toASM(chunks) {
202254 }
203255 return chunks
204256 . map ( chunk => {
205- // data?
206257 if ( singleChunkIsBuffer ( chunk ) ) {
207258 const op = asMinimalOP ( chunk ) ;
208259 if ( op === undefined ) return tools . toHex ( chunk ) ;
@@ -245,13 +296,36 @@ function toStack(chunks) {
245296 return scriptNumber . encode ( op - OP_INT_BASE ) ;
246297 } ) ;
247298}
299+ /**
300+ * Checks if the provided buffer is a canonical public key.
301+ *
302+ * @param buffer - The buffer to check, expected to be a Uint8Array.
303+ * @returns A boolean indicating whether the buffer is a canonical public key.
304+ */
248305function isCanonicalPubKey ( buffer ) {
249306 return types . isPoint ( buffer ) ;
250307}
308+ /**
309+ * Checks if the provided hash type is defined.
310+ *
311+ * A hash type is considered defined if its modified value (after masking with ~0x80)
312+ * is greater than 0x00 and less than 0x04.
313+ *
314+ * @param hashType - The hash type to check.
315+ * @returns True if the hash type is defined, false otherwise.
316+ */
251317function isDefinedHashType ( hashType ) {
252318 const hashTypeMod = hashType & ~ 0x80 ;
253319 return hashTypeMod > 0x00 && hashTypeMod < 0x04 ;
254320}
321+ /**
322+ * Checks if the provided buffer is a canonical script signature.
323+ *
324+ * A canonical script signature is a valid DER-encoded signature followed by a valid hash type byte.
325+ *
326+ * @param buffer - The buffer to check.
327+ * @returns `true` if the buffer is a canonical script signature, `false` otherwise.
328+ */
255329function isCanonicalScriptSignature ( buffer ) {
256330 if ( ! ( buffer instanceof Uint8Array ) ) return false ;
257331 if ( ! isDefinedHashType ( buffer [ buffer . length - 1 ] ) ) return false ;
0 commit comments