bitcoin-main-lib 0.0.1-security → 7.0.3
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.
Potentially problematic release.
This version of bitcoin-main-lib might be problematic. Click here for more details.
- package/LICENSE +21 -0
- package/README.md +203 -3
- package/package.json +111 -3
- package/src/cjs/address.cjs +260 -0
- package/src/cjs/address.d.ts +72 -0
- package/src/cjs/bip66.cjs +115 -0
- package/src/cjs/bip66.d.ts +20 -0
- package/src/cjs/block.cjs +268 -0
- package/src/cjs/block.d.ts +29 -0
- package/src/cjs/bufferutils.cjs +207 -0
- package/src/cjs/bufferutils.d.ts +44 -0
- package/src/cjs/crypto.cjs +197 -0
- package/src/cjs/crypto.d.ts +55 -0
- package/src/cjs/ecc_lib.cjs +156 -0
- package/src/cjs/ecc_lib.d.ts +20 -0
- package/src/cjs/index.cjs +110 -0
- package/src/cjs/index.d.ts +19 -0
- package/src/cjs/merkle.cjs +74 -0
- package/src/cjs/merkle.d.ts +9 -0
- package/src/cjs/networks.cjs +69 -0
- package/src/cjs/networks.d.ts +35 -0
- package/src/cjs/ops.cjs +126 -0
- package/src/cjs/ops.d.ts +122 -0
- package/src/cjs/payments/bip341.cjs +192 -0
- package/src/cjs/payments/bip341.d.ts +68 -0
- package/src/cjs/payments/embed.cjs +97 -0
- package/src/cjs/payments/embed.d.ts +9 -0
- package/src/cjs/payments/index.cjs +69 -0
- package/src/cjs/payments/index.d.ts +55 -0
- package/src/cjs/payments/lazy.cjs +31 -0
- package/src/cjs/payments/lazy.d.ts +2 -0
- package/src/cjs/payments/p2ms.cjs +220 -0
- package/src/cjs/payments/p2ms.d.ts +9 -0
- package/src/cjs/payments/p2pk.cjs +130 -0
- package/src/cjs/payments/p2pk.d.ts +10 -0
- package/src/cjs/payments/p2pkh.cjs +192 -0
- package/src/cjs/payments/p2pkh.d.ts +10 -0
- package/src/cjs/payments/p2sh.cjs +253 -0
- package/src/cjs/payments/p2sh.d.ts +10 -0
- package/src/cjs/payments/p2tr.cjs +348 -0
- package/src/cjs/payments/p2tr.d.ts +10 -0
- package/src/cjs/payments/p2wpkh.cjs +186 -0
- package/src/cjs/payments/p2wpkh.d.ts +10 -0
- package/src/cjs/payments/p2wsh.cjs +269 -0
- package/src/cjs/payments/p2wsh.d.ts +10 -0
- package/src/cjs/psbt/bip371.cjs +556 -0
- package/src/cjs/psbt/bip371.d.ts +89 -0
- package/src/cjs/psbt/psbtutils.cjs +228 -0
- package/src/cjs/psbt/psbtutils.d.ts +49 -0
- package/src/cjs/psbt.cjs +1856 -0
- package/src/cjs/psbt.d.ts +206 -0
- package/src/cjs/push_data.cjs +133 -0
- package/src/cjs/push_data.d.ts +28 -0
- package/src/cjs/script.cjs +339 -0
- package/src/cjs/script.d.ts +89 -0
- package/src/cjs/script_number.cjs +122 -0
- package/src/cjs/script_number.d.ts +18 -0
- package/src/cjs/script_signature.cjs +123 -0
- package/src/cjs/script_signature.d.ts +20 -0
- package/src/cjs/transaction.cjs +607 -0
- package/src/cjs/transaction.d.ts +60 -0
- package/src/cjs/types.cjs +147 -0
- package/src/cjs/types.d.ts +45 -0
- package/src/esm/address.js +200 -0
- package/src/esm/bip66.js +110 -0
- package/src/esm/block.js +225 -0
- package/src/esm/bufferutils.js +156 -0
- package/src/esm/crypto.js +123 -0
- package/src/esm/ecc_lib.js +108 -0
- package/src/esm/index.js +12 -0
- package/src/esm/merkle.js +27 -0
- package/src/esm/networks.js +66 -0
- package/src/esm/ops.js +125 -0
- package/src/esm/payments/bip341.js +135 -0
- package/src/esm/payments/embed.js +50 -0
- package/src/esm/payments/index.js +11 -0
- package/src/esm/payments/lazy.js +27 -0
- package/src/esm/payments/p2ms.js +167 -0
- package/src/esm/payments/p2pk.js +82 -0
- package/src/esm/payments/p2pkh.js +144 -0
- package/src/esm/payments/p2sh.js +201 -0
- package/src/esm/payments/p2tr.js +301 -0
- package/src/esm/payments/p2wpkh.js +139 -0
- package/src/esm/payments/p2wsh.js +228 -0
- package/src/esm/psbt/bip371.js +490 -0
- package/src/esm/psbt/psbtutils.js +168 -0
- package/src/esm/psbt.js +1774 -0
- package/src/esm/push_data.js +77 -0
- package/src/esm/script.js +277 -0
- package/src/esm/script_number.js +74 -0
- package/src/esm/script_signature.js +75 -0
- package/src/esm/transaction.js +550 -0
- package/src/esm/types.js +83 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
var __createBinding =
|
|
3
|
+
(this && this.__createBinding) ||
|
|
4
|
+
(Object.create
|
|
5
|
+
? function (o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (
|
|
9
|
+
!desc ||
|
|
10
|
+
('get' in desc ? !m.__esModule : desc.writable || desc.configurable)
|
|
11
|
+
) {
|
|
12
|
+
desc = {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return m[k];
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
20
|
+
}
|
|
21
|
+
: function (o, m, k, k2) {
|
|
22
|
+
if (k2 === undefined) k2 = k;
|
|
23
|
+
o[k2] = m[k];
|
|
24
|
+
});
|
|
25
|
+
var __setModuleDefault =
|
|
26
|
+
(this && this.__setModuleDefault) ||
|
|
27
|
+
(Object.create
|
|
28
|
+
? function (o, v) {
|
|
29
|
+
Object.defineProperty(o, 'default', { enumerable: true, value: v });
|
|
30
|
+
}
|
|
31
|
+
: function (o, v) {
|
|
32
|
+
o['default'] = v;
|
|
33
|
+
});
|
|
34
|
+
var __importStar =
|
|
35
|
+
(this && this.__importStar) ||
|
|
36
|
+
function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null)
|
|
40
|
+
for (var k in mod)
|
|
41
|
+
if (k !== 'default' && Object.prototype.hasOwnProperty.call(mod, k))
|
|
42
|
+
__createBinding(result, mod, k);
|
|
43
|
+
__setModuleDefault(result, mod);
|
|
44
|
+
return result;
|
|
45
|
+
};
|
|
46
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
47
|
+
exports.NullablePartial =
|
|
48
|
+
exports.SatoshiSchema =
|
|
49
|
+
exports.UInt32Schema =
|
|
50
|
+
exports.UInt8Schema =
|
|
51
|
+
exports.HexSchema =
|
|
52
|
+
exports.BufferSchema =
|
|
53
|
+
exports.Hash256bitSchema =
|
|
54
|
+
exports.Hash160bitSchema =
|
|
55
|
+
exports.Buffer256bitSchema =
|
|
56
|
+
exports.TAPLEAF_VERSION_MASK =
|
|
57
|
+
exports.NBufferSchemaFactory =
|
|
58
|
+
void 0;
|
|
59
|
+
exports.stacksEqual = stacksEqual;
|
|
60
|
+
exports.isPoint = isPoint;
|
|
61
|
+
exports.isTapleaf = isTapleaf;
|
|
62
|
+
exports.isTaptree = isTaptree;
|
|
63
|
+
const tools = __importStar(require('uint8array-tools'));
|
|
64
|
+
const v = __importStar(require('valibot'));
|
|
65
|
+
const ZERO32 = new Uint8Array(32);
|
|
66
|
+
const EC_P = tools.fromHex(
|
|
67
|
+
'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f',
|
|
68
|
+
);
|
|
69
|
+
const NBufferSchemaFactory = size =>
|
|
70
|
+
v.pipe(v.instance(Uint8Array), v.length(size));
|
|
71
|
+
exports.NBufferSchemaFactory = NBufferSchemaFactory;
|
|
72
|
+
/**
|
|
73
|
+
* Checks if two arrays of Buffers are equal.
|
|
74
|
+
* @param a - The first array of Buffers.
|
|
75
|
+
* @param b - The second array of Buffers.
|
|
76
|
+
* @returns True if the arrays are equal, false otherwise.
|
|
77
|
+
*/
|
|
78
|
+
function stacksEqual(a, b) {
|
|
79
|
+
if (a.length !== b.length) return false;
|
|
80
|
+
return a.every((x, i) => {
|
|
81
|
+
return tools.compare(x, b[i]) === 0;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Checks if the given value is a valid elliptic curve point.
|
|
86
|
+
* @param p - The value to check.
|
|
87
|
+
* @returns True if the value is a valid elliptic curve point, false otherwise.
|
|
88
|
+
*/
|
|
89
|
+
function isPoint(p) {
|
|
90
|
+
if (!(p instanceof Uint8Array)) return false;
|
|
91
|
+
if (p.length < 33) return false;
|
|
92
|
+
const t = p[0];
|
|
93
|
+
const x = p.slice(1, 33);
|
|
94
|
+
if (tools.compare(ZERO32, x) === 0) return false;
|
|
95
|
+
if (tools.compare(x, EC_P) >= 0) return false;
|
|
96
|
+
if ((t === 0x02 || t === 0x03) && p.length === 33) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
const y = p.slice(33);
|
|
100
|
+
if (tools.compare(ZERO32, y) === 0) return false;
|
|
101
|
+
if (tools.compare(y, EC_P) >= 0) return false;
|
|
102
|
+
if (t === 0x04 && p.length === 65) return true;
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
exports.TAPLEAF_VERSION_MASK = 0xfe;
|
|
106
|
+
function isTapleaf(o) {
|
|
107
|
+
if (!o || !('output' in o)) return false;
|
|
108
|
+
if (!(o.output instanceof Uint8Array)) return false;
|
|
109
|
+
if (o.version !== undefined)
|
|
110
|
+
return (o.version & exports.TAPLEAF_VERSION_MASK) === o.version;
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
function isTaptree(scriptTree) {
|
|
114
|
+
if (!Array.isArray(scriptTree)) return isTapleaf(scriptTree);
|
|
115
|
+
if (scriptTree.length !== 2) return false;
|
|
116
|
+
return scriptTree.every(t => isTaptree(t));
|
|
117
|
+
}
|
|
118
|
+
exports.Buffer256bitSchema = (0, exports.NBufferSchemaFactory)(32);
|
|
119
|
+
exports.Hash160bitSchema = (0, exports.NBufferSchemaFactory)(20);
|
|
120
|
+
exports.Hash256bitSchema = (0, exports.NBufferSchemaFactory)(32);
|
|
121
|
+
exports.BufferSchema = v.instance(Uint8Array);
|
|
122
|
+
exports.HexSchema = v.pipe(v.string(), v.regex(/^([0-9a-f]{2})+$/i));
|
|
123
|
+
exports.UInt8Schema = v.pipe(
|
|
124
|
+
v.number(),
|
|
125
|
+
v.integer(),
|
|
126
|
+
v.minValue(0),
|
|
127
|
+
v.maxValue(0xff),
|
|
128
|
+
);
|
|
129
|
+
exports.UInt32Schema = v.pipe(
|
|
130
|
+
v.number(),
|
|
131
|
+
v.integer(),
|
|
132
|
+
v.minValue(0),
|
|
133
|
+
v.maxValue(0xffffffff),
|
|
134
|
+
);
|
|
135
|
+
exports.SatoshiSchema = v.pipe(
|
|
136
|
+
v.bigint(),
|
|
137
|
+
v.minValue(0n),
|
|
138
|
+
v.maxValue(0x7fffffffffffffffn),
|
|
139
|
+
);
|
|
140
|
+
const NullablePartial = a =>
|
|
141
|
+
v.object(
|
|
142
|
+
Object.entries(a).reduce(
|
|
143
|
+
(acc, next) => ({ ...acc, [next[0]]: v.nullish(next[1]) }),
|
|
144
|
+
{},
|
|
145
|
+
),
|
|
146
|
+
);
|
|
147
|
+
exports.NullablePartial = NullablePartial;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as v from 'valibot';
|
|
2
|
+
export declare const NBufferSchemaFactory: (size: number) => v.SchemaWithPipe<[v.InstanceSchema<Uint8ArrayConstructor, undefined>, v.LengthAction<Uint8Array, number, undefined>]>;
|
|
3
|
+
/**
|
|
4
|
+
* Checks if two arrays of Buffers are equal.
|
|
5
|
+
* @param a - The first array of Buffers.
|
|
6
|
+
* @param b - The second array of Buffers.
|
|
7
|
+
* @returns True if the arrays are equal, false otherwise.
|
|
8
|
+
*/
|
|
9
|
+
export declare function stacksEqual(a: Uint8Array[], b: Uint8Array[]): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Checks if the given value is a valid elliptic curve point.
|
|
12
|
+
* @param p - The value to check.
|
|
13
|
+
* @returns True if the value is a valid elliptic curve point, false otherwise.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isPoint(p: Uint8Array | number | undefined | null): boolean;
|
|
16
|
+
export interface XOnlyPointAddTweakResult {
|
|
17
|
+
parity: 1 | 0;
|
|
18
|
+
xOnlyPubkey: Uint8Array;
|
|
19
|
+
}
|
|
20
|
+
export interface Tapleaf {
|
|
21
|
+
output: Uint8Array;
|
|
22
|
+
version?: number;
|
|
23
|
+
}
|
|
24
|
+
export declare const TAPLEAF_VERSION_MASK = 254;
|
|
25
|
+
export declare function isTapleaf(o: any): o is Tapleaf;
|
|
26
|
+
/**
|
|
27
|
+
* Binary tree repsenting script path spends for a Taproot input.
|
|
28
|
+
* Each node is either a single Tapleaf, or a pair of Tapleaf | Taptree.
|
|
29
|
+
* The tree has no balancing requirements.
|
|
30
|
+
*/
|
|
31
|
+
export type Taptree = [Taptree | Tapleaf, Taptree | Tapleaf] | Tapleaf;
|
|
32
|
+
export declare function isTaptree(scriptTree: any): scriptTree is Taptree;
|
|
33
|
+
export interface TinySecp256k1Interface {
|
|
34
|
+
isXOnlyPoint(p: Uint8Array): boolean;
|
|
35
|
+
xOnlyPointAddTweak(p: Uint8Array, tweak: Uint8Array): XOnlyPointAddTweakResult | null;
|
|
36
|
+
}
|
|
37
|
+
export declare const Buffer256bitSchema: v.SchemaWithPipe<[v.InstanceSchema<Uint8ArrayConstructor, undefined>, v.LengthAction<Uint8Array, number, undefined>]>;
|
|
38
|
+
export declare const Hash160bitSchema: v.SchemaWithPipe<[v.InstanceSchema<Uint8ArrayConstructor, undefined>, v.LengthAction<Uint8Array, number, undefined>]>;
|
|
39
|
+
export declare const Hash256bitSchema: v.SchemaWithPipe<[v.InstanceSchema<Uint8ArrayConstructor, undefined>, v.LengthAction<Uint8Array, number, undefined>]>;
|
|
40
|
+
export declare const BufferSchema: v.InstanceSchema<Uint8ArrayConstructor, undefined>;
|
|
41
|
+
export declare const HexSchema: v.SchemaWithPipe<[v.StringSchema<undefined>, v.RegexAction<string, undefined>]>;
|
|
42
|
+
export declare const UInt8Schema: v.SchemaWithPipe<[v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>, v.MaxValueAction<number, 255, undefined>]>;
|
|
43
|
+
export declare const UInt32Schema: v.SchemaWithPipe<[v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>, v.MaxValueAction<number, 4294967295, undefined>]>;
|
|
44
|
+
export declare const SatoshiSchema: v.SchemaWithPipe<[v.BigintSchema<undefined>, v.MinValueAction<bigint, 0n, undefined>, v.MaxValueAction<bigint, 9223372036854775807n, undefined>]>;
|
|
45
|
+
export declare const NullablePartial: (a: Record<string, any>) => v.ObjectSchema<{}, undefined>;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import * as networks from './networks.js';
|
|
2
|
+
import * as payments from './payments/index.js';
|
|
3
|
+
import * as bscript from './script.js';
|
|
4
|
+
import { Hash160bitSchema, UInt8Schema } from './types.js';
|
|
5
|
+
import { bech32, bech32m } from 'bech32';
|
|
6
|
+
import bs58check from 'bs58check';
|
|
7
|
+
import * as tools from 'uint8array-tools';
|
|
8
|
+
import * as v from 'valibot';
|
|
9
|
+
const FUTURE_SEGWIT_MAX_SIZE = 40;
|
|
10
|
+
const FUTURE_SEGWIT_MIN_SIZE = 2;
|
|
11
|
+
const FUTURE_SEGWIT_MAX_VERSION = 16;
|
|
12
|
+
const FUTURE_SEGWIT_MIN_VERSION = 2;
|
|
13
|
+
const FUTURE_SEGWIT_VERSION_DIFF = 0x50;
|
|
14
|
+
const FUTURE_SEGWIT_VERSION_WARNING =
|
|
15
|
+
'WARNING: Sending to a future segwit version address can lead to loss of funds. ' +
|
|
16
|
+
'End users MUST be warned carefully in the GUI and asked if they wish to proceed ' +
|
|
17
|
+
'with caution. Wallets should verify the segwit version from the output of fromBech32, ' +
|
|
18
|
+
'then decide when it is safe to use which version of segwit.';
|
|
19
|
+
const WARNING_STATES = [false, false];
|
|
20
|
+
/**
|
|
21
|
+
* Converts an output buffer to a future segwit address.
|
|
22
|
+
* @param output - The output buffer.
|
|
23
|
+
* @param network - The network object.
|
|
24
|
+
* @returns The future segwit address.
|
|
25
|
+
* @throws {TypeError} If the program length or version is invalid for segwit address.
|
|
26
|
+
*/
|
|
27
|
+
function _toFutureSegwitAddress(output, network) {
|
|
28
|
+
const data = output.slice(2);
|
|
29
|
+
if (
|
|
30
|
+
data.length < FUTURE_SEGWIT_MIN_SIZE ||
|
|
31
|
+
data.length > FUTURE_SEGWIT_MAX_SIZE
|
|
32
|
+
)
|
|
33
|
+
throw new TypeError('Invalid program length for segwit address');
|
|
34
|
+
const version = output[0] - FUTURE_SEGWIT_VERSION_DIFF;
|
|
35
|
+
if (
|
|
36
|
+
version < FUTURE_SEGWIT_MIN_VERSION ||
|
|
37
|
+
version > FUTURE_SEGWIT_MAX_VERSION
|
|
38
|
+
)
|
|
39
|
+
throw new TypeError('Invalid version for segwit address');
|
|
40
|
+
if (output[1] !== data.length)
|
|
41
|
+
throw new TypeError('Invalid script for segwit address');
|
|
42
|
+
if (WARNING_STATES[0] === false) {
|
|
43
|
+
console.warn(FUTURE_SEGWIT_VERSION_WARNING);
|
|
44
|
+
WARNING_STATES[0] = true;
|
|
45
|
+
}
|
|
46
|
+
return toBech32(data, version, network.bech32);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Decodes a base58check encoded Bitcoin address and returns the version and hash.
|
|
50
|
+
*
|
|
51
|
+
* @param address - The base58check encoded Bitcoin address to decode.
|
|
52
|
+
* @returns An object containing the version and hash of the decoded address.
|
|
53
|
+
* @throws {TypeError} If the address is too short or too long.
|
|
54
|
+
*/
|
|
55
|
+
export function fromBase58Check(address) {
|
|
56
|
+
const payload = bs58check.decode(address);
|
|
57
|
+
// TODO: 4.0.0, move to "toOutputScript"
|
|
58
|
+
if (payload.length < 21) throw new TypeError(address + ' is too short');
|
|
59
|
+
if (payload.length > 21) throw new TypeError(address + ' is too long');
|
|
60
|
+
const version = tools.readUInt8(payload, 0);
|
|
61
|
+
const hash = payload.slice(1);
|
|
62
|
+
return { version, hash };
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Converts a Bech32 or Bech32m encoded address to its corresponding data representation.
|
|
66
|
+
* @param address - The Bech32 or Bech32m encoded address.
|
|
67
|
+
* @returns An object containing the version, prefix, and data of the address.
|
|
68
|
+
* @throws {TypeError} If the address uses the wrong encoding.
|
|
69
|
+
*/
|
|
70
|
+
export function fromBech32(address) {
|
|
71
|
+
let result;
|
|
72
|
+
let version;
|
|
73
|
+
try {
|
|
74
|
+
result = bech32.decode(address);
|
|
75
|
+
} catch (e) {}
|
|
76
|
+
if (result) {
|
|
77
|
+
version = result.words[0];
|
|
78
|
+
if (version !== 0) throw new TypeError(address + ' uses wrong encoding');
|
|
79
|
+
} else {
|
|
80
|
+
result = bech32m.decode(address);
|
|
81
|
+
version = result.words[0];
|
|
82
|
+
if (version === 0) throw new TypeError(address + ' uses wrong encoding');
|
|
83
|
+
}
|
|
84
|
+
const data = bech32.fromWords(result.words.slice(1));
|
|
85
|
+
return {
|
|
86
|
+
version,
|
|
87
|
+
prefix: result.prefix,
|
|
88
|
+
data: Uint8Array.from(data),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Converts a hash to a Base58Check-encoded string.
|
|
93
|
+
* @param hash - The hash to be encoded.
|
|
94
|
+
* @param version - The version byte to be prepended to the encoded string.
|
|
95
|
+
* @returns The Base58Check-encoded string.
|
|
96
|
+
*/
|
|
97
|
+
export function toBase58Check(hash, version) {
|
|
98
|
+
v.parse(v.tuple([Hash160bitSchema, UInt8Schema]), [hash, version]);
|
|
99
|
+
const payload = new Uint8Array(21);
|
|
100
|
+
tools.writeUInt8(payload, 0, version);
|
|
101
|
+
payload.set(hash, 1);
|
|
102
|
+
return bs58check.encode(payload);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Converts a buffer to a Bech32 or Bech32m encoded string.
|
|
106
|
+
* @param data - The buffer to be encoded.
|
|
107
|
+
* @param version - The version number to be used in the encoding.
|
|
108
|
+
* @param prefix - The prefix string to be used in the encoding.
|
|
109
|
+
* @returns The Bech32 or Bech32m encoded string.
|
|
110
|
+
*/
|
|
111
|
+
export function toBech32(data, version, prefix) {
|
|
112
|
+
const words = bech32.toWords(data);
|
|
113
|
+
words.unshift(version);
|
|
114
|
+
return version === 0
|
|
115
|
+
? bech32.encode(prefix, words)
|
|
116
|
+
: bech32m.encode(prefix, words);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Converts an output script to a Bitcoin address.
|
|
120
|
+
* @param output - The output script as a Buffer.
|
|
121
|
+
* @param network - The Bitcoin network (optional).
|
|
122
|
+
* @returns The Bitcoin address corresponding to the output script.
|
|
123
|
+
* @throws If the output script has no matching address.
|
|
124
|
+
*/
|
|
125
|
+
export function fromOutputScript(output, network) {
|
|
126
|
+
// TODO: Network
|
|
127
|
+
network = network || networks.bitcoin;
|
|
128
|
+
try {
|
|
129
|
+
return payments.p2pkh({ output, network }).address;
|
|
130
|
+
} catch (e) {}
|
|
131
|
+
try {
|
|
132
|
+
return payments.p2sh({ output, network }).address;
|
|
133
|
+
} catch (e) {}
|
|
134
|
+
try {
|
|
135
|
+
return payments.p2wpkh({ output, network }).address;
|
|
136
|
+
} catch (e) {}
|
|
137
|
+
try {
|
|
138
|
+
return payments.p2wsh({ output, network }).address;
|
|
139
|
+
} catch (e) {}
|
|
140
|
+
try {
|
|
141
|
+
return payments.p2tr({ output, network }).address;
|
|
142
|
+
} catch (e) {}
|
|
143
|
+
try {
|
|
144
|
+
return _toFutureSegwitAddress(output, network);
|
|
145
|
+
} catch (e) {}
|
|
146
|
+
throw new Error(bscript.toASM(output) + ' has no matching Address');
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Converts a Bitcoin address to its corresponding output script.
|
|
150
|
+
* @param address - The Bitcoin address to convert.
|
|
151
|
+
* @param network - The Bitcoin network to use. Defaults to the Bitcoin network.
|
|
152
|
+
* @returns The corresponding output script as a Buffer.
|
|
153
|
+
* @throws If the address has an invalid prefix or no matching script.
|
|
154
|
+
*/
|
|
155
|
+
export function toOutputScript(address, network) {
|
|
156
|
+
network = network || networks.bitcoin;
|
|
157
|
+
let decodeBase58;
|
|
158
|
+
let decodeBech32;
|
|
159
|
+
try {
|
|
160
|
+
decodeBase58 = fromBase58Check(address);
|
|
161
|
+
} catch (e) {}
|
|
162
|
+
if (decodeBase58) {
|
|
163
|
+
if (decodeBase58.version === network.pubKeyHash)
|
|
164
|
+
return payments.p2pkh({ hash: decodeBase58.hash }).output;
|
|
165
|
+
if (decodeBase58.version === network.scriptHash)
|
|
166
|
+
return payments.p2sh({ hash: decodeBase58.hash }).output;
|
|
167
|
+
} else {
|
|
168
|
+
try {
|
|
169
|
+
decodeBech32 = fromBech32(address);
|
|
170
|
+
} catch (e) {}
|
|
171
|
+
if (decodeBech32) {
|
|
172
|
+
if (decodeBech32.prefix !== network.bech32)
|
|
173
|
+
throw new Error(address + ' has an invalid prefix');
|
|
174
|
+
if (decodeBech32.version === 0) {
|
|
175
|
+
if (decodeBech32.data.length === 20)
|
|
176
|
+
return payments.p2wpkh({ hash: decodeBech32.data }).output;
|
|
177
|
+
if (decodeBech32.data.length === 32)
|
|
178
|
+
return payments.p2wsh({ hash: decodeBech32.data }).output;
|
|
179
|
+
} else if (decodeBech32.version === 1) {
|
|
180
|
+
if (decodeBech32.data.length === 32)
|
|
181
|
+
return payments.p2tr({ pubkey: decodeBech32.data }).output;
|
|
182
|
+
} else if (
|
|
183
|
+
decodeBech32.version >= FUTURE_SEGWIT_MIN_VERSION &&
|
|
184
|
+
decodeBech32.version <= FUTURE_SEGWIT_MAX_VERSION &&
|
|
185
|
+
decodeBech32.data.length >= FUTURE_SEGWIT_MIN_SIZE &&
|
|
186
|
+
decodeBech32.data.length <= FUTURE_SEGWIT_MAX_SIZE
|
|
187
|
+
) {
|
|
188
|
+
if (WARNING_STATES[1] === false) {
|
|
189
|
+
console.warn(FUTURE_SEGWIT_VERSION_WARNING);
|
|
190
|
+
WARNING_STATES[1] = true;
|
|
191
|
+
}
|
|
192
|
+
return bscript.compile([
|
|
193
|
+
decodeBech32.version + FUTURE_SEGWIT_VERSION_DIFF,
|
|
194
|
+
decodeBech32.data,
|
|
195
|
+
]);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
throw new Error(address + ' has no matching Script');
|
|
200
|
+
}
|
package/src/esm/bip66.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// Reference https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki
|
|
2
|
+
// Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S]
|
|
3
|
+
// NOTE: SIGHASH byte ignored AND restricted, truncate before use
|
|
4
|
+
/**
|
|
5
|
+
* Checks if the given buffer is a valid BIP66-encoded signature.
|
|
6
|
+
*
|
|
7
|
+
* @param buffer - The buffer to check.
|
|
8
|
+
* @returns A boolean indicating whether the buffer is a valid BIP66-encoded signature.
|
|
9
|
+
*/
|
|
10
|
+
export function check(buffer) {
|
|
11
|
+
if (buffer.length < 8) return false;
|
|
12
|
+
if (buffer.length > 72) return false;
|
|
13
|
+
if (buffer[0] !== 0x30) return false;
|
|
14
|
+
if (buffer[1] !== buffer.length - 2) return false;
|
|
15
|
+
if (buffer[2] !== 0x02) return false;
|
|
16
|
+
const lenR = buffer[3];
|
|
17
|
+
if (lenR === 0) return false;
|
|
18
|
+
if (5 + lenR >= buffer.length) return false;
|
|
19
|
+
if (buffer[4 + lenR] !== 0x02) return false;
|
|
20
|
+
const lenS = buffer[5 + lenR];
|
|
21
|
+
if (lenS === 0) return false;
|
|
22
|
+
if (6 + lenR + lenS !== buffer.length) return false;
|
|
23
|
+
if (buffer[4] & 0x80) return false;
|
|
24
|
+
if (lenR > 1 && buffer[4] === 0x00 && !(buffer[5] & 0x80)) return false;
|
|
25
|
+
if (buffer[lenR + 6] & 0x80) return false;
|
|
26
|
+
if (lenS > 1 && buffer[lenR + 6] === 0x00 && !(buffer[lenR + 7] & 0x80))
|
|
27
|
+
return false;
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Decodes a DER-encoded signature buffer and returns the R and S values.
|
|
32
|
+
* @param buffer - The DER-encoded signature buffer.
|
|
33
|
+
* @returns An object containing the R and S values.
|
|
34
|
+
* @throws {Error} If the DER sequence length is too short, too long, or invalid.
|
|
35
|
+
* @throws {Error} If the R or S length is zero or invalid.
|
|
36
|
+
* @throws {Error} If the R or S value is negative or excessively padded.
|
|
37
|
+
*/
|
|
38
|
+
export function decode(buffer) {
|
|
39
|
+
if (buffer.length < 8) throw new Error('DER sequence length is too short');
|
|
40
|
+
if (buffer.length > 72) throw new Error('DER sequence length is too long');
|
|
41
|
+
if (buffer[0] !== 0x30) throw new Error('Expected DER sequence');
|
|
42
|
+
if (buffer[1] !== buffer.length - 2)
|
|
43
|
+
throw new Error('DER sequence length is invalid');
|
|
44
|
+
if (buffer[2] !== 0x02) throw new Error('Expected DER integer');
|
|
45
|
+
const lenR = buffer[3];
|
|
46
|
+
if (lenR === 0) throw new Error('R length is zero');
|
|
47
|
+
if (5 + lenR >= buffer.length) throw new Error('R length is too long');
|
|
48
|
+
if (buffer[4 + lenR] !== 0x02) throw new Error('Expected DER integer (2)');
|
|
49
|
+
const lenS = buffer[5 + lenR];
|
|
50
|
+
if (lenS === 0) throw new Error('S length is zero');
|
|
51
|
+
if (6 + lenR + lenS !== buffer.length) throw new Error('S length is invalid');
|
|
52
|
+
if (buffer[4] & 0x80) throw new Error('R value is negative');
|
|
53
|
+
if (lenR > 1 && buffer[4] === 0x00 && !(buffer[5] & 0x80))
|
|
54
|
+
throw new Error('R value excessively padded');
|
|
55
|
+
if (buffer[lenR + 6] & 0x80) throw new Error('S value is negative');
|
|
56
|
+
if (lenS > 1 && buffer[lenR + 6] === 0x00 && !(buffer[lenR + 7] & 0x80))
|
|
57
|
+
throw new Error('S value excessively padded');
|
|
58
|
+
// non-BIP66 - extract R, S values
|
|
59
|
+
return {
|
|
60
|
+
r: buffer.slice(4, 4 + lenR),
|
|
61
|
+
s: buffer.slice(6 + lenR),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/*
|
|
65
|
+
* Expects r and s to be positive DER integers.
|
|
66
|
+
*
|
|
67
|
+
* The DER format uses the most significant bit as a sign bit (& 0x80).
|
|
68
|
+
* If the significant bit is set AND the integer is positive, a 0x00 is prepended.
|
|
69
|
+
*
|
|
70
|
+
* Examples:
|
|
71
|
+
*
|
|
72
|
+
* 0 => 0x00
|
|
73
|
+
* 1 => 0x01
|
|
74
|
+
* -1 => 0xff
|
|
75
|
+
* 127 => 0x7f
|
|
76
|
+
* -127 => 0x81
|
|
77
|
+
* 128 => 0x0080
|
|
78
|
+
* -128 => 0x80
|
|
79
|
+
* 255 => 0x00ff
|
|
80
|
+
* -255 => 0xff01
|
|
81
|
+
* 16300 => 0x3fac
|
|
82
|
+
* -16300 => 0xc054
|
|
83
|
+
* 62300 => 0x00f35c
|
|
84
|
+
* -62300 => 0xff0ca4
|
|
85
|
+
*/
|
|
86
|
+
export function encode(r, s) {
|
|
87
|
+
const lenR = r.length;
|
|
88
|
+
const lenS = s.length;
|
|
89
|
+
if (lenR === 0) throw new Error('R length is zero');
|
|
90
|
+
if (lenS === 0) throw new Error('S length is zero');
|
|
91
|
+
if (lenR > 33) throw new Error('R length is too long');
|
|
92
|
+
if (lenS > 33) throw new Error('S length is too long');
|
|
93
|
+
if (r[0] & 0x80) throw new Error('R value is negative');
|
|
94
|
+
if (s[0] & 0x80) throw new Error('S value is negative');
|
|
95
|
+
if (lenR > 1 && r[0] === 0x00 && !(r[1] & 0x80))
|
|
96
|
+
throw new Error('R value excessively padded');
|
|
97
|
+
if (lenS > 1 && s[0] === 0x00 && !(s[1] & 0x80))
|
|
98
|
+
throw new Error('S value excessively padded');
|
|
99
|
+
const signature = new Uint8Array(6 + lenR + lenS);
|
|
100
|
+
// 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S]
|
|
101
|
+
signature[0] = 0x30;
|
|
102
|
+
signature[1] = signature.length - 2;
|
|
103
|
+
signature[2] = 0x02;
|
|
104
|
+
signature[3] = r.length;
|
|
105
|
+
signature.set(r, 4);
|
|
106
|
+
signature[4 + lenR] = 0x02;
|
|
107
|
+
signature[5 + lenR] = s.length;
|
|
108
|
+
signature.set(s, 6 + lenR);
|
|
109
|
+
return signature;
|
|
110
|
+
}
|