@aztec/stdlib 2.1.0-rc.8 → 2.1.1-rc.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/dest/block/attestation_info.d.ts +30 -0
- package/dest/block/attestation_info.d.ts.map +1 -0
- package/dest/block/attestation_info.js +39 -0
- package/dest/block/index.d.ts +1 -0
- package/dest/block/index.d.ts.map +1 -1
- package/dest/block/index.js +1 -0
- package/dest/block/l2_block_source.d.ts +34 -5
- package/dest/block/l2_block_source.d.ts.map +1 -1
- package/dest/block/published_l2_block.d.ts +0 -6
- package/dest/block/published_l2_block.d.ts.map +1 -1
- package/dest/block/published_l2_block.js +0 -9
- package/dest/interfaces/archiver.d.ts +1 -1
- package/dest/interfaces/archiver.d.ts.map +1 -1
- package/dest/interfaces/archiver.js +10 -3
- package/dest/interfaces/aztec-node-admin.d.ts +35 -34
- package/dest/interfaces/aztec-node-admin.d.ts.map +1 -1
- package/dest/interfaces/aztec-node-admin.js +2 -2
- package/dest/interfaces/aztec-node.d.ts +24 -0
- package/dest/interfaces/aztec-node.d.ts.map +1 -1
- package/dest/interfaces/aztec-node.js +4 -0
- package/dest/interfaces/p2p.d.ts +2 -0
- package/dest/interfaces/p2p.d.ts.map +1 -1
- package/dest/interfaces/p2p.js +2 -1
- package/dest/interfaces/tx_provider.d.ts +1 -1
- package/dest/interfaces/tx_provider.d.ts.map +1 -1
- package/dest/interfaces/validator.d.ts +93 -1
- package/dest/interfaces/validator.d.ts.map +1 -1
- package/dest/interfaces/validator.js +6 -0
- package/dest/p2p/block_attestation.d.ts +13 -13
- package/dest/p2p/block_attestation.d.ts.map +1 -1
- package/dest/p2p/block_attestation.js +27 -25
- package/dest/p2p/block_proposal.d.ts +4 -8
- package/dest/p2p/block_proposal.d.ts.map +1 -1
- package/dest/p2p/block_proposal.js +10 -13
- package/dest/p2p/gossipable.d.ts +4 -12
- package/dest/p2p/gossipable.d.ts.map +1 -1
- package/dest/p2p/gossipable.js +4 -7
- package/dest/p2p/topic_type.d.ts +4 -8
- package/dest/p2p/topic_type.d.ts.map +1 -1
- package/dest/p2p/topic_type.js +14 -8
- package/dest/tests/factories.d.ts +1 -1
- package/dest/tests/factories.d.ts.map +1 -1
- package/dest/tests/factories.js +6 -5
- package/dest/tests/mocks.d.ts +3 -1
- package/dest/tests/mocks.d.ts.map +1 -1
- package/dest/tests/mocks.js +33 -11
- package/dest/zkpassport/index.d.ts +15 -11
- package/dest/zkpassport/index.d.ts.map +1 -1
- package/dest/zkpassport/index.js +18 -17
- package/package.json +9 -9
- package/src/block/attestation_info.ts +62 -0
- package/src/block/index.ts +1 -0
- package/src/block/l2_block_source.ts +37 -5
- package/src/block/published_l2_block.ts +0 -17
- package/src/interfaces/archiver.ts +12 -4
- package/src/interfaces/aztec-node-admin.ts +2 -2
- package/src/interfaces/aztec-node.ts +36 -0
- package/src/interfaces/p2p.ts +4 -0
- package/src/interfaces/tx_provider.ts +1 -0
- package/src/interfaces/validator.ts +14 -1
- package/src/p2p/block_attestation.ts +31 -24
- package/src/p2p/block_proposal.ts +9 -16
- package/src/p2p/gossipable.ts +4 -12
- package/src/p2p/topic_type.ts +15 -8
- package/src/tests/factories.ts +7 -10
- package/src/tests/mocks.ts +53 -17
- package/src/zkpassport/index.ts +37 -33
package/src/interfaces/p2p.ts
CHANGED
|
@@ -57,6 +57,9 @@ export interface P2PApiWithAttestations extends P2PApiWithoutAttestations {
|
|
|
57
57
|
* @returns BlockAttestations
|
|
58
58
|
*/
|
|
59
59
|
getAttestationsForSlot(slot: bigint, proposalId?: string): Promise<BlockAttestation[]>;
|
|
60
|
+
|
|
61
|
+
/** Deletes a given attestation manually from the p2p client attestation pool. */
|
|
62
|
+
deleteAttestation(attestation: BlockAttestation): Promise<void>;
|
|
60
63
|
}
|
|
61
64
|
|
|
62
65
|
export interface P2PClient extends P2PApiWithAttestations {
|
|
@@ -85,4 +88,5 @@ export const P2PApiSchema: ApiSchemaFor<P2PApi> = {
|
|
|
85
88
|
getPendingTxCount: z.function().returns(schemas.Integer),
|
|
86
89
|
getEncodedEnr: z.function().returns(z.string().optional()),
|
|
87
90
|
getPeers: z.function().args(optional(z.boolean())).returns(z.array(PeerInfoSchema)),
|
|
91
|
+
deleteAttestation: z.function().args(BlockAttestation.schema).returns(z.void()),
|
|
88
92
|
};
|
|
@@ -11,6 +11,7 @@ import type { PeerId } from '@libp2p/interface';
|
|
|
11
11
|
import { z } from 'zod';
|
|
12
12
|
|
|
13
13
|
import type { CommitteeAttestationsAndSigners } from '../block/index.js';
|
|
14
|
+
import { AllowedElementSchema } from './allowed_element.js';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Validator client configuration
|
|
@@ -43,7 +44,13 @@ export interface ValidatorClientConfig {
|
|
|
43
44
|
|
|
44
45
|
export type ValidatorClientFullConfig = ValidatorClientConfig &
|
|
45
46
|
Pick<SequencerConfig, 'txPublicSetupAllowList'> &
|
|
46
|
-
Pick<SlasherConfig, 'slashBroadcastedInvalidBlockPenalty'
|
|
47
|
+
Pick<SlasherConfig, 'slashBroadcastedInvalidBlockPenalty'> & {
|
|
48
|
+
/**
|
|
49
|
+
* Whether transactions are disabled for this node
|
|
50
|
+
* @remarks This should match the property in P2PConfig. It's not picked from there to avoid circular dependencies.
|
|
51
|
+
*/
|
|
52
|
+
disableTransactions?: boolean;
|
|
53
|
+
};
|
|
47
54
|
|
|
48
55
|
export const ValidatorClientConfigSchema = z.object({
|
|
49
56
|
validatorAddresses: z.array(schemas.EthAddress).optional(),
|
|
@@ -55,6 +62,12 @@ export const ValidatorClientConfigSchema = z.object({
|
|
|
55
62
|
alwaysReexecuteBlockProposals: z.boolean().optional(),
|
|
56
63
|
}) satisfies ZodFor<Omit<ValidatorClientConfig, 'validatorPrivateKeys'>>;
|
|
57
64
|
|
|
65
|
+
export const ValidatorClientFullConfigSchema = ValidatorClientConfigSchema.extend({
|
|
66
|
+
txPublicSetupAllowList: z.array(AllowedElementSchema).optional(),
|
|
67
|
+
slashBroadcastedInvalidBlockPenalty: schemas.BigInt,
|
|
68
|
+
disableTransactions: z.boolean().optional(),
|
|
69
|
+
}) satisfies ZodFor<Omit<ValidatorClientFullConfig, 'validatorPrivateKeys'>>;
|
|
70
|
+
|
|
58
71
|
export interface Validator {
|
|
59
72
|
start(): Promise<void>;
|
|
60
73
|
updateConfig(config: Partial<ValidatorClientFullConfig>): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
2
|
-
import { keccak256,
|
|
2
|
+
import { keccak256, tryRecoverAddress } from '@aztec/foundation/crypto';
|
|
3
3
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
4
|
import { Signature } from '@aztec/foundation/eth-signature';
|
|
5
5
|
import { Fr } from '@aztec/foundation/fields';
|
|
@@ -7,8 +7,7 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
|
7
7
|
|
|
8
8
|
import { z } from 'zod';
|
|
9
9
|
|
|
10
|
-
import {
|
|
11
|
-
import type { UInt32 } from '../types/index.js';
|
|
10
|
+
import type { ZodFor } from '../schemas/index.js';
|
|
12
11
|
import { ConsensusPayload } from './consensus_payload.js';
|
|
13
12
|
import { Gossipable } from './gossipable.js';
|
|
14
13
|
import { SignatureDomainSeparator, getHashedSignaturePayloadEthSignedMessage } from './signature_utils.js';
|
|
@@ -30,16 +29,17 @@ export class BlockAttestation extends Gossipable {
|
|
|
30
29
|
static override p2pTopic = TopicType.block_attestation;
|
|
31
30
|
|
|
32
31
|
private sender: EthAddress | undefined;
|
|
32
|
+
private proposer: EthAddress | undefined;
|
|
33
33
|
|
|
34
34
|
constructor(
|
|
35
|
-
/** The block number of the attestation. */
|
|
36
|
-
public readonly blockNumber: UInt32,
|
|
37
|
-
|
|
38
35
|
/** The payload of the message, and what the signature is over */
|
|
39
36
|
public readonly payload: ConsensusPayload,
|
|
40
37
|
|
|
41
38
|
/** The signature of the block attester */
|
|
42
39
|
public readonly signature: Signature,
|
|
40
|
+
|
|
41
|
+
/** The signature from the block proposer */
|
|
42
|
+
public readonly proposerSignature: Signature,
|
|
43
43
|
) {
|
|
44
44
|
super();
|
|
45
45
|
}
|
|
@@ -47,11 +47,11 @@ export class BlockAttestation extends Gossipable {
|
|
|
47
47
|
static get schema(): ZodFor<BlockAttestation> {
|
|
48
48
|
return z
|
|
49
49
|
.object({
|
|
50
|
-
blockNumber: schemas.UInt32,
|
|
51
50
|
payload: ConsensusPayload.schema,
|
|
52
51
|
signature: Signature.schema,
|
|
52
|
+
proposerSignature: Signature.schema,
|
|
53
53
|
})
|
|
54
|
-
.transform(obj => new BlockAttestation(obj.
|
|
54
|
+
.transform(obj => new BlockAttestation(obj.payload, obj.signature, obj.proposerSignature));
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
override generateP2PMessageIdentifier(): Promise<Buffer32> {
|
|
@@ -68,29 +68,32 @@ export class BlockAttestation extends Gossipable {
|
|
|
68
68
|
|
|
69
69
|
/**
|
|
70
70
|
* Lazily evaluate and cache the signer of the attestation
|
|
71
|
-
* @returns The signer of the attestation
|
|
71
|
+
* @returns The signer of the attestation, or undefined if signature recovery fails
|
|
72
72
|
*/
|
|
73
|
-
getSender(): EthAddress {
|
|
73
|
+
getSender(): EthAddress | undefined {
|
|
74
74
|
if (!this.sender) {
|
|
75
75
|
// Recover the sender from the attestation
|
|
76
76
|
const hashed = getHashedSignaturePayloadEthSignedMessage(this.payload, SignatureDomainSeparator.blockAttestation);
|
|
77
77
|
// Cache the sender for later use
|
|
78
|
-
this.sender =
|
|
78
|
+
this.sender = tryRecoverAddress(hashed, this.signature);
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
return this.sender;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
/**
|
|
85
|
-
*
|
|
86
|
-
* @returns The
|
|
85
|
+
* Lazily evaluate and cache the proposer of the block
|
|
86
|
+
* @returns The proposer of the block
|
|
87
87
|
*/
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
getProposer(): EthAddress | undefined {
|
|
89
|
+
if (!this.proposer) {
|
|
90
|
+
// Recover the proposer from the proposal signature
|
|
91
|
+
const hashed = getHashedSignaturePayloadEthSignedMessage(this.payload, SignatureDomainSeparator.blockProposal);
|
|
92
|
+
// Cache the proposer for later use
|
|
93
|
+
this.proposer = tryRecoverAddress(hashed, this.proposerSignature);
|
|
93
94
|
}
|
|
95
|
+
|
|
96
|
+
return this.proposer;
|
|
94
97
|
}
|
|
95
98
|
|
|
96
99
|
getPayload(): Buffer {
|
|
@@ -98,31 +101,35 @@ export class BlockAttestation extends Gossipable {
|
|
|
98
101
|
}
|
|
99
102
|
|
|
100
103
|
toBuffer(): Buffer {
|
|
101
|
-
return serializeToBuffer([this.
|
|
104
|
+
return serializeToBuffer([this.payload, this.signature, this.proposerSignature]);
|
|
102
105
|
}
|
|
103
106
|
|
|
104
107
|
static fromBuffer(buf: Buffer | BufferReader): BlockAttestation {
|
|
105
108
|
const reader = BufferReader.asReader(buf);
|
|
106
|
-
return new BlockAttestation(
|
|
109
|
+
return new BlockAttestation(
|
|
110
|
+
reader.readObject(ConsensusPayload),
|
|
111
|
+
reader.readObject(Signature),
|
|
112
|
+
reader.readObject(Signature),
|
|
113
|
+
);
|
|
107
114
|
}
|
|
108
115
|
|
|
109
116
|
static empty(): BlockAttestation {
|
|
110
|
-
return new BlockAttestation(
|
|
117
|
+
return new BlockAttestation(ConsensusPayload.empty(), Signature.empty(), Signature.empty());
|
|
111
118
|
}
|
|
112
119
|
|
|
113
120
|
static random(): BlockAttestation {
|
|
114
|
-
return new BlockAttestation(
|
|
121
|
+
return new BlockAttestation(ConsensusPayload.random(), Signature.random(), Signature.random());
|
|
115
122
|
}
|
|
116
123
|
|
|
117
124
|
getSize(): number {
|
|
118
|
-
return
|
|
125
|
+
return this.payload.getSize() + this.signature.getSize() + this.proposerSignature.getSize();
|
|
119
126
|
}
|
|
120
127
|
|
|
121
128
|
toInspect() {
|
|
122
129
|
return {
|
|
123
|
-
blockNumber: this.blockNumber,
|
|
124
130
|
payload: this.payload.toInspect(),
|
|
125
131
|
signature: this.signature.toString(),
|
|
132
|
+
proposerSignature: this.proposerSignature.toString(),
|
|
126
133
|
};
|
|
127
134
|
}
|
|
128
135
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
2
|
-
import { keccak256,
|
|
2
|
+
import { keccak256, tryRecoverAddress } from '@aztec/foundation/crypto';
|
|
3
3
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
4
|
import { Signature } from '@aztec/foundation/eth-signature';
|
|
5
5
|
import { Fr } from '@aztec/foundation/fields';
|
|
@@ -8,7 +8,6 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
|
8
8
|
import type { L2BlockInfo } from '../block/l2_block_info.js';
|
|
9
9
|
import { TxHash } from '../tx/index.js';
|
|
10
10
|
import { Tx } from '../tx/tx.js';
|
|
11
|
-
import type { UInt32 } from '../types/index.js';
|
|
12
11
|
import { ConsensusPayload } from './consensus_payload.js';
|
|
13
12
|
import { Gossipable } from './gossipable.js';
|
|
14
13
|
import {
|
|
@@ -40,9 +39,6 @@ export class BlockProposal extends Gossipable {
|
|
|
40
39
|
private sender: EthAddress | undefined;
|
|
41
40
|
|
|
42
41
|
constructor(
|
|
43
|
-
/** The number of the block */
|
|
44
|
-
public readonly blockNumber: UInt32,
|
|
45
|
-
|
|
46
42
|
/** The payload of the message, and what the signature is over */
|
|
47
43
|
public readonly payload: ConsensusPayload,
|
|
48
44
|
|
|
@@ -71,9 +67,8 @@ export class BlockProposal extends Gossipable {
|
|
|
71
67
|
return this.payload.header.slotNumber;
|
|
72
68
|
}
|
|
73
69
|
|
|
74
|
-
toBlockInfo(): L2BlockInfo {
|
|
70
|
+
toBlockInfo(): Omit<L2BlockInfo, 'blockNumber'> {
|
|
75
71
|
return {
|
|
76
|
-
blockNumber: this.blockNumber,
|
|
77
72
|
slotNumber: this.slotNumber.toNumber(),
|
|
78
73
|
lastArchive: this.payload.header.lastArchiveRoot,
|
|
79
74
|
timestamp: this.payload.header.timestamp,
|
|
@@ -83,7 +78,6 @@ export class BlockProposal extends Gossipable {
|
|
|
83
78
|
}
|
|
84
79
|
|
|
85
80
|
static async createProposalFromSigner(
|
|
86
|
-
blockNumber: UInt32,
|
|
87
81
|
payload: ConsensusPayload,
|
|
88
82
|
txHashes: TxHash[],
|
|
89
83
|
// Note(md): Provided separately to tx hashes such that this function can be optional
|
|
@@ -93,17 +87,18 @@ export class BlockProposal extends Gossipable {
|
|
|
93
87
|
const hashed = getHashedSignaturePayload(payload, SignatureDomainSeparator.blockProposal);
|
|
94
88
|
const sig = await payloadSigner(hashed);
|
|
95
89
|
|
|
96
|
-
return new BlockProposal(
|
|
90
|
+
return new BlockProposal(payload, sig, txHashes, txs);
|
|
97
91
|
}
|
|
98
92
|
|
|
99
93
|
/**Get Sender
|
|
100
94
|
* Lazily evaluate the sender of the proposal; result is cached
|
|
95
|
+
* @returns The sender address, or undefined if signature recovery fails
|
|
101
96
|
*/
|
|
102
|
-
getSender() {
|
|
97
|
+
getSender(): EthAddress | undefined {
|
|
103
98
|
if (!this.sender) {
|
|
104
99
|
const hashed = getHashedSignaturePayloadEthSignedMessage(this.payload, SignatureDomainSeparator.blockProposal);
|
|
105
100
|
// Cache the sender for later use
|
|
106
|
-
this.sender =
|
|
101
|
+
this.sender = tryRecoverAddress(hashed, this.signature);
|
|
107
102
|
}
|
|
108
103
|
|
|
109
104
|
return this.sender;
|
|
@@ -114,7 +109,7 @@ export class BlockProposal extends Gossipable {
|
|
|
114
109
|
}
|
|
115
110
|
|
|
116
111
|
toBuffer(): Buffer {
|
|
117
|
-
const buffer: any[] = [this.
|
|
112
|
+
const buffer: any[] = [this.payload, this.signature, this.txHashes.length, this.txHashes];
|
|
118
113
|
if (this.txs) {
|
|
119
114
|
buffer.push(this.txs.length);
|
|
120
115
|
buffer.push(this.txs);
|
|
@@ -125,22 +120,20 @@ export class BlockProposal extends Gossipable {
|
|
|
125
120
|
static fromBuffer(buf: Buffer | BufferReader): BlockProposal {
|
|
126
121
|
const reader = BufferReader.asReader(buf);
|
|
127
122
|
|
|
128
|
-
const blockNumber = reader.readNumber();
|
|
129
123
|
const payload = reader.readObject(ConsensusPayload);
|
|
130
124
|
const sig = reader.readObject(Signature);
|
|
131
125
|
const txHashes = reader.readArray(reader.readNumber(), TxHash);
|
|
132
126
|
|
|
133
127
|
if (!reader.isEmpty()) {
|
|
134
128
|
const txs = reader.readArray(reader.readNumber(), Tx);
|
|
135
|
-
return new BlockProposal(
|
|
129
|
+
return new BlockProposal(payload, sig, txHashes, txs);
|
|
136
130
|
}
|
|
137
131
|
|
|
138
|
-
return new BlockProposal(
|
|
132
|
+
return new BlockProposal(payload, sig, txHashes);
|
|
139
133
|
}
|
|
140
134
|
|
|
141
135
|
getSize(): number {
|
|
142
136
|
return (
|
|
143
|
-
4 /* blockNumber */ +
|
|
144
137
|
this.payload.getSize() +
|
|
145
138
|
this.signature.getSize() +
|
|
146
139
|
4 /* txHashes.length */ +
|
package/src/p2p/gossipable.ts
CHANGED
|
@@ -28,15 +28,12 @@ export class P2PMessage {
|
|
|
28
28
|
*/
|
|
29
29
|
export abstract class Gossipable {
|
|
30
30
|
private cachedId: Buffer32 | undefined;
|
|
31
|
-
/** p2p
|
|
32
|
-
*
|
|
33
|
-
* - The p2p topic identifier, this determines how the message is handled
|
|
34
|
-
*/
|
|
31
|
+
/** The p2p topic identifier, this determines how the message is handled */
|
|
35
32
|
static p2pTopic: TopicType;
|
|
36
33
|
|
|
37
|
-
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
34
|
+
/**
|
|
35
|
+
* A digest of the message information **used for logging only**.
|
|
36
|
+
* The identifier used for deduplication is `getMsgIdFn` as defined in `encoding.ts` which is a hash over topic and data.
|
|
40
37
|
*/
|
|
41
38
|
async p2pMessageIdentifier(): Promise<Buffer32> {
|
|
42
39
|
if (this.cachedId) {
|
|
@@ -48,10 +45,6 @@ export abstract class Gossipable {
|
|
|
48
45
|
|
|
49
46
|
abstract generateP2PMessageIdentifier(): Promise<Buffer32>;
|
|
50
47
|
|
|
51
|
-
/** To Buffer
|
|
52
|
-
*
|
|
53
|
-
* - Serialization method
|
|
54
|
-
*/
|
|
55
48
|
abstract toBuffer(): Buffer;
|
|
56
49
|
|
|
57
50
|
toMessage(): Buffer {
|
|
@@ -60,7 +53,6 @@ export abstract class Gossipable {
|
|
|
60
53
|
|
|
61
54
|
/**
|
|
62
55
|
* Get the size of the gossipable object.
|
|
63
|
-
*
|
|
64
56
|
* This is used for metrics recording.
|
|
65
57
|
*/
|
|
66
58
|
abstract getSize(): number;
|
package/src/p2p/topic_type.ts
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
import { P2PClientType } from './client_type.js';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
* The topic channel identifier
|
|
6
|
-
* @param topicType
|
|
7
|
-
* @returns
|
|
3
|
+
/**
|
|
4
|
+
* Creates the topic channel identifier string from a given topic type
|
|
8
5
|
*/
|
|
9
6
|
export function createTopicString(topicType: TopicType, protocolVersion: string) {
|
|
10
7
|
return `/aztec/${TopicType[topicType]}/${protocolVersion}`;
|
|
11
8
|
}
|
|
12
9
|
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
/** Extracts the topic type from a topic string */
|
|
11
|
+
export function getTopicFromString(topicStr: string): TopicType | undefined {
|
|
12
|
+
const parts = topicStr.split('/');
|
|
13
|
+
if (parts.length < 4 || parts[1] !== 'aztec') {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
const topic = parts[2];
|
|
17
|
+
if (Object.values(TopicType).includes(topic as TopicType)) {
|
|
18
|
+
return topic as TopicType;
|
|
19
|
+
}
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
16
23
|
export enum TopicType {
|
|
17
24
|
tx = 'tx',
|
|
18
25
|
block_proposal = 'block_proposal',
|
package/src/tests/factories.ts
CHANGED
|
@@ -46,9 +46,9 @@ import {
|
|
|
46
46
|
} from '@aztec/constants';
|
|
47
47
|
import { type FieldsOf, makeHalfFullTuple, makeTuple } from '@aztec/foundation/array';
|
|
48
48
|
import { compact, padArrayEnd } from '@aztec/foundation/collection';
|
|
49
|
-
import { SchnorrSignature, poseidon2HashWithSeparator, sha256 } from '@aztec/foundation/crypto';
|
|
49
|
+
import { Grumpkin, SchnorrSignature, poseidon2HashWithSeparator, sha256 } from '@aztec/foundation/crypto';
|
|
50
50
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
51
|
-
import { BLS12Point, Fr, GrumpkinScalar, Point } from '@aztec/foundation/fields';
|
|
51
|
+
import { BLS12Point, Fq, Fr, GrumpkinScalar, Point } from '@aztec/foundation/fields';
|
|
52
52
|
import type { Bufferable, Serializable, Tuple } from '@aztec/foundation/serialize';
|
|
53
53
|
import { MembershipWitness } from '@aztec/foundation/trees';
|
|
54
54
|
|
|
@@ -1250,13 +1250,10 @@ export async function makeMapAsync<T>(size: number, fn: (i: number) => Promise<[
|
|
|
1250
1250
|
return new Map(await makeArrayAsync(size, i => fn(i + offset)));
|
|
1251
1251
|
}
|
|
1252
1252
|
|
|
1253
|
-
export function makePublicKeys(seed = 0): PublicKeys {
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
new Point(new Fr(seed + 4), new Fr(seed + 5), false),
|
|
1258
|
-
new Point(new Fr(seed + 6), new Fr(seed + 7), false),
|
|
1259
|
-
);
|
|
1253
|
+
export async function makePublicKeys(seed = 0): Promise<PublicKeys> {
|
|
1254
|
+
const f = (offset: number) => new Grumpkin().mul(Grumpkin.generator, new Fq(seed + offset));
|
|
1255
|
+
|
|
1256
|
+
return new PublicKeys(await f(0), await f(1), await f(2), await f(3));
|
|
1260
1257
|
}
|
|
1261
1258
|
|
|
1262
1259
|
export async function makeContractInstanceFromClassId(
|
|
@@ -1272,7 +1269,7 @@ export async function makeContractInstanceFromClassId(
|
|
|
1272
1269
|
const salt = new Fr(seed);
|
|
1273
1270
|
const initializationHash = overrides?.initializationHash ?? new Fr(seed + 1);
|
|
1274
1271
|
const deployer = overrides?.deployer ?? new AztecAddress(new Fr(seed + 2));
|
|
1275
|
-
const publicKeys = overrides?.publicKeys ?? makePublicKeys(seed + 3);
|
|
1272
|
+
const publicKeys = overrides?.publicKeys ?? (await makePublicKeys(seed + 3));
|
|
1276
1273
|
|
|
1277
1274
|
const saltedInitializationHash = await poseidon2HashWithSeparator(
|
|
1278
1275
|
[salt, initializationHash, deployer],
|
package/src/tests/mocks.ts
CHANGED
|
@@ -248,6 +248,8 @@ export const randomDeployedContract = async () => {
|
|
|
248
248
|
|
|
249
249
|
export interface MakeConsensusPayloadOptions {
|
|
250
250
|
signer?: Secp256k1Signer;
|
|
251
|
+
attesterSigner?: Secp256k1Signer;
|
|
252
|
+
proposerSigner?: Secp256k1Signer;
|
|
251
253
|
header?: BlockHeader;
|
|
252
254
|
archive?: Fr;
|
|
253
255
|
stateReference?: StateReference;
|
|
@@ -286,31 +288,65 @@ export const makeAndSignCommitteeAttestationsAndSigners = (
|
|
|
286
288
|
};
|
|
287
289
|
|
|
288
290
|
export const makeBlockProposal = (options?: MakeConsensusPayloadOptions): BlockProposal => {
|
|
289
|
-
const {
|
|
290
|
-
SignatureDomainSeparator.blockProposal,
|
|
291
|
-
options,
|
|
292
|
-
);
|
|
291
|
+
const { payload, signature } = makeAndSignConsensusPayload(SignatureDomainSeparator.blockProposal, options);
|
|
293
292
|
const txHashes = options?.txHashes ?? [0, 1, 2, 3, 4, 5].map(() => TxHash.random());
|
|
294
|
-
return new BlockProposal(
|
|
293
|
+
return new BlockProposal(payload, signature, txHashes, options?.txs ?? []);
|
|
295
294
|
};
|
|
296
295
|
|
|
297
296
|
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/8028)
|
|
298
297
|
export const makeBlockAttestation = (options?: MakeConsensusPayloadOptions): BlockAttestation => {
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
298
|
+
const header = options?.header ?? makeHeader(1);
|
|
299
|
+
const {
|
|
300
|
+
signer,
|
|
301
|
+
attesterSigner = signer ?? Secp256k1Signer.random(),
|
|
302
|
+
proposerSigner = signer ?? Secp256k1Signer.random(),
|
|
303
|
+
archive = Fr.random(),
|
|
304
|
+
stateReference = header.state,
|
|
305
|
+
} = options ?? {};
|
|
306
|
+
|
|
307
|
+
const payload = ConsensusPayload.fromFields({
|
|
308
|
+
header: header.toPropose(),
|
|
309
|
+
archive,
|
|
310
|
+
stateReference,
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
// Sign as attester
|
|
314
|
+
const attestationHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockAttestation);
|
|
315
|
+
const attestationSignature = attesterSigner.sign(attestationHash);
|
|
316
|
+
|
|
317
|
+
// Sign as proposer
|
|
318
|
+
const proposalHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockProposal);
|
|
319
|
+
const proposerSignature = proposerSigner.sign(proposalHash);
|
|
320
|
+
|
|
321
|
+
return new BlockAttestation(payload, attestationSignature, proposerSignature);
|
|
304
322
|
};
|
|
305
323
|
|
|
306
|
-
export const makeBlockAttestationFromBlock = (
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
324
|
+
export const makeBlockAttestationFromBlock = (
|
|
325
|
+
block: L2Block,
|
|
326
|
+
attesterSigner?: Secp256k1Signer,
|
|
327
|
+
proposerSigner?: Secp256k1Signer,
|
|
328
|
+
): BlockAttestation => {
|
|
329
|
+
const header = block.header;
|
|
330
|
+
const archive = block.archive.root;
|
|
331
|
+
const stateReference = block.header.state;
|
|
332
|
+
|
|
333
|
+
const payload = ConsensusPayload.fromFields({
|
|
334
|
+
header: header.toPropose(),
|
|
335
|
+
archive,
|
|
336
|
+
stateReference,
|
|
313
337
|
});
|
|
338
|
+
|
|
339
|
+
// Sign as attester
|
|
340
|
+
const attestationHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockAttestation);
|
|
341
|
+
const attestationSigner = attesterSigner ?? Secp256k1Signer.random();
|
|
342
|
+
const attestationSignature = attestationSigner.sign(attestationHash);
|
|
343
|
+
|
|
344
|
+
// Sign as proposer
|
|
345
|
+
const proposalHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockProposal);
|
|
346
|
+
const proposalSignerToUse = proposerSigner ?? Secp256k1Signer.random();
|
|
347
|
+
const proposerSignature = proposalSignerToUse.sign(proposalHash);
|
|
348
|
+
|
|
349
|
+
return new BlockAttestation(payload, attestationSignature, proposerSignature);
|
|
314
350
|
};
|
|
315
351
|
|
|
316
352
|
export async function randomPublishedL2Block(
|
package/src/zkpassport/index.ts
CHANGED
|
@@ -5,15 +5,20 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
|
5
5
|
import { withoutHexPrefix } from '@aztec/foundation/string';
|
|
6
6
|
|
|
7
7
|
export type ViemZkPassportProofParams = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
proofVerificationData: {
|
|
9
|
+
vkeyHash: `0x${string}`;
|
|
10
|
+
proof: `0x${string}`;
|
|
11
|
+
publicInputs: `0x${string}`[];
|
|
12
|
+
};
|
|
13
|
+
commitments: {
|
|
14
|
+
committedInputs: `0x${string}`;
|
|
15
|
+
};
|
|
16
|
+
serviceConfig: {
|
|
17
|
+
validityPeriodInSeconds: bigint;
|
|
18
|
+
domain: string;
|
|
19
|
+
scope: string;
|
|
20
|
+
devMode: boolean;
|
|
21
|
+
};
|
|
17
22
|
};
|
|
18
23
|
|
|
19
24
|
// NOTE: Must match the ZkPassportProofParams struct in the zkpassport verifier contract
|
|
@@ -25,7 +30,6 @@ export class ZkPassportProofParams {
|
|
|
25
30
|
public proof: Buffer,
|
|
26
31
|
public publicInputs: Fr[],
|
|
27
32
|
public committedInputs: Buffer,
|
|
28
|
-
public committedInputCounts: bigint[],
|
|
29
33
|
public validityPeriodInSeconds: bigint,
|
|
30
34
|
public domain: string,
|
|
31
35
|
public scope: string,
|
|
@@ -41,8 +45,6 @@ export class ZkPassportProofParams {
|
|
|
41
45
|
this.publicInputs,
|
|
42
46
|
this.committedInputs.length,
|
|
43
47
|
this.committedInputs,
|
|
44
|
-
this.committedInputCounts.length,
|
|
45
|
-
this.committedInputCounts,
|
|
46
48
|
this.validityPeriodInSeconds,
|
|
47
49
|
this.domain,
|
|
48
50
|
this.scope,
|
|
@@ -63,8 +65,7 @@ export class ZkPassportProofParams {
|
|
|
63
65
|
randomBytes(1024),
|
|
64
66
|
publicInputs,
|
|
65
67
|
committedInputs,
|
|
66
|
-
|
|
67
|
-
BigInt(100 * 60 * 60 * 24),
|
|
68
|
+
BigInt(7 * 24 * 60 * 60), // 7 days
|
|
68
69
|
'sequencer.alpha-testnet.aztec.network',
|
|
69
70
|
'personhood',
|
|
70
71
|
);
|
|
@@ -78,7 +79,6 @@ export class ZkPassportProofParams {
|
|
|
78
79
|
reader.readBuffer(),
|
|
79
80
|
reader.readVector(Fr),
|
|
80
81
|
reader.readBuffer(),
|
|
81
|
-
reader.readUint256Vector(),
|
|
82
82
|
reader.readUInt256(),
|
|
83
83
|
reader.readString(),
|
|
84
84
|
reader.readString(),
|
|
@@ -87,29 +87,33 @@ export class ZkPassportProofParams {
|
|
|
87
87
|
|
|
88
88
|
static fromViem(params: ViemZkPassportProofParams) {
|
|
89
89
|
return new ZkPassportProofParams(
|
|
90
|
-
params.devMode,
|
|
91
|
-
Buffer32.fromString(params.vkeyHash),
|
|
92
|
-
Buffer.from(withoutHexPrefix(params.proof), 'hex'),
|
|
93
|
-
params.publicInputs.map(input => Fr.fromString(input)),
|
|
94
|
-
Buffer.from(withoutHexPrefix(params.committedInputs), 'hex'),
|
|
95
|
-
params.
|
|
96
|
-
params.
|
|
97
|
-
params.
|
|
98
|
-
params.scope,
|
|
90
|
+
params.serviceConfig.devMode,
|
|
91
|
+
Buffer32.fromString(params.proofVerificationData.vkeyHash),
|
|
92
|
+
Buffer.from(withoutHexPrefix(params.proofVerificationData.proof), 'hex'),
|
|
93
|
+
params.proofVerificationData.publicInputs.map(input => Fr.fromString(input)),
|
|
94
|
+
Buffer.from(withoutHexPrefix(params.commitments.committedInputs), 'hex'),
|
|
95
|
+
params.serviceConfig.validityPeriodInSeconds,
|
|
96
|
+
params.serviceConfig.domain,
|
|
97
|
+
params.serviceConfig.scope,
|
|
99
98
|
);
|
|
100
99
|
}
|
|
101
100
|
|
|
102
101
|
toViem(): ViemZkPassportProofParams {
|
|
103
102
|
return {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
103
|
+
serviceConfig: {
|
|
104
|
+
devMode: this.devMode,
|
|
105
|
+
validityPeriodInSeconds: this.validityPeriodInSeconds,
|
|
106
|
+
domain: this.domain,
|
|
107
|
+
scope: this.scope,
|
|
108
|
+
},
|
|
109
|
+
proofVerificationData: {
|
|
110
|
+
vkeyHash: this.vkeyHash.toString(),
|
|
111
|
+
proof: `0x${this.proof.toString('hex')}`,
|
|
112
|
+
publicInputs: this.publicInputs.map(input => input.toString()),
|
|
113
|
+
},
|
|
114
|
+
commitments: {
|
|
115
|
+
committedInputs: `0x${this.committedInputs.toString('hex')}`,
|
|
116
|
+
},
|
|
113
117
|
};
|
|
114
118
|
}
|
|
115
119
|
}
|