Skip to content

Commit 16d8915

Browse files
authored
Merge pull request #404 from proto-kit/fix/block-prover-state-carrying
Fix state carrying issue with block prover
2 parents cc77e23 + 4e7fd90 commit 16d8915

19 files changed

Lines changed: 662 additions & 263 deletions

packages/common/src/trees/sparse/RollupMerkleTree.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ export function createMerkleTree(height: number): AbstractMerkleTreeClass {
189189
return hash;
190190
}
191191

192+
// TODO Make sure this implementation is as efficient as it gets.
193+
// Especially compared to doing calculateRoot + witness new witness + check index
192194
public calculateRootIncrement(
193195
leafIndex: Field,
194196
leaf: Field

packages/protocol/src/prover/accumulators/WitnessedRootHashList.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Bool, Field, Struct } from "o1js";
1+
import { Bool, Field, Provable, Struct } from "o1js";
22

33
import { DefaultProvableHashList } from "../../utils/ProvableHashList";
44

@@ -13,15 +13,17 @@ export class WitnessedRoot extends Struct({
1313

1414
export class WitnessedRootWitness extends Struct({
1515
witnessedRoot: Field,
16-
preimage: Field,
1716
}) {}
1817

1918
/**
2019
* Accumulator as of section "Intermediary state roots" of the STProver v2 spec
2120
*/
2221

2322
export class WitnessedRootHashList extends DefaultProvableHashList<WitnessedRoot> {
24-
public constructor(commitment: Field = Field(0)) {
23+
public constructor(
24+
commitment: Field = Field(0),
25+
public preimage: Field = Field(0)
26+
) {
2527
super(WitnessedRoot, commitment);
2628
}
2729

@@ -34,20 +36,14 @@ export class WitnessedRootHashList extends DefaultProvableHashList<WitnessedRoot
3436
* points fall back to the same ST (because any batches in between were empty),
3537
* this has to be detected and compensated for.
3638
* This function does this using the preimage of the current list state.
37-
*
38-
* @param preimage The preimage to the **current** state of the list.
3939
*/
40-
public witnessRoot(
41-
witnessedRoot: WitnessedRoot,
42-
preimage: Field,
43-
condition: Bool
44-
) {
40+
public witnessRoot(witnessedRoot: WitnessedRoot, condition: Bool) {
4541
// Note, we don't have to validate the preimage here because of the following
4642
// 1. If the sequencer doesn't provide the correct witness, the BlockProver's
4743
// equality check will fail
4844
// 2. If the list is empty, no preimage exists, therefore condition (2) doesn't
4945
// apply, which is the same outcome when the sequencer provides an arbitrary witness
50-
const preimageCheckList = new WitnessedRootHashList(preimage).push(
46+
const preimageCheckList = new WitnessedRootHashList(this.preimage).push(
5147
witnessedRoot
5248
);
5349

@@ -56,6 +52,11 @@ export class WitnessedRootHashList extends DefaultProvableHashList<WitnessedRoot
5652
// (2) don't append if preimage.push({ finalizedRoot, pendingSTBatchesHash }) == this.commitment
5753
const skipPush = preimageCheckList.commitment.equals(this.commitment);
5854

59-
return this.pushIf(witnessedRoot, condition.and(skipPush.not()));
55+
const fromCommitment = this.commitment;
56+
57+
const pushCondition = condition.and(skipPush.not());
58+
this.pushIf(witnessedRoot, pushCondition);
59+
60+
this.preimage = Provable.if(pushCondition, fromCommitment, this.preimage);
6061
}
6162
}

packages/protocol/src/prover/block/BlockProvable.ts

Lines changed: 127 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Bool, Field, Proof, Provable, Struct } from "o1js";
1+
import { Bool, Field, Poseidon, Proof, Provable, Struct } from "o1js";
22
import { CompilableModule, WithZkProgrammable } from "@proto-kit/common";
33

44
import { StateTransitionProof } from "../statetransition/StateTransitionProvable";
@@ -32,7 +32,6 @@ export class BlockArguments extends Struct({
3232
return new BlockArguments({
3333
afterBlockRootWitness: {
3434
witnessedRoot: stateRoot,
35-
preimage: Field(0),
3635
},
3736
transactionsHash: Field(0),
3837
pendingSTBatchesHash: {
@@ -52,6 +51,92 @@ export class BlockArgumentsBatch extends Struct({
5251
batch: Provable.Array(BlockArguments, BLOCK_ARGUMENT_BATCH_SIZE),
5352
}) {}
5453

54+
const BlockProverStateBaseFields = {
55+
eternalTransactionsHash: Field,
56+
incomingMessagesHash: Field,
57+
stateRoot: Field,
58+
blockHashRoot: Field,
59+
blockNumber: Field,
60+
networkStateHash: Field,
61+
};
62+
63+
export class BlockProverPublicInput extends Struct({
64+
// Tracker of the current block prover state
65+
proverStateRemainder: Field,
66+
...BlockProverStateBaseFields,
67+
}) {
68+
public equals(input: BlockProverPublicInput): Bool {
69+
const output2 = BlockProverPublicInput.toFields(input);
70+
const output1 = BlockProverPublicInput.toFields(this);
71+
return output1
72+
.map((value1, index) => value1.equals(output2[index]))
73+
.reduce((a, b) => a.and(b));
74+
}
75+
76+
public clone() {
77+
return new BlockProverPublicInput(
78+
BlockProverPublicInput.fromFields(BlockProverPublicInput.toFields(this))
79+
);
80+
}
81+
}
82+
83+
export const BlockProverStateCommitments = {
84+
remainders: {
85+
// Commitment to the list of unprocessed (pending) batches of STs that need to be proven
86+
pendingSTBatchesHash: Field,
87+
witnessedRootsHash: Field,
88+
bundlesHash: Field,
89+
witnessedRootsPreimage: Field,
90+
},
91+
...BlockProverStateBaseFields,
92+
};
93+
94+
export class BlockProverStateInput extends Struct(BlockProverStateCommitments) {
95+
public hash() {
96+
return Poseidon.hash(BlockProverStateInput.toFields(this));
97+
}
98+
99+
public static fromPublicInput(input: BlockProverPublicInput) {
100+
return new BlockProverStateInput({
101+
remainders: {
102+
bundlesHash: Field(0),
103+
pendingSTBatchesHash: Field(0),
104+
witnessedRootsHash: Field(0),
105+
witnessedRootsPreimage: Field(0),
106+
},
107+
eternalTransactionsHash: input.eternalTransactionsHash,
108+
incomingMessagesHash: input.incomingMessagesHash,
109+
stateRoot: input.stateRoot,
110+
blockHashRoot: input.blockHashRoot,
111+
blockNumber: input.blockNumber,
112+
networkStateHash: input.networkStateHash,
113+
});
114+
}
115+
116+
public finalize(condition: Bool) {
117+
condition
118+
.implies(
119+
this.remainders.bundlesHash
120+
.equals(0)
121+
.and(this.remainders.pendingSTBatchesHash.equals(0))
122+
.and(this.remainders.witnessedRootsHash.equals(0))
123+
)
124+
.assertTrue("Remainers not fully removed");
125+
126+
return new BlockProverPublicInput({
127+
proverStateRemainder: Field(0),
128+
eternalTransactionsHash: this.eternalTransactionsHash,
129+
incomingMessagesHash: this.incomingMessagesHash,
130+
stateRoot: this.stateRoot,
131+
blockHashRoot: this.blockHashRoot,
132+
blockNumber: this.blockNumber,
133+
networkStateHash: this.networkStateHash,
134+
});
135+
}
136+
}
137+
138+
export class BlockProverPublicOutput extends BlockProverPublicInput {}
139+
55140
export class BlockProverState {
56141
/**
57142
* The network state which gives access to values such as blockHeight
@@ -113,44 +198,46 @@ export class BlockProverState {
113198
this.incomingMessages = args.incomingMessages;
114199
}
115200

116-
public toCommitments(): BlockProverPublicInput {
117-
return {
201+
public toCommitments(): BlockProverStateInput {
202+
return new BlockProverStateInput({
118203
remainders: {
119204
bundlesHash: this.bundleList.commitment,
120205
pendingSTBatchesHash: this.pendingSTBatches.commitment,
121206
witnessedRootsHash: this.witnessedRoots.commitment,
207+
witnessedRootsPreimage: this.witnessedRoots.preimage,
122208
},
123209
eternalTransactionsHash: this.eternalTransactionsList.commitment,
124210
incomingMessagesHash: this.incomingMessages.commitment,
125211
stateRoot: this.stateRoot,
126212
blockHashRoot: this.blockHashRoot,
127213
blockNumber: this.blockNumber,
128214
networkStateHash: this.networkState.hash(),
129-
};
215+
});
130216
}
131217

132218
public static blockProverFromCommitments(
133-
publicInput: BlockProverPublicInput,
219+
stateInput: NonMethods<BlockProverStateInput>,
134220
networkState: NetworkState,
135221
blockWitness: BlockHashMerkleTreeWitness
136222
): BlockProverState {
137223
return new BlockProverState({
138-
bundleList: new BundleHashList(publicInput.remainders.bundlesHash),
224+
bundleList: new BundleHashList(stateInput.remainders.bundlesHash),
139225
eternalTransactionsList: new TransactionHashList(
140-
publicInput.eternalTransactionsHash
226+
stateInput.eternalTransactionsHash
141227
),
142228
incomingMessages: new MinaActionsHashList(
143-
publicInput.incomingMessagesHash
229+
stateInput.incomingMessagesHash
144230
),
145231
pendingSTBatches: new AppliedBatchHashList(
146-
publicInput.remainders.pendingSTBatchesHash
232+
stateInput.remainders.pendingSTBatchesHash
147233
),
148234
witnessedRoots: new WitnessedRootHashList(
149-
publicInput.remainders.witnessedRootsHash
235+
stateInput.remainders.witnessedRootsHash,
236+
stateInput.remainders.witnessedRootsPreimage
150237
),
151-
stateRoot: publicInput.stateRoot,
152-
blockHashRoot: publicInput.blockHashRoot,
153-
blockNumber: publicInput.blockNumber,
238+
stateRoot: stateInput.stateRoot,
239+
blockHashRoot: stateInput.blockHashRoot,
240+
blockNumber: stateInput.blockNumber,
154241
networkState,
155242
blockWitness,
156243
});
@@ -167,6 +254,7 @@ export class BlockProverState {
167254
this.pendingSTBatches.commitment,
168255
this.incomingMessages.commitment,
169256
this.witnessedRoots.commitment,
257+
this.witnessedRoots.preimage,
170258
this.stateRoot,
171259
this.blockHashRoot,
172260
this.blockNumber,
@@ -182,14 +270,14 @@ export class BlockProverState {
182270
eternalTransactionsList: new TransactionHashList(fields[1]),
183271
pendingSTBatches: new AppliedBatchHashList(fields[2]),
184272
incomingMessages: new MinaActionsHashList(fields[3]),
185-
witnessedRoots: new WitnessedRootHashList(fields[4]),
186-
stateRoot: fields[5],
187-
blockHashRoot: fields[6],
188-
blockNumber: fields[7],
189-
networkState: new NetworkState(NetworkState.fromFields(fields.slice(8))),
273+
witnessedRoots: new WitnessedRootHashList(fields[4], fields[5]),
274+
stateRoot: fields[6],
275+
blockHashRoot: fields[7],
276+
blockNumber: fields[8],
277+
networkState: new NetworkState(NetworkState.fromFields(fields.slice(9))),
190278
blockWitness: new BlockHashMerkleTreeWitness(
191279
BlockHashMerkleTreeWitness.fromFields(
192-
fields.slice(8 + NetworkState.sizeInFields())
280+
fields.slice(9 + NetworkState.sizeInFields())
193281
)
194282
),
195283
});
@@ -230,6 +318,11 @@ export class BlockProverState {
230318
condition,
231319
a.witnessedRoots.commitment,
232320
b.witnessedRoots.commitment
321+
),
322+
Provable.if(
323+
condition,
324+
a.witnessedRoots.preimage,
325+
b.witnessedRoots.preimage
233326
)
234327
),
235328
stateRoot: Provable.if(condition, a.stateRoot, b.stateRoot),
@@ -250,51 +343,30 @@ export class BlockProverState {
250343
}
251344
}
252345

253-
export const BlockProverStateCommitments = {
254-
remainders: {
255-
// Commitment to the list of unprocessed (pending) batches of STs that need to be proven
256-
pendingSTBatchesHash: Field,
257-
witnessedRootsHash: Field,
258-
bundlesHash: Field,
259-
},
260-
eternalTransactionsHash: Field,
261-
incomingMessagesHash: Field,
262-
stateRoot: Field,
263-
blockHashRoot: Field,
264-
blockNumber: Field,
265-
networkStateHash: Field,
266-
};
267-
268-
export class BlockProverPublicInput extends Struct(
269-
BlockProverStateCommitments
270-
) {}
271-
272-
export class BlockProverPublicOutput extends Struct({
273-
...BlockProverStateCommitments,
274-
}) {
275-
public equals(input: BlockProverPublicInput): Bool {
276-
const output2 = BlockProverPublicOutput.toFields(input);
277-
const output1 = BlockProverPublicOutput.toFields(this);
278-
return output1
279-
.map((value1, index) => value1.equals(output2[index]))
280-
.reduce((a, b) => a.and(b));
281-
}
282-
}
283-
284346
export type BlockProof = Proof<BlockProverPublicInput, BlockProverPublicOutput>;
285347

286348
export interface BlockProvable
287349
extends WithZkProgrammable<BlockProverPublicInput, BlockProverPublicOutput>,
288350
CompilableModule {
289-
proveBlockBatch: (
351+
proveBlockBatchNoProofs: (
290352
publicInput: BlockProverPublicInput,
353+
stateWitness: BlockProverStateInput,
291354
networkState: NetworkState,
292355
blockWitness: BlockHashMerkleTreeWitness,
293-
stateTransitionProof: StateTransitionProof,
356+
batch: BlockArgumentsBatch,
357+
finalize: Bool
358+
) => Promise<BlockProverPublicOutput>;
359+
360+
proveBlockBatchWithProofs: (
361+
publicInput: BlockProverPublicInput,
362+
stateWitness: BlockProverStateInput,
363+
networkState: NetworkState,
364+
blockWitness: BlockHashMerkleTreeWitness,
365+
batch: BlockArgumentsBatch,
294366
deferSTProof: Bool,
295-
transactionProof: TransactionProof,
296367
deferTransactionProof: Bool,
297-
batch: BlockArgumentsBatch
368+
stateTransitionProof: StateTransitionProof,
369+
transactionProof: TransactionProof
298370
) => Promise<BlockProverPublicOutput>;
299371

300372
merge: (

0 commit comments

Comments
 (0)