-
Notifications
You must be signed in to change notification settings - Fork 292
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds a block builder that assembles an L2Block out of a set of processed txs without relying on base, merge, block root, or parity circuits, and works using only ts code. Keeps the same interface as the current block builder for drop-in replacement within the orchestrator.
- Loading branch information
1 parent
87e0a17
commit 54bde06
Showing
8 changed files
with
297 additions
and
119 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
export * from './variable_merkle_root.js'; | ||
|
||
/** | ||
* A leaf of an indexed merkle tree. | ||
*/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { padArrayEnd } from '@aztec/foundation/collection'; | ||
import { sha256Trunc } from '@aztec/foundation/crypto'; | ||
|
||
/** | ||
* Adapted from proving-state.ts -> findMergeLevel and unbalanced_tree.ts | ||
* Calculates the tree upwards layer by layer until we reach the root | ||
* The L1 calculation instead computes the tree from right to left (slightly cheaper gas) | ||
* TODO: A more thorough investigation of which method is cheaper, then use that method everywhere | ||
*/ | ||
export function computeVariableMerkleRoot(leaves: Buffer[], emptyLeaf?: Buffer, hasher = sha256Trunc): Buffer { | ||
// pad leaves to 2 | ||
if (leaves.length < 2) { | ||
if (emptyLeaf === undefined) { | ||
throw new Error('Cannot compute a Merkle root with less than 2 leaves'); | ||
} else { | ||
leaves = padArrayEnd(leaves, emptyLeaf, 2); | ||
} | ||
} | ||
|
||
const depth = Math.ceil(Math.log2(leaves.length)); | ||
let [layerWidth, nodeToShift] = | ||
leaves.length & 1 ? [leaves.length - 1, leaves[leaves.length - 1]] : [leaves.length, Buffer.alloc(0)]; | ||
// Allocate this layer's leaves and init the next layer up | ||
let thisLayer = leaves.slice(0, layerWidth); | ||
let nextLayer = []; | ||
for (let i = 0; i < depth; i++) { | ||
for (let j = 0; j < layerWidth; j += 2) { | ||
// Store the hash of each pair one layer up | ||
nextLayer[j / 2] = hasher(Buffer.concat([thisLayer[j], thisLayer[j + 1]])); | ||
} | ||
layerWidth /= 2; | ||
if (layerWidth & 1) { | ||
if (nodeToShift.length) { | ||
// If the next layer has odd length, and we have a node that needs to be shifted up, add it here | ||
nextLayer.push(nodeToShift); | ||
layerWidth += 1; | ||
nodeToShift = Buffer.alloc(0); | ||
} else { | ||
// If we don't have a node waiting to be shifted, store the next layer's final node to be shifted | ||
layerWidth -= 1; | ||
nodeToShift = nextLayer[layerWidth]; | ||
} | ||
} | ||
// reset the layers | ||
thisLayer = nextLayer; | ||
nextLayer = []; | ||
} | ||
// return the root | ||
return thisLayer[0]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,51 +1,7 @@ | ||
import { TestCircuitProver } from '@aztec/bb-prover'; | ||
import { | ||
type BlockSimulator, | ||
type MerkleTreeOperations, | ||
type ProcessedTx, | ||
type ProvingTicket, | ||
type SimulationBlockResult, | ||
} from '@aztec/circuit-types'; | ||
import { type Fr, type GlobalVariables } from '@aztec/circuits.js'; | ||
import { ProvingOrchestrator } from '@aztec/prover-client/orchestrator'; | ||
import { type SimulationProvider } from '@aztec/simulator'; | ||
import { type TelemetryClient } from '@aztec/telemetry-client'; | ||
import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; | ||
import { type BlockSimulator, type MerkleTreeOperations } from '@aztec/circuit-types'; | ||
|
||
/** | ||
* Implements a block simulator using a test circuit prover under the hood, which just simulates circuits and outputs empty proofs. | ||
* This class is temporary and should die once we switch from tx effects to tx objects submissions, since sequencers won't have | ||
* the need to create L2 block headers to submit to L1. When we do that, we should also remove the references to the | ||
* prover-client and bb-prover packages from this package. | ||
*/ | ||
export class BlockBuilder implements BlockSimulator { | ||
private orchestrator: ProvingOrchestrator; | ||
constructor(db: MerkleTreeOperations, simulationProvider: SimulationProvider, telemetry: TelemetryClient) { | ||
const testProver = new TestCircuitProver(telemetry, simulationProvider); | ||
this.orchestrator = new ProvingOrchestrator(db, testProver, telemetry); | ||
} | ||
|
||
startNewBlock(numTxs: number, globalVariables: GlobalVariables, l1ToL2Messages: Fr[]): Promise<ProvingTicket> { | ||
return this.orchestrator.startNewBlock(numTxs, globalVariables, l1ToL2Messages); | ||
} | ||
cancelBlock(): void { | ||
this.orchestrator.cancelBlock(); | ||
} | ||
finaliseBlock(): Promise<SimulationBlockResult> { | ||
return this.orchestrator.finaliseBlock(); | ||
} | ||
setBlockCompleted(): Promise<void> { | ||
return this.orchestrator.setBlockCompleted(); | ||
} | ||
addNewTx(tx: ProcessedTx): Promise<void> { | ||
return this.orchestrator.addNewTx(tx); | ||
} | ||
} | ||
|
||
export class BlockBuilderFactory { | ||
constructor(private simulationProvider: SimulationProvider, private telemetry?: TelemetryClient) {} | ||
|
||
create(db: MerkleTreeOperations): BlockSimulator { | ||
return new BlockBuilder(db, this.simulationProvider, this.telemetry ?? new NoopTelemetryClient()); | ||
} | ||
export * from './orchestrator.js'; | ||
export * from './light.js'; | ||
export interface BlockBuilderFactory { | ||
create(db: MerkleTreeOperations): BlockSimulator; | ||
} |
Oops, something went wrong.