@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.
- package/CHANGELOG.md +94 -0
- package/README.md +260 -3
- package/dist/const.d.ts +3 -0
- package/dist/const.js +23 -22
- package/dist/index.d.ts +11 -11
- package/dist/index.js +10 -10
- package/dist/lib/address/api.d.ts +2 -2
- package/dist/lib/address/api.js +12 -12
- package/dist/lib/address/encode.d.ts +1 -1
- package/dist/lib/address/encode.js +24 -24
- package/dist/lib/address/index.d.ts +6 -6
- package/dist/lib/address/index.js +6 -6
- package/dist/lib/address/p2pkh.d.ts +2 -2
- package/dist/lib/address/p2pkh.js +14 -14
- package/dist/lib/address/p2sh.d.ts +2 -2
- package/dist/lib/address/p2sh.js +13 -13
- package/dist/lib/address/p2tr.d.ts +2 -2
- package/dist/lib/address/p2tr.js +13 -13
- package/dist/lib/address/p2wpkh.d.ts +2 -2
- package/dist/lib/address/p2wpkh.js +14 -14
- package/dist/lib/address/p2wsh.d.ts +2 -2
- package/dist/lib/address/p2wsh.js +13 -13
- package/dist/lib/address/script.d.ts +1 -1
- package/dist/lib/address/script.js +16 -16
- package/dist/lib/address/util.d.ts +1 -1
- package/dist/lib/address/util.js +22 -22
- package/dist/lib/meta/index.d.ts +4 -4
- package/dist/lib/meta/index.js +4 -4
- package/dist/lib/meta/locktime.d.ts +1 -1
- package/dist/lib/meta/locktime.js +12 -12
- package/dist/lib/meta/ref.js +9 -6
- package/dist/lib/meta/scribe.d.ts +2 -2
- package/dist/lib/meta/scribe.js +48 -53
- package/dist/lib/meta/sequence.d.ts +1 -1
- package/dist/lib/meta/sequence.js +16 -15
- package/dist/lib/script/decode.d.ts +2 -2
- package/dist/lib/script/decode.js +50 -15
- package/dist/lib/script/encode.d.ts +1 -1
- package/dist/lib/script/encode.js +20 -16
- package/dist/lib/script/index.d.ts +5 -13
- package/dist/lib/script/index.js +5 -14
- package/dist/lib/script/lock.d.ts +2 -2
- package/dist/lib/script/lock.js +15 -12
- package/dist/lib/script/util.js +4 -4
- package/dist/lib/script/words.js +129 -129
- package/dist/lib/sighash/index.d.ts +3 -3
- package/dist/lib/sighash/index.js +3 -3
- package/dist/lib/sighash/segwit.d.ts +2 -2
- package/dist/lib/sighash/segwit.js +15 -14
- package/dist/lib/sighash/taproot.d.ts +2 -2
- package/dist/lib/sighash/taproot.js +24 -23
- package/dist/lib/sighash/util.d.ts +2 -2
- package/dist/lib/sighash/util.js +7 -7
- package/dist/lib/signer/index.d.ts +2 -2
- package/dist/lib/signer/index.js +2 -2
- package/dist/lib/signer/sign.d.ts +1 -1
- package/dist/lib/signer/sign.js +42 -7
- package/dist/lib/signer/verify.d.ts +17 -3
- package/dist/lib/signer/verify.js +233 -3
- package/dist/lib/taproot/cblock.d.ts +1 -1
- package/dist/lib/taproot/cblock.js +14 -16
- package/dist/lib/taproot/encode.d.ts +1 -1
- package/dist/lib/taproot/encode.js +7 -7
- package/dist/lib/taproot/index.d.ts +4 -4
- package/dist/lib/taproot/index.js +4 -4
- package/dist/lib/taproot/parse.d.ts +1 -1
- package/dist/lib/taproot/parse.js +12 -14
- package/dist/lib/taproot/tree.d.ts +2 -2
- package/dist/lib/taproot/tree.js +11 -7
- package/dist/lib/tx/create.d.ts +1 -1
- package/dist/lib/tx/create.js +28 -12
- package/dist/lib/tx/decode.d.ts +2 -2
- package/dist/lib/tx/decode.js +50 -17
- package/dist/lib/tx/encode.d.ts +2 -2
- package/dist/lib/tx/encode.js +13 -16
- package/dist/lib/tx/index.d.ts +7 -7
- package/dist/lib/tx/index.js +7 -7
- package/dist/lib/tx/parse.d.ts +1 -1
- package/dist/lib/tx/parse.js +9 -9
- package/dist/lib/tx/size.d.ts +2 -2
- package/dist/lib/tx/size.js +9 -9
- package/dist/lib/tx/util.d.ts +2 -2
- package/dist/lib/tx/util.js +23 -20
- package/dist/lib/tx/validate.d.ts +1 -1
- package/dist/lib/tx/validate.js +3 -3
- package/dist/lib/witness/index.d.ts +2 -2
- package/dist/lib/witness/index.js +2 -2
- package/dist/lib/witness/parse.d.ts +2 -2
- package/dist/lib/witness/parse.js +24 -23
- package/dist/lib/witness/util.d.ts +2 -2
- package/dist/lib/witness/util.js +5 -5
- package/dist/main.cjs +2308 -1005
- package/dist/main.cjs.map +1 -1
- package/dist/module.mjs +2308 -1005
- package/dist/module.mjs.map +1 -1
- package/dist/package.json +20 -17
- package/dist/schema/base.d.ts +1 -1
- package/dist/schema/base.js +17 -13
- package/dist/schema/index.d.ts +2 -2
- package/dist/schema/index.js +2 -2
- package/dist/schema/taproot.d.ts +1 -1
- package/dist/schema/taproot.js +2 -2
- package/dist/schema/tx.d.ts +1 -1
- package/dist/schema/tx.js +4 -4
- package/dist/script.js +8 -8
- package/dist/script.js.map +1 -1
- package/dist/types/address.d.ts +4 -4
- package/dist/types/index.d.ts +8 -8
- package/dist/types/index.js +8 -8
- package/dist/types/meta.d.ts +4 -4
- package/dist/types/psbt.d.ts +2 -2
- package/dist/types/script.d.ts +2 -2
- package/dist/types/sighash.d.ts +2 -2
- package/dist/types/witness.d.ts +5 -5
- package/package.json +20 -17
- package/src/const.ts +0 -61
- package/src/index.ts +0 -13
- package/src/lib/address/api.ts +0 -50
- package/src/lib/address/encode.ts +0 -183
- package/src/lib/address/index.ts +0 -7
- package/src/lib/address/p2pkh.ts +0 -94
- package/src/lib/address/p2sh.ts +0 -96
- package/src/lib/address/p2tr.ts +0 -91
- package/src/lib/address/p2wpkh.ts +0 -94
- package/src/lib/address/p2wsh.ts +0 -92
- package/src/lib/address/script.ts +0 -63
- package/src/lib/address/util.ts +0 -87
- package/src/lib/meta/index.ts +0 -4
- package/src/lib/meta/locktime.ts +0 -57
- package/src/lib/meta/ref.ts +0 -107
- package/src/lib/meta/scribe.ts +0 -256
- package/src/lib/meta/sequence.ts +0 -146
- package/src/lib/script/decode.ts +0 -85
- package/src/lib/script/encode.ts +0 -129
- package/src/lib/script/index.ts +0 -20
- package/src/lib/script/lock.ts +0 -73
- package/src/lib/script/util.ts +0 -78
- package/src/lib/script/words.ts +0 -182
- package/src/lib/sighash/index.ts +0 -3
- package/src/lib/sighash/segwit.ts +0 -152
- package/src/lib/sighash/taproot.ts +0 -206
- package/src/lib/sighash/util.ts +0 -51
- package/src/lib/signer/index.ts +0 -2
- package/src/lib/signer/sign.ts +0 -39
- package/src/lib/signer/verify.ts +0 -88
- package/src/lib/taproot/cblock.ts +0 -96
- package/src/lib/taproot/encode.ts +0 -49
- package/src/lib/taproot/index.ts +0 -4
- package/src/lib/taproot/parse.ts +0 -65
- package/src/lib/taproot/tree.ts +0 -94
- package/src/lib/tx/create.ts +0 -90
- package/src/lib/tx/decode.ts +0 -123
- package/src/lib/tx/encode.ts +0 -155
- package/src/lib/tx/index.ts +0 -7
- package/src/lib/tx/parse.ts +0 -69
- package/src/lib/tx/size.ts +0 -68
- package/src/lib/tx/util.ts +0 -111
- package/src/lib/tx/validate.ts +0 -49
- package/src/lib/witness/index.ts +0 -2
- package/src/lib/witness/parse.ts +0 -127
- package/src/lib/witness/util.ts +0 -18
- package/src/schema/base.ts +0 -57
- package/src/schema/index.ts +0 -2
- package/src/schema/taproot.ts +0 -12
- package/src/schema/tx.ts +0 -48
- package/src/types/address.ts +0 -35
- package/src/types/index.ts +0 -8
- package/src/types/meta.ts +0 -48
- package/src/types/psbt.ts +0 -15
- package/src/types/script.ts +0 -18
- package/src/types/sighash.ts +0 -16
- package/src/types/taproot.ts +0 -41
- package/src/types/txdata.ts +0 -85
- package/src/types/witness.ts +0 -42
package/dist/lib/meta/scribe.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Buff, Stream } from
|
|
2
|
-
import { Assert } from
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { Buff, Stream } from "@vbyte/buff";
|
|
2
|
+
import { Assert } from "@vbyte/micro-lib";
|
|
3
|
+
import { decode_script } from "../../lib/script/decode.js";
|
|
4
|
+
import { encode_script } from "../../lib/script/encode.js";
|
|
5
5
|
const _0n = BigInt(0);
|
|
6
6
|
const _1n = BigInt(1);
|
|
7
7
|
const _26n = BigInt(26);
|
|
@@ -18,51 +18,51 @@ export function encode_inscription(data) {
|
|
|
18
18
|
return Buff.join(data.map(create_envelope));
|
|
19
19
|
}
|
|
20
20
|
function create_envelope(data) {
|
|
21
|
-
|
|
22
|
-
if (typeof data.delegate ===
|
|
21
|
+
const asm = ["OP_0", "OP_IF", "6f7264"];
|
|
22
|
+
if (typeof data.delegate === "string") {
|
|
23
23
|
const id = encode_id(data.delegate);
|
|
24
|
-
asm.push(
|
|
24
|
+
asm.push("OP_11", id);
|
|
25
25
|
}
|
|
26
|
-
if (typeof data.ref ===
|
|
27
|
-
asm.push(
|
|
26
|
+
if (typeof data.ref === "string") {
|
|
27
|
+
asm.push("OP_WITHIN", data.ref);
|
|
28
28
|
}
|
|
29
|
-
if (typeof data.parent ===
|
|
29
|
+
if (typeof data.parent === "string") {
|
|
30
30
|
const id = encode_id(data.parent);
|
|
31
|
-
asm.push(
|
|
31
|
+
asm.push("OP_3", id);
|
|
32
32
|
}
|
|
33
|
-
if (typeof data.opcode ===
|
|
33
|
+
if (typeof data.opcode === "number") {
|
|
34
34
|
const code = encode_pointer(data.opcode);
|
|
35
|
-
asm.push(
|
|
35
|
+
asm.push("OP_NOP", code);
|
|
36
36
|
}
|
|
37
|
-
if (typeof data.pointer ===
|
|
37
|
+
if (typeof data.pointer === "number") {
|
|
38
38
|
const ptr = encode_pointer(data.pointer);
|
|
39
|
-
asm.push(
|
|
39
|
+
asm.push("OP_2", ptr);
|
|
40
40
|
}
|
|
41
|
-
if (typeof data.rune ===
|
|
41
|
+
if (typeof data.rune === "string") {
|
|
42
42
|
const label = encode_rune_label(data.rune);
|
|
43
|
-
asm.push(
|
|
43
|
+
asm.push("OP_13", label);
|
|
44
44
|
}
|
|
45
|
-
if (typeof data.mimetype ===
|
|
45
|
+
if (typeof data.mimetype === "string") {
|
|
46
46
|
const label = encode_label(data.mimetype);
|
|
47
|
-
asm.push(
|
|
47
|
+
asm.push("OP_1", label);
|
|
48
48
|
}
|
|
49
|
-
if (typeof data.content ===
|
|
49
|
+
if (typeof data.content === "string") {
|
|
50
50
|
const chunks = encode_content(data.content);
|
|
51
|
-
asm.push(
|
|
51
|
+
asm.push("OP_0", ...chunks);
|
|
52
52
|
}
|
|
53
|
-
asm.push(
|
|
53
|
+
asm.push("OP_ENDIF");
|
|
54
54
|
return encode_script(asm);
|
|
55
55
|
}
|
|
56
56
|
function parse_envelopes(script) {
|
|
57
57
|
const words = decode_script(script);
|
|
58
|
-
const start_idx = words.
|
|
59
|
-
Assert.ok(start_idx !== -1,
|
|
58
|
+
const start_idx = words.indexOf("OP_0");
|
|
59
|
+
Assert.ok(start_idx !== -1, "inscription envelope not found");
|
|
60
60
|
const envelopes = [];
|
|
61
61
|
for (let idx = start_idx; idx < words.length; idx++) {
|
|
62
|
-
Assert.ok(words[idx + 1] ===
|
|
63
|
-
Assert.ok(words[idx + 2] ===
|
|
64
|
-
const stop_idx = words.
|
|
65
|
-
Assert.ok(stop_idx !== -1,
|
|
62
|
+
Assert.ok(words[idx + 1] === "OP_IF", "OP_IF missing from envelope");
|
|
63
|
+
Assert.ok(words[idx + 2] === "6f7264", "magic bytes missing from envelope");
|
|
64
|
+
const stop_idx = words.indexOf("OP_ENDIF");
|
|
65
|
+
Assert.ok(stop_idx !== -1, "inscription envelope missing END_IF statement");
|
|
66
66
|
const env = words.slice(idx + 3, stop_idx);
|
|
67
67
|
envelopes.push(env);
|
|
68
68
|
idx += stop_idx;
|
|
@@ -73,35 +73,35 @@ function parse_record(envelope) {
|
|
|
73
73
|
const record = {};
|
|
74
74
|
for (let i = 0; i < envelope.length; i++) {
|
|
75
75
|
switch (envelope[i]) {
|
|
76
|
-
case
|
|
76
|
+
case "OP_1":
|
|
77
77
|
record.mimetype = decode_label(envelope[i + 1]);
|
|
78
78
|
i += 1;
|
|
79
79
|
break;
|
|
80
|
-
case
|
|
80
|
+
case "OP_2":
|
|
81
81
|
record.pointer = decode_pointer(envelope[i + 1]);
|
|
82
82
|
i += 1;
|
|
83
83
|
break;
|
|
84
|
-
case
|
|
84
|
+
case "OP_3":
|
|
85
85
|
record.parent = decode_id(envelope[i + 1]);
|
|
86
86
|
i += 1;
|
|
87
87
|
break;
|
|
88
|
-
case
|
|
88
|
+
case "OP_11":
|
|
89
89
|
record.delegate = decode_id(envelope[i + 1]);
|
|
90
90
|
i += 1;
|
|
91
91
|
break;
|
|
92
|
-
case
|
|
92
|
+
case "OP_13":
|
|
93
93
|
record.rune = decode_rune_label(envelope[i + 1]);
|
|
94
94
|
i += 1;
|
|
95
95
|
break;
|
|
96
|
-
case
|
|
96
|
+
case "OP_WITHIN":
|
|
97
97
|
record.ref = decode_bytes(envelope[i + 1]);
|
|
98
98
|
i += 1;
|
|
99
99
|
break;
|
|
100
|
-
case
|
|
100
|
+
case "OP_NOP":
|
|
101
101
|
record.opcode = decode_pointer(envelope[i + 1]);
|
|
102
102
|
i += 1;
|
|
103
103
|
break;
|
|
104
|
-
case
|
|
104
|
+
case "OP_0":
|
|
105
105
|
record.content = decode_content(envelope.slice(i + 1));
|
|
106
106
|
return record;
|
|
107
107
|
}
|
|
@@ -112,18 +112,18 @@ function decode_bytes(bytes) {
|
|
|
112
112
|
return Buff.bytes(bytes).hex;
|
|
113
113
|
}
|
|
114
114
|
function encode_id(identifier) {
|
|
115
|
-
Assert.ok(identifier.includes(
|
|
116
|
-
const parts = identifier.split(
|
|
115
|
+
Assert.ok(identifier.includes("i"), "identifier must include an index");
|
|
116
|
+
const parts = identifier.split("i");
|
|
117
117
|
const bytes = Buff.hex(parts[0]);
|
|
118
118
|
const idx = Number(parts[1]);
|
|
119
119
|
const txid = bytes.reverse().hex;
|
|
120
|
-
return
|
|
120
|
+
return idx !== 0 ? txid + Buff.num(idx).hex : txid;
|
|
121
121
|
}
|
|
122
122
|
function decode_id(identifier) {
|
|
123
123
|
const bytes = Buff.bytes(identifier);
|
|
124
124
|
const idx = bytes.at(-1) ?? 0;
|
|
125
125
|
const txid = bytes.slice(0, -1).reverse().hex;
|
|
126
|
-
return txid
|
|
126
|
+
return `${txid}i${String(idx)}`;
|
|
127
127
|
}
|
|
128
128
|
function encode_pointer(pointer) {
|
|
129
129
|
return Buff.num(pointer).reverse().hex;
|
|
@@ -138,9 +138,7 @@ function decode_label(label) {
|
|
|
138
138
|
return Buff.bytes(label).str;
|
|
139
139
|
}
|
|
140
140
|
function encode_content(content) {
|
|
141
|
-
const bytes = Buff.is_hex(content)
|
|
142
|
-
? Buff.hex(content)
|
|
143
|
-
: Buff.str(content);
|
|
141
|
+
const bytes = Buff.is_hex(content) ? Buff.hex(content) : Buff.str(content);
|
|
144
142
|
const stream = new Stream(bytes);
|
|
145
143
|
const chunks = [];
|
|
146
144
|
while (stream.size > 0) {
|
|
@@ -155,21 +153,18 @@ function encode_content(content) {
|
|
|
155
153
|
}
|
|
156
154
|
return chunks;
|
|
157
155
|
}
|
|
158
|
-
function decode_content(chunks, format =
|
|
156
|
+
function decode_content(chunks, format = "hex") {
|
|
159
157
|
const data = Buff.join(chunks);
|
|
160
|
-
return
|
|
161
|
-
? data.hex
|
|
162
|
-
: data.str;
|
|
158
|
+
return format === "hex" ? data.hex : data.str;
|
|
163
159
|
}
|
|
164
160
|
function encode_rune_label(label) {
|
|
165
161
|
const str = label.toUpperCase();
|
|
166
162
|
let big = _0n;
|
|
167
163
|
for (const char of str) {
|
|
168
|
-
if (char >=
|
|
169
|
-
big = big * _26n + BigInt(char.charCodeAt(0) - (
|
|
164
|
+
if (char >= "A" && char <= "Z") {
|
|
165
|
+
big = big * _26n + BigInt(char.charCodeAt(0) - ("A".charCodeAt(0) - 1));
|
|
170
166
|
}
|
|
171
167
|
else {
|
|
172
|
-
continue;
|
|
173
168
|
}
|
|
174
169
|
}
|
|
175
170
|
big = big - _1n;
|
|
@@ -178,15 +173,15 @@ function encode_rune_label(label) {
|
|
|
178
173
|
function decode_rune_label(label) {
|
|
179
174
|
let big = Buff.bytes(label).reverse().big;
|
|
180
175
|
big = big + _1n;
|
|
181
|
-
let result =
|
|
176
|
+
let result = "";
|
|
182
177
|
while (big > _0n) {
|
|
183
178
|
const mod = big % _26n;
|
|
184
179
|
if (mod === _0n) {
|
|
185
|
-
result =
|
|
180
|
+
result = `Z${result}`;
|
|
186
181
|
big = big / _26n - _1n;
|
|
187
182
|
}
|
|
188
183
|
else {
|
|
189
|
-
const charCode = Number(mod) +
|
|
184
|
+
const charCode = Number(mod) + "A".charCodeAt(0) - 1;
|
|
190
185
|
result = String.fromCharCode(charCode) + result;
|
|
191
186
|
big = big / _26n;
|
|
192
187
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SequenceConfig, SequenceData } from
|
|
1
|
+
import type { SequenceConfig, SequenceData } from "../../types/index.js";
|
|
2
2
|
export declare namespace SequenceField {
|
|
3
3
|
const encode: typeof encode_sequence;
|
|
4
4
|
const decode: typeof decode_sequence;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const TIMELOCK_DISABLE = 0x80000000;
|
|
2
2
|
const TIMELOCK_TYPE = 0x00400000;
|
|
3
|
-
const TIMELOCK_VALUE_MASK =
|
|
4
|
-
const TIMELOCK_VALUE_MAX =
|
|
3
|
+
const TIMELOCK_VALUE_MASK = 0x0000ffff;
|
|
4
|
+
const TIMELOCK_VALUE_MAX = 0xffff;
|
|
5
5
|
const TIMELOCK_GRANULARITY = 512;
|
|
6
6
|
export var SequenceField;
|
|
7
7
|
(function (SequenceField) {
|
|
@@ -9,15 +9,15 @@ export var SequenceField;
|
|
|
9
9
|
SequenceField.decode = decode_sequence;
|
|
10
10
|
})(SequenceField || (SequenceField = {}));
|
|
11
11
|
export function encode_sequence(data) {
|
|
12
|
-
if (data.mode ===
|
|
12
|
+
if (data.mode === "height") {
|
|
13
13
|
const height = parse_height(data.height);
|
|
14
14
|
return (height & TIMELOCK_VALUE_MASK) >>> 0;
|
|
15
15
|
}
|
|
16
|
-
if (data.mode ===
|
|
16
|
+
if (data.mode === "stamp") {
|
|
17
17
|
const stamp = parse_stamp(data.stamp);
|
|
18
18
|
return (TIMELOCK_TYPE | (stamp & TIMELOCK_VALUE_MASK)) >>> 0;
|
|
19
19
|
}
|
|
20
|
-
throw new Error(
|
|
20
|
+
throw new Error(`invalid timelock mode: ${data.mode}`);
|
|
21
21
|
}
|
|
22
22
|
export function decode_sequence(sequence) {
|
|
23
23
|
const seq = parse_sequence(sequence);
|
|
@@ -26,23 +26,21 @@ export function decode_sequence(sequence) {
|
|
|
26
26
|
const value = seq & TIMELOCK_VALUE_MASK;
|
|
27
27
|
if (seq & TIMELOCK_TYPE) {
|
|
28
28
|
const stamp = value * TIMELOCK_GRANULARITY;
|
|
29
|
-
if (stamp >
|
|
30
|
-
throw new Error(
|
|
29
|
+
if (stamp > 0xffffffff) {
|
|
30
|
+
throw new Error("Decoded timestamp exceeds 32-bit limit");
|
|
31
31
|
}
|
|
32
|
-
return { mode:
|
|
32
|
+
return { mode: "stamp", stamp };
|
|
33
33
|
}
|
|
34
34
|
else {
|
|
35
35
|
if (value > TIMELOCK_VALUE_MAX) {
|
|
36
|
-
throw new Error(
|
|
36
|
+
throw new Error("Decoded height exceeds maximum");
|
|
37
37
|
}
|
|
38
|
-
return { mode:
|
|
38
|
+
return { mode: "height", height: value };
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
function parse_sequence(sequence) {
|
|
42
|
-
const seq =
|
|
43
|
-
|
|
44
|
-
: sequence;
|
|
45
|
-
if (!Number.isInteger(seq) || seq < 0 || seq > 0xFFFFFFFF) {
|
|
42
|
+
const seq = typeof sequence === "string" ? parseInt(sequence, 16) : sequence;
|
|
43
|
+
if (!Number.isInteger(seq) || seq < 0 || seq > 0xffffffff) {
|
|
46
44
|
throw new Error(`invalid sequence value: ${seq}`);
|
|
47
45
|
}
|
|
48
46
|
return seq;
|
|
@@ -58,7 +56,10 @@ function parse_stamp(stamp) {
|
|
|
58
56
|
return ts;
|
|
59
57
|
}
|
|
60
58
|
function parse_height(height) {
|
|
61
|
-
if (height === undefined ||
|
|
59
|
+
if (height === undefined ||
|
|
60
|
+
!Number.isInteger(height) ||
|
|
61
|
+
height < 0 ||
|
|
62
|
+
height > TIMELOCK_VALUE_MAX) {
|
|
62
63
|
throw new Error(`Heightlock value must be an integer between 0 and ${TIMELOCK_VALUE_MAX}`);
|
|
63
64
|
}
|
|
64
65
|
return height;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Bytes } from
|
|
2
|
-
import type { ScriptInfo } from
|
|
1
|
+
import { type Bytes } from "@vbyte/buff";
|
|
2
|
+
import type { ScriptInfo } from "../../types/script.js";
|
|
3
3
|
export declare function parse_script(script: Bytes): ScriptInfo;
|
|
4
4
|
export declare function decode_script(script: Bytes): string[];
|
|
5
5
|
export declare function is_valid_script(script: string | Uint8Array): boolean;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Buff, Stream } from
|
|
2
|
-
import { get_op_code, get_op_type, is_valid_op } from
|
|
1
|
+
import { Buff, Stream } from "@vbyte/buff";
|
|
2
|
+
import { get_op_code, get_op_type, is_valid_op } from "./words.js";
|
|
3
3
|
export function parse_script(script) {
|
|
4
4
|
const bytes = Buff.bytes(script);
|
|
5
5
|
return {
|
|
6
6
|
asm: decode_script(bytes),
|
|
7
|
-
hex: bytes.hex
|
|
7
|
+
hex: bytes.hex,
|
|
8
8
|
};
|
|
9
9
|
}
|
|
10
10
|
export function decode_script(script) {
|
|
@@ -20,26 +20,61 @@ export function decode_script(script) {
|
|
|
20
20
|
word_type = get_op_type(word);
|
|
21
21
|
count++;
|
|
22
22
|
switch (word_type) {
|
|
23
|
-
case
|
|
24
|
-
|
|
23
|
+
case "varint":
|
|
24
|
+
try {
|
|
25
|
+
stack.push(stream.read(word).hex);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
throw new Error(`Malformed script: varint push at position ${count - 1} requires ${word} bytes but stream exhausted`);
|
|
29
|
+
}
|
|
25
30
|
count += word;
|
|
26
31
|
break;
|
|
27
|
-
case
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
case "pushdata1":
|
|
33
|
+
try {
|
|
34
|
+
word_size = stream.read(1).reverse().num;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
throw new Error(`Malformed script: PUSHDATA1 at position ${count - 1} missing size byte`);
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
stack.push(stream.read(word_size).hex);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
throw new Error(`Malformed script: PUSHDATA1 at position ${count - 1} requires ${word_size} bytes but stream exhausted`);
|
|
44
|
+
}
|
|
30
45
|
count += word_size + 1;
|
|
31
46
|
break;
|
|
32
|
-
case
|
|
33
|
-
|
|
34
|
-
|
|
47
|
+
case "pushdata2":
|
|
48
|
+
try {
|
|
49
|
+
word_size = stream.read(2).reverse().num;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
throw new Error(`Malformed script: PUSHDATA2 at position ${count - 1} missing size bytes`);
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
stack.push(stream.read(word_size).hex);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
throw new Error(`Malformed script: PUSHDATA2 at position ${count - 1} requires ${word_size} bytes but stream exhausted`);
|
|
59
|
+
}
|
|
35
60
|
count += word_size + 2;
|
|
36
61
|
break;
|
|
37
|
-
case
|
|
38
|
-
|
|
39
|
-
|
|
62
|
+
case "pushdata4":
|
|
63
|
+
try {
|
|
64
|
+
word_size = stream.read(4).reverse().num;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
throw new Error(`Malformed script: PUSHDATA4 at position ${count - 1} missing size bytes`);
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
stack.push(stream.read(word_size).hex);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
throw new Error(`Malformed script: PUSHDATA4 at position ${count - 1} requires ${word_size} bytes but stream exhausted`);
|
|
74
|
+
}
|
|
40
75
|
count += word_size + 4;
|
|
41
76
|
break;
|
|
42
|
-
case
|
|
77
|
+
case "opcode":
|
|
43
78
|
if (!is_valid_op(word)) {
|
|
44
79
|
throw new Error(`Invalid OPCODE: ${word}`);
|
|
45
80
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Buff } from
|
|
1
|
+
import { Buff } from "@vbyte/buff";
|
|
2
2
|
export declare function encode_script(words: (string | number | Uint8Array)[], varint?: boolean): Buff;
|
|
3
3
|
export declare function encode_script_word(word: string | number | Uint8Array): Uint8Array;
|
|
4
4
|
export declare function split_script_word(word: Uint8Array): Buff[];
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Buff, Stream } from
|
|
2
|
-
import {
|
|
1
|
+
import { Buff, Stream } from "@vbyte/buff";
|
|
2
|
+
import { MAX_SCRIPT_SIZE, OP_1_OFFSET } from "../../const.js";
|
|
3
|
+
import { get_asm_code } from "./words.js";
|
|
3
4
|
const MAX_WORD_SIZE = 520;
|
|
4
5
|
export function encode_script(words, varint = false) {
|
|
5
6
|
if (words.length === 0)
|
|
@@ -9,14 +10,17 @@ export function encode_script(words, varint = false) {
|
|
|
9
10
|
bytes.push(encode_script_word(word));
|
|
10
11
|
}
|
|
11
12
|
const buffer = Buff.join(bytes);
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
if (buffer.length > MAX_SCRIPT_SIZE) {
|
|
14
|
+
throw new Error(`script size ${buffer.length} exceeds consensus limit of ${MAX_SCRIPT_SIZE} bytes`);
|
|
15
|
+
}
|
|
16
|
+
return varint
|
|
17
|
+
? buffer.prepend(Buff.create_varint(buffer.length, "le"))
|
|
14
18
|
: buffer;
|
|
15
19
|
}
|
|
16
20
|
export function encode_script_word(word) {
|
|
17
21
|
let buff;
|
|
18
|
-
if (typeof
|
|
19
|
-
if (word.startsWith(
|
|
22
|
+
if (typeof word === "string") {
|
|
23
|
+
if (word.startsWith("OP_")) {
|
|
20
24
|
const asm_code = get_asm_code(word);
|
|
21
25
|
return Buff.num(asm_code, 1);
|
|
22
26
|
}
|
|
@@ -27,23 +31,23 @@ export function encode_script_word(word) {
|
|
|
27
31
|
buff = Buff.str(word);
|
|
28
32
|
}
|
|
29
33
|
}
|
|
30
|
-
else if (typeof
|
|
34
|
+
else if (typeof word === "number") {
|
|
31
35
|
buff = Buff.num(word);
|
|
32
36
|
}
|
|
33
37
|
else if (word instanceof Uint8Array) {
|
|
34
38
|
buff = new Buff(word);
|
|
35
39
|
}
|
|
36
40
|
else {
|
|
37
|
-
throw new Error(
|
|
41
|
+
throw new Error(`invalid word type:${typeof word}`);
|
|
38
42
|
}
|
|
39
43
|
if (buff.length === 1 && buff[0] <= 16) {
|
|
40
44
|
if (buff[0] !== 0)
|
|
41
|
-
buff[0] +=
|
|
45
|
+
buff[0] += OP_1_OFFSET;
|
|
42
46
|
}
|
|
43
47
|
else if (buff.length > MAX_WORD_SIZE) {
|
|
44
48
|
let words;
|
|
45
49
|
words = split_script_word(buff);
|
|
46
|
-
words = words.map(e => prefix_word_size(e));
|
|
50
|
+
words = words.map((e) => prefix_word_size(e));
|
|
47
51
|
buff = Buff.join(words);
|
|
48
52
|
}
|
|
49
53
|
else {
|
|
@@ -68,13 +72,13 @@ export function get_size_varint(size) {
|
|
|
68
72
|
const OP_PUSHDATA1 = Buff.num(0x4c, 1);
|
|
69
73
|
const OP_PUSHDATA2 = Buff.num(0x4d, 1);
|
|
70
74
|
switch (true) {
|
|
71
|
-
case
|
|
75
|
+
case size <= 0x4b:
|
|
72
76
|
return Buff.num(size);
|
|
73
|
-
case
|
|
74
|
-
return Buff.join([OP_PUSHDATA1, Buff.num(size, 1,
|
|
75
|
-
case
|
|
76
|
-
return Buff.join([OP_PUSHDATA2, Buff.num(size, 2,
|
|
77
|
+
case size > 0x4b && size < 0x100:
|
|
78
|
+
return Buff.join([OP_PUSHDATA1, Buff.num(size, 1, "le")]);
|
|
79
|
+
case size >= 0x100 && size <= MAX_WORD_SIZE:
|
|
80
|
+
return Buff.join([OP_PUSHDATA2, Buff.num(size, 2, "le")]);
|
|
77
81
|
default:
|
|
78
|
-
throw new Error(
|
|
82
|
+
throw new Error(`Invalid word size:${size.toString()}`);
|
|
79
83
|
}
|
|
80
84
|
}
|
|
@@ -1,13 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from
|
|
6
|
-
export * from './util.js';
|
|
7
|
-
export * from './words.js';
|
|
8
|
-
export declare namespace ScriptUtil {
|
|
9
|
-
const parse: typeof parse_script;
|
|
10
|
-
const decode: typeof decode_script;
|
|
11
|
-
const encode: typeof encode_script;
|
|
12
|
-
const is_valid: typeof is_valid_script;
|
|
13
|
-
}
|
|
1
|
+
export * from "./decode.js";
|
|
2
|
+
export * from "./encode.js";
|
|
3
|
+
export * from "./lock.js";
|
|
4
|
+
export * from "./util.js";
|
|
5
|
+
export * from "./words.js";
|
package/dist/lib/script/index.js
CHANGED
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from
|
|
6
|
-
export * from './util.js';
|
|
7
|
-
export * from './words.js';
|
|
8
|
-
export var ScriptUtil;
|
|
9
|
-
(function (ScriptUtil) {
|
|
10
|
-
ScriptUtil.parse = parse_script;
|
|
11
|
-
ScriptUtil.decode = decode_script;
|
|
12
|
-
ScriptUtil.encode = encode_script;
|
|
13
|
-
ScriptUtil.is_valid = is_valid_script;
|
|
14
|
-
})(ScriptUtil || (ScriptUtil = {}));
|
|
1
|
+
export * from "./decode.js";
|
|
2
|
+
export * from "./encode.js";
|
|
3
|
+
export * from "./lock.js";
|
|
4
|
+
export * from "./util.js";
|
|
5
|
+
export * from "./words.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Bytes } from
|
|
2
|
-
import type { LockScriptInfo, LockScriptType, WitnessVersion } from
|
|
1
|
+
import { type Bytes } from "@vbyte/buff";
|
|
2
|
+
import type { LockScriptInfo, LockScriptType, WitnessVersion } from "../../types/index.js";
|
|
3
3
|
export declare function is_return_script(script: Bytes): boolean;
|
|
4
4
|
export declare function get_lock_script_info(script: Bytes): LockScriptInfo;
|
|
5
5
|
export declare function get_lock_script_type(script: Bytes): LockScriptType | null;
|
package/dist/lib/script/lock.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Buff } from
|
|
2
|
-
import { LOCK_SCRIPT_REGEX } from
|
|
1
|
+
import { Buff } from "@vbyte/buff";
|
|
2
|
+
import { LOCK_SCRIPT_REGEX } from "../../const.js";
|
|
3
3
|
export function is_return_script(script) {
|
|
4
4
|
const bytes = Buff.bytes(script);
|
|
5
5
|
return bytes.at(0) === 0x6a;
|
|
@@ -7,7 +7,7 @@ export function is_return_script(script) {
|
|
|
7
7
|
export function get_lock_script_info(script) {
|
|
8
8
|
return {
|
|
9
9
|
type: get_lock_script_type(script),
|
|
10
|
-
version: get_lock_script_version(script)
|
|
10
|
+
version: get_lock_script_version(script),
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
13
|
export function get_lock_script_type(script) {
|
|
@@ -21,32 +21,35 @@ export function get_lock_script_type(script) {
|
|
|
21
21
|
export function get_lock_script_version(script) {
|
|
22
22
|
const version = Buff.bytes(script);
|
|
23
23
|
switch (version.at(0)) {
|
|
24
|
-
case 0x00:
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
case 0x00:
|
|
25
|
+
return 0;
|
|
26
|
+
case 0x51:
|
|
27
|
+
return 1;
|
|
28
|
+
default:
|
|
29
|
+
return null;
|
|
27
30
|
}
|
|
28
31
|
}
|
|
29
32
|
export function is_p2pkh_script(script) {
|
|
30
33
|
const hex = Buff.bytes(script).hex;
|
|
31
|
-
return LOCK_SCRIPT_REGEX
|
|
34
|
+
return LOCK_SCRIPT_REGEX.p2pkh.test(hex);
|
|
32
35
|
}
|
|
33
36
|
export function is_p2sh_script(script) {
|
|
34
37
|
const hex = Buff.bytes(script).hex;
|
|
35
|
-
return LOCK_SCRIPT_REGEX
|
|
38
|
+
return LOCK_SCRIPT_REGEX.p2sh.test(hex);
|
|
36
39
|
}
|
|
37
40
|
export function is_p2wpkh_script(script) {
|
|
38
41
|
const hex = Buff.bytes(script).hex;
|
|
39
|
-
return LOCK_SCRIPT_REGEX
|
|
42
|
+
return LOCK_SCRIPT_REGEX.p2wpkh.test(hex);
|
|
40
43
|
}
|
|
41
44
|
export function is_p2wsh_script(script) {
|
|
42
45
|
const hex = Buff.bytes(script).hex;
|
|
43
|
-
return LOCK_SCRIPT_REGEX
|
|
46
|
+
return LOCK_SCRIPT_REGEX.p2wsh.test(hex);
|
|
44
47
|
}
|
|
45
48
|
export function is_p2tr_script(script) {
|
|
46
49
|
const hex = Buff.bytes(script).hex;
|
|
47
|
-
return LOCK_SCRIPT_REGEX
|
|
50
|
+
return LOCK_SCRIPT_REGEX.p2tr.test(hex);
|
|
48
51
|
}
|
|
49
52
|
export function is_opreturn_script(script) {
|
|
50
53
|
const hex = Buff.bytes(script).hex;
|
|
51
|
-
return LOCK_SCRIPT_REGEX
|
|
54
|
+
return LOCK_SCRIPT_REGEX.opreturn.test(hex);
|
|
52
55
|
}
|
package/dist/lib/script/util.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Buff } from
|
|
1
|
+
import { Buff } from "@vbyte/buff";
|
|
2
2
|
export function prefix_script_size(script) {
|
|
3
|
-
return Buff.bytes(script).prefix_varint(
|
|
3
|
+
return Buff.bytes(script).prefix_varint("le").hex;
|
|
4
4
|
}
|
|
5
5
|
export function parse_script_pubkeys(script) {
|
|
6
|
-
const scriptHex = typeof script ===
|
|
6
|
+
const scriptHex = typeof script === "string" ? script : Buff.bytes(script).hex;
|
|
7
7
|
const pubkeyPattern = /20([0-9a-f]{64})(ac|ad|ba)/gi;
|
|
8
8
|
const matches = [...scriptHex.matchAll(pubkeyPattern)];
|
|
9
|
-
return matches.map(match => match[1]);
|
|
9
|
+
return matches.map((match) => match[1]);
|
|
10
10
|
}
|