Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Estimate tx size #6928

Merged
merged 1 commit into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions yarn-project/circuit-types/src/tx/tx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
Proof,
PublicCallRequest,
} from '@aztec/circuits.js';
import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection';
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';

import { type GetUnencryptedLogsResponse } from '../logs/get_unencrypted_logs_response.js';
Expand Down Expand Up @@ -193,6 +194,18 @@ export class Tx {
};
}

getSize() {
return (
this.data.getSize() +
this.proof.buffer.length +
this.noteEncryptedLogs.getSerializedLength() +
this.encryptedLogs.getSerializedLength() +
this.unencryptedLogs.getSerializedLength() +
arraySerializedSizeOfNonEmpty(this.enqueuedPublicFunctionCalls) +
arraySerializedSizeOfNonEmpty([this.publicTeardownFunctionCall])
);
}

/**
* Convenience function to get a hash out of a tx or a tx-like.
* @param tx - Tx-like object.
Expand Down
4 changes: 4 additions & 0 deletions yarn-project/circuits.js/src/structs/content_commitment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ export class ContentCommitment {
}
}

getSize() {
return this.toBuffer().length;
}

toBuffer() {
return serializeToBuffer(this.txTreeHeight, this.txsEffectsHash, this.inHash, this.outHash);
}
Expand Down
4 changes: 4 additions & 0 deletions yarn-project/circuits.js/src/structs/gas_settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ export class GasSettings {
public readonly inclusionFee: Fr,
) {}

getSize(): number {
return this.toBuffer().length;
}

static from(args: {
gasLimits: FieldsOf<Gas>;
teardownGasLimits: FieldsOf<Gas>;
Expand Down
4 changes: 4 additions & 0 deletions yarn-project/circuits.js/src/structs/global_variables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ export class GlobalVariables {
public gasFees: GasFees,
) {}

getSize(): number {
return this.toBuffer().length;
}

static from(fields: FieldsOf<GlobalVariables>): GlobalVariables {
return new GlobalVariables(...GlobalVariables.getFields(fields));
}
Expand Down
10 changes: 10 additions & 0 deletions yarn-project/circuits.js/src/structs/header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ export class Header {
] as const;
}

getSize() {
return (
this.lastArchive.getSize() +
this.contentCommitment.getSize() +
this.state.getSize() +
this.globalVariables.getSize() +
this.totalFees.size
);
}

toBuffer() {
return serializeToBuffer(...Header.getFields(this));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { type FieldsOf, makeTuple } from '@aztec/foundation/array';
import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection';
import { Fr } from '@aztec/foundation/fields';
import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize';

Expand Down Expand Up @@ -67,6 +68,22 @@ export class CombinedAccumulatedData {
public gasUsed: Gas,
) {}

getSize() {
return (
arraySerializedSizeOfNonEmpty(this.newNoteHashes) +
arraySerializedSizeOfNonEmpty(this.newNullifiers) +
arraySerializedSizeOfNonEmpty(this.newL2ToL1Msgs) +
this.noteEncryptedLogsHash.size +
this.encryptedLogsHash.size +
this.unencryptedLogsHash.size +
this.noteEncryptedLogPreimagesLength.size +
this.encryptedLogPreimagesLength.size +
this.unencryptedLogPreimagesLength.size +
arraySerializedSizeOfNonEmpty(this.publicDataUpdateRequests) +
this.gasUsed.toBuffer().length
);
}

static getFields(fields: FieldsOf<CombinedAccumulatedData>) {
return [
fields.newNoteHashes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ export class CombinedConstantData {
return serializeToBuffer(this.historicalHeader, this.txContext, this.globalVariables);
}

getSize() {
return this.historicalHeader.getSize() + this.txContext.getSize() + this.globalVariables.getSize();
}

static from({ historicalHeader, txContext, globalVariables }: FieldsOf<CombinedConstantData>): CombinedConstantData {
return new CombinedConstantData(historicalHeader, txContext, globalVariables);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { makeTuple } from '@aztec/foundation/array';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection';
import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize';

import { MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX } from '../../constants.gen.js';
Expand Down Expand Up @@ -35,6 +36,15 @@ export class PartialPrivateTailPublicInputsForPublic {
public publicTeardownCallStack: Tuple<CallRequest, typeof MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX>,
) {}

getSize() {
return (
this.validationRequests.getSize() +
this.endNonRevertibleData.getSize() +
this.end.getSize() +
arraySerializedSizeOfNonEmpty(this.publicTeardownCallStack)
);
}

get needsSetup() {
return !this.endNonRevertibleData.publicCallStack[0].isEmpty();
}
Expand Down Expand Up @@ -87,6 +97,10 @@ export class PartialPrivateTailPublicInputsForRollup {
);
}

getSize() {
return this.rollupValidationRequests.getSize() + this.end.getSize();
}

toBuffer() {
return serializeToBuffer(this.rollupValidationRequests, this.end);
}
Expand Down Expand Up @@ -131,6 +145,16 @@ export class PrivateKernelTailCircuitPublicInputs {
return (this.forPublic ?? this.forRollup)!;
}

getSize() {
return (
(this.forPublic?.getSize() ?? 0) +
(this.forRollup?.getSize() ?? 0) +
this.constants.getSize() +
this.revertCode.getSerializedLength() +
this.feePayer.size
);
}

toPublicKernelCircuitPublicInputs() {
if (!this.forPublic) {
throw new Error('Private tail public inputs is not for public circuit.');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { makeTuple } from '@aztec/foundation/array';
import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection';
import { Fr } from '@aztec/foundation/fields';
import { BufferReader, FieldReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize';

Expand Down Expand Up @@ -67,6 +68,20 @@ export class PublicAccumulatedData {
public readonly gasUsed: Gas,
) {}

getSize() {
return (
arraySerializedSizeOfNonEmpty(this.newNoteHashes) +
arraySerializedSizeOfNonEmpty(this.newNullifiers) +
arraySerializedSizeOfNonEmpty(this.newL2ToL1Msgs) +
arraySerializedSizeOfNonEmpty(this.noteEncryptedLogsHashes) +
arraySerializedSizeOfNonEmpty(this.encryptedLogsHashes) +
arraySerializedSizeOfNonEmpty(this.unencryptedLogsHashes) +
arraySerializedSizeOfNonEmpty(this.publicDataUpdateRequests) +
arraySerializedSizeOfNonEmpty(this.publicCallStack) +
this.gasUsed.toBuffer().length
);
}

toBuffer() {
return serializeToBuffer(
this.newNoteHashes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ export class PartialStateReference {
public readonly publicDataTree: AppendOnlyTreeSnapshot,
) {}

getSize() {
return this.noteHashTree.getSize() + this.nullifierTree.getSize() + this.publicDataTree.getSize();
}

static fromBuffer(buffer: Buffer | BufferReader): PartialStateReference {
const reader = BufferReader.asReader(buffer);
return new PartialStateReference(
Expand Down
4 changes: 4 additions & 0 deletions yarn-project/circuits.js/src/structs/public_call_request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ export class PublicCallRequest {
public args: Fr[],
) {}

getSize() {
return this.isEmpty() ? 0 : this.toBuffer().length;
}

/**
* Serialize this as a buffer.
* @returns The buffer.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ export class AppendOnlyTreeSnapshot {
public nextAvailableLeafIndex: UInt32,
) {}

getSize() {
return this.root.size + 4;
}

toBuffer() {
return serializeToBuffer(this.root, this.nextAvailableLeafIndex);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export class RollupValidationRequests {
public maxBlockNumber: MaxBlockNumber,
) {}

getSize() {
return this.toBuffer().length;
}

toBuffer() {
return serializeToBuffer(this.maxBlockNumber);
}
Expand Down
4 changes: 4 additions & 0 deletions yarn-project/circuits.js/src/structs/state_reference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ export class StateReference {
public partial: PartialStateReference,
) {}

getSize() {
return this.l1ToL2MessageTree.getSize() + this.partial.getSize();
}

toBuffer() {
// Note: The order here must match the order in the HeaderLib solidity library.
return serializeToBuffer(this.l1ToL2MessageTree, this.partial);
Expand Down
4 changes: 4 additions & 0 deletions yarn-project/circuits.js/src/structs/tx_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ export class TxContext {
this.version = new Fr(version);
}

getSize() {
return this.chainId.size + this.version.size + this.gasSettings.getSize();
}

clone() {
return new TxContext(this.chainId, this.version, this.gasSettings.clone());
}
Expand Down
12 changes: 12 additions & 0 deletions yarn-project/circuits.js/src/structs/validation_requests.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { makeTuple } from '@aztec/foundation/array';
import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection';
import { type Fr } from '@aztec/foundation/fields';
import { BufferReader, FieldReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize';

Expand Down Expand Up @@ -54,6 +55,17 @@ export class ValidationRequests {
public publicDataReads: Tuple<PublicDataRead, typeof MAX_PUBLIC_DATA_READS_PER_TX>,
) {}

getSize() {
return (
this.forRollup.getSize() +
arraySerializedSizeOfNonEmpty(this.noteHashReadRequests) +
arraySerializedSizeOfNonEmpty(this.nullifierReadRequests) +
arraySerializedSizeOfNonEmpty(this.nullifierNonExistentReadRequests) +
arraySerializedSizeOfNonEmpty(this.scopedKeyValidationRequestsAndGenerators) +
arraySerializedSizeOfNonEmpty(this.publicDataReads)
);
}

toBuffer() {
return serializeToBuffer(
this.forRollup,
Expand Down
14 changes: 14 additions & 0 deletions yarn-project/foundation/src/collection/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,17 @@ export function arrayNonEmptyLength<T>(arr: T[], isEmpty: (item: T) => boolean):
export function times<T>(n: number, fn: (i: number) => T): T[] {
return [...Array(n).keys()].map(i => fn(i));
}

/**
* Returns the serialized size of all non-empty items in an array.
* @param arr - Array
* @returns The serialized size in bytes.
*/
export function arraySerializedSizeOfNonEmpty(
arr: (({ isZero: () => boolean } | { isEmpty: () => boolean }) & { toBuffer: () => Buffer })[],
) {
return arr
.filter(x => x && ('isZero' in x ? !x.isZero() : !x.isEmpty()))
.map(x => x!.toBuffer().length)
.reduce((a, b) => a + b, 0);
}
5 changes: 5 additions & 0 deletions yarn-project/foundation/src/fields/fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ abstract class BaseField {
return this.toBigInt();
}

/** Returns the size in bytes. */
get size(): number {
return BaseField.SIZE_IN_BYTES;
}

protected constructor(value: number | bigint | boolean | BaseField | Buffer) {
if (value instanceof Buffer) {
if (value.length > BaseField.SIZE_IN_BYTES) {
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/sequencer-client/src/sequencer/sequencer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,10 +321,10 @@ export class Sequencer {

const toReturn: Tx[] = [];
for (const tx of txs) {
const txSize = tx.getStats().size - tx.proof.toBuffer().length;
const txSize = tx.getSize() - tx.proof.toBuffer().length;
if (totalSize + txSize > maxSize) {
this.log.warn(
`Dropping tx ${tx.getTxHash()} with size ${txSize} due to exceeding ${maxSize} block size limit (currently at ${totalSize})`,
`Dropping tx ${tx.getTxHash()} with estimated size ${txSize} due to exceeding ${maxSize} block size limit (currently at ${totalSize})`,
);
continue;
}
Expand Down
Loading