@aztec/stdlib 5.0.0-nightly.20260629 → 5.0.0-nightly.20260701
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/dest/avm/avm.js +1 -1
- package/dest/aztec-address/index.d.ts +35 -5
- package/dest/aztec-address/index.d.ts.map +1 -1
- package/dest/aztec-address/index.js +32 -8
- package/dest/contract/interfaces/contract_data_source.d.ts +3 -5
- package/dest/contract/interfaces/contract_data_source.d.ts.map +1 -1
- package/dest/interfaces/archiver.js +1 -1
- package/dest/interfaces/aztec-node.d.ts +11 -3
- package/dest/interfaces/aztec-node.d.ts.map +1 -1
- package/dest/interfaces/aztec-node.js +2 -1
- package/dest/kernel/hints/read_request.js +1 -1
- package/dest/kernel/log_hash.d.ts +1 -1
- package/dest/kernel/log_hash.d.ts.map +1 -1
- package/dest/kernel/log_hash.js +2 -2
- package/dest/kernel/note_hash.js +1 -1
- package/dest/kernel/nullifier.js +1 -1
- package/dest/kernel/private_log_data.d.ts +1 -1
- package/dest/kernel/private_log_data.d.ts.map +1 -1
- package/dest/kernel/private_log_data.js +1 -1
- package/dest/keys/derivation.d.ts +7 -1
- package/dest/keys/derivation.d.ts.map +1 -1
- package/dest/keys/derivation.js +24 -7
- package/dest/logs/app_tagging_secret.d.ts +21 -6
- package/dest/logs/app_tagging_secret.d.ts.map +1 -1
- package/dest/logs/app_tagging_secret.js +32 -22
- package/dest/logs/contract_class_log.d.ts +1 -2
- package/dest/logs/contract_class_log.d.ts.map +1 -1
- package/dest/logs/contract_class_log.js +0 -4
- package/dest/logs/message_context.d.ts +5 -15
- package/dest/logs/message_context.d.ts.map +1 -1
- package/dest/logs/message_context.js +1 -66
- package/dest/logs/pending_tagged_log.d.ts +6 -8
- package/dest/logs/pending_tagged_log.d.ts.map +1 -1
- package/dest/logs/pending_tagged_log.js +1 -31
- package/dest/tests/factories.js +2 -2
- package/dest/trees/nullifier_membership_witness.d.ts +5 -8
- package/dest/trees/nullifier_membership_witness.d.ts.map +1 -1
- package/dest/trees/nullifier_membership_witness.js +0 -9
- package/dest/trees/public_data_witness.d.ts +7 -17
- package/dest/trees/public_data_witness.d.ts.map +1 -1
- package/dest/trees/public_data_witness.js +0 -27
- package/dest/tx/execution_payload.d.ts +1 -1
- package/dest/tx/execution_payload.d.ts.map +1 -1
- package/dest/tx/execution_payload.js +1 -1
- package/dest/tx/global_variables.js +2 -2
- package/package.json +8 -8
- package/src/avm/avm.ts +1 -1
- package/src/aztec-address/index.ts +36 -6
- package/src/contract/interfaces/contract_data_source.ts +2 -4
- package/src/interfaces/archiver.ts +1 -1
- package/src/interfaces/aztec-node.ts +11 -3
- package/src/kernel/hints/read_request.ts +1 -1
- package/src/kernel/log_hash.ts +5 -2
- package/src/kernel/note_hash.ts +1 -1
- package/src/kernel/nullifier.ts +1 -1
- package/src/kernel/private_log_data.ts +4 -1
- package/src/keys/derivation.ts +21 -8
- package/src/logs/app_tagging_secret.ts +39 -23
- package/src/logs/contract_class_log.ts +0 -9
- package/src/logs/message_context.ts +7 -65
- package/src/logs/pending_tagged_log.ts +6 -33
- package/src/tests/factories.ts +2 -2
- package/src/trees/nullifier_membership_witness.ts +0 -11
- package/src/trees/public_data_witness.ts +0 -31
- package/src/tx/execution_payload.ts +2 -1
- package/src/tx/global_variables.ts +2 -2
|
@@ -43,34 +43,64 @@ export class AztecAddress {
|
|
|
43
43
|
static ZERO = new AztecAddress(Buffer.alloc(32, 0));
|
|
44
44
|
|
|
45
45
|
/** Null msg sender address. Not part of the protocol contracts tree. */
|
|
46
|
-
static NULL_MSG_SENDER = AztecAddress.
|
|
46
|
+
static NULL_MSG_SENDER = AztecAddress.fromBigIntUnsafe(NULL_MSG_SENDER_CONTRACT_ADDRESS);
|
|
47
47
|
|
|
48
48
|
static zero(): AztecAddress {
|
|
49
49
|
return AztecAddress.ZERO;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Builds an `AztecAddress` from a field **without checking it is a valid address** (the x-coordinate of a point on
|
|
54
|
+
* the Grumpkin curve, which is what lets it be encrypted to). Use {@link AztecAddress.isValid} to validate an
|
|
55
|
+
* untrusted one, or {@link AztecAddress.random} for valid test addresses.
|
|
56
|
+
*/
|
|
57
|
+
static fromFieldUnsafe(fr: Fr) {
|
|
53
58
|
return new AztecAddress(fr);
|
|
54
59
|
}
|
|
55
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Deserializes an `AztecAddress` from a buffer. It does **not** check the value is a valid Grumpkin-curve address
|
|
63
|
+
* (see {@link AztecAddress.isValid}); it is meant for reading addresses from already-validated serialized data. Use
|
|
64
|
+
* {@link AztecAddress.random} for valid test addresses.
|
|
65
|
+
*/
|
|
56
66
|
static fromBuffer(buffer: Buffer | BufferReader) {
|
|
57
67
|
return new AztecAddress(fromBuffer(buffer, Fr));
|
|
58
68
|
}
|
|
59
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Deserializes an `AztecAddress` from a field reader. It does **not** check the value is a valid Grumpkin-curve
|
|
72
|
+
* address (see {@link AztecAddress.isValid}); it is meant for reading addresses from already-validated serialized
|
|
73
|
+
* data. Use {@link AztecAddress.random} for valid test addresses.
|
|
74
|
+
*/
|
|
60
75
|
static fromFields(fields: Fr[] | FieldReader) {
|
|
61
76
|
const reader = FieldReader.asReader(fields);
|
|
62
77
|
return new AztecAddress(reader.readField());
|
|
63
78
|
}
|
|
64
79
|
|
|
65
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Builds an `AztecAddress` from a bigint **without checking it is a valid address** (the x-coordinate of a point on
|
|
82
|
+
* the Grumpkin curve, which is what lets it be encrypted to). Use {@link AztecAddress.isValid} to validate an
|
|
83
|
+
* untrusted one, or {@link AztecAddress.random} for valid test addresses.
|
|
84
|
+
*/
|
|
85
|
+
static fromBigIntUnsafe(value: bigint) {
|
|
66
86
|
return new AztecAddress(new Fr(value));
|
|
67
87
|
}
|
|
68
88
|
|
|
69
|
-
|
|
89
|
+
/**
|
|
90
|
+
* Builds an `AztecAddress` from a number **without checking it is a valid address** (the x-coordinate of a point on
|
|
91
|
+
* the Grumpkin curve, which is what lets it be encrypted to). Use {@link AztecAddress.isValid} to validate an
|
|
92
|
+
* untrusted one, or {@link AztecAddress.random} for valid test addresses.
|
|
93
|
+
*/
|
|
94
|
+
static fromNumberUnsafe(value: number) {
|
|
70
95
|
return new AztecAddress(new Fr(value));
|
|
71
96
|
}
|
|
72
97
|
|
|
73
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Builds an `AztecAddress` from a hex string **without checking it is a valid address** (the x-coordinate of a
|
|
100
|
+
* point on the Grumpkin curve, which is what lets it be encrypted to). Use {@link AztecAddress.isValid} to
|
|
101
|
+
* validate an untrusted one, or {@link AztecAddress.random} for valid test addresses.
|
|
102
|
+
*/
|
|
103
|
+
static fromStringUnsafe(buf: string) {
|
|
74
104
|
return new AztecAddress(hexToBuffer(buf));
|
|
75
105
|
}
|
|
76
106
|
|
|
@@ -89,7 +119,7 @@ export class AztecAddress {
|
|
|
89
119
|
if (obj instanceof Buffer || Buffer.isBuffer(obj)) {
|
|
90
120
|
return new AztecAddress(obj);
|
|
91
121
|
}
|
|
92
|
-
return AztecAddress.
|
|
122
|
+
return AztecAddress.fromStringUnsafe(obj);
|
|
93
123
|
}
|
|
94
124
|
|
|
95
125
|
/**
|
|
@@ -25,11 +25,9 @@ export interface ContractDataSource {
|
|
|
25
25
|
/**
|
|
26
26
|
* Returns a publicly deployed contract instance given its address.
|
|
27
27
|
* @param address - Address of the deployed contract.
|
|
28
|
-
* @param timestamp - Timestamp at which to
|
|
29
|
-
* be used.
|
|
30
|
-
* TODO(#15170): Fix the implementations ignoring the timestamp param and make timestamp required.
|
|
28
|
+
* @param timestamp - Timestamp at which to resolve the contract instance's current class id.
|
|
31
29
|
*/
|
|
32
|
-
getContract(address: AztecAddress, timestamp
|
|
30
|
+
getContract(address: AztecAddress, timestamp: UInt64): Promise<ContractInstanceWithAddress | undefined>;
|
|
33
31
|
|
|
34
32
|
/**
|
|
35
33
|
* Returns the list of all class ids known.
|
|
@@ -122,7 +122,7 @@ export const ArchiverApiSchema: ApiSchemaFor<ArchiverApi> = {
|
|
|
122
122
|
getContractClass: z.function({ input: z.tuple([schemas.Fr]), output: ContractClassPublicSchema.optional() }),
|
|
123
123
|
getBytecodeCommitment: z.function({ input: z.tuple([schemas.Fr]), output: schemas.Fr }),
|
|
124
124
|
getContract: z.function({
|
|
125
|
-
input: z.tuple([schemas.AztecAddress,
|
|
125
|
+
input: z.tuple([schemas.AztecAddress, schemas.BigInt]),
|
|
126
126
|
output: ContractInstanceWithAddressSchema.optional(),
|
|
127
127
|
}),
|
|
128
128
|
getContractClassIds: z.function({ input: z.tuple([]), output: z.array(schemas.Fr) }),
|
|
@@ -522,10 +522,18 @@ export interface AztecNode {
|
|
|
522
522
|
getContractClass(id: Fr): Promise<ContractClassPublic | undefined>;
|
|
523
523
|
|
|
524
524
|
/**
|
|
525
|
-
* Returns a publicly deployed contract instance given its address.
|
|
525
|
+
* Returns a publicly deployed contract instance given its address. Its current class id is resolved as of the given
|
|
526
|
+
* reference block.
|
|
527
|
+
*
|
|
528
|
+
* Returns `undefined` if the instance has not been published (i.e. `publish_for_public_execution` was never called
|
|
529
|
+
* on the `ContractInstanceRegistry`). A contract whose class has been updated will never return `undefined`:
|
|
530
|
+
* scheduling an update requires the contract's deployment nullifier, which is only emitted by publishing, so any
|
|
531
|
+
* updatable contract has necessarily been published.
|
|
526
532
|
* @param address - Address of the deployed contract.
|
|
533
|
+
* @param referenceBlock - The block parameter (block number, block hash, or 'latest') at which to get the data.
|
|
534
|
+
* Defaults to 'latest'.
|
|
527
535
|
*/
|
|
528
|
-
getContract(address: AztecAddress): Promise<ContractInstanceWithAddress | undefined>;
|
|
536
|
+
getContract(address: AztecAddress, referenceBlock?: BlockParameter): Promise<ContractInstanceWithAddress | undefined>;
|
|
529
537
|
|
|
530
538
|
/**
|
|
531
539
|
* Returns the ENR of this node for peer discovery, if available.
|
|
@@ -758,7 +766,7 @@ export const AztecNodeApiSchema: ApiSchemaFor<AztecNode> = {
|
|
|
758
766
|
getContractClass: z.function({ input: z.tuple([schemas.Fr]), output: ContractClassPublicSchema.optional() }),
|
|
759
767
|
|
|
760
768
|
getContract: z.function({
|
|
761
|
-
input: z.tuple([schemas.AztecAddress]),
|
|
769
|
+
input: z.tuple([schemas.AztecAddress, optional(BlockParameterSchema)]),
|
|
762
770
|
output: ContractInstanceWithAddressSchema.optional(),
|
|
763
771
|
}),
|
|
764
772
|
|
|
@@ -112,7 +112,7 @@ export class ScopedReadRequest {
|
|
|
112
112
|
|
|
113
113
|
static fromFields(fields: Fr[] | FieldReader) {
|
|
114
114
|
const reader = FieldReader.asReader(fields);
|
|
115
|
-
return new ScopedReadRequest(reader.readObject(ReadRequest), AztecAddress.
|
|
115
|
+
return new ScopedReadRequest(reader.readObject(ReadRequest), AztecAddress.fromFieldUnsafe(reader.readField()));
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
/**
|
package/src/kernel/log_hash.ts
CHANGED
|
@@ -114,7 +114,7 @@ export class ScopedLogHash {
|
|
|
114
114
|
|
|
115
115
|
static fromFields(fields: Fr[] | FieldReader) {
|
|
116
116
|
const reader = FieldReader.asReader(fields);
|
|
117
|
-
return new ScopedLogHash(reader.readObject(LogHash), AztecAddress.
|
|
117
|
+
return new ScopedLogHash(reader.readObject(LogHash), AztecAddress.fromFieldUnsafe(reader.readField()));
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
isEmpty() {
|
|
@@ -156,7 +156,10 @@ export class ScopedCountedLogHash {
|
|
|
156
156
|
|
|
157
157
|
static fromFields(fields: Fr[] | FieldReader) {
|
|
158
158
|
const reader = FieldReader.asReader(fields);
|
|
159
|
-
return new ScopedCountedLogHash(
|
|
159
|
+
return new ScopedCountedLogHash(
|
|
160
|
+
reader.readObject(CountedLogHash),
|
|
161
|
+
AztecAddress.fromFieldUnsafe(reader.readField()),
|
|
162
|
+
);
|
|
160
163
|
}
|
|
161
164
|
|
|
162
165
|
toBuffer(): Buffer;
|
package/src/kernel/note_hash.ts
CHANGED
|
@@ -65,7 +65,7 @@ export class ScopedNoteHash implements Ordered {
|
|
|
65
65
|
|
|
66
66
|
static fromFields(fields: Fr[] | FieldReader) {
|
|
67
67
|
const reader = FieldReader.asReader(fields);
|
|
68
|
-
return new ScopedNoteHash(reader.readObject(NoteHash), AztecAddress.
|
|
68
|
+
return new ScopedNoteHash(reader.readObject(NoteHash), AztecAddress.fromFieldUnsafe(reader.readField()));
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
isEmpty() {
|
package/src/kernel/nullifier.ts
CHANGED
|
@@ -70,7 +70,7 @@ export class ScopedNullifier implements Ordered {
|
|
|
70
70
|
|
|
71
71
|
static fromFields(fields: Fr[] | FieldReader) {
|
|
72
72
|
const reader = FieldReader.asReader(fields);
|
|
73
|
-
return new ScopedNullifier(reader.readObject(Nullifier), AztecAddress.
|
|
73
|
+
return new ScopedNullifier(reader.readObject(Nullifier), AztecAddress.fromFieldUnsafe(reader.readField()));
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
isEmpty() {
|
|
@@ -85,7 +85,10 @@ export class ScopedPrivateLogData {
|
|
|
85
85
|
|
|
86
86
|
static fromFields(fields: Fr[] | FieldReader) {
|
|
87
87
|
const reader = FieldReader.asReader(fields);
|
|
88
|
-
return new ScopedPrivateLogData(
|
|
88
|
+
return new ScopedPrivateLogData(
|
|
89
|
+
reader.readObject(PrivateLogData),
|
|
90
|
+
AztecAddress.fromFieldUnsafe(reader.readField()),
|
|
91
|
+
);
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
isEmpty() {
|
package/src/keys/derivation.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DomainSeparator } from '@aztec/constants';
|
|
2
2
|
import { Grumpkin } from '@aztec/foundation/crypto/grumpkin';
|
|
3
3
|
import { poseidon2HashWithSeparator } from '@aztec/foundation/crypto/poseidon';
|
|
4
4
|
import { sha512ToGrumpkinScalar } from '@aztec/foundation/crypto/sha512';
|
|
@@ -39,6 +39,14 @@ export function deriveMasterOutgoingViewingSecretKey(secretKey: Fr): GrumpkinSca
|
|
|
39
39
|
return sha512ToGrumpkinScalar([secretKey, DomainSeparator.OVSK_M]);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
export function deriveMasterMessageSigningSecretKey(secretKey: Fr): GrumpkinScalar {
|
|
43
|
+
return sha512ToGrumpkinScalar([secretKey, DomainSeparator.MSSK_M]);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function deriveMasterFallbackSecretKey(secretKey: Fr): GrumpkinScalar {
|
|
47
|
+
return sha512ToGrumpkinScalar([secretKey, DomainSeparator.FBSK_M]);
|
|
48
|
+
}
|
|
49
|
+
|
|
42
50
|
export function deriveSigningKey(secretKey: Fr): GrumpkinScalar {
|
|
43
51
|
// TODO(#5837): come up with a standard signing key derivation scheme instead of using ivsk_m as signing keys here
|
|
44
52
|
return sha512ToGrumpkinScalar([secretKey, DomainSeparator.IVSK_M]);
|
|
@@ -100,27 +108,28 @@ export async function deriveKeys(secretKey: Fr) {
|
|
|
100
108
|
const masterIncomingViewingSecretKey = deriveMasterIncomingViewingSecretKey(secretKey);
|
|
101
109
|
const masterOutgoingViewingSecretKey = deriveMasterOutgoingViewingSecretKey(secretKey);
|
|
102
110
|
const masterTaggingSecretKey = sha512ToGrumpkinScalar([secretKey, DomainSeparator.TSK_M]);
|
|
111
|
+
const masterMessageSigningSecretKey = deriveMasterMessageSigningSecretKey(secretKey);
|
|
112
|
+
const masterFallbackSecretKey = deriveMasterFallbackSecretKey(secretKey);
|
|
103
113
|
|
|
104
114
|
// Then we derive master public keys
|
|
105
115
|
const masterNullifierPublicKey = await derivePublicKeyFromSecretKey(masterNullifierHidingKey);
|
|
106
116
|
const masterIncomingViewingPublicKey = await derivePublicKeyFromSecretKey(masterIncomingViewingSecretKey);
|
|
107
117
|
const masterOutgoingViewingPublicKey = await derivePublicKeyFromSecretKey(masterOutgoingViewingSecretKey);
|
|
108
118
|
const masterTaggingPublicKey = await derivePublicKeyFromSecretKey(masterTaggingSecretKey);
|
|
119
|
+
const masterMessageSigningPublicKey = await derivePublicKeyFromSecretKey(masterMessageSigningSecretKey);
|
|
120
|
+
const masterFallbackPublicKey = await derivePublicKeyFromSecretKey(masterFallbackSecretKey);
|
|
109
121
|
|
|
110
122
|
// The non-owner-visible PublicKeys carries hashes for npk/ovpk/tpk/mspk/fbpk and the raw
|
|
111
|
-
// point only for ivpk_m. The npk/ovpk/tpk raw points are also returned alongside so the key
|
|
112
|
-
// store can persist them under `${account}-{n|ov|t}pk_m` (only their hashes live in publicKeys).
|
|
123
|
+
// point only for ivpk_m. The npk/ovpk/tpk/mspk/fbpk raw points are also returned alongside so the key
|
|
124
|
+
// store can persist them under `${account}-{n|ov|t|ms|fb}pk_m` (only their hashes live in publicKeys).
|
|
113
125
|
// The ivpk_m point isn't returned separately because it already lives in publicKeys.ivpkM.
|
|
114
|
-
//
|
|
115
|
-
// TODO: There isn't a derivation path for the message signing(msk) and fallback(fbk) keys yet. So we just use the the
|
|
116
|
-
// default values for now.
|
|
117
126
|
const publicKeys = new PublicKeys(
|
|
118
127
|
await hashPublicKey(masterNullifierPublicKey),
|
|
119
128
|
masterIncomingViewingPublicKey,
|
|
120
129
|
await hashPublicKey(masterOutgoingViewingPublicKey),
|
|
121
130
|
await hashPublicKey(masterTaggingPublicKey),
|
|
122
|
-
|
|
123
|
-
|
|
131
|
+
await hashPublicKey(masterMessageSigningPublicKey),
|
|
132
|
+
await hashPublicKey(masterFallbackPublicKey),
|
|
124
133
|
);
|
|
125
134
|
|
|
126
135
|
return {
|
|
@@ -128,9 +137,13 @@ export async function deriveKeys(secretKey: Fr) {
|
|
|
128
137
|
masterIncomingViewingSecretKey,
|
|
129
138
|
masterOutgoingViewingSecretKey,
|
|
130
139
|
masterTaggingSecretKey,
|
|
140
|
+
masterMessageSigningSecretKey,
|
|
141
|
+
masterFallbackSecretKey,
|
|
131
142
|
masterNullifierPublicKey,
|
|
132
143
|
masterOutgoingViewingPublicKey,
|
|
133
144
|
masterTaggingPublicKey,
|
|
145
|
+
masterMessageSigningPublicKey,
|
|
146
|
+
masterFallbackPublicKey,
|
|
134
147
|
publicKeys,
|
|
135
148
|
};
|
|
136
149
|
}
|
|
@@ -30,16 +30,33 @@ export class AppTaggingSecret {
|
|
|
30
30
|
) {}
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* Derives
|
|
34
|
-
* secret. Returns undefined if `externalAddress` is an invalid address.
|
|
33
|
+
* Derives an app-siloed, recipient-directional tagging secret from a shared tagging secret point.
|
|
35
34
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
35
|
+
* The point is obtained either via {@link computeSharedTaggingSecret} (an ECDH key exchange against a sender) or
|
|
36
|
+
* registered directly as a pre-shared secret. Each secret point yields a distinct tagging secret per (app, recipient)
|
|
37
|
+
* pair.
|
|
38
|
+
*
|
|
39
|
+
* @param taggingSecretPoint - The shared tagging secret point (ECDH output, or a directly registered pre-shared secret)
|
|
39
40
|
* @param app - Contract address to silo the secret to
|
|
40
41
|
* @param recipient - Recipient of the log. Defines the "direction of the secret".
|
|
41
42
|
* @returns The secret that can be used along with an index to compute a tag to be included in a log.
|
|
42
43
|
*/
|
|
44
|
+
static async compute(
|
|
45
|
+
taggingSecretPoint: Point,
|
|
46
|
+
app: AztecAddress,
|
|
47
|
+
recipient: AztecAddress,
|
|
48
|
+
): Promise<AppTaggingSecret> {
|
|
49
|
+
const appTaggingSecret = await poseidon2Hash([taggingSecretPoint.x, taggingSecretPoint.y, app]);
|
|
50
|
+
const directionalAppTaggingSecret = await poseidon2Hash([appTaggingSecret, recipient]);
|
|
51
|
+
|
|
52
|
+
return new AppTaggingSecret(directionalAppTaggingSecret, app);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Derives the unconstrained tagging secret for `(externalAddress, recipient, app)` by performing the ECDH key
|
|
57
|
+
* exchange against `externalAddress` and then siloing and directing the result. Returns undefined if
|
|
58
|
+
* `externalAddress` is not a valid address.
|
|
59
|
+
*/
|
|
43
60
|
static async computeUnconstrained(
|
|
44
61
|
localAddress: CompleteAddress,
|
|
45
62
|
localIvsk: Fq,
|
|
@@ -52,10 +69,7 @@ export class AppTaggingSecret {
|
|
|
52
69
|
return undefined;
|
|
53
70
|
}
|
|
54
71
|
|
|
55
|
-
|
|
56
|
-
const directionalAppTaggingSecret = await poseidon2Hash([appTaggingSecret, recipient]);
|
|
57
|
-
|
|
58
|
-
return new AppTaggingSecret(directionalAppTaggingSecret, app);
|
|
72
|
+
return AppTaggingSecret.compute(taggingSecretPoint, app, recipient);
|
|
59
73
|
}
|
|
60
74
|
|
|
61
75
|
toString(): string {
|
|
@@ -71,13 +85,13 @@ export class AppTaggingSecret {
|
|
|
71
85
|
if (parts.length === 2) {
|
|
72
86
|
// TODO(F-680): Remove legacy two-part parsing after stored tagging keys are migrated.
|
|
73
87
|
const [secretStr, appStr] = parts;
|
|
74
|
-
return new AppTaggingSecret(Fr.fromString(secretStr), AztecAddress.
|
|
88
|
+
return new AppTaggingSecret(Fr.fromString(secretStr), AztecAddress.fromStringUnsafe(appStr));
|
|
75
89
|
}
|
|
76
90
|
if (parts.length === 3) {
|
|
77
91
|
const [kindStr, secretStr, appStr] = parts;
|
|
78
92
|
return new AppTaggingSecret(
|
|
79
93
|
Fr.fromString(secretStr),
|
|
80
|
-
AztecAddress.
|
|
94
|
+
AztecAddress.fromStringUnsafe(appStr),
|
|
81
95
|
appTaggingSecretKindFromString(kindStr),
|
|
82
96
|
);
|
|
83
97
|
}
|
|
@@ -111,18 +125,17 @@ function appTaggingSecretKindFromString(kind: string): AppTaggingSecretKind {
|
|
|
111
125
|
}
|
|
112
126
|
}
|
|
113
127
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Computes the shared tagging secret point between a local address (i.e. one for which the privacy keys are known) and
|
|
130
|
+
* an external one via a Diffie-Hellman key exchange.
|
|
131
|
+
*
|
|
132
|
+
* Returns undefined if `externalAddress` is an invalid address.
|
|
133
|
+
*/
|
|
134
|
+
export async function computeSharedTaggingSecret(
|
|
117
135
|
localAddress: CompleteAddress,
|
|
118
136
|
localIvsk: Fq,
|
|
119
137
|
externalAddress: AztecAddress,
|
|
120
138
|
): Promise<Point | undefined> {
|
|
121
|
-
// Given A (local complete address) -> B (external address) and h == preaddress
|
|
122
|
-
// Compute shared secret as S = (h_A + local_ivsk_A) * Addr_Point_B
|
|
123
|
-
|
|
124
|
-
const knownPreaddress = await computePreaddress(await localAddress.publicKeys.hash(), localAddress.partialAddress);
|
|
125
|
-
|
|
126
139
|
// An invalid address has no corresponding address point
|
|
127
140
|
if (!(await externalAddress.isValid())) {
|
|
128
141
|
return undefined;
|
|
@@ -130,8 +143,11 @@ async function computeSharedTaggingSecret(
|
|
|
130
143
|
|
|
131
144
|
const externalAddressPoint = await externalAddress.toAddressPoint();
|
|
132
145
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
146
|
+
const localPreaddress = await computePreaddress(await localAddress.publicKeys.hash(), localAddress.partialAddress);
|
|
147
|
+
const localAddressSecret = await computeAddressSecret(localPreaddress, localIvsk);
|
|
148
|
+
|
|
149
|
+
// For a given local address A and external address B, the shared tagging secret S is (h_A + ivsk_A) * Addr_Point_B
|
|
150
|
+
// (conceptually, in reality we don't use h_A + ivsk_A directly but rather the actual address secret, which is the
|
|
151
|
+
// same but with an optional sign adjustment to prevent A's address point from having a negative y-coordinate).
|
|
152
|
+
return Grumpkin.mul(externalAddressPoint, localAddressSecret);
|
|
137
153
|
}
|
|
@@ -138,15 +138,6 @@ export class ContractClassLog {
|
|
|
138
138
|
);
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
static fromFields(fields: Fr[] | FieldReader) {
|
|
142
|
-
const reader = FieldReader.asReader(fields);
|
|
143
|
-
return new ContractClassLog(
|
|
144
|
-
reader.readObject(AztecAddress),
|
|
145
|
-
reader.readObject(ContractClassLogFields),
|
|
146
|
-
reader.readU32(),
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
141
|
getEmittedFields() {
|
|
151
142
|
return this.fields.getEmittedFields(this.emittedLength);
|
|
152
143
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { range } from '@aztec/foundation/array';
|
|
3
|
-
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
1
|
+
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
2
|
|
|
5
|
-
import { TxHash } from '../tx/tx_hash.js';
|
|
3
|
+
import type { TxHash } from '../tx/tx_hash.js';
|
|
6
4
|
|
|
7
5
|
/**
|
|
8
6
|
* Additional information needed to process a message.
|
|
@@ -13,64 +11,8 @@ import { TxHash } from '../tx/tx_hash.js';
|
|
|
13
11
|
*
|
|
14
12
|
* A TS version of `message_context.nr`.
|
|
15
13
|
*/
|
|
16
|
-
export
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
) {}
|
|
22
|
-
|
|
23
|
-
toFields(): Fr[] {
|
|
24
|
-
return [
|
|
25
|
-
this.txHash.hash,
|
|
26
|
-
...serializeBoundedVec(this.uniqueNoteHashesInTx, MAX_NOTE_HASHES_PER_TX),
|
|
27
|
-
this.firstNullifierInTx,
|
|
28
|
-
];
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
toNoirStruct() {
|
|
32
|
-
/* eslint-disable camelcase */
|
|
33
|
-
return {
|
|
34
|
-
tx_hash: this.txHash.hash,
|
|
35
|
-
unique_note_hashes_in_tx: this.uniqueNoteHashesInTx,
|
|
36
|
-
first_nullifier_in_tx: this.firstNullifierInTx,
|
|
37
|
-
};
|
|
38
|
-
/* eslint-enable camelcase */
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
static empty(): MessageContext {
|
|
42
|
-
return new MessageContext(TxHash.zero(), [], Fr.ZERO);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
static toEmptyFields(): Fr[] {
|
|
46
|
-
const serializationLen =
|
|
47
|
-
1 /* txHash */ + MAX_NOTE_HASHES_PER_TX + 1 /* uniqueNoteHashesInTx BVec */ + 1; /* firstNullifierInTx */
|
|
48
|
-
return range(serializationLen).map(_ => Fr.zero());
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
static toSerializedOption(response: MessageContext | null): Fr[] {
|
|
52
|
-
if (response) {
|
|
53
|
-
return [new Fr(1), ...response.toFields()];
|
|
54
|
-
} else {
|
|
55
|
-
return [new Fr(0), ...MessageContext.toEmptyFields()];
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Helper function to serialize a bounded vector according to Noir's BoundedVec format
|
|
62
|
-
* @param values - The values to serialize
|
|
63
|
-
* @param maxLength - The maximum length of the bounded vector
|
|
64
|
-
* @returns The serialized bounded vector as Fr[]
|
|
65
|
-
* @dev Copied over from pending_tagged_log.ts.
|
|
66
|
-
*/
|
|
67
|
-
function serializeBoundedVec(values: Fr[], maxLength: number): Fr[] {
|
|
68
|
-
if (values.length > maxLength) {
|
|
69
|
-
throw new Error(`Attempted to serialize ${values} values into a BoundedVec with max length ${maxLength}`);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const lengthDiff = maxLength - values.length;
|
|
73
|
-
const zeroPaddingArray = Array(lengthDiff).fill(Fr.ZERO);
|
|
74
|
-
const storage = values.concat(zeroPaddingArray);
|
|
75
|
-
return [...storage, new Fr(values.length)];
|
|
76
|
-
}
|
|
14
|
+
export type MessageContext = {
|
|
15
|
+
txHash: TxHash;
|
|
16
|
+
uniqueNoteHashesInTx: Fr[];
|
|
17
|
+
firstNullifierInTx: Fr;
|
|
18
|
+
};
|
|
@@ -1,39 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
1
|
+
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
2
|
|
|
4
|
-
import type {
|
|
5
|
-
import { MessageContext } from './message_context.js';
|
|
3
|
+
import type { MessageContext } from './message_context.js';
|
|
6
4
|
|
|
7
5
|
/**
|
|
8
6
|
* Represents a pending tagged log as it is stored in the pending tagged log array to which the fetchTaggedLogs oracle
|
|
9
7
|
* inserts found private logs. A TS version of `pending_tagged_log.nr`.
|
|
10
8
|
*/
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
public log: Fr[],
|
|
16
|
-
txHash: TxHash,
|
|
17
|
-
uniqueNoteHashesInTx: Fr[],
|
|
18
|
-
firstNullifierInTx: Fr,
|
|
19
|
-
) {
|
|
20
|
-
this.context = new MessageContext(txHash, uniqueNoteHashesInTx, firstNullifierInTx);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
toFields(): Fr[] {
|
|
24
|
-
return [...serializeBoundedVec(this.log, PRIVATE_LOG_SIZE_IN_FIELDS), ...this.context.toFields()];
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Helper function to serialize a bounded vector according to Noir's BoundedVec format
|
|
30
|
-
* @param values - The values to serialize
|
|
31
|
-
* @param maxLength - The maximum length of the bounded vector
|
|
32
|
-
* @returns The serialized bounded vector as Fr[]
|
|
33
|
-
*/
|
|
34
|
-
function serializeBoundedVec(values: Fr[], maxLength: number): Fr[] {
|
|
35
|
-
const lengthDiff = maxLength - values.length;
|
|
36
|
-
const zeroPaddingArray = Array(lengthDiff).fill(Fr.ZERO);
|
|
37
|
-
const storage = values.concat(zeroPaddingArray);
|
|
38
|
-
return [...storage, new Fr(values.length)];
|
|
39
|
-
}
|
|
9
|
+
export type PendingTaggedLog = {
|
|
10
|
+
log: Fr[];
|
|
11
|
+
context: MessageContext;
|
|
12
|
+
};
|
package/src/tests/factories.ts
CHANGED
|
@@ -703,7 +703,7 @@ export function makeGlobalVariables(seed = 1, overrides: Partial<FieldsOf<Global
|
|
|
703
703
|
slotNumber: SlotNumber(seed + 3),
|
|
704
704
|
timestamp: BigInt(seed + 4),
|
|
705
705
|
coinbase: EthAddress.fromField(new Fr(seed + 5)),
|
|
706
|
-
feeRecipient: AztecAddress.
|
|
706
|
+
feeRecipient: AztecAddress.fromFieldUnsafe(new Fr(seed + 6)),
|
|
707
707
|
gasFees: new GasFees(seed + 7, seed + 8),
|
|
708
708
|
...compact(overrides),
|
|
709
709
|
});
|
|
@@ -753,7 +753,7 @@ export function makeBytes(size = 32, fill = 1): Buffer {
|
|
|
753
753
|
* @returns An aztec address.
|
|
754
754
|
*/
|
|
755
755
|
export function makeAztecAddress(seed = 1): AztecAddress {
|
|
756
|
-
return AztecAddress.
|
|
756
|
+
return AztecAddress.fromFieldUnsafe(fr(seed));
|
|
757
757
|
}
|
|
758
758
|
|
|
759
759
|
function makeBlockConstantData(seed = 1, globalVariables?: GlobalVariables) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { NULLIFIER_TREE_HEIGHT } from '@aztec/constants';
|
|
2
|
-
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
2
|
import { MembershipWitness, SiblingPath } from '@aztec/foundation/trees';
|
|
4
3
|
|
|
5
4
|
import { z } from 'zod';
|
|
@@ -52,14 +51,4 @@ export class NullifierMembershipWitness {
|
|
|
52
51
|
public withoutPreimage(): MembershipWitness<typeof NULLIFIER_TREE_HEIGHT> {
|
|
53
52
|
return new MembershipWitness(NULLIFIER_TREE_HEIGHT, this.index, this.siblingPath.toTuple());
|
|
54
53
|
}
|
|
55
|
-
|
|
56
|
-
/** Serializes as `(NullifierLeafPreimage, MembershipWitness)` to match the Noir oracle return type. */
|
|
57
|
-
public toNoirRepresentation(): (string | string[])[] {
|
|
58
|
-
// TODO(#12874): remove the stupid as string conversion by modifying ForeignCallOutput type in acvm.js
|
|
59
|
-
return [
|
|
60
|
-
...(this.leafPreimage.toFields().map(fr => fr.toString()) as string[]),
|
|
61
|
-
new Fr(this.index).toString() as string,
|
|
62
|
-
this.siblingPath.toFields().map(fr => fr.toString()) as string[],
|
|
63
|
-
];
|
|
64
|
-
}
|
|
65
54
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { PUBLIC_DATA_TREE_HEIGHT } from '@aztec/constants';
|
|
2
2
|
import { toBigIntBE } from '@aztec/foundation/bigint-buffer';
|
|
3
|
-
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
3
|
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
5
4
|
import { bufferToHex, hexToBuffer } from '@aztec/foundation/string';
|
|
6
5
|
import { MembershipWitness, SiblingPath } from '@aztec/foundation/trees';
|
|
@@ -43,36 +42,6 @@ export class PublicDataWitness {
|
|
|
43
42
|
.transform(({ index, leafPreimage, siblingPath }) => new PublicDataWitness(index, leafPreimage, siblingPath));
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
/**
|
|
47
|
-
* Returns a field array representation of a public data witness.
|
|
48
|
-
* @returns A field array representation of a public data witness.
|
|
49
|
-
*/
|
|
50
|
-
public toFields(): Fr[] {
|
|
51
|
-
return [
|
|
52
|
-
new Fr(this.index),
|
|
53
|
-
new Fr(this.leafPreimage.leaf.slot),
|
|
54
|
-
new Fr(this.leafPreimage.leaf.value),
|
|
55
|
-
new Fr(this.leafPreimage.nextIndex),
|
|
56
|
-
new Fr(this.leafPreimage.nextKey),
|
|
57
|
-
...this.siblingPath.toFields(),
|
|
58
|
-
];
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Returns a representation of the public data witness as expected by intrinsic Noir deserialization.
|
|
63
|
-
*/
|
|
64
|
-
public toNoirRepresentation(): (string | string[])[] {
|
|
65
|
-
// TODO(#12874): remove the stupid as string conversion by modifying ForeignCallOutput type in acvm.js
|
|
66
|
-
return [
|
|
67
|
-
new Fr(this.index).toString() as string,
|
|
68
|
-
new Fr(this.leafPreimage.leaf.slot).toString() as string,
|
|
69
|
-
new Fr(this.leafPreimage.leaf.value).toString() as string,
|
|
70
|
-
new Fr(this.leafPreimage.nextKey).toString() as string,
|
|
71
|
-
new Fr(this.leafPreimage.nextIndex).toString() as string,
|
|
72
|
-
this.siblingPath.toFields().map(fr => fr.toString()) as string[],
|
|
73
|
-
];
|
|
74
|
-
}
|
|
75
|
-
|
|
76
45
|
toBuffer(): Buffer {
|
|
77
46
|
return serializeToBuffer([this.index, this.leafPreimage, this.siblingPath]);
|
|
78
47
|
}
|
|
@@ -54,7 +54,8 @@ export function mergeExecutionPayloads(requests: ExecutionPayload[]): ExecutionP
|
|
|
54
54
|
);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
const feePayer =
|
|
57
|
+
const feePayer =
|
|
58
|
+
uniqueFeePayers.size === 1 ? AztecAddress.fromStringUnsafe(Array.from(uniqueFeePayers)[0]) : undefined;
|
|
58
59
|
|
|
59
60
|
return new ExecutionPayload(calls, combinedAuthWitnesses, combinedCapsules, combinedExtraHashedArgs, feePayer);
|
|
60
61
|
}
|
|
@@ -125,7 +125,7 @@ export class GlobalVariables {
|
|
|
125
125
|
SlotNumber(reader.readU32()),
|
|
126
126
|
reader.readField().toBigInt(),
|
|
127
127
|
EthAddress.fromField(reader.readField()),
|
|
128
|
-
AztecAddress.
|
|
128
|
+
AztecAddress.fromFieldUnsafe(reader.readField()),
|
|
129
129
|
GasFees.fromFields(reader),
|
|
130
130
|
);
|
|
131
131
|
}
|
|
@@ -220,7 +220,7 @@ export class GlobalVariables {
|
|
|
220
220
|
blockNumber: BlockNumber(randomInt(100_000)),
|
|
221
221
|
slotNumber: SlotNumber(randomInt(100_000)),
|
|
222
222
|
coinbase: EthAddress.random(),
|
|
223
|
-
feeRecipient: AztecAddress.
|
|
223
|
+
feeRecipient: AztecAddress.fromFieldUnsafe(Fr.random()),
|
|
224
224
|
gasFees: GasFees.random(),
|
|
225
225
|
timestamp: BigInt(randomInt(100_000_000)),
|
|
226
226
|
...overrides,
|