@btc-vision/transaction 1.6.18 → 1.7.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/browser/index.js +1 -1
- package/browser/index.js.LICENSE.txt +2 -0
- package/browser/src/_version.d.ts +1 -0
- package/browser/{epoch → src/epoch}/interfaces/IChallengeSolution.d.ts +2 -0
- package/browser/{keypair → src/keypair}/Address.d.ts +7 -4
- package/browser/{keypair → src/keypair}/AddressVerificator.d.ts +3 -0
- package/browser/{keypair → src/keypair}/EcKeyPair.d.ts +3 -2
- package/browser/{keypair → src/keypair}/MessageSigner.d.ts +9 -0
- package/browser/src/keypair/Wallet.d.ts +47 -0
- package/browser/{keypair → src/keypair}/interfaces/IWallet.d.ts +2 -0
- package/browser/src/mnemonic/Mnemonic.d.ts +29 -0
- package/browser/src/mnemonic/MnemonicStrength.d.ts +7 -0
- package/browser/{opnet.d.ts → src/opnet.d.ts} +4 -0
- package/browser/src/transaction/browser/types/OPWallet.d.ts +14 -0
- package/browser/test/address.test.d.ts +1 -0
- package/browser/test/addressverificator-mldsa.test.d.ts +1 -0
- package/browser/test/derivePath.test.d.ts +1 -0
- package/browser/test/messagesigner-mldsa.test.d.ts +1 -0
- package/browser/test/messagesigner-schnorr.test.d.ts +1 -0
- package/browser/test/network-awareness.test.d.ts +1 -0
- package/build/_version.d.ts +1 -1
- package/build/_version.js +1 -1
- package/build/crypto/crypto-browser.d.ts +11 -0
- package/build/crypto/crypto-browser.js +56 -0
- package/build/epoch/ChallengeSolution.js +3 -2
- package/build/epoch/interfaces/IChallengeSolution.d.ts +2 -0
- package/build/keypair/Address.d.ts +7 -4
- package/build/keypair/Address.js +88 -37
- package/build/keypair/AddressVerificator.d.ts +3 -0
- package/build/keypair/AddressVerificator.js +49 -1
- package/build/keypair/EcKeyPair.d.ts +3 -2
- package/build/keypair/EcKeyPair.js +17 -3
- package/build/keypair/MessageSigner.d.ts +9 -0
- package/build/keypair/MessageSigner.js +23 -0
- package/build/keypair/Wallet.d.ts +20 -3
- package/build/keypair/Wallet.js +108 -9
- package/build/keypair/interfaces/IWallet.d.ts +2 -0
- package/build/mnemonic/Mnemonic.d.ts +29 -0
- package/build/mnemonic/Mnemonic.js +98 -0
- package/build/mnemonic/MnemonicStrength.d.ts +7 -0
- package/build/mnemonic/MnemonicStrength.js +8 -0
- package/build/opnet.d.ts +4 -0
- package/build/opnet.js +4 -0
- package/build/transaction/browser/types/OPWallet.d.ts +14 -0
- package/build/transaction/browser/types/OPWallet.js +6 -0
- package/gulpfile.js +2 -2
- package/package.json +28 -20
- package/src/_version.ts +1 -1
- package/src/epoch/ChallengeSolution.ts +3 -2
- package/src/epoch/interfaces/IChallengeSolution.ts +2 -0
- package/src/keypair/Address.ts +145 -43
- package/src/keypair/AddressVerificator.ts +87 -2
- package/src/keypair/EcKeyPair.ts +58 -6
- package/src/keypair/MessageSigner.ts +58 -0
- package/src/keypair/Wallet.ts +339 -57
- package/src/keypair/interfaces/IWallet.ts +13 -3
- package/src/mnemonic/Mnemonic.ts +340 -0
- package/src/mnemonic/MnemonicStrength.ts +12 -0
- package/src/network/ChainId.ts +1 -4
- package/src/opnet.ts +16 -0
- package/src/transaction/browser/types/OPWallet.ts +73 -0
- package/test/address.test.ts +1068 -0
- package/test/addressverificator-mldsa.test.ts +473 -0
- package/test/derivePath.test.ts +234 -0
- package/test/messagesigner-mldsa.test.ts +1060 -0
- package/test/messagesigner-schnorr.test.ts +1011 -0
- package/test/network-awareness.test.ts +163 -0
- package/tsconfig.json +1 -1
- package/vitest.config.ts +21 -0
- package/browser/_version.d.ts +0 -1
- package/browser/keypair/Wallet.d.ts +0 -30
- /package/browser/{abi → src/abi}/ABICoder.d.ts +0 -0
- /package/browser/{buffer → src/buffer}/BinaryReader.d.ts +0 -0
- /package/browser/{buffer → src/buffer}/BinaryWriter.d.ts +0 -0
- /package/browser/{bytecode → src/bytecode}/Compressor.d.ts +0 -0
- /package/browser/{consensus → src/consensus}/Consensus.d.ts +0 -0
- /package/browser/{consensus → src/consensus}/ConsensusConfig.d.ts +0 -0
- /package/browser/{consensus → src/consensus}/metadata/RoswellConsensus.d.ts +0 -0
- /package/browser/{crypto → src/crypto}/crypto-browser.d.ts +0 -0
- /package/browser/{crypto → src/crypto}/crypto.d.ts +0 -0
- /package/browser/{deterministic → src/deterministic}/AddressMap.d.ts +0 -0
- /package/browser/{deterministic → src/deterministic}/AddressSet.d.ts +0 -0
- /package/browser/{deterministic → src/deterministic}/DeterministicMap.d.ts +0 -0
- /package/browser/{deterministic → src/deterministic}/DeterministicSet.d.ts +0 -0
- /package/browser/{deterministic → src/deterministic}/Map.d.ts +0 -0
- /package/browser/{epoch → src/epoch}/ChallengeSolution.d.ts +0 -0
- /package/browser/{epoch → src/epoch}/validator/EpochValidator.d.ts +0 -0
- /package/browser/{event → src/event}/NetEvent.d.ts +0 -0
- /package/browser/{generators → src/generators}/AddressGenerator.d.ts +0 -0
- /package/browser/{generators → src/generators}/Features.d.ts +0 -0
- /package/browser/{generators → src/generators}/Generator.d.ts +0 -0
- /package/browser/{generators → src/generators}/builders/CalldataGenerator.d.ts +0 -0
- /package/browser/{generators → src/generators}/builders/CustomGenerator.d.ts +0 -0
- /package/browser/{generators → src/generators}/builders/DeploymentGenerator.d.ts +0 -0
- /package/browser/{generators → src/generators}/builders/LegacyCalldataGenerator.d.ts +0 -0
- /package/browser/{generators → src/generators}/builders/MultiSignGenerator.d.ts +0 -0
- /package/browser/{generators → src/generators}/builders/P2WDAGenerator.d.ts +0 -0
- /package/browser/{index.d.ts → src/index.d.ts} +0 -0
- /package/browser/{keypair → src/keypair}/Secp256k1PointDeriver.d.ts +0 -0
- /package/browser/{metadata → src/metadata}/ContractBaseMetadata.d.ts +0 -0
- /package/browser/{metadata → src/metadata}/tokens.d.ts +0 -0
- /package/browser/{network → src/network}/ChainId.d.ts +0 -0
- /package/browser/{p2wda → src/p2wda}/P2WDADetector.d.ts +0 -0
- /package/browser/{signer → src/signer}/SignerUtils.d.ts +0 -0
- /package/browser/{signer → src/signer}/TweakedSigner.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/ContractAddress.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/TransactionFactory.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/browser/BrowserSignerBase.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/browser/Web3Provider.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/browser/extensions/UnisatSigner.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/browser/extensions/XverseSigner.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/browser/types/Unisat.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/browser/types/Xverse.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/CancelTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/ChallengeSolutionTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/CustomScriptTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/DeploymentTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/FundingTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/InteractionTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/InteractionTransactionP2WDA.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/MultiSignTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/SharedInteractionTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/TransactionBuilder.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/enums/TransactionType.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/interfaces/ITransactionParameters.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/interfaces/Tap.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/mineable/IP2WSHAddress.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/mineable/TimelockGenerator.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/processor/PsbtTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/psbt/PSBTTypes.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/shared/P2TR_MS.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/shared/TweakedTransaction.d.ts +0 -0
- /package/browser/{utils → src/utils}/BitcoinUtils.d.ts +0 -0
- /package/browser/{utils → src/utils}/BufferHelper.d.ts +0 -0
- /package/browser/{utils → src/utils}/StringToBuffer.d.ts +0 -0
- /package/browser/{utils → src/utils}/lengths.d.ts +0 -0
- /package/browser/{utils → src/utils}/types.d.ts +0 -0
- /package/browser/{utxo → src/utxo}/OPNetLimitedProvider.d.ts +0 -0
- /package/browser/{utxo → src/utxo}/interfaces/BroadcastResponse.d.ts +0 -0
- /package/browser/{utxo → src/utxo}/interfaces/IUTXO.d.ts +0 -0
- /package/browser/{verification → src/verification}/TapscriptVerificator.d.ts +0 -0
package/build/keypair/Address.js
CHANGED
|
@@ -9,7 +9,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
10
10
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
11
11
|
};
|
|
12
|
-
var _Address_p2tr, _Address_p2op, _Address_network, _Address_originalPublicKey, _Address_keyPair, _Address_uncompressed, _Address_tweakedUncompressed, _Address_p2wda;
|
|
12
|
+
var _Address_p2tr, _Address_p2op, _Address_network, _Address_originalPublicKey, _Address_keyPair, _Address_uncompressed, _Address_tweakedUncompressed, _Address_p2wda, _Address_mldsaPublicKey;
|
|
13
13
|
import { decompressPublicKey, toXOnly } from '@btc-vision/bitcoin';
|
|
14
14
|
import { ADDRESS_BYTE_LENGTH } from '../utils/lengths.js';
|
|
15
15
|
import { AddressVerificator } from './AddressVerificator.js';
|
|
@@ -18,8 +18,9 @@ import { ContractAddress } from '../transaction/ContractAddress.js';
|
|
|
18
18
|
import { BitcoinUtils } from '../utils/BitcoinUtils.js';
|
|
19
19
|
import { TimeLockGenerator } from '../transaction/mineable/TimelockGenerator.js';
|
|
20
20
|
import { P2WDADetector } from '../p2wda/P2WDADetector.js';
|
|
21
|
+
import { sha256 } from '@noble/hashes/sha2';
|
|
21
22
|
export class Address extends Uint8Array {
|
|
22
|
-
constructor(
|
|
23
|
+
constructor(mldsaPublicKey, publicKeyOrTweak) {
|
|
23
24
|
super(ADDRESS_BYTE_LENGTH);
|
|
24
25
|
_Address_p2tr.set(this, void 0);
|
|
25
26
|
_Address_p2op.set(this, void 0);
|
|
@@ -29,37 +30,52 @@ export class Address extends Uint8Array {
|
|
|
29
30
|
_Address_uncompressed.set(this, void 0);
|
|
30
31
|
_Address_tweakedUncompressed.set(this, void 0);
|
|
31
32
|
_Address_p2wda.set(this, void 0);
|
|
32
|
-
|
|
33
|
+
_Address_mldsaPublicKey.set(this, void 0);
|
|
34
|
+
if (!mldsaPublicKey) {
|
|
33
35
|
return;
|
|
34
36
|
}
|
|
35
|
-
|
|
37
|
+
if (publicKeyOrTweak) {
|
|
38
|
+
this.classicPublicKey = new Uint8Array(publicKeyOrTweak.length);
|
|
39
|
+
this.classicPublicKey.set(publicKeyOrTweak);
|
|
40
|
+
}
|
|
41
|
+
this.set(mldsaPublicKey);
|
|
36
42
|
}
|
|
37
43
|
get originalPublicKey() {
|
|
38
44
|
return __classPrivateFieldGet(this, _Address_originalPublicKey, "f");
|
|
39
45
|
}
|
|
46
|
+
get mldsaPublicKey() {
|
|
47
|
+
return __classPrivateFieldGet(this, _Address_mldsaPublicKey, "f");
|
|
48
|
+
}
|
|
40
49
|
get keyPair() {
|
|
41
50
|
if (!__classPrivateFieldGet(this, _Address_keyPair, "f")) {
|
|
42
|
-
throw new Error('
|
|
51
|
+
throw new Error('Classical public key not set for address');
|
|
43
52
|
}
|
|
44
53
|
return __classPrivateFieldGet(this, _Address_keyPair, "f");
|
|
45
54
|
}
|
|
46
55
|
static dead() {
|
|
47
|
-
return Address.fromString('0x04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f');
|
|
56
|
+
return Address.fromString('0x0000000000000000000000000000000000000000000000000000000000000000', '0x04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f');
|
|
48
57
|
}
|
|
49
|
-
static
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
static fromString(pubKey) {
|
|
53
|
-
if (!pubKey) {
|
|
58
|
+
static fromString(mldsaPublicKey, classicPublicKey) {
|
|
59
|
+
if (!mldsaPublicKey) {
|
|
54
60
|
throw new Error('Invalid public key');
|
|
55
61
|
}
|
|
56
|
-
if (
|
|
57
|
-
|
|
62
|
+
if (mldsaPublicKey.startsWith('0x')) {
|
|
63
|
+
mldsaPublicKey = mldsaPublicKey.slice(2);
|
|
58
64
|
}
|
|
59
|
-
if (!BitcoinUtils.isValidHex(
|
|
65
|
+
if (!BitcoinUtils.isValidHex(mldsaPublicKey)) {
|
|
60
66
|
throw new Error('You must only pass public keys in hexadecimal format. If you have an address such as bc1q... you must convert it to a public key first. Please refer to await provider.getPublicKeyInfo("bc1q..."). If the public key associated with the address is not found, you must force the user to enter the destination public key. It looks like: 0x020373626d317ae8788ce3280b491068610d840c23ecb64c14075bbb9f670af52c.');
|
|
61
67
|
}
|
|
62
|
-
|
|
68
|
+
let classicBuffer;
|
|
69
|
+
if (classicPublicKey) {
|
|
70
|
+
if (classicPublicKey.startsWith('0x')) {
|
|
71
|
+
classicPublicKey = classicPublicKey.slice(2);
|
|
72
|
+
}
|
|
73
|
+
if (!BitcoinUtils.isValidHex(classicPublicKey)) {
|
|
74
|
+
throw new Error('You must only pass classical public keys in hexadecimal format. If you have an address such as bc1q... you must convert it to a public key first. Please refer to await provider.getPublicKeyInfo("bc1q..."). If the public key associated with the address is not found, you must force the user to enter the destination public key. It looks like: 0x020373626d317ae8788ce3280b491068610d840c23ecb64c14075bbb9f670af52c.');
|
|
75
|
+
}
|
|
76
|
+
classicBuffer = Buffer.from(classicPublicKey, 'hex');
|
|
77
|
+
}
|
|
78
|
+
return new Address(Buffer.from(mldsaPublicKey, 'hex'), classicBuffer);
|
|
63
79
|
}
|
|
64
80
|
static wrap(bytes) {
|
|
65
81
|
return new Address(bytes);
|
|
@@ -76,36 +92,48 @@ export class Address extends Uint8Array {
|
|
|
76
92
|
toHex() {
|
|
77
93
|
return '0x' + Buffer.from(this).toString('hex');
|
|
78
94
|
}
|
|
95
|
+
tweakedToHex() {
|
|
96
|
+
if (!this.classicPublicKey) {
|
|
97
|
+
throw new Error('Classical public key not set');
|
|
98
|
+
}
|
|
99
|
+
return '0x' + Buffer.from(this.classicPublicKey).toString('hex');
|
|
100
|
+
}
|
|
79
101
|
toBuffer() {
|
|
80
102
|
return Buffer.from(this);
|
|
81
103
|
}
|
|
104
|
+
tweakedPublicKeyToBuffer() {
|
|
105
|
+
if (!this.classicPublicKey) {
|
|
106
|
+
throw new Error('Classical public key not set');
|
|
107
|
+
}
|
|
108
|
+
return Buffer.from(this.classicPublicKey);
|
|
109
|
+
}
|
|
82
110
|
toUncompressedHex() {
|
|
83
111
|
if (!__classPrivateFieldGet(this, _Address_uncompressed, "f")) {
|
|
84
|
-
throw new Error('
|
|
112
|
+
throw new Error('Classical public key not set');
|
|
85
113
|
}
|
|
86
114
|
return '0x' + __classPrivateFieldGet(this, _Address_uncompressed, "f").uncompressed.toString('hex');
|
|
87
115
|
}
|
|
88
116
|
toUncompressedBuffer() {
|
|
89
117
|
if (!__classPrivateFieldGet(this, _Address_uncompressed, "f")) {
|
|
90
|
-
throw new Error('
|
|
118
|
+
throw new Error('Classical public key not set');
|
|
91
119
|
}
|
|
92
120
|
return __classPrivateFieldGet(this, _Address_uncompressed, "f").uncompressed;
|
|
93
121
|
}
|
|
94
122
|
toHybridPublicKeyHex() {
|
|
95
123
|
if (!__classPrivateFieldGet(this, _Address_uncompressed, "f")) {
|
|
96
|
-
throw new Error('
|
|
124
|
+
throw new Error('Classical public key not set');
|
|
97
125
|
}
|
|
98
126
|
return '0x' + __classPrivateFieldGet(this, _Address_uncompressed, "f").hybrid.toString('hex');
|
|
99
127
|
}
|
|
100
128
|
toHybridPublicKeyBuffer() {
|
|
101
129
|
if (!__classPrivateFieldGet(this, _Address_uncompressed, "f")) {
|
|
102
|
-
throw new Error('
|
|
130
|
+
throw new Error('Classical public key not set');
|
|
103
131
|
}
|
|
104
132
|
return __classPrivateFieldGet(this, _Address_uncompressed, "f").hybrid;
|
|
105
133
|
}
|
|
106
134
|
originalPublicKeyBuffer() {
|
|
107
135
|
if (!__classPrivateFieldGet(this, _Address_originalPublicKey, "f")) {
|
|
108
|
-
throw new Error('
|
|
136
|
+
throw new Error('Classical public key not set');
|
|
109
137
|
}
|
|
110
138
|
return Buffer.from(__classPrivateFieldGet(this, _Address_originalPublicKey, "f"));
|
|
111
139
|
}
|
|
@@ -149,19 +177,38 @@ export class Address extends Uint8Array {
|
|
|
149
177
|
}
|
|
150
178
|
return false;
|
|
151
179
|
}
|
|
152
|
-
set(
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
180
|
+
set(mldsaPublicKey) {
|
|
181
|
+
if (this.classicPublicKey) {
|
|
182
|
+
const validLengths = [ADDRESS_BYTE_LENGTH, 33, 65];
|
|
183
|
+
if (!validLengths.includes(this.classicPublicKey.length)) {
|
|
184
|
+
throw new Error(`Invalid public key length ${this.classicPublicKey.length}`);
|
|
185
|
+
}
|
|
186
|
+
if (this.classicPublicKey.length === ADDRESS_BYTE_LENGTH) {
|
|
187
|
+
const buf = Buffer.alloc(ADDRESS_BYTE_LENGTH);
|
|
188
|
+
buf.set(this.classicPublicKey);
|
|
189
|
+
__classPrivateFieldSet(this, _Address_tweakedUncompressed, ContractAddress.generateHybridKeyFromHash(buf), "f");
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
this.autoFormat(this.classicPublicKey);
|
|
193
|
+
}
|
|
156
194
|
}
|
|
157
|
-
if (
|
|
158
|
-
const buf =
|
|
159
|
-
buf.set(
|
|
160
|
-
|
|
161
|
-
super.set(publicKey);
|
|
195
|
+
if (mldsaPublicKey.length === ADDRESS_BYTE_LENGTH) {
|
|
196
|
+
const buf = new Uint8Array(ADDRESS_BYTE_LENGTH);
|
|
197
|
+
buf.set(mldsaPublicKey);
|
|
198
|
+
super.set(buf);
|
|
162
199
|
}
|
|
163
200
|
else {
|
|
164
|
-
|
|
201
|
+
const validMLDSALengths = [1312, 1952, 2592];
|
|
202
|
+
if (!validMLDSALengths.includes(mldsaPublicKey.length)) {
|
|
203
|
+
throw new Error(`Invalid ML-DSA public key length: ${mldsaPublicKey.length}. ` +
|
|
204
|
+
`Expected 1312 (ML-DSA-44/LEVEL2), 1952 (ML-DSA-65/LEVEL3), or 2592 (ML-DSA-87/LEVEL5) bytes.`);
|
|
205
|
+
}
|
|
206
|
+
__classPrivateFieldSet(this, _Address_mldsaPublicKey, new Uint8Array(mldsaPublicKey.length), "f");
|
|
207
|
+
__classPrivateFieldGet(this, _Address_mldsaPublicKey, "f").set(mldsaPublicKey);
|
|
208
|
+
const hashedPublicKey = sha256(new Uint8Array(mldsaPublicKey));
|
|
209
|
+
const buf = new Uint8Array(ADDRESS_BYTE_LENGTH);
|
|
210
|
+
buf.set(hashedPublicKey);
|
|
211
|
+
super.set(buf);
|
|
165
212
|
}
|
|
166
213
|
}
|
|
167
214
|
isValid(network) {
|
|
@@ -186,16 +233,19 @@ export class Address extends Uint8Array {
|
|
|
186
233
|
return this.toHex();
|
|
187
234
|
}
|
|
188
235
|
p2tr(network) {
|
|
236
|
+
if (!this.classicPublicKey) {
|
|
237
|
+
throw new Error('Classical public key not set');
|
|
238
|
+
}
|
|
189
239
|
if (__classPrivateFieldGet(this, _Address_p2tr, "f") && __classPrivateFieldGet(this, _Address_network, "f") === network) {
|
|
190
240
|
return __classPrivateFieldGet(this, _Address_p2tr, "f");
|
|
191
241
|
}
|
|
192
|
-
const p2trAddy = EcKeyPair.tweakedPubKeyBufferToAddress(this, network);
|
|
242
|
+
const p2trAddy = EcKeyPair.tweakedPubKeyBufferToAddress(this.classicPublicKey, network);
|
|
193
243
|
if (p2trAddy) {
|
|
194
244
|
__classPrivateFieldSet(this, _Address_network, network, "f");
|
|
195
245
|
__classPrivateFieldSet(this, _Address_p2tr, p2trAddy, "f");
|
|
196
246
|
return p2trAddy;
|
|
197
247
|
}
|
|
198
|
-
throw new Error('
|
|
248
|
+
throw new Error('Classical public key not set');
|
|
199
249
|
}
|
|
200
250
|
p2wda(network) {
|
|
201
251
|
if (__classPrivateFieldGet(this, _Address_p2wda, "f") && __classPrivateFieldGet(this, _Address_network, "f") === network) {
|
|
@@ -242,17 +292,17 @@ export class Address extends Uint8Array {
|
|
|
242
292
|
__classPrivateFieldSet(this, _Address_p2op, p2opAddy, "f");
|
|
243
293
|
return p2opAddy;
|
|
244
294
|
}
|
|
245
|
-
throw new Error('
|
|
295
|
+
throw new Error('ML-DSA public key not set');
|
|
246
296
|
}
|
|
247
297
|
toTweakedHybridPublicKeyHex() {
|
|
248
298
|
if (!__classPrivateFieldGet(this, _Address_tweakedUncompressed, "f")) {
|
|
249
|
-
throw new Error('
|
|
299
|
+
throw new Error('Classical public key not set');
|
|
250
300
|
}
|
|
251
301
|
return '0x' + __classPrivateFieldGet(this, _Address_tweakedUncompressed, "f").toString('hex');
|
|
252
302
|
}
|
|
253
303
|
toTweakedHybridPublicKeyBuffer() {
|
|
254
304
|
if (!__classPrivateFieldGet(this, _Address_tweakedUncompressed, "f")) {
|
|
255
|
-
throw new Error('
|
|
305
|
+
throw new Error('Classical public key not set');
|
|
256
306
|
}
|
|
257
307
|
return __classPrivateFieldGet(this, _Address_tweakedUncompressed, "f");
|
|
258
308
|
}
|
|
@@ -268,7 +318,8 @@ export class Address extends Uint8Array {
|
|
|
268
318
|
__classPrivateFieldSet(this, _Address_uncompressed, decompressPublicKey(__classPrivateFieldGet(this, _Address_originalPublicKey, "f")), "f");
|
|
269
319
|
const tweakedBytes = toXOnly(EcKeyPair.tweakPublicKey(Buffer.from(__classPrivateFieldGet(this, _Address_originalPublicKey, "f"))));
|
|
270
320
|
__classPrivateFieldSet(this, _Address_tweakedUncompressed, ContractAddress.generateHybridKeyFromHash(tweakedBytes), "f");
|
|
271
|
-
|
|
321
|
+
this.classicPublicKey = new Uint8Array(ADDRESS_BYTE_LENGTH);
|
|
322
|
+
this.classicPublicKey.set(tweakedBytes);
|
|
272
323
|
}
|
|
273
324
|
}
|
|
274
|
-
_Address_p2tr = new WeakMap(), _Address_p2op = new WeakMap(), _Address_network = new WeakMap(), _Address_originalPublicKey = new WeakMap(), _Address_keyPair = new WeakMap(), _Address_uncompressed = new WeakMap(), _Address_tweakedUncompressed = new WeakMap(), _Address_p2wda = new WeakMap();
|
|
325
|
+
_Address_p2tr = new WeakMap(), _Address_p2op = new WeakMap(), _Address_network = new WeakMap(), _Address_originalPublicKey = new WeakMap(), _Address_keyPair = new WeakMap(), _Address_uncompressed = new WeakMap(), _Address_tweakedUncompressed = new WeakMap(), _Address_p2wda = new WeakMap(), _Address_mldsaPublicKey = new WeakMap();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Network } from '@btc-vision/bitcoin';
|
|
2
|
+
import { MLDSASecurityLevel } from '@btc-vision/bip32';
|
|
2
3
|
export declare enum AddressTypes {
|
|
3
4
|
P2PKH = "P2PKH",
|
|
4
5
|
P2OP = "P2OP",
|
|
@@ -22,6 +23,8 @@ export declare class AddressVerificator {
|
|
|
22
23
|
static isP2WDAWitnessScript(witnessScript: Buffer): boolean;
|
|
23
24
|
static isP2PKHOrP2SH(addy: string, network: Network): boolean;
|
|
24
25
|
static isValidPublicKey(input: string, network: Network): boolean;
|
|
26
|
+
static isValidMLDSAPublicKey(input: string | Buffer | Uint8Array): MLDSASecurityLevel | null;
|
|
27
|
+
static isValidP2OPAddress(inAddress: string, network: Network): boolean;
|
|
25
28
|
static requireRedeemScript(addy: string, network: Network): boolean;
|
|
26
29
|
static detectAddressType(addy: string, network: Network): AddressTypes | null;
|
|
27
30
|
static detectAddressTypeWithWitnessScript(addy: string, network: Network, witnessScript?: Buffer): AddressTypes | null;
|
|
@@ -3,6 +3,7 @@ import * as ecc from '@bitcoinerlab/secp256k1';
|
|
|
3
3
|
import { EcKeyPair } from './EcKeyPair.js';
|
|
4
4
|
import { BitcoinUtils } from '../utils/BitcoinUtils.js';
|
|
5
5
|
import { P2WDADetector } from '../p2wda/P2WDADetector.js';
|
|
6
|
+
import { MLDSASecurityLevel } from '@btc-vision/bip32';
|
|
6
7
|
initEccLib(ecc);
|
|
7
8
|
export var AddressTypes;
|
|
8
9
|
(function (AddressTypes) {
|
|
@@ -81,6 +82,52 @@ export class AddressVerificator {
|
|
|
81
82
|
}
|
|
82
83
|
return false;
|
|
83
84
|
}
|
|
85
|
+
static isValidMLDSAPublicKey(input) {
|
|
86
|
+
try {
|
|
87
|
+
let byteLength;
|
|
88
|
+
if (Buffer.isBuffer(input) || input instanceof Uint8Array) {
|
|
89
|
+
byteLength = input.length;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
if (input.startsWith('0x')) {
|
|
93
|
+
input = input.slice(2);
|
|
94
|
+
}
|
|
95
|
+
if (!BitcoinUtils.isValidHex(input)) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
byteLength = input.length / 2;
|
|
99
|
+
}
|
|
100
|
+
switch (byteLength) {
|
|
101
|
+
case 1312:
|
|
102
|
+
return MLDSASecurityLevel.LEVEL2;
|
|
103
|
+
case 1952:
|
|
104
|
+
return MLDSASecurityLevel.LEVEL3;
|
|
105
|
+
case 2592:
|
|
106
|
+
return MLDSASecurityLevel.LEVEL5;
|
|
107
|
+
default:
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (e) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
static isValidP2OPAddress(inAddress, network) {
|
|
116
|
+
if (!inAddress || inAddress.length < 20)
|
|
117
|
+
return false;
|
|
118
|
+
try {
|
|
119
|
+
const decodedAddress = address.fromBech32(inAddress);
|
|
120
|
+
const validPrefix = decodedAddress.prefix === network.bech32 ||
|
|
121
|
+
decodedAddress.prefix === network.bech32Opnet;
|
|
122
|
+
if (!validPrefix) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
return decodedAddress.version === 16 && decodedAddress.data.length === 21;
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
84
131
|
static requireRedeemScript(addy, network) {
|
|
85
132
|
try {
|
|
86
133
|
const decodedBase58 = address.fromBase58Check(addy);
|
|
@@ -111,7 +158,8 @@ export class AddressVerificator {
|
|
|
111
158
|
const decodedBech32 = address.fromBech32(addy);
|
|
112
159
|
if ((decodedBech32.prefix === network.bech32Opnet ||
|
|
113
160
|
decodedBech32.prefix === network.bech32) &&
|
|
114
|
-
decodedBech32.version === 16
|
|
161
|
+
decodedBech32.version === 16 &&
|
|
162
|
+
decodedBech32.data.length === 21) {
|
|
115
163
|
return AddressTypes.P2OP;
|
|
116
164
|
}
|
|
117
165
|
if (decodedBech32.prefix === network.bech32) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BIP32API, BIP32Interface } from 'bip32';
|
|
1
|
+
import { BIP32API, BIP32Interface, MLDSAKeyPair, MLDSASecurityLevel } from '@btc-vision/bip32';
|
|
2
2
|
import { Network, Signer } from '@btc-vision/bitcoin';
|
|
3
3
|
import { ECPairAPI, ECPairInterface } from 'ecpair';
|
|
4
4
|
import { IWallet } from './interfaces/IWallet.js';
|
|
@@ -17,7 +17,8 @@ export declare class EcKeyPair {
|
|
|
17
17
|
static xOnlyTweakedPubKeyToAddress(tweakedPubKeyHex: string, network: Network): string;
|
|
18
18
|
static tweakPublicKey(pub: Uint8Array | Buffer | string): Buffer;
|
|
19
19
|
static tweakBatchSharedT(pubkeys: readonly Uint8Array[], tweakScalar: bigint): Uint8Array[];
|
|
20
|
-
static generateWallet(network?: Network): IWallet;
|
|
20
|
+
static generateWallet(network?: Network, securityLevel?: MLDSASecurityLevel): IWallet;
|
|
21
|
+
static generateQuantumKeyPair(securityLevel?: MLDSASecurityLevel, network?: Network): MLDSAKeyPair;
|
|
21
22
|
static verifyContractAddress(contractAddress: string, network?: Network): boolean;
|
|
22
23
|
static getLegacySegwitAddress(keyPair: ECPairInterface, network?: Network): string;
|
|
23
24
|
static getLegacyAddress(keyPair: ECPairInterface, network?: Network): string;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as ecc from '@bitcoinerlab/secp256k1';
|
|
2
|
-
import bip32, { BIP32Factory } from 'bip32';
|
|
2
|
+
import bip32, { BIP32Factory, MLDSASecurityLevel, QuantumBIP32Factory, } from '@btc-vision/bip32';
|
|
3
3
|
import bitcoin, { address, fromOutputScript, initEccLib, networks, opcodes, payments, script, toXOnly, } from '@btc-vision/bitcoin';
|
|
4
4
|
import { ECPairFactory } from 'ecpair';
|
|
5
5
|
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
6
6
|
import { mod } from '@noble/curves/abstract/modular';
|
|
7
7
|
import { sha256 } from '@noble/hashes/sha2';
|
|
8
|
-
import { bytesToNumberBE, concatBytes, utf8ToBytes } from '@noble/curves/utils.js';
|
|
8
|
+
import { bytesToNumberBE, concatBytes, randomBytes, utf8ToBytes } from '@noble/curves/utils.js';
|
|
9
9
|
initEccLib(ecc);
|
|
10
10
|
const BIP32factory = typeof bip32 === 'function' ? bip32 : BIP32Factory;
|
|
11
11
|
if (!BIP32factory) {
|
|
@@ -128,7 +128,7 @@ export class EcKeyPair {
|
|
|
128
128
|
return Q.toBytes(true);
|
|
129
129
|
});
|
|
130
130
|
}
|
|
131
|
-
static generateWallet(network = networks.bitcoin) {
|
|
131
|
+
static generateWallet(network = networks.bitcoin, securityLevel = MLDSASecurityLevel.LEVEL2) {
|
|
132
132
|
const keyPair = this.ECPair.makeRandom({
|
|
133
133
|
network: network,
|
|
134
134
|
});
|
|
@@ -136,10 +136,24 @@ export class EcKeyPair {
|
|
|
136
136
|
if (!wallet) {
|
|
137
137
|
throw new Error('Failed to generate wallet');
|
|
138
138
|
}
|
|
139
|
+
const quantumKeyPair = this.generateQuantumKeyPair(securityLevel, network);
|
|
139
140
|
return {
|
|
140
141
|
address: wallet,
|
|
141
142
|
privateKey: keyPair.toWIF(),
|
|
142
143
|
publicKey: Buffer.from(keyPair.publicKey).toString('hex'),
|
|
144
|
+
quantumPrivateKey: Buffer.from(quantumKeyPair.privateKey).toString('hex'),
|
|
145
|
+
quantumPublicKey: Buffer.from(quantumKeyPair.publicKey).toString('hex'),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
static generateQuantumKeyPair(securityLevel = MLDSASecurityLevel.LEVEL2, network = networks.bitcoin) {
|
|
149
|
+
const randomSeed = randomBytes(64);
|
|
150
|
+
const quantumRoot = QuantumBIP32Factory.fromSeed(Buffer.from(randomSeed), network, securityLevel);
|
|
151
|
+
if (!quantumRoot.privateKey || !quantumRoot.publicKey) {
|
|
152
|
+
throw new Error('Failed to generate quantum keypair');
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
privateKey: Buffer.from(quantumRoot.privateKey),
|
|
156
|
+
publicKey: Buffer.from(quantumRoot.publicKey),
|
|
143
157
|
};
|
|
144
158
|
}
|
|
145
159
|
static verifyContractAddress(contractAddress, network = networks.bitcoin) {
|
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
import { ECPairInterface } from 'ecpair';
|
|
2
2
|
import { Network } from '@btc-vision/bitcoin';
|
|
3
|
+
import { MLDSASecurityLevel, QuantumBIP32Interface } from '@btc-vision/bip32';
|
|
3
4
|
export interface SignedMessage {
|
|
4
5
|
readonly signature: Uint8Array;
|
|
5
6
|
readonly message: Uint8Array;
|
|
6
7
|
}
|
|
8
|
+
export interface MLDSASignedMessage {
|
|
9
|
+
readonly signature: Uint8Array;
|
|
10
|
+
readonly message: Uint8Array;
|
|
11
|
+
readonly publicKey: Uint8Array;
|
|
12
|
+
readonly securityLevel: MLDSASecurityLevel;
|
|
13
|
+
}
|
|
7
14
|
declare class MessageSignerBase {
|
|
8
15
|
sha256(message: Buffer | Uint8Array): Buffer;
|
|
9
16
|
tweakAndSignMessage(keypair: ECPairInterface, message: Uint8Array | Buffer | string, network: Network): SignedMessage;
|
|
10
17
|
signMessage(keypair: ECPairInterface, message: Uint8Array | Buffer | string): SignedMessage;
|
|
11
18
|
verifySignature(publicKey: Uint8Array | Buffer, message: Uint8Array | Buffer | string, signature: Uint8Array | Buffer): boolean;
|
|
12
19
|
tweakAndVerifySignature(publicKey: Uint8Array | Buffer, message: Uint8Array | Buffer | string, signature: Uint8Array | Buffer): boolean;
|
|
20
|
+
signMLDSAMessage(mldsaKeypair: QuantumBIP32Interface, message: Uint8Array | Buffer | string): MLDSASignedMessage;
|
|
21
|
+
verifyMLDSASignature(mldsaKeypair: QuantumBIP32Interface, message: Uint8Array | Buffer | string, signature: Uint8Array | Buffer): boolean;
|
|
13
22
|
}
|
|
14
23
|
export declare const MessageSigner: MessageSignerBase;
|
|
15
24
|
export {};
|
|
@@ -39,5 +39,28 @@ class MessageSignerBase {
|
|
|
39
39
|
const tweakedPublicKey = EcKeyPair.tweakPublicKey(Buffer.from(publicKey));
|
|
40
40
|
return this.verifySignature(tweakedPublicKey, message, signature);
|
|
41
41
|
}
|
|
42
|
+
signMLDSAMessage(mldsaKeypair, message) {
|
|
43
|
+
if (typeof message === 'string') {
|
|
44
|
+
message = Buffer.from(message, 'utf-8');
|
|
45
|
+
}
|
|
46
|
+
if (!mldsaKeypair.privateKey) {
|
|
47
|
+
throw new Error('ML-DSA private key not found in keypair.');
|
|
48
|
+
}
|
|
49
|
+
const hashedMessage = this.sha256(message);
|
|
50
|
+
const signature = mldsaKeypair.sign(hashedMessage);
|
|
51
|
+
return {
|
|
52
|
+
signature: Buffer.from(signature),
|
|
53
|
+
message: hashedMessage,
|
|
54
|
+
publicKey: Buffer.from(mldsaKeypair.publicKey),
|
|
55
|
+
securityLevel: mldsaKeypair.securityLevel,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
verifyMLDSASignature(mldsaKeypair, message, signature) {
|
|
59
|
+
if (typeof message === 'string') {
|
|
60
|
+
message = Buffer.from(message, 'utf-8');
|
|
61
|
+
}
|
|
62
|
+
const hashedMessage = this.sha256(message);
|
|
63
|
+
return mldsaKeypair.verify(hashedMessage, signature);
|
|
64
|
+
}
|
|
42
65
|
}
|
|
43
66
|
export const MessageSigner = new MessageSignerBase();
|
|
@@ -2,9 +2,13 @@ import { ECPairInterface } from 'ecpair';
|
|
|
2
2
|
import { Network } from '@btc-vision/bitcoin';
|
|
3
3
|
import { Address } from './Address.js';
|
|
4
4
|
import { IP2WSHAddress } from '../transaction/mineable/IP2WSHAddress.js';
|
|
5
|
+
import { MLDSASecurityLevel, QuantumBIP32Interface } from '@btc-vision/bip32';
|
|
5
6
|
export declare class Wallet {
|
|
6
7
|
readonly network: Network;
|
|
7
8
|
private readonly _keypair;
|
|
9
|
+
private readonly _mldsaKeypair;
|
|
10
|
+
private readonly _securityLevel;
|
|
11
|
+
private readonly _chainCode;
|
|
8
12
|
private readonly _p2wpkh;
|
|
9
13
|
private readonly _p2tr;
|
|
10
14
|
private readonly _p2wda;
|
|
@@ -13,10 +17,13 @@ export declare class Wallet {
|
|
|
13
17
|
private readonly _bufferPubKey;
|
|
14
18
|
private readonly _tweakedKey;
|
|
15
19
|
private readonly _address;
|
|
16
|
-
constructor(privateKeyOrWif: string, network?: Network);
|
|
20
|
+
constructor(privateKeyOrWif: string, mldsaPrivateKeyOrBase58: string, network?: Network, securityLevel?: MLDSASecurityLevel, chainCode?: Buffer);
|
|
17
21
|
get address(): Address;
|
|
18
22
|
get tweakedPubKeyKey(): Buffer;
|
|
19
23
|
get keypair(): ECPairInterface;
|
|
24
|
+
get mldsaKeypair(): QuantumBIP32Interface;
|
|
25
|
+
get securityLevel(): MLDSASecurityLevel;
|
|
26
|
+
get chainCode(): Buffer;
|
|
20
27
|
get p2wpkh(): string;
|
|
21
28
|
get p2tr(): string;
|
|
22
29
|
get p2wda(): IP2WSHAddress;
|
|
@@ -24,7 +31,17 @@ export declare class Wallet {
|
|
|
24
31
|
get addresses(): string[];
|
|
25
32
|
get segwitLegacy(): string;
|
|
26
33
|
get publicKey(): Buffer;
|
|
34
|
+
get quantumPublicKey(): Buffer;
|
|
35
|
+
get quantumPrivateKey(): Buffer;
|
|
36
|
+
get quantumPublicKeyHex(): string;
|
|
37
|
+
get quantumPrivateKeyHex(): string;
|
|
27
38
|
get xOnly(): Buffer;
|
|
28
|
-
static fromWif(wif: string, network?: Network): Wallet;
|
|
29
|
-
static
|
|
39
|
+
static fromWif(wif: string, quantumPrivateKeyHex: string, network?: Network, securityLevel?: MLDSASecurityLevel, chainCode?: Buffer): Wallet;
|
|
40
|
+
static generate(network?: Network, securityLevel?: MLDSASecurityLevel): Wallet;
|
|
41
|
+
static fromPrivateKeys(privateKeyHexOrWif: string, mldsaPrivateKeyOrBase58: string, network?: Network, securityLevel?: MLDSASecurityLevel, chainCode?: Buffer): Wallet;
|
|
42
|
+
toWIF(): string;
|
|
43
|
+
toPrivateKeyHex(): string;
|
|
44
|
+
toPublicKeyHex(): string;
|
|
45
|
+
toQuantumBase58(): string;
|
|
46
|
+
derivePath(path: string): Wallet;
|
|
30
47
|
}
|
package/build/keypair/Wallet.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { EcKeyPair } from './EcKeyPair.js';
|
|
2
|
-
import { networks, toXOnly } from '@btc-vision/bitcoin';
|
|
2
|
+
import { initEccLib, networks, toXOnly } from '@btc-vision/bitcoin';
|
|
3
3
|
import { Address } from './Address.js';
|
|
4
4
|
import { BitcoinUtils } from '../utils/BitcoinUtils.js';
|
|
5
|
+
import * as ecc from '@bitcoinerlab/secp256k1';
|
|
6
|
+
import { getMLDSAConfig, MLDSASecurityLevel, QuantumBIP32Factory, } from '@btc-vision/bip32';
|
|
7
|
+
import { randomBytes } from 'crypto';
|
|
8
|
+
initEccLib(ecc);
|
|
5
9
|
export class Wallet {
|
|
6
|
-
constructor(privateKeyOrWif, network = networks.bitcoin) {
|
|
10
|
+
constructor(privateKeyOrWif, mldsaPrivateKeyOrBase58, network = networks.bitcoin, securityLevel = MLDSASecurityLevel.LEVEL2, chainCode) {
|
|
7
11
|
this.network = network;
|
|
12
|
+
this._securityLevel = securityLevel;
|
|
8
13
|
const parsedPrivateKey = privateKeyOrWif.startsWith('0x')
|
|
9
14
|
? privateKeyOrWif.replace('0x', '')
|
|
10
15
|
: privateKeyOrWif;
|
|
@@ -14,14 +19,44 @@ export class Wallet {
|
|
|
14
19
|
else {
|
|
15
20
|
this._keypair = EcKeyPair.fromWIF(parsedPrivateKey, this.network);
|
|
16
21
|
}
|
|
22
|
+
const parsedMLDSAKey = mldsaPrivateKeyOrBase58.startsWith('0x')
|
|
23
|
+
? mldsaPrivateKeyOrBase58.replace('0x', '')
|
|
24
|
+
: mldsaPrivateKeyOrBase58;
|
|
25
|
+
if (BitcoinUtils.isValidHex(parsedMLDSAKey)) {
|
|
26
|
+
const mldsaBuffer = Buffer.from(parsedMLDSAKey, 'hex');
|
|
27
|
+
const config = getMLDSAConfig(securityLevel, this.network);
|
|
28
|
+
const privateKeySize = config.privateKeySize;
|
|
29
|
+
const publicKeySize = config.publicKeySize;
|
|
30
|
+
const combinedSize = privateKeySize + publicKeySize;
|
|
31
|
+
let mldsaPrivateKeyBuffer;
|
|
32
|
+
if (mldsaBuffer.length === privateKeySize) {
|
|
33
|
+
mldsaPrivateKeyBuffer = mldsaBuffer;
|
|
34
|
+
}
|
|
35
|
+
else if (mldsaBuffer.length === combinedSize) {
|
|
36
|
+
mldsaPrivateKeyBuffer = mldsaBuffer.subarray(0, privateKeySize);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
throw new Error(`Invalid ML-DSA key length for security level ${securityLevel}. Expected ${privateKeySize} bytes (private only) or ${combinedSize} bytes (private+public), got ${mldsaBuffer.length} bytes.`);
|
|
40
|
+
}
|
|
41
|
+
if (chainCode && chainCode.length !== 32) {
|
|
42
|
+
throw new Error('Chain code must be 32 bytes');
|
|
43
|
+
}
|
|
44
|
+
this._chainCode = chainCode || randomBytes(32);
|
|
45
|
+
this._mldsaKeypair = QuantumBIP32Factory.fromPrivateKey(mldsaPrivateKeyBuffer, this._chainCode, this.network, securityLevel);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
this._mldsaKeypair = QuantumBIP32Factory.fromBase58(parsedMLDSAKey);
|
|
49
|
+
this._chainCode = Buffer.from(this._mldsaKeypair.chainCode);
|
|
50
|
+
this._securityLevel = this._mldsaKeypair.securityLevel;
|
|
51
|
+
}
|
|
17
52
|
this._bufferPubKey = this._keypair.publicKey;
|
|
18
|
-
this._address = new Address(this._keypair.publicKey);
|
|
53
|
+
this._address = new Address(this._mldsaKeypair.publicKey, this._keypair.publicKey);
|
|
19
54
|
this._p2tr = this._address.p2tr(this.network);
|
|
20
55
|
this._p2wpkh = this._address.p2wpkh(this.network);
|
|
21
56
|
this._legacy = this._address.p2pkh(this.network);
|
|
22
|
-
this._segwitLegacy = this._address.
|
|
57
|
+
this._segwitLegacy = this._address.p2shp2wpkh(this.network);
|
|
23
58
|
this._p2wda = this._address.p2wda(this.network);
|
|
24
|
-
this._tweakedKey = this._address.
|
|
59
|
+
this._tweakedKey = this._address.tweakedPublicKeyToBuffer();
|
|
25
60
|
}
|
|
26
61
|
get address() {
|
|
27
62
|
return this._address;
|
|
@@ -34,6 +69,15 @@ export class Wallet {
|
|
|
34
69
|
throw new Error('Keypair not set');
|
|
35
70
|
return this._keypair;
|
|
36
71
|
}
|
|
72
|
+
get mldsaKeypair() {
|
|
73
|
+
return this._mldsaKeypair;
|
|
74
|
+
}
|
|
75
|
+
get securityLevel() {
|
|
76
|
+
return this._securityLevel;
|
|
77
|
+
}
|
|
78
|
+
get chainCode() {
|
|
79
|
+
return this._chainCode;
|
|
80
|
+
}
|
|
37
81
|
get p2wpkh() {
|
|
38
82
|
return this._p2wpkh;
|
|
39
83
|
}
|
|
@@ -57,15 +101,70 @@ export class Wallet {
|
|
|
57
101
|
throw new Error('Public key not set');
|
|
58
102
|
return this._bufferPubKey;
|
|
59
103
|
}
|
|
104
|
+
get quantumPublicKey() {
|
|
105
|
+
return Buffer.from(this._mldsaKeypair.publicKey);
|
|
106
|
+
}
|
|
107
|
+
get quantumPrivateKey() {
|
|
108
|
+
if (!this._mldsaKeypair.privateKey) {
|
|
109
|
+
throw new Error('Quantum private key not set');
|
|
110
|
+
}
|
|
111
|
+
return Buffer.from(this._mldsaKeypair.privateKey);
|
|
112
|
+
}
|
|
113
|
+
get quantumPublicKeyHex() {
|
|
114
|
+
return Buffer.from(this._mldsaKeypair.publicKey).toString('hex');
|
|
115
|
+
}
|
|
116
|
+
get quantumPrivateKeyHex() {
|
|
117
|
+
if (!this._mldsaKeypair.privateKey) {
|
|
118
|
+
throw new Error('Quantum private key not set');
|
|
119
|
+
}
|
|
120
|
+
return Buffer.from(this._mldsaKeypair.privateKey).toString('hex');
|
|
121
|
+
}
|
|
60
122
|
get xOnly() {
|
|
61
123
|
if (!this.keypair)
|
|
62
124
|
throw new Error('Keypair not set');
|
|
63
125
|
return toXOnly(this._bufferPubKey);
|
|
64
126
|
}
|
|
65
|
-
static fromWif(wif, network = networks.bitcoin) {
|
|
66
|
-
return new Wallet(wif, network);
|
|
127
|
+
static fromWif(wif, quantumPrivateKeyHex, network = networks.bitcoin, securityLevel = MLDSASecurityLevel.LEVEL2, chainCode) {
|
|
128
|
+
return new Wallet(wif, quantumPrivateKeyHex, network, securityLevel, chainCode);
|
|
67
129
|
}
|
|
68
|
-
static
|
|
69
|
-
|
|
130
|
+
static generate(network = networks.bitcoin, securityLevel = MLDSASecurityLevel.LEVEL2) {
|
|
131
|
+
const walletData = EcKeyPair.generateWallet(network, securityLevel);
|
|
132
|
+
if (!walletData.quantumPrivateKey) {
|
|
133
|
+
throw new Error('Failed to generate quantum keys');
|
|
134
|
+
}
|
|
135
|
+
return new Wallet(walletData.privateKey, walletData.quantumPrivateKey, network, securityLevel);
|
|
136
|
+
}
|
|
137
|
+
static fromPrivateKeys(privateKeyHexOrWif, mldsaPrivateKeyOrBase58, network = networks.bitcoin, securityLevel = MLDSASecurityLevel.LEVEL2, chainCode) {
|
|
138
|
+
return new Wallet(privateKeyHexOrWif, mldsaPrivateKeyOrBase58, network, securityLevel, chainCode);
|
|
139
|
+
}
|
|
140
|
+
toWIF() {
|
|
141
|
+
return this._keypair.toWIF();
|
|
142
|
+
}
|
|
143
|
+
toPrivateKeyHex() {
|
|
144
|
+
if (!this._keypair.privateKey) {
|
|
145
|
+
throw new Error('Private key not available');
|
|
146
|
+
}
|
|
147
|
+
return this._keypair.privateKey.toString('hex');
|
|
148
|
+
}
|
|
149
|
+
toPublicKeyHex() {
|
|
150
|
+
return this._bufferPubKey.toString('hex');
|
|
151
|
+
}
|
|
152
|
+
toQuantumBase58() {
|
|
153
|
+
return this._mldsaKeypair.toBase58();
|
|
154
|
+
}
|
|
155
|
+
derivePath(path) {
|
|
156
|
+
const derivedQuantum = this._mldsaKeypair.derivePath(path);
|
|
157
|
+
if (!this._keypair.privateKey) {
|
|
158
|
+
throw new Error('Cannot derive from a watch-only wallet (no private key available)');
|
|
159
|
+
}
|
|
160
|
+
const bip32Root = EcKeyPair.BIP32.fromPrivateKey(this._keypair.privateKey, this._chainCode, this.network);
|
|
161
|
+
const derivedClassical = bip32Root.derivePath(path);
|
|
162
|
+
if (!derivedClassical.privateKey) {
|
|
163
|
+
throw new Error('Failed to derive classical private key');
|
|
164
|
+
}
|
|
165
|
+
if (!derivedClassical.chainCode) {
|
|
166
|
+
throw new Error('Failed to derive classical chain code');
|
|
167
|
+
}
|
|
168
|
+
return new Wallet(Buffer.from(derivedClassical.privateKey).toString('hex'), derivedQuantum.toBase58(), this.network, this._securityLevel, Buffer.from(derivedClassical.chainCode));
|
|
70
169
|
}
|
|
71
170
|
}
|