algosdk 3.6.0 → 3.7.0-beta.1
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/dist/browser/algosdk.min.js +1 -1
- package/dist/browser/algosdk.min.js.map +1 -1
- package/dist/cjs/client/v2/algod/algod.js +0 -18
- package/dist/cjs/client/v2/algod/algod.js.map +1 -1
- package/dist/cjs/client/v2/algod/models/types.js +2 -434
- package/dist/cjs/client/v2/algod/models/types.js.map +1 -1
- package/dist/cjs/ed25519-signer.js +76 -0
- package/dist/cjs/ed25519-signer.js.map +1 -0
- package/dist/cjs/encoding/address.js +61 -1
- package/dist/cjs/encoding/address.js.map +1 -1
- package/dist/cjs/falcon-signer.js +17 -0
- package/dist/cjs/falcon-signer.js.map +1 -0
- package/dist/cjs/logicsig.js +201 -16
- package/dist/cjs/logicsig.js.map +1 -1
- package/dist/cjs/main.js +32 -63
- package/dist/cjs/main.js.map +1 -1
- package/dist/cjs/mnemonic/mnemonic.js +26 -1
- package/dist/cjs/mnemonic/mnemonic.js.map +1 -1
- package/dist/cjs/multisigSigning.js +78 -1
- package/dist/cjs/multisigSigning.js.map +1 -1
- package/dist/cjs/pq-signer.js +54 -0
- package/dist/cjs/pq-signer.js.map +1 -0
- package/dist/cjs/signedTransaction.js +15 -1
- package/dist/cjs/signedTransaction.js.map +1 -1
- package/dist/cjs/signer.js.map +1 -1
- package/dist/cjs/signing.js +94 -7
- package/dist/cjs/signing.js.map +1 -1
- package/dist/cjs/transaction.js +9 -1
- package/dist/cjs/transaction.js.map +1 -1
- package/dist/cjs/types/transactions/encoded.js +51 -1
- package/dist/cjs/types/transactions/encoded.js.map +1 -1
- package/dist/cjs/utils/ed25519-check.js +69 -0
- package/dist/cjs/utils/ed25519-check.js.map +1 -0
- package/dist/esm/client/v2/algod/algod.js +0 -18
- package/dist/esm/client/v2/algod/algod.js.map +1 -1
- package/dist/esm/client/v2/algod/models/types.js +0 -427
- package/dist/esm/client/v2/algod/models/types.js.map +1 -1
- package/dist/esm/ed25519-signer.js +72 -0
- package/dist/esm/ed25519-signer.js.map +1 -0
- package/dist/esm/encoding/address.js +58 -0
- package/dist/esm/encoding/address.js.map +1 -1
- package/dist/esm/falcon-signer.js +13 -0
- package/dist/esm/falcon-signer.js.map +1 -0
- package/dist/esm/logicsig.js +200 -15
- package/dist/esm/logicsig.js.map +1 -1
- package/dist/esm/main.js +8 -56
- package/dist/esm/main.js.map +1 -1
- package/dist/esm/mnemonic/mnemonic.js +25 -1
- package/dist/esm/mnemonic/mnemonic.js.map +1 -1
- package/dist/esm/multisigSigning.js +75 -0
- package/dist/esm/multisigSigning.js.map +1 -1
- package/dist/esm/pq-signer.js +50 -0
- package/dist/esm/pq-signer.js.map +1 -0
- package/dist/esm/signedTransaction.js +16 -2
- package/dist/esm/signedTransaction.js.map +1 -1
- package/dist/esm/signer.js.map +1 -1
- package/dist/esm/signing.js +91 -8
- package/dist/esm/signing.js.map +1 -1
- package/dist/esm/transaction.js +9 -1
- package/dist/esm/transaction.js.map +1 -1
- package/dist/esm/types/transactions/encoded.js +49 -1
- package/dist/esm/types/transactions/encoded.js.map +1 -1
- package/dist/esm/utils/ed25519-check.js +65 -0
- package/dist/esm/utils/ed25519-check.js.map +1 -0
- package/dist/types/client/v2/algod/algod.d.ts +0 -16
- package/dist/types/client/v2/algod/models/types.d.ts +0 -217
- package/dist/types/ed25519-signer.d.ts +7 -0
- package/dist/types/encoding/address.d.ts +37 -0
- package/dist/types/falcon-signer.d.ts +11 -0
- package/dist/types/logicsig.d.ts +72 -1
- package/dist/types/main.d.ts +8 -44
- package/dist/types/mnemonic/mnemonic.d.ts +13 -0
- package/dist/types/multisigSigning.d.ts +49 -0
- package/dist/types/pq-signer.d.ts +8 -0
- package/dist/types/signedTransaction.d.ts +7 -2
- package/dist/types/signer.d.ts +38 -0
- package/dist/types/signing.d.ts +45 -0
- package/dist/types/transaction.d.ts +9 -0
- package/dist/types/types/transactions/encoded.d.ts +27 -0
- package/dist/types/utils/ed25519-check.d.ts +10 -0
- package/package.json +2 -1
- package/src/client/v2/algod/algod.ts +0 -19
- package/src/client/v2/algod/models/types.ts +0 -700
- package/src/ed25519-signer.ts +125 -0
- package/src/encoding/address.ts +80 -0
- package/src/falcon-signer.ts +30 -0
- package/src/logicsig.ts +258 -16
- package/src/main.ts +30 -60
- package/src/mnemonic/mnemonic.ts +34 -1
- package/src/multisigSigning.ts +111 -0
- package/src/pq-signer.ts +90 -0
- package/src/signedTransaction.ts +24 -0
- package/src/signer.ts +53 -0
- package/src/signing.ts +109 -8
- package/src/transaction.ts +9 -1
- package/src/types/transactions/encoded.ts +88 -0
- package/src/utils/ed25519-check.ts +67 -0
- package/dist/cjs/client/v2/algod/dryrun.js +0 -34
- package/dist/cjs/client/v2/algod/dryrun.js.map +0 -1
- package/dist/cjs/dryrun.js +0 -214
- package/dist/cjs/dryrun.js.map +0 -1
- package/dist/esm/client/v2/algod/dryrun.js +0 -28
- package/dist/esm/client/v2/algod/dryrun.js.map +0 -1
- package/dist/esm/dryrun.js +0 -208
- package/dist/esm/dryrun.js.map +0 -1
- package/dist/types/client/v2/algod/dryrun.d.ts +0 -11
- package/dist/types/dryrun.d.ts +0 -28
- package/src/client/v2/algod/dryrun.ts +0 -38
- package/src/dryrun.ts +0 -292
package/src/logicsig.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import * as nacl from './nacl/naclWrappers.js';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Address,
|
|
4
|
+
addressFromPQSig,
|
|
5
|
+
isValidAddress,
|
|
6
|
+
} from './encoding/address.js';
|
|
3
7
|
import * as encoding from './encoding/encoding.js';
|
|
4
8
|
import {
|
|
5
9
|
NamedMapSchema,
|
|
@@ -21,7 +25,12 @@ import {
|
|
|
21
25
|
encodedMultiSigToEncodingData,
|
|
22
26
|
encodedMultiSigFromEncodingData,
|
|
23
27
|
ENCODED_MULTISIG_SCHEMA,
|
|
28
|
+
EncodedPQSig,
|
|
29
|
+
ENCODED_PQSIG_SCHEMA,
|
|
30
|
+
encodedPQSigToEncodingData,
|
|
31
|
+
encodedPQSigFromEncodingData,
|
|
24
32
|
} from './types/transactions/encoded.js';
|
|
33
|
+
import type { DelegatedLsigSigner, ProgramDataSigner } from './signer.js';
|
|
25
34
|
|
|
26
35
|
// base64regex is the regex to test for base64 strings
|
|
27
36
|
const base64regex =
|
|
@@ -59,8 +68,9 @@ export function sanityCheckProgram(program: Uint8Array) {
|
|
|
59
68
|
}
|
|
60
69
|
}
|
|
61
70
|
|
|
62
|
-
const
|
|
63
|
-
const
|
|
71
|
+
export const PROGRAM_TAG = new TextEncoder().encode('Program');
|
|
72
|
+
export const PQ_PROGRAM_TAG = new TextEncoder().encode('PQProgram');
|
|
73
|
+
export const MSIG_PROGRAM_TAG = new TextEncoder().encode('MsigProgram');
|
|
64
74
|
|
|
65
75
|
/**
|
|
66
76
|
LogicSig implementation
|
|
@@ -90,6 +100,10 @@ export class LogicSig implements encoding.Encodable {
|
|
|
90
100
|
key: 'lmsig',
|
|
91
101
|
valueSchema: new OptionalSchema(ENCODED_MULTISIG_SCHEMA),
|
|
92
102
|
},
|
|
103
|
+
{
|
|
104
|
+
key: 'pqsig',
|
|
105
|
+
valueSchema: new OptionalSchema(ENCODED_PQSIG_SCHEMA),
|
|
106
|
+
},
|
|
93
107
|
])
|
|
94
108
|
);
|
|
95
109
|
|
|
@@ -98,6 +112,7 @@ export class LogicSig implements encoding.Encodable {
|
|
|
98
112
|
sig?: Uint8Array;
|
|
99
113
|
msig?: EncodedMultisig;
|
|
100
114
|
lmsig?: EncodedMultisig;
|
|
115
|
+
pqsig?: EncodedPQSig;
|
|
101
116
|
|
|
102
117
|
constructor(program: Uint8Array, programArgs?: Array<Uint8Array> | null) {
|
|
103
118
|
if (
|
|
@@ -119,6 +134,7 @@ export class LogicSig implements encoding.Encodable {
|
|
|
119
134
|
this.sig = undefined;
|
|
120
135
|
this.msig = undefined;
|
|
121
136
|
this.lmsig = undefined;
|
|
137
|
+
this.pqsig = undefined;
|
|
122
138
|
}
|
|
123
139
|
|
|
124
140
|
// eslint-disable-next-line class-methods-use-this
|
|
@@ -138,6 +154,9 @@ export class LogicSig implements encoding.Encodable {
|
|
|
138
154
|
if (this.lmsig) {
|
|
139
155
|
data.set('lmsig', encodedMultiSigToEncodingData(this.lmsig));
|
|
140
156
|
}
|
|
157
|
+
if (this.pqsig) {
|
|
158
|
+
data.set('pqsig', encodedPQSigToEncodingData(this.pqsig));
|
|
159
|
+
}
|
|
141
160
|
return data;
|
|
142
161
|
}
|
|
143
162
|
|
|
@@ -153,15 +172,23 @@ export class LogicSig implements encoding.Encodable {
|
|
|
153
172
|
if (data.get('lmsig')) {
|
|
154
173
|
lsig.lmsig = encodedMultiSigFromEncodingData(data.get('lmsig'));
|
|
155
174
|
}
|
|
175
|
+
if (data.get('pqsig')) {
|
|
176
|
+
lsig.pqsig = encodedPQSigFromEncodingData(data.get('pqsig'));
|
|
177
|
+
}
|
|
156
178
|
return lsig;
|
|
157
179
|
}
|
|
158
180
|
|
|
159
181
|
/**
|
|
182
|
+
* @deprecated This function does not perform full verification and should not be fully trusted on its own.
|
|
183
|
+
* For example, it does not evaluate programs and does not have the ability to validate PQ signatures.
|
|
184
|
+
*
|
|
160
185
|
* Performs signature verification
|
|
161
186
|
* @param publicKey - Verification key (derived from sender address or escrow address)
|
|
162
187
|
*/
|
|
163
188
|
verify(publicKey: Uint8Array) {
|
|
164
|
-
const sigCount = [this.sig, this.msig, this.lmsig].filter(
|
|
189
|
+
const sigCount = [this.sig, this.msig, this.lmsig, this.pqsig].filter(
|
|
190
|
+
Boolean
|
|
191
|
+
).length;
|
|
165
192
|
if (sigCount > 1) {
|
|
166
193
|
return false;
|
|
167
194
|
}
|
|
@@ -172,13 +199,21 @@ export class LogicSig implements encoding.Encodable {
|
|
|
172
199
|
return false;
|
|
173
200
|
}
|
|
174
201
|
|
|
175
|
-
const toBeSigned = utils.concatArrays(
|
|
202
|
+
const toBeSigned = utils.concatArrays(PROGRAM_TAG, this.logic);
|
|
176
203
|
|
|
177
|
-
if (!this.sig && !this.msig && !this.lmsig) {
|
|
204
|
+
if (!this.sig && !this.msig && !this.lmsig && !this.pqsig) {
|
|
178
205
|
const hash = nacl.genericHash(toBeSigned);
|
|
179
206
|
return utils.arrayEqual(hash, publicKey);
|
|
180
207
|
}
|
|
181
208
|
|
|
209
|
+
if (this.pqsig) {
|
|
210
|
+
// This function has no way to validate a post-quantum signature, so it
|
|
211
|
+
// cannot report success here. Callers that need to sign a transaction
|
|
212
|
+
// with a PQ delegated LogicSig should go through
|
|
213
|
+
// signLogicSigTransactionObject, which skips this check.
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
|
|
182
217
|
if (this.sig) {
|
|
183
218
|
return nacl.verify(toBeSigned, this.sig, publicKey);
|
|
184
219
|
}
|
|
@@ -190,7 +225,7 @@ export class LogicSig implements encoding.Encodable {
|
|
|
190
225
|
pks: this.lmsig.subsig.map((subsig) => subsig.pk),
|
|
191
226
|
});
|
|
192
227
|
const lmsigProgram = utils.concatArrays(
|
|
193
|
-
|
|
228
|
+
MSIG_PROGRAM_TAG,
|
|
194
229
|
multisigAddr.publicKey,
|
|
195
230
|
this.logic
|
|
196
231
|
);
|
|
@@ -209,12 +244,14 @@ export class LogicSig implements encoding.Encodable {
|
|
|
209
244
|
* @returns String representation of the address
|
|
210
245
|
*/
|
|
211
246
|
address(): Address {
|
|
212
|
-
const toBeSigned = utils.concatArrays(
|
|
247
|
+
const toBeSigned = utils.concatArrays(PROGRAM_TAG, this.logic);
|
|
213
248
|
const hash = nacl.genericHash(toBeSigned);
|
|
214
249
|
return new Address(Uint8Array.from(hash));
|
|
215
250
|
}
|
|
216
251
|
|
|
217
252
|
/**
|
|
253
|
+
* @deprecated Use `signWithSigner` instead
|
|
254
|
+
*
|
|
218
255
|
* Creates signature (if no msig provided) or multi signature otherwise
|
|
219
256
|
* @param secretKey - Secret key to sign with
|
|
220
257
|
* @param msig - Multisig account as \{version, threshold, addrs\}
|
|
@@ -237,6 +274,81 @@ export class LogicSig implements encoding.Encodable {
|
|
|
237
274
|
}
|
|
238
275
|
|
|
239
276
|
/**
|
|
277
|
+
* Signs this LogicSig for delegation using the given signer.
|
|
278
|
+
*
|
|
279
|
+
* @param signer - The signer to delegate to
|
|
280
|
+
* @param msig - Optional multisig account the signer is a subsigner of
|
|
281
|
+
* @returns The address the signer signed as. When `msig` is omitted this is
|
|
282
|
+
* the delegating account. When `msig` is given it is the individual
|
|
283
|
+
* subsigner, not the multisig, so the delegating account is
|
|
284
|
+
* `multisigAddress(msig)`. Either way it is an authorizing address, which
|
|
285
|
+
* is not necessarily the address a signer sends transactions from.
|
|
286
|
+
*
|
|
287
|
+
* Re-signing an already-signed LogicSig is allowed, and replaces the previous
|
|
288
|
+
* delegation signature. At most one of `sig`, `msig`, `lmsig` and `pqsig` may
|
|
289
|
+
* be set, so any signature left over from an earlier call is cleared.
|
|
290
|
+
*/
|
|
291
|
+
async signWithSigner(
|
|
292
|
+
signer: DelegatedLsigSigner,
|
|
293
|
+
msig?: MultisigMetadata
|
|
294
|
+
): Promise<Address> {
|
|
295
|
+
const sigResult = await signer(this, msig);
|
|
296
|
+
if (msig == null) {
|
|
297
|
+
if ('pqsig' in sigResult && sigResult.pqsig) {
|
|
298
|
+
this.clearSignatures();
|
|
299
|
+
this.pqsig = sigResult.pqsig;
|
|
300
|
+
return sigResult.address;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (!('sig' in sigResult) || !sigResult.sig) {
|
|
304
|
+
throw Error(
|
|
305
|
+
'Expected DelegatedLsigSigner to return sig or pqsig, but both are undefined. If signing for an msig, be sure to pass the msig argument'
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
this.clearSignatures();
|
|
309
|
+
this.sig = sigResult.sig;
|
|
310
|
+
} else {
|
|
311
|
+
if (!('lmsig' in sigResult) || !sigResult.lmsig) {
|
|
312
|
+
throw Error(
|
|
313
|
+
'Expected DelegatedLsigSigner to return lmsig, but lmsig is undefined. If signing for a single account, do not pass msig argument'
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
const { lmsig } = sigResult;
|
|
317
|
+
const expectedPks = pksFromAddresses(msig.addrs);
|
|
318
|
+
if (
|
|
319
|
+
lmsig.v !== msig.version ||
|
|
320
|
+
lmsig.thr !== msig.threshold ||
|
|
321
|
+
lmsig.subsig.length !== expectedPks.length ||
|
|
322
|
+
!lmsig.subsig.every((subsig, i) =>
|
|
323
|
+
utils.arrayEqual(subsig.pk, expectedPks[i])
|
|
324
|
+
)
|
|
325
|
+
) {
|
|
326
|
+
throw Error(
|
|
327
|
+
'DelegatedLsigSigner returned an lmsig whose version, threshold or public keys do not match the requested multisig'
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
this.clearSignatures();
|
|
332
|
+
this.lmsig = sigResult.lmsig;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return sigResult.address;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Removes every delegation signature from this LogicSig, so that exactly one
|
|
340
|
+
* of them can be set afterwards.
|
|
341
|
+
*/
|
|
342
|
+
private clearSignatures() {
|
|
343
|
+
this.sig = undefined;
|
|
344
|
+
this.msig = undefined;
|
|
345
|
+
this.lmsig = undefined;
|
|
346
|
+
this.pqsig = undefined;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* @deprecated Use `appendToMultisigWithSigner` instead
|
|
351
|
+
*
|
|
240
352
|
* Appends a signature to multi signature
|
|
241
353
|
* @param secretKey - Secret key to sign with
|
|
242
354
|
*/
|
|
@@ -248,12 +360,71 @@ export class LogicSig implements encoding.Encodable {
|
|
|
248
360
|
this.lmsig.subsig[index].s = sig;
|
|
249
361
|
}
|
|
250
362
|
|
|
363
|
+
async appendToMultisigWithSigner(signer: DelegatedLsigSigner) {
|
|
364
|
+
if (this.lmsig === undefined) {
|
|
365
|
+
throw new Error('no multisig present');
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const sigResult = await signer(this, {
|
|
369
|
+
version: this.lmsig.v,
|
|
370
|
+
threshold: this.lmsig.thr,
|
|
371
|
+
addrs: this.lmsig.subsig.map((s) => new Address(s.pk)),
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
if (!('lmsig' in sigResult) || !sigResult.lmsig) {
|
|
375
|
+
throw Error(
|
|
376
|
+
'Expected DelegatedLsigSigner to return lmsig, but lmsig is undefined'
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
if (
|
|
380
|
+
sigResult.lmsig.v !== this.lmsig.v ||
|
|
381
|
+
sigResult.lmsig.thr !== this.lmsig.thr
|
|
382
|
+
) {
|
|
383
|
+
throw Error(
|
|
384
|
+
'DelegatedLsigSigner returned an lmsig whose version or threshold does not match the current msig'
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
let signaturesReturned = false;
|
|
389
|
+
for (const subsig of sigResult.lmsig.subsig) {
|
|
390
|
+
if (subsig.s) {
|
|
391
|
+
signaturesReturned = true;
|
|
392
|
+
const thisSubsig = this.lmsig.subsig.find((s) =>
|
|
393
|
+
utils.arrayEqual(s.pk, subsig.pk)
|
|
394
|
+
);
|
|
395
|
+
if (thisSubsig === undefined) {
|
|
396
|
+
throw Error(
|
|
397
|
+
`DelegatedLsigSigner returned a signature for ${new Address(subsig.pk)} but this pk is not in the current msig`
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
// Never let the signer silently replace a signature already collected
|
|
401
|
+
// from another member.
|
|
402
|
+
if (thisSubsig.s && !utils.arrayEqual(thisSubsig.s, subsig.s)) {
|
|
403
|
+
throw Error(
|
|
404
|
+
`DelegatedLsigSigner returned a signature for ${new Address(subsig.pk)} that conflicts with the signature already collected for it`
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
thisSubsig.s = subsig.s;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (!signaturesReturned) {
|
|
412
|
+
throw Error('DelegatedLsigSigner returned an lmsig with no signatures');
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* @deprecated Use `signWithSigner` followed by `.sig` instead
|
|
418
|
+
*/
|
|
251
419
|
signProgram(secretKey: Uint8Array) {
|
|
252
|
-
const toBeSigned = utils.concatArrays(
|
|
420
|
+
const toBeSigned = utils.concatArrays(PROGRAM_TAG, this.logic);
|
|
253
421
|
const sig = nacl.sign(toBeSigned, secretKey);
|
|
254
422
|
return sig;
|
|
255
423
|
}
|
|
256
424
|
|
|
425
|
+
/**
|
|
426
|
+
* @deprecated Use `signWithSigner` followed by `.sig` instead
|
|
427
|
+
*/
|
|
257
428
|
signProgramMultisig(secretKey: Uint8Array, msig: EncodedMultisig) {
|
|
258
429
|
const multisigAddr = addressFromMultisigPreImg({
|
|
259
430
|
version: msig.v,
|
|
@@ -261,7 +432,7 @@ export class LogicSig implements encoding.Encodable {
|
|
|
261
432
|
pks: msig.subsig.map((subsig) => subsig.pk),
|
|
262
433
|
});
|
|
263
434
|
const toBeSigned = utils.concatArrays(
|
|
264
|
-
|
|
435
|
+
MSIG_PROGRAM_TAG,
|
|
265
436
|
multisigAddr.publicKey,
|
|
266
437
|
this.logic
|
|
267
438
|
);
|
|
@@ -269,6 +440,9 @@ export class LogicSig implements encoding.Encodable {
|
|
|
269
440
|
return sig;
|
|
270
441
|
}
|
|
271
442
|
|
|
443
|
+
/**
|
|
444
|
+
* @deprecated Use `signWithSigner` followed by `.sig` instead
|
|
445
|
+
*/
|
|
272
446
|
singleSignMultisig(
|
|
273
447
|
secretKey: Uint8Array,
|
|
274
448
|
msig: EncodedMultisig
|
|
@@ -296,6 +470,17 @@ export class LogicSig implements encoding.Encodable {
|
|
|
296
470
|
static fromByte(encoded: ArrayLike<any>): LogicSig {
|
|
297
471
|
return encoding.decodeMsgpack(encoded, LogicSig);
|
|
298
472
|
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Signs arbitrary data for use with the `ed25519verify` opcode from within
|
|
476
|
+
* this LogicSig's program.
|
|
477
|
+
*
|
|
478
|
+
* @param signer - The signer to sign the data with
|
|
479
|
+
* @param data - The data to sign
|
|
480
|
+
*/
|
|
481
|
+
async signDataWithSigner(signer: ProgramDataSigner, data: Uint8Array) {
|
|
482
|
+
return signer(data, this);
|
|
483
|
+
}
|
|
299
484
|
}
|
|
300
485
|
|
|
301
486
|
/**
|
|
@@ -379,10 +564,18 @@ export class LogicSigAccount implements encoding.Encodable {
|
|
|
379
564
|
* To verify the delegation signature, use `verify`.
|
|
380
565
|
*/
|
|
381
566
|
isDelegated() {
|
|
382
|
-
return !!(
|
|
567
|
+
return !!(
|
|
568
|
+
this.lsig.sig ||
|
|
569
|
+
this.lsig.msig ||
|
|
570
|
+
this.lsig.lmsig ||
|
|
571
|
+
this.lsig.pqsig
|
|
572
|
+
);
|
|
383
573
|
}
|
|
384
574
|
|
|
385
575
|
/**
|
|
576
|
+
* @deprecated This function does not perform full verification and should not be fully trusted on its own.
|
|
577
|
+
* For example, it does not evaluate programs and does not have the ability to validate PQ signatures.
|
|
578
|
+
*
|
|
386
579
|
* Verifies this LogicSig's program and signatures.
|
|
387
580
|
* @returns true if and only if the LogicSig program and signatures are valid.
|
|
388
581
|
*/
|
|
@@ -401,15 +594,31 @@ export class LogicSigAccount implements encoding.Encodable {
|
|
|
401
594
|
* escrow address that is the hash of the LogicSig's program code.
|
|
402
595
|
*/
|
|
403
596
|
address(): Address {
|
|
404
|
-
const sigCount = [
|
|
405
|
-
|
|
406
|
-
|
|
597
|
+
const sigCount = [
|
|
598
|
+
this.lsig.sig,
|
|
599
|
+
this.lsig.msig,
|
|
600
|
+
this.lsig.lmsig,
|
|
601
|
+
this.lsig.pqsig,
|
|
602
|
+
].filter(Boolean).length;
|
|
407
603
|
if (sigCount > 1) {
|
|
408
604
|
throw new Error(
|
|
409
|
-
'LogicSig has too many signatures. At most one of sig, msig, or
|
|
605
|
+
'LogicSig has too many signatures. At most one of sig, msig, lmsig, or pqsig may be present'
|
|
410
606
|
);
|
|
411
607
|
}
|
|
412
608
|
|
|
609
|
+
if (this.lsig.pqsig) {
|
|
610
|
+
// A PQ signature carries the scheme, salt and public key of the
|
|
611
|
+
// delegating account, so derive the address rather than trusting
|
|
612
|
+
// `sigkey`. Also throws if the signature is not self-consistent.
|
|
613
|
+
const derived = addressFromPQSig(this.lsig.pqsig);
|
|
614
|
+
if (this.sigkey && !utils.arrayEqual(this.sigkey, derived.publicKey)) {
|
|
615
|
+
throw new Error(
|
|
616
|
+
`Signing key for delegated account does not match the PQ signature. The signature authorizes ${derived}, but sigkey is ${new Address(this.sigkey)}`
|
|
617
|
+
);
|
|
618
|
+
}
|
|
619
|
+
return derived;
|
|
620
|
+
}
|
|
621
|
+
|
|
413
622
|
if (this.lsig.sig) {
|
|
414
623
|
if (!this.sigkey) {
|
|
415
624
|
throw new Error('Signing key for delegated account is missing');
|
|
@@ -431,6 +640,8 @@ export class LogicSigAccount implements encoding.Encodable {
|
|
|
431
640
|
}
|
|
432
641
|
|
|
433
642
|
/**
|
|
643
|
+
* @deprecated Use `signMultisigWithSigner` instead
|
|
644
|
+
*
|
|
434
645
|
* Turns this LogicSigAccount into a delegated LogicSig. This type of LogicSig
|
|
435
646
|
* has the authority to sign transactions on behalf of another account, called
|
|
436
647
|
* the delegating account. Use this function if the delegating account is a
|
|
@@ -445,7 +656,16 @@ export class LogicSigAccount implements encoding.Encodable {
|
|
|
445
656
|
this.lsig.sign(secretKey, msig);
|
|
446
657
|
}
|
|
447
658
|
|
|
659
|
+
async signMultisigWithSigner(
|
|
660
|
+
msig: MultisigMetadata,
|
|
661
|
+
signer: DelegatedLsigSigner
|
|
662
|
+
) {
|
|
663
|
+
await this.lsig.signWithSigner(signer, msig);
|
|
664
|
+
}
|
|
665
|
+
|
|
448
666
|
/**
|
|
667
|
+
* @deprecated Use appendToMultisigWithSigner
|
|
668
|
+
*
|
|
449
669
|
* Adds an additional signature from a member of the delegating multisig
|
|
450
670
|
* account.
|
|
451
671
|
*
|
|
@@ -456,7 +676,13 @@ export class LogicSigAccount implements encoding.Encodable {
|
|
|
456
676
|
this.lsig.appendToMultisig(secretKey);
|
|
457
677
|
}
|
|
458
678
|
|
|
679
|
+
async appendToMultisigWithSigner(signer: DelegatedLsigSigner) {
|
|
680
|
+
await this.lsig.appendToMultisigWithSigner(signer);
|
|
681
|
+
}
|
|
682
|
+
|
|
459
683
|
/**
|
|
684
|
+
* @deprecated Use `signWithSigner` instead
|
|
685
|
+
*
|
|
460
686
|
* Turns this LogicSigAccount into a delegated LogicSig. This type of LogicSig
|
|
461
687
|
* has the authority to sign transactions on behalf of another account, called
|
|
462
688
|
* the delegating account. If the delegating account is a multisig account,
|
|
@@ -468,6 +694,22 @@ export class LogicSigAccount implements encoding.Encodable {
|
|
|
468
694
|
this.lsig.sign(secretKey);
|
|
469
695
|
this.sigkey = nacl.keyPairFromSecretKey(secretKey).publicKey;
|
|
470
696
|
}
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* Turns this LogicSigAccount into a delegated LogicSig, signed by the given
|
|
700
|
+
* signer. If the delegating account is a multisig account, use
|
|
701
|
+
* `signMultisigWithSigner` instead.
|
|
702
|
+
*
|
|
703
|
+
* @param signer - The signer of the delegating account.
|
|
704
|
+
*/
|
|
705
|
+
async signWithSigner(signer: DelegatedLsigSigner) {
|
|
706
|
+
// Record the address the signer reports rather than any sending address it
|
|
707
|
+
// may advertise: the latter is the address the signer sends transactions
|
|
708
|
+
// from, which for a rekeyed account is not the account that authorizes
|
|
709
|
+
// this delegation.
|
|
710
|
+
const delegatingAddress = await this.lsig.signWithSigner(signer);
|
|
711
|
+
this.sigkey = delegatingAddress.publicKey;
|
|
712
|
+
}
|
|
471
713
|
}
|
|
472
714
|
|
|
473
715
|
/**
|
|
@@ -478,7 +720,7 @@ export function logicSigFromByte(encoded: Uint8Array): LogicSig {
|
|
|
478
720
|
return encoding.decodeMsgpack(encoded, LogicSig);
|
|
479
721
|
}
|
|
480
722
|
|
|
481
|
-
const SIGN_PROGRAM_DATA_PREFIX = new TextEncoder().encode('ProgData');
|
|
723
|
+
export const SIGN_PROGRAM_DATA_PREFIX = new TextEncoder().encode('ProgData');
|
|
482
724
|
|
|
483
725
|
/**
|
|
484
726
|
* tealSign creates a signature compatible with ed25519verify opcode from program hash
|
package/src/main.ts
CHANGED
|
@@ -1,68 +1,9 @@
|
|
|
1
|
-
import * as nacl from './nacl/naclWrappers.js';
|
|
2
|
-
import { Address } from './encoding/address.js';
|
|
3
|
-
import { Transaction } from './transaction.js';
|
|
4
1
|
import * as convert from './convert.js';
|
|
5
|
-
import * as utils from './utils/utils.js';
|
|
6
|
-
|
|
7
|
-
const SIGN_BYTES_PREFIX = Uint8Array.from([77, 88]); // "MX"
|
|
8
2
|
|
|
9
3
|
// Errors
|
|
10
4
|
export const MULTISIG_BAD_SENDER_ERROR_MSG =
|
|
11
5
|
'The transaction sender address and multisig preimage do not match.';
|
|
12
6
|
|
|
13
|
-
/**
|
|
14
|
-
* signTransaction takes an object with either payment or key registration fields and
|
|
15
|
-
* a secret key and returns a signed blob.
|
|
16
|
-
*
|
|
17
|
-
* Payment transaction fields: from, to, amount, fee, firstValid, lastValid, genesisHash,
|
|
18
|
-
* note(optional), GenesisID(optional), closeRemainderTo(optional)
|
|
19
|
-
*
|
|
20
|
-
* Key registration fields: fee, firstValid, lastValid, voteKey, selectionKey, voteFirst,
|
|
21
|
-
* voteLast, voteKeyDilution, genesisHash, note(optional), GenesisID(optional)
|
|
22
|
-
*
|
|
23
|
-
* If flatFee is not set and the final calculated fee is lower than the protocol minimum fee, the fee will be increased to match the minimum.
|
|
24
|
-
* @param txn - object with either payment or key registration fields
|
|
25
|
-
* @param sk - Algorand Secret Key
|
|
26
|
-
* @returns object contains the binary signed transaction and its txID
|
|
27
|
-
*/
|
|
28
|
-
export function signTransaction(txn: Transaction, sk: Uint8Array) {
|
|
29
|
-
return {
|
|
30
|
-
txID: txn.txID(),
|
|
31
|
-
blob: txn.signTxn(sk),
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* signBytes takes arbitrary bytes and a secret key, prepends the bytes with "MX" for domain separation, signs the bytes
|
|
37
|
-
* with the private key, and returns the signature.
|
|
38
|
-
* @param bytes - Uint8array
|
|
39
|
-
* @param sk - Algorand secret key
|
|
40
|
-
* @returns binary signature
|
|
41
|
-
*/
|
|
42
|
-
export function signBytes(bytes: Uint8Array, sk: Uint8Array) {
|
|
43
|
-
const toBeSigned = utils.concatArrays(SIGN_BYTES_PREFIX, bytes);
|
|
44
|
-
const sig = nacl.sign(toBeSigned, sk);
|
|
45
|
-
return sig;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* verifyBytes takes array of bytes, an address, and a signature and verifies if the signature is correct for the public
|
|
50
|
-
* key and the bytes (the bytes should have been signed with "MX" prepended for domain separation).
|
|
51
|
-
* @param bytes - Uint8Array
|
|
52
|
-
* @param signature - binary signature
|
|
53
|
-
* @param addr - string address
|
|
54
|
-
* @returns bool
|
|
55
|
-
*/
|
|
56
|
-
export function verifyBytes(
|
|
57
|
-
bytes: Uint8Array,
|
|
58
|
-
signature: Uint8Array,
|
|
59
|
-
addr: string | Address
|
|
60
|
-
) {
|
|
61
|
-
const toBeVerified = utils.concatArrays(SIGN_BYTES_PREFIX, bytes);
|
|
62
|
-
const addrObj = typeof addr === 'string' ? Address.fromString(addr) : addr;
|
|
63
|
-
return nacl.verify(toBeVerified, signature, addrObj.publicKey);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
7
|
export const ERROR_MULTISIG_BAD_SENDER = new Error(
|
|
67
8
|
MULTISIG_BAD_SENDER_ERROR_MSG
|
|
68
9
|
);
|
|
@@ -109,6 +50,10 @@ export {
|
|
|
109
50
|
encodeAddress,
|
|
110
51
|
decodeAddress,
|
|
111
52
|
getApplicationAddress,
|
|
53
|
+
addressFromPQKey,
|
|
54
|
+
addressFromPQSig,
|
|
55
|
+
PQ_SCHEME_SIZE,
|
|
56
|
+
PQ_SALT_MAX,
|
|
112
57
|
ALGORAND_ZERO_ADDRESS_STRING,
|
|
113
58
|
} from './encoding/address.js';
|
|
114
59
|
export { bytesToBigInt, bigIntToBytes } from './encoding/bigint.js';
|
|
@@ -136,6 +81,7 @@ export {
|
|
|
136
81
|
mnemonicToSecretKey,
|
|
137
82
|
seedFromMnemonic,
|
|
138
83
|
mnemonicFromSeed,
|
|
84
|
+
pq25WordMnemonicToSeed,
|
|
139
85
|
} from './mnemonic/mnemonic.js';
|
|
140
86
|
export {
|
|
141
87
|
microalgosToAlgos,
|
|
@@ -149,6 +95,11 @@ export {
|
|
|
149
95
|
encodeUnsignedSimulateTransaction,
|
|
150
96
|
} from './signedTransaction.js';
|
|
151
97
|
export {
|
|
98
|
+
SIGN_BYTES_PREFIX,
|
|
99
|
+
signTransaction,
|
|
100
|
+
signTransactionWithSigner,
|
|
101
|
+
signBytes,
|
|
102
|
+
verifyBytes,
|
|
152
103
|
signLogicSigTransaction,
|
|
153
104
|
signLogicSigTransactionObject,
|
|
154
105
|
} from './signing.js';
|
|
@@ -159,6 +110,10 @@ export {
|
|
|
159
110
|
tealSign,
|
|
160
111
|
tealSignFromProgram,
|
|
161
112
|
verifyTealSign,
|
|
113
|
+
PROGRAM_TAG,
|
|
114
|
+
PQ_PROGRAM_TAG,
|
|
115
|
+
MSIG_PROGRAM_TAG,
|
|
116
|
+
SIGN_PROGRAM_DATA_PREFIX,
|
|
162
117
|
} from './logicsig.js';
|
|
163
118
|
export {
|
|
164
119
|
MultisigMetadata,
|
|
@@ -171,6 +126,8 @@ export {
|
|
|
171
126
|
appendSignMultisigTransaction,
|
|
172
127
|
createMultisigTransaction,
|
|
173
128
|
appendSignRawMultisigSignature,
|
|
129
|
+
signMultisigTransactionWithSigner,
|
|
130
|
+
appendSignMultisigTransactionWithSigner,
|
|
174
131
|
} from './multisigSigning.js';
|
|
175
132
|
export {
|
|
176
133
|
ProgramSourceMap,
|
|
@@ -178,7 +135,20 @@ export {
|
|
|
178
135
|
PcLineLocation,
|
|
179
136
|
} from './logic/sourcemap.js';
|
|
180
137
|
|
|
181
|
-
export
|
|
138
|
+
export {
|
|
139
|
+
Ed25519SigningKey,
|
|
140
|
+
addressWithSignersFromRawEd25519Signer,
|
|
141
|
+
} from './ed25519-signer.js';
|
|
142
|
+
export {
|
|
143
|
+
FALCON_1024_SCHEME,
|
|
144
|
+
Falcon1024SigningKey,
|
|
145
|
+
addressWithSignersFromRawFalcon1024Signer,
|
|
146
|
+
} from './falcon-signer.js';
|
|
147
|
+
export {
|
|
148
|
+
PQSigningKey,
|
|
149
|
+
addressWithSignersFromRawPQSigner,
|
|
150
|
+
} from './pq-signer.js';
|
|
151
|
+
|
|
182
152
|
export * from './makeTxn.js';
|
|
183
153
|
export * from './transaction.js';
|
|
184
154
|
export * from './signer.js';
|
package/src/mnemonic/mnemonic.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/* eslint-disable no-bitwise */
|
|
2
2
|
import english from './wordlists/english.js';
|
|
3
3
|
import * as nacl from '../nacl/naclWrappers.js';
|
|
4
|
-
import { Address } from '../encoding/address.js';
|
|
4
|
+
import { Address, PQ_SCHEME_SIZE } from '../encoding/address.js';
|
|
5
5
|
import Account from '../types/account.js';
|
|
6
|
+
import { concatArrays } from '../utils/utils.js';
|
|
6
7
|
|
|
7
8
|
export const FAIL_TO_DECODE_MNEMONIC_ERROR_MSG = 'failed to decode mnemonic';
|
|
8
9
|
export const NOT_IN_WORDS_LIST_ERROR_MSG =
|
|
@@ -179,3 +180,35 @@ export function mnemonicToMasterDerivationKey(mn: string) {
|
|
|
179
180
|
export function masterDerivationKeyToMnemonic(mdk: Uint8Array) {
|
|
180
181
|
return mnemonicFromSeed(mdk);
|
|
181
182
|
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* The domain-separation prefix prepended to a post-quantum key seed preimage
|
|
186
|
+
* before hashing. Matches go-algorand's protocol.PostQuantumKey HashID.
|
|
187
|
+
*/
|
|
188
|
+
const PQ_KEY_PREFIX = new TextEncoder().encode('PQK');
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* pq25WordMnemonicToSeed derives a post-quantum key seed from a standard 25-word
|
|
192
|
+
* Algorand mnemonic.
|
|
193
|
+
*
|
|
194
|
+
* The seed is domain-separated by the PQ scheme, so the same mnemonic yields a
|
|
195
|
+
* different key for each scheme, and a different key again from the ed25519
|
|
196
|
+
* account that `mnemonicToSecretKey` derives from it.
|
|
197
|
+
*
|
|
198
|
+
* @param mn - A 25-word Algorand mnemonic
|
|
199
|
+
* @param scheme - The 2-byte ASCII PQ scheme identifier (e.g. "f1" for Falcon-1024)
|
|
200
|
+
* @returns The 32-byte seed to hand to the scheme's key generator
|
|
201
|
+
*/
|
|
202
|
+
export function pq25WordMnemonicToSeed(
|
|
203
|
+
mn: string,
|
|
204
|
+
scheme: Uint8Array
|
|
205
|
+
): Uint8Array {
|
|
206
|
+
if (scheme.length !== PQ_SCHEME_SIZE) {
|
|
207
|
+
throw new Error(
|
|
208
|
+
`invalid PQ scheme length: expected ${PQ_SCHEME_SIZE} bytes, got ${scheme.length}`
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
return new Uint8Array(
|
|
212
|
+
nacl.genericHash(concatArrays(PQ_KEY_PREFIX, scheme, seedFromMnemonic(mn)))
|
|
213
|
+
);
|
|
214
|
+
}
|