@aztec/stdlib 5.0.0-nightly.20260521 → 5.0.0-nightly.20260522
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.d.ts +33 -26
- package/dest/avm/avm.d.ts.map +1 -1
- package/dest/avm/avm.js +6 -3
- package/dest/avm/avm_proving_request.d.ts +11 -9
- package/dest/avm/avm_proving_request.d.ts.map +1 -1
- package/dest/contract/complete_address.d.ts +2 -1
- package/dest/contract/complete_address.d.ts.map +1 -1
- package/dest/contract/complete_address.js +6 -2
- package/dest/contract/contract_address.d.ts +5 -5
- package/dest/contract/contract_address.d.ts.map +1 -1
- package/dest/contract/contract_address.js +4 -3
- package/dest/contract/contract_instance.d.ts +4 -2
- package/dest/contract/contract_instance.d.ts.map +1 -1
- package/dest/contract/contract_instance.js +10 -3
- package/dest/contract/interfaces/contract_instance.d.ts +24 -20
- package/dest/contract/interfaces/contract_instance.d.ts.map +1 -1
- package/dest/contract/interfaces/contract_instance.js +4 -2
- package/dest/interfaces/proving-job.d.ts +11 -9
- package/dest/interfaces/proving-job.d.ts.map +1 -1
- package/dest/kernel/hints/key_validation_request.d.ts +12 -8
- package/dest/kernel/hints/key_validation_request.d.ts.map +1 -1
- package/dest/kernel/hints/key_validation_request.js +20 -18
- package/dest/keys/derivation.d.ts +4 -1
- package/dest/keys/derivation.d.ts.map +1 -1
- package/dest/keys/derivation.js +12 -5
- package/dest/keys/public_key.d.ts +8 -1
- package/dest/keys/public_key.d.ts.map +1 -1
- package/dest/keys/public_key.js +12 -1
- package/dest/keys/public_keys.d.ts +47 -73
- package/dest/keys/public_keys.d.ts.map +1 -1
- package/dest/keys/public_keys.js +96 -79
- package/dest/tests/factories.d.ts +2 -1
- package/dest/tests/factories.d.ts.map +1 -1
- package/dest/tests/factories.js +9 -5
- package/dest/tx/simulated_tx.d.ts +17 -13
- package/dest/tx/simulated_tx.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/avm/avm.ts +5 -0
- package/src/contract/complete_address.ts +7 -3
- package/src/contract/contract_address.ts +5 -5
- package/src/contract/contract_instance.ts +11 -2
- package/src/contract/interfaces/contract_instance.ts +6 -2
- package/src/kernel/hints/key_validation_request.ts +18 -16
- package/src/keys/derivation.ts +14 -7
- package/src/keys/public_key.ts +12 -0
- package/src/keys/public_keys.ts +101 -118
- package/src/tests/factories.ts +18 -8
package/src/keys/public_keys.ts
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DEFAULT_IVPK_M_X,
|
|
3
3
|
DEFAULT_IVPK_M_Y,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
DEFAULT_OVPK_M_Y,
|
|
8
|
-
DEFAULT_TPK_M_X,
|
|
9
|
-
DEFAULT_TPK_M_Y,
|
|
4
|
+
DEFAULT_NPK_M_HASH,
|
|
5
|
+
DEFAULT_OVPK_M_HASH,
|
|
6
|
+
DEFAULT_TPK_M_HASH,
|
|
10
7
|
DomainSeparator,
|
|
11
8
|
} from '@aztec/constants';
|
|
12
9
|
import { poseidon2HashWithSeparator } from '@aztec/foundation/crypto/poseidon';
|
|
@@ -19,189 +16,175 @@ import type { FieldsOf } from '@aztec/foundation/types';
|
|
|
19
16
|
|
|
20
17
|
import { z } from 'zod';
|
|
21
18
|
|
|
22
|
-
import type
|
|
19
|
+
import { type PublicKey, hashPublicKey } from './public_key.js';
|
|
23
20
|
|
|
21
|
+
/**
|
|
22
|
+
* A non-owner's view of an account's master public keys.
|
|
23
|
+
*
|
|
24
|
+
* Only `ivpkM` is exposed as a point (since address derivation needs the curve
|
|
25
|
+
* point in-circuit); the other three keys are exposed as their `hashPublicKey` digests.
|
|
26
|
+
*/
|
|
24
27
|
export class PublicKeys {
|
|
25
28
|
public constructor(
|
|
26
|
-
/**
|
|
27
|
-
public
|
|
29
|
+
/** Hash of the master nullifier public key */
|
|
30
|
+
public npkMHash: Fr,
|
|
28
31
|
/** Master incoming viewing public key */
|
|
29
|
-
public
|
|
30
|
-
/**
|
|
31
|
-
public
|
|
32
|
-
/**
|
|
33
|
-
public
|
|
32
|
+
public ivpkM: PublicKey,
|
|
33
|
+
/** Hash of the master outgoing viewing public key */
|
|
34
|
+
public ovpkMHash: Fr,
|
|
35
|
+
/** Hash of the master tagging public key */
|
|
36
|
+
public tpkMHash: Fr,
|
|
34
37
|
) {}
|
|
35
38
|
|
|
36
39
|
static get schema() {
|
|
37
40
|
return z
|
|
38
41
|
.object({
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
npkMHash: schemas.Fr,
|
|
43
|
+
ivpkM: schemas.Point,
|
|
44
|
+
ovpkMHash: schemas.Fr,
|
|
45
|
+
tpkMHash: schemas.Fr,
|
|
43
46
|
})
|
|
44
47
|
.transform(PublicKeys.from);
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
static from(fields: FieldsOf<PublicKeys>) {
|
|
48
|
-
return new PublicKeys(
|
|
49
|
-
fields.masterNullifierPublicKey,
|
|
50
|
-
fields.masterIncomingViewingPublicKey,
|
|
51
|
-
fields.masterOutgoingViewingPublicKey,
|
|
52
|
-
fields.masterTaggingPublicKey,
|
|
53
|
-
);
|
|
51
|
+
return new PublicKeys(fields.npkMHash, fields.ivpkM, fields.ovpkMHash, fields.tpkMHash);
|
|
54
52
|
}
|
|
55
53
|
|
|
56
54
|
/**
|
|
57
55
|
* Creates a PublicKeys from a plain object without Zod validation.
|
|
58
|
-
*
|
|
59
|
-
* for deserializing trusted data (e.g., from C++ via MessagePack).
|
|
60
|
-
* @param obj - Plain object containing PublicKeys fields
|
|
61
|
-
* @returns A PublicKeys instance
|
|
56
|
+
* Suitable for deserializing trusted data (e.g., from C++ via MessagePack).
|
|
62
57
|
*/
|
|
63
58
|
static fromPlainObject(obj: any): PublicKeys {
|
|
64
59
|
if (obj instanceof PublicKeys) {
|
|
65
60
|
return obj;
|
|
66
61
|
}
|
|
67
62
|
return new PublicKeys(
|
|
68
|
-
|
|
69
|
-
Point.fromPlainObject(obj.
|
|
70
|
-
|
|
71
|
-
|
|
63
|
+
Fr.fromPlainObject(obj.npkMHash),
|
|
64
|
+
Point.fromPlainObject(obj.ivpkM),
|
|
65
|
+
Fr.fromPlainObject(obj.ovpkMHash),
|
|
66
|
+
Fr.fromPlainObject(obj.tpkMHash),
|
|
72
67
|
);
|
|
73
68
|
}
|
|
74
69
|
|
|
75
|
-
hash() {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
70
|
+
async hash() {
|
|
71
|
+
if (this.isEmpty()) {
|
|
72
|
+
return Fr.ZERO;
|
|
73
|
+
}
|
|
74
|
+
// Mirror Noir's `PublicKeys::hash`: hash the four single-key digests under
|
|
75
|
+
// DOM_SEP__PUBLIC_KEYS_HASH. `ivpk_m` must be reduced to its single-key digest first
|
|
76
|
+
// (Poseidon2 over [x, y]); passing the Point directly would inadvertently include
|
|
77
|
+
// `is_infinite` and produce a different value.
|
|
78
|
+
const ivpkMHash = await hashPublicKey(this.ivpkM);
|
|
79
|
+
return poseidon2HashWithSeparator(
|
|
80
|
+
[this.npkMHash, ivpkMHash, this.ovpkMHash, this.tpkMHash],
|
|
81
|
+
DomainSeparator.PUBLIC_KEYS_HASH,
|
|
82
|
+
);
|
|
87
83
|
}
|
|
88
84
|
|
|
89
85
|
isEmpty() {
|
|
90
|
-
return (
|
|
91
|
-
this.masterNullifierPublicKey.isZero() &&
|
|
92
|
-
this.masterIncomingViewingPublicKey.isZero() &&
|
|
93
|
-
this.masterOutgoingViewingPublicKey.isZero() &&
|
|
94
|
-
this.masterTaggingPublicKey.isZero()
|
|
95
|
-
);
|
|
86
|
+
return this.npkMHash.isZero() && this.ivpkM.isZero() && this.ovpkMHash.isZero() && this.tpkMHash.isZero();
|
|
96
87
|
}
|
|
97
88
|
|
|
98
89
|
static default(): PublicKeys {
|
|
90
|
+
// Precomputed `hash_public_key(Point { DEFAULT_*_X, DEFAULT_*_Y, false })` for npk/ovpk/tpk.
|
|
91
|
+
// Sourced from constants.gen.ts (originally defined in
|
|
92
|
+
// noir-protocol-circuits/crates/types/src/constants.nr); a self-test in public_keys.nr
|
|
93
|
+
// (`default_hashes_match_default_points`) catches drift between the *_HASH constants and
|
|
94
|
+
// the underlying X/Y points.
|
|
99
95
|
return new PublicKeys(
|
|
100
|
-
new
|
|
96
|
+
new Fr(DEFAULT_NPK_M_HASH),
|
|
101
97
|
new Point(new Fr(DEFAULT_IVPK_M_X), new Fr(DEFAULT_IVPK_M_Y), false),
|
|
102
|
-
new
|
|
103
|
-
new
|
|
98
|
+
new Fr(DEFAULT_OVPK_M_HASH),
|
|
99
|
+
new Fr(DEFAULT_TPK_M_HASH),
|
|
104
100
|
);
|
|
105
101
|
}
|
|
106
102
|
|
|
107
103
|
static async random(): Promise<PublicKeys> {
|
|
108
|
-
|
|
104
|
+
const npkM = await Point.random();
|
|
105
|
+
const ovpkM = await Point.random();
|
|
106
|
+
const tpkM = await Point.random();
|
|
107
|
+
return new PublicKeys(
|
|
108
|
+
await hashPublicKey(npkM),
|
|
109
|
+
await Point.random(),
|
|
110
|
+
await hashPublicKey(ovpkM),
|
|
111
|
+
await hashPublicKey(tpkM),
|
|
112
|
+
);
|
|
109
113
|
}
|
|
110
114
|
|
|
111
|
-
/**
|
|
112
|
-
* Determines if this PublicKeys instance is equal to the given PublicKeys instance.
|
|
113
|
-
* Equality is based on the content of their respective buffers.
|
|
114
|
-
*
|
|
115
|
-
* @param other - The PublicKeys instance to compare against.
|
|
116
|
-
* @returns True if the buffers of both instances are equal, false otherwise.
|
|
117
|
-
*/
|
|
118
115
|
equals(other: PublicKeys): boolean {
|
|
119
116
|
return (
|
|
120
|
-
this.
|
|
121
|
-
this.
|
|
122
|
-
this.
|
|
123
|
-
this.
|
|
117
|
+
this.npkMHash.equals(other.npkMHash) &&
|
|
118
|
+
this.ivpkM.equals(other.ivpkM) &&
|
|
119
|
+
this.ovpkMHash.equals(other.ovpkMHash) &&
|
|
120
|
+
this.tpkMHash.equals(other.tpkMHash)
|
|
124
121
|
);
|
|
125
122
|
}
|
|
126
123
|
|
|
127
|
-
/**
|
|
128
|
-
* Converts the PublicKeys instance into a Buffer.
|
|
129
|
-
* This method should be used when encoding the address for storage, transmission or serialization purposes.
|
|
130
|
-
*
|
|
131
|
-
* @returns A Buffer representation of the PublicKeys instance.
|
|
132
|
-
*/
|
|
133
124
|
toBuffer(): Buffer {
|
|
134
|
-
return serializeToBuffer([
|
|
135
|
-
this.masterNullifierPublicKey,
|
|
136
|
-
this.masterIncomingViewingPublicKey,
|
|
137
|
-
this.masterOutgoingViewingPublicKey,
|
|
138
|
-
this.masterTaggingPublicKey,
|
|
139
|
-
]);
|
|
125
|
+
return serializeToBuffer([this.npkMHash, this.ivpkM, this.ovpkMHash, this.tpkMHash]);
|
|
140
126
|
}
|
|
141
127
|
|
|
142
|
-
/**
|
|
143
|
-
* Creates an PublicKeys instance from a given buffer or BufferReader.
|
|
144
|
-
* If the input is a Buffer, it wraps it in a BufferReader before processing.
|
|
145
|
-
* Throws an error if the input length is not equal to the expected size.
|
|
146
|
-
*
|
|
147
|
-
* @param buffer - The input buffer or BufferReader containing the address data.
|
|
148
|
-
* @returns - A new PublicKeys instance with the extracted address data.
|
|
149
|
-
*/
|
|
150
128
|
static fromBuffer(buffer: Buffer | BufferReader): PublicKeys {
|
|
151
129
|
const reader = BufferReader.asReader(buffer);
|
|
152
|
-
const
|
|
153
|
-
const
|
|
154
|
-
const
|
|
155
|
-
const
|
|
156
|
-
return new PublicKeys(
|
|
157
|
-
masterNullifierPublicKey,
|
|
158
|
-
masterIncomingViewingPublicKey,
|
|
159
|
-
masterOutgoingViewingPublicKey,
|
|
160
|
-
masterTaggingPublicKey,
|
|
161
|
-
);
|
|
130
|
+
const npkMHash = Fr.fromBuffer(reader);
|
|
131
|
+
const ivpkM = reader.readObject(Point);
|
|
132
|
+
const ovpkMHash = Fr.fromBuffer(reader);
|
|
133
|
+
const tpkMHash = Fr.fromBuffer(reader);
|
|
134
|
+
return new PublicKeys(npkMHash, ivpkM, ovpkMHash, tpkMHash);
|
|
162
135
|
}
|
|
163
136
|
|
|
164
137
|
toNoirStruct() {
|
|
165
|
-
// We need to use lowercase identifiers as those are what the noir interface expects
|
|
166
|
-
|
|
138
|
+
// We need to use lowercase identifiers as those are what the noir interface expects.
|
|
139
|
+
/* eslint-disable camelcase */
|
|
167
140
|
return {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
ovpk_m: this.masterOutgoingViewingPublicKey.toWrappedNoirStruct(),
|
|
173
|
-
tpk_m: this.masterTaggingPublicKey.toWrappedNoirStruct(),
|
|
174
|
-
/* eslint-enable camelcase */
|
|
141
|
+
npk_m_hash: this.npkMHash,
|
|
142
|
+
ivpk_m: this.ivpkM.toWrappedNoirStruct(),
|
|
143
|
+
ovpk_m_hash: this.ovpkMHash,
|
|
144
|
+
tpk_m_hash: this.tpkMHash,
|
|
175
145
|
};
|
|
146
|
+
/* eslint-enable camelcase */
|
|
176
147
|
}
|
|
177
148
|
|
|
178
149
|
/**
|
|
179
|
-
*
|
|
180
|
-
*
|
|
150
|
+
* Wire-format fields matching Noir's struct flattening of `PublicKeys`:
|
|
151
|
+
* `[npk_m_hash, ivpk_m.x, ivpk_m.y, ivpk_m.is_infinite, ovpk_m_hash, tpk_m_hash]` (6 fields).
|
|
152
|
+
*
|
|
153
|
+
* The `is_infinite` slot is `0` for `ivpkM` produced by `deriveKeys` (fixed-base scalar
|
|
154
|
+
* multiplication on Grumpkin cannot reach infinity for a non-zero scalar, and Poseidon-derived
|
|
155
|
+
* scalars are non-zero with cryptographically negligible exception). External flows that
|
|
156
|
+
* import pre-derived keys are responsible for maintaining this invariant (see the AZIP-8
|
|
157
|
+
* migration note "Security note (PXE side)"). The slot stays on the wire because the Noir
|
|
158
|
+
* struct's `Point` still carries the flag. AZIP-8's "drop `is_infinite`" goal applies to the
|
|
159
|
+
* address-derivation hash (via `hash_public_key`, computed elsewhere), not to the
|
|
160
|
+
* contract-call args wire.
|
|
161
|
+
* TODO(F-553): drop the `is_infinite` slot once `Point` no longer carries the flag.
|
|
181
162
|
*/
|
|
182
163
|
toFields(): Fr[] {
|
|
183
164
|
return [
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
165
|
+
this.npkMHash,
|
|
166
|
+
this.ivpkM.x,
|
|
167
|
+
this.ivpkM.y,
|
|
168
|
+
new Fr(this.ivpkM.isInfinite ? 1 : 0),
|
|
169
|
+
this.ovpkMHash,
|
|
170
|
+
this.tpkMHash,
|
|
188
171
|
];
|
|
189
172
|
}
|
|
190
173
|
|
|
191
|
-
//
|
|
192
|
-
// to spend too much time on the encoder now. It probably needs a refactor.
|
|
174
|
+
// Used in foundation/src/abi/encoder. Probably non-optimal but the encoder needs a refactor.
|
|
193
175
|
encodeToNoir(): Fr[] {
|
|
194
176
|
return this.toFields();
|
|
195
177
|
}
|
|
196
178
|
|
|
197
179
|
static fromFields(fields: Fr[] | FieldReader): PublicKeys {
|
|
198
180
|
const reader = FieldReader.asReader(fields);
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
);
|
|
181
|
+
const npkMHash = reader.readField();
|
|
182
|
+
const ivpkMX = reader.readField();
|
|
183
|
+
const ivpkMY = reader.readField();
|
|
184
|
+
const ivpkMIsInfinite = reader.readBoolean();
|
|
185
|
+
const ovpkMHash = reader.readField();
|
|
186
|
+
const tpkMHash = reader.readField();
|
|
187
|
+
return new PublicKeys(npkMHash, new Point(ivpkMX, ivpkMY, ivpkMIsInfinite), ovpkMHash, tpkMHash);
|
|
205
188
|
}
|
|
206
189
|
|
|
207
190
|
toString() {
|
package/src/tests/factories.ts
CHANGED
|
@@ -123,7 +123,7 @@ import {
|
|
|
123
123
|
PublicCallRequest,
|
|
124
124
|
PublicCallRequestArrayLengths,
|
|
125
125
|
} from '../kernel/public_call_request.js';
|
|
126
|
-
import { PublicKeys, computeAddress } from '../keys/index.js';
|
|
126
|
+
import { PublicKeys, computeAddress, hashPublicKey } from '../keys/index.js';
|
|
127
127
|
import { ExtendedDirectionalAppTaggingSecret } from '../logs/extended_directional_app_tagging_secret.js';
|
|
128
128
|
import { ContractClassLog, ContractClassLogFields } from '../logs/index.js';
|
|
129
129
|
import { PrivateLog } from '../logs/private_log.js';
|
|
@@ -252,7 +252,7 @@ function makeScopedReadRequest(n: number): ScopedReadRequest {
|
|
|
252
252
|
* @returns A KeyValidationRequest.
|
|
253
253
|
*/
|
|
254
254
|
function makeKeyValidationRequests(seed: number): KeyValidationRequest {
|
|
255
|
-
return new KeyValidationRequest(
|
|
255
|
+
return new KeyValidationRequest(fr(seed), fr(seed + 2));
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
/**
|
|
@@ -1220,8 +1220,13 @@ export async function makeMapAsync<T>(size: number, fn: (i: number) => Promise<[
|
|
|
1220
1220
|
|
|
1221
1221
|
export async function makePublicKeys(seed = 0): Promise<PublicKeys> {
|
|
1222
1222
|
const f = (offset: number) => Grumpkin.mul(Grumpkin.generator, new Fq(seed + offset));
|
|
1223
|
-
|
|
1224
|
-
return new PublicKeys(
|
|
1223
|
+
const ivpkM = await f(1);
|
|
1224
|
+
return new PublicKeys(
|
|
1225
|
+
await hashPublicKey(await f(0)),
|
|
1226
|
+
ivpkM,
|
|
1227
|
+
await hashPublicKey(await f(2)),
|
|
1228
|
+
await hashPublicKey(await f(3)),
|
|
1229
|
+
);
|
|
1225
1230
|
}
|
|
1226
1231
|
|
|
1227
1232
|
export async function makeContractInstanceFromClassId(
|
|
@@ -1230,6 +1235,7 @@ export async function makeContractInstanceFromClassId(
|
|
|
1230
1235
|
overrides?: {
|
|
1231
1236
|
deployer?: AztecAddress;
|
|
1232
1237
|
initializationHash?: Fr;
|
|
1238
|
+
immutablesHash?: Fr;
|
|
1233
1239
|
publicKeys?: PublicKeys;
|
|
1234
1240
|
currentClassId?: Fr;
|
|
1235
1241
|
},
|
|
@@ -1238,21 +1244,24 @@ export async function makeContractInstanceFromClassId(
|
|
|
1238
1244
|
const initializationHash = overrides?.initializationHash ?? new Fr(seed + 1);
|
|
1239
1245
|
const deployer = overrides?.deployer ?? new AztecAddress(new Fr(seed + 2));
|
|
1240
1246
|
const publicKeys = overrides?.publicKeys ?? (await makePublicKeys(seed + 3));
|
|
1247
|
+
const immutablesHash = overrides?.immutablesHash ?? new Fr(seed + 4);
|
|
1241
1248
|
|
|
1242
1249
|
const partialAddress = await computePartialAddress({
|
|
1243
1250
|
originalContractClassId: classId,
|
|
1244
1251
|
salt,
|
|
1245
1252
|
initializationHash,
|
|
1253
|
+
immutablesHash,
|
|
1246
1254
|
deployer,
|
|
1247
1255
|
});
|
|
1248
1256
|
const address = await computeAddress(publicKeys, partialAddress);
|
|
1249
1257
|
return new SerializableContractInstance({
|
|
1250
|
-
version:
|
|
1258
|
+
version: 2,
|
|
1251
1259
|
salt,
|
|
1252
1260
|
deployer,
|
|
1253
1261
|
currentContractClassId: overrides?.currentClassId ?? classId,
|
|
1254
1262
|
originalContractClassId: classId,
|
|
1255
1263
|
initializationHash,
|
|
1264
|
+
immutablesHash,
|
|
1256
1265
|
publicKeys,
|
|
1257
1266
|
}).withAddress(address);
|
|
1258
1267
|
}
|
|
@@ -1430,11 +1439,12 @@ export function makeAvmContractInstanceHint(seed = 0): AvmContractInstanceHint {
|
|
|
1430
1439
|
new Fr(seed + 0x4),
|
|
1431
1440
|
new Fr(seed + 0x5),
|
|
1432
1441
|
new Fr(seed + 0x6),
|
|
1442
|
+
new Fr(seed + 0x7),
|
|
1433
1443
|
new PublicKeys(
|
|
1434
|
-
new
|
|
1444
|
+
new Fr(seed + 0x7),
|
|
1435
1445
|
new Point(new Fr(seed + 0x9), new Fr(seed + 0x10), false),
|
|
1436
|
-
new
|
|
1437
|
-
new
|
|
1446
|
+
new Fr(seed + 0x11),
|
|
1447
|
+
new Fr(seed + 0x13),
|
|
1438
1448
|
),
|
|
1439
1449
|
);
|
|
1440
1450
|
}
|