From c9efe9ff99661c64ffcc9255c63bc394af90bb25 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Mon, 17 Feb 2025 20:19:28 +0000 Subject: [PATCH 1/7] chore: cleanup libp2p logger --- .../foundation/src/log/pino-logger.ts | 13 +--- .../p2p/src/services/libp2p/libp2p_logger.ts | 60 +++++-------------- 2 files changed, 16 insertions(+), 57 deletions(-) diff --git a/yarn-project/foundation/src/log/pino-logger.ts b/yarn-project/foundation/src/log/pino-logger.ts index 38991a706cd6..d1f729a6244d 100644 --- a/yarn-project/foundation/src/log/pino-logger.ts +++ b/yarn-project/foundation/src/log/pino-logger.ts @@ -11,23 +11,14 @@ import { getLogLevelFromFilters, parseEnv } from './log-filters.js'; import { type LogLevel } from './log-levels.js'; import { type LogData, type LogFn } from './log_fn.js'; -export function createLogger(module: string, fixedTerms = {}): Logger { +export function createLogger(module: string): Logger { module = logNameHandlers.reduce((moduleName, handler) => handler(moduleName), module.replace(/^aztec:/, '')); const pinoLogger = logger.child({ module }, { level: getLogLevelFromFilters(logFilters, module) }); - // Only perform copy of data if fixed terms are provided - const hasFixedTerms = Object.keys(fixedTerms).length > 0; - // We check manually for isLevelEnabled to avoid calling processLogData unnecessarily. // Note that isLevelEnabled is missing from the browser version of pino. const logFn = (level: LogLevel, msg: string, data?: unknown) => - isLevelEnabled(pinoLogger, level) && - pinoLogger[level]( - hasFixedTerms - ? processLogData({ ...fixedTerms, ...(data ?? {}) } as LogData) - : processLogData((data as LogData) ?? {}), - msg, - ); + isLevelEnabled(pinoLogger, level) && pinoLogger[level](processLogData((data as LogData) ?? {}), msg); return { silent: () => {}, diff --git a/yarn-project/p2p/src/services/libp2p/libp2p_logger.ts b/yarn-project/p2p/src/services/libp2p/libp2p_logger.ts index 02dc823c6632..07089c3e8406 100644 --- a/yarn-project/p2p/src/services/libp2p/libp2p_logger.ts +++ b/yarn-project/p2p/src/services/libp2p/libp2p_logger.ts @@ -12,67 +12,35 @@ export function createLibp2pComponentLogger(namespace: string, fixedTerms = {}): }; } -function createLibp2pLogger(component: string, fixedTerms = {}): Logger { - const logger = createLogger(component, fixedTerms); +function createLibp2pLogger(component: string): Logger { + const logger = createLogger(component); // Default log level is trace as this is super super noisy - const logFn = (formatter: any, ...args: any[]) => { - // Handle %p format specifier by manually replacing with args - if (typeof formatter === 'string' && args.length > 0) { - // Handle %p, %a, %s and %d format specifiers - const parts = formatter.split(/(%p|%a|%s|%d)/); - let result = parts[0]; - let argIndex = 0; - - for (let i = 1; i < parts.length; i += 2) { - if (argIndex < args.length) { - result += String(args[argIndex]) + (parts[i + 1] || ''); - argIndex++; - } - } - - formatter = result; - // Only keep non-format args as data - args = args.slice(argIndex); - } - - // Handle object args by spreading them, but only if they weren't used in formatting - if (args.length === 1 && typeof args[0] === 'object') { - logger.trace(formatter, args[0]); - } else if (args.length > 0) { - // If we have remaining args after formatting, pass them as data - logger.trace(formatter, { _args: args }); - } else { - logger.trace(formatter); - } + const logFn = (message: string, ...args: unknown[]) => { + logger.trace(message, ...args); }; return Object.assign(logFn, { enabled: logger.isLevelEnabled('debug'), - error(...args: any[]) { - const [msg, ...rest] = args; - logger.error(msg as string, ...rest); + error(message: string, ...args: unknown[]) { + logger.error(message, ...args); }, - debug(...args: any[]) { - const [msg, ...rest] = args; - logger.debug(msg as string, ...rest); + debug(message: string, ...args: unknown[]) { + logger.debug(message, ...args); }, - info(...args: any[]) { - const [msg, ...rest] = args; - logger.info(msg as string, ...rest); + info(message: string, ...args: unknown[]) { + logger.info(message, ...args); }, - warn(...args: any[]) { - const [msg, ...rest] = args; - logger.warn(msg as string, ...rest); + warn(message: string, ...args: unknown[]) { + logger.warn(message, ...args); }, - trace(...args: any[]) { - const [msg, ...rest] = args; - logger.trace(msg as string, ...rest); + trace(message: string, ...args: unknown[]) { + logger.trace(message, ...args); }, }); } From 0c7288eaebbef359daee28a2ddac530bfc83eed6 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Mon, 17 Feb 2025 20:21:36 +0000 Subject: [PATCH 2/7] fix: simplify libp2p logger, remove fixed terms --- yarn-project/p2p/src/services/libp2p/libp2p_logger.ts | 4 ++-- yarn-project/p2p/src/services/libp2p/libp2p_service.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn-project/p2p/src/services/libp2p/libp2p_logger.ts b/yarn-project/p2p/src/services/libp2p/libp2p_logger.ts index 07089c3e8406..5fced01784b7 100644 --- a/yarn-project/p2p/src/services/libp2p/libp2p_logger.ts +++ b/yarn-project/p2p/src/services/libp2p/libp2p_logger.ts @@ -6,9 +6,9 @@ import { type ComponentLogger, type Logger } from '@libp2p/interface'; * Creates a libp2p compatible logger that wraps our pino logger. * This adapter implements the ComponentLogger interface required by libp2p. */ -export function createLibp2pComponentLogger(namespace: string, fixedTerms = {}): ComponentLogger { +export function createLibp2pComponentLogger(namespace: string): ComponentLogger { return { - forComponent: (component: string) => createLibp2pLogger(`${namespace}:${component}`, fixedTerms), + forComponent: (component: string) => createLibp2pLogger(`${namespace}:${component}`), }; } diff --git a/yarn-project/p2p/src/services/libp2p/libp2p_service.ts b/yarn-project/p2p/src/services/libp2p/libp2p_service.ts index d679b2a989d7..432a4110e249 100644 --- a/yarn-project/p2p/src/services/libp2p/libp2p_service.ts +++ b/yarn-project/p2p/src/services/libp2p/libp2p_service.ts @@ -269,7 +269,7 @@ export class LibP2PService extends WithTracer implement }), }, // Fix the peer id in libp2p logs so we can see the source of the log - logger: createLibp2pComponentLogger(logger.module, { sourcePeerId: peerId }), + logger: createLibp2pComponentLogger(logger.module), }); return new LibP2PService( From fb2b07a0d8102b57ec264f6ee7b169b836d78635 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 18 Feb 2025 11:37:30 +0000 Subject: [PATCH 3/7] fix: move libp2p logger into foundation - use pino directly --- yarn-project/foundation/src/log/index.ts | 1 + .../foundation/src/log/libp2p_logger.ts | 48 +++++++++++++++++++ .../foundation/src/log/pino-logger.ts | 4 +- .../p2p/src/services/libp2p/libp2p_logger.ts | 46 ------------------ .../p2p/src/services/libp2p/libp2p_service.ts | 2 +- 5 files changed, 52 insertions(+), 49 deletions(-) create mode 100644 yarn-project/foundation/src/log/libp2p_logger.ts diff --git a/yarn-project/foundation/src/log/index.ts b/yarn-project/foundation/src/log/index.ts index 8e61bc817825..dcc425e972c2 100644 --- a/yarn-project/foundation/src/log/index.ts +++ b/yarn-project/foundation/src/log/index.ts @@ -3,3 +3,4 @@ export * from './debug.js'; export * from './pino-logger.js'; export * from './log_history.js'; export * from './log_fn.js'; +export * from './libp2p_logger.js'; diff --git a/yarn-project/foundation/src/log/libp2p_logger.ts b/yarn-project/foundation/src/log/libp2p_logger.ts new file mode 100644 index 000000000000..3877d7ac137d --- /dev/null +++ b/yarn-project/foundation/src/log/libp2p_logger.ts @@ -0,0 +1,48 @@ +import { type ComponentLogger, type Logger } from '@libp2p/interface'; + +import { getLogLevelFromFilters } from './log-filters.js'; +import { logFilters, logger } from './pino-logger.js'; + +/** + * Creates a libp2p compatible logger that wraps our pino logger. + * This adapter implements the ComponentLogger interface required by libp2p. + */ +export function createLibp2pComponentLogger(namespace: string): ComponentLogger { + return { + forComponent: (component: string) => createLibp2pLogger(`${namespace}:${component}`), + }; +} + +function createLibp2pLogger(component: string): Logger { + // Create a direct pino logger instance for libp2p that supports string interpolation + const log = logger.child({ module: component }, { level: getLogLevelFromFilters(logFilters, component) }); + + // Default log level is trace as this is super super noisy + const logFn = (message: string, ...args: unknown[]) => { + log.trace(message, ...args); + }; + + return Object.assign(logFn, { + enabled: log.isLevelEnabled('debug'), + + error(message: string, ...args: unknown[]) { + log.error(message, ...args); + }, + + debug(message: string, ...args: unknown[]) { + log.debug(message, ...args); + }, + + info(message: string, ...args: unknown[]) { + log.info(message, ...args); + }, + + warn(message: string, ...args: unknown[]) { + log.warn(message, ...args); + }, + + trace(message: string, ...args: unknown[]) { + log.trace(message, ...args); + }, + }); +} diff --git a/yarn-project/foundation/src/log/pino-logger.ts b/yarn-project/foundation/src/log/pino-logger.ts index d1f729a6244d..8b5a3232c209 100644 --- a/yarn-project/foundation/src/log/pino-logger.ts +++ b/yarn-project/foundation/src/log/pino-logger.ts @@ -83,7 +83,7 @@ function isLevelEnabled(logger: pino.Logger<'verbose', boolean>, level: LogLevel // Load log levels from environment variables. const defaultLogLevel = process.env.NODE_ENV === 'test' ? 'silent' : 'info'; -const [logLevel, logFilters] = parseEnv(process.env.LOG_LEVEL, defaultLogLevel); +export const [logLevel, logFilters] = parseEnv(process.env.LOG_LEVEL, defaultLogLevel); // Define custom logging levels for pino. const customLevels = { verbose: 25 }; @@ -169,7 +169,7 @@ function makeLogger() { } } -const logger = makeLogger(); +export const logger = makeLogger(); // Log the logger configuration. logger.verbose( diff --git a/yarn-project/p2p/src/services/libp2p/libp2p_logger.ts b/yarn-project/p2p/src/services/libp2p/libp2p_logger.ts index 5fced01784b7..e69de29bb2d1 100644 --- a/yarn-project/p2p/src/services/libp2p/libp2p_logger.ts +++ b/yarn-project/p2p/src/services/libp2p/libp2p_logger.ts @@ -1,46 +0,0 @@ -import { createLogger } from '@aztec/foundation/log'; - -import { type ComponentLogger, type Logger } from '@libp2p/interface'; - -/** - * Creates a libp2p compatible logger that wraps our pino logger. - * This adapter implements the ComponentLogger interface required by libp2p. - */ -export function createLibp2pComponentLogger(namespace: string): ComponentLogger { - return { - forComponent: (component: string) => createLibp2pLogger(`${namespace}:${component}`), - }; -} - -function createLibp2pLogger(component: string): Logger { - const logger = createLogger(component); - - // Default log level is trace as this is super super noisy - const logFn = (message: string, ...args: unknown[]) => { - logger.trace(message, ...args); - }; - - return Object.assign(logFn, { - enabled: logger.isLevelEnabled('debug'), - - error(message: string, ...args: unknown[]) { - logger.error(message, ...args); - }, - - debug(message: string, ...args: unknown[]) { - logger.debug(message, ...args); - }, - - info(message: string, ...args: unknown[]) { - logger.info(message, ...args); - }, - - warn(message: string, ...args: unknown[]) { - logger.warn(message, ...args); - }, - - trace(message: string, ...args: unknown[]) { - logger.trace(message, ...args); - }, - }); -} diff --git a/yarn-project/p2p/src/services/libp2p/libp2p_service.ts b/yarn-project/p2p/src/services/libp2p/libp2p_service.ts index 432a4110e249..4453cc8746d8 100644 --- a/yarn-project/p2p/src/services/libp2p/libp2p_service.ts +++ b/yarn-project/p2p/src/services/libp2p/libp2p_service.ts @@ -20,6 +20,7 @@ import { import { Fr } from '@aztec/circuits.js'; import { type EpochCacheInterface } from '@aztec/epoch-cache'; import { createLogger } from '@aztec/foundation/log'; +import { createLibp2pComponentLogger } from '@aztec/foundation/log'; import { SerialQueue } from '@aztec/foundation/queue'; import { RunningPromise } from '@aztec/foundation/running-promise'; import type { AztecAsyncKVStore } from '@aztec/kv-store'; @@ -65,7 +66,6 @@ import { pingHandler, reqRespBlockHandler, reqRespTxHandler, statusHandler } fro import { ReqResp } from '../reqresp/reqresp.js'; import type { P2PService, PeerDiscoveryService } from '../service.js'; import { GossipSubEvent } from '../types.js'; -import { createLibp2pComponentLogger } from './libp2p_logger.js'; interface MessageValidator { validator: { From 646eadf6263182fc03ff5cc128ba31831e31a860 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 18 Feb 2025 11:38:49 +0000 Subject: [PATCH 4/7] fmt --- yarn-project/p2p/src/services/libp2p/libp2p_service.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/yarn-project/p2p/src/services/libp2p/libp2p_service.ts b/yarn-project/p2p/src/services/libp2p/libp2p_service.ts index 4453cc8746d8..79dc9675e8bd 100644 --- a/yarn-project/p2p/src/services/libp2p/libp2p_service.ts +++ b/yarn-project/p2p/src/services/libp2p/libp2p_service.ts @@ -19,8 +19,7 @@ import { } from '@aztec/circuit-types'; import { Fr } from '@aztec/circuits.js'; import { type EpochCacheInterface } from '@aztec/epoch-cache'; -import { createLogger } from '@aztec/foundation/log'; -import { createLibp2pComponentLogger } from '@aztec/foundation/log'; +import { createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log'; import { SerialQueue } from '@aztec/foundation/queue'; import { RunningPromise } from '@aztec/foundation/running-promise'; import type { AztecAsyncKVStore } from '@aztec/kv-store'; From 484e3614270f78c78afcea94be3941d4de576f54 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 18 Feb 2025 13:07:02 +0000 Subject: [PATCH 5/7] fix: review --- yarn-project/foundation/package.json | 1 + yarn-project/foundation/src/log/libp2p_logger.ts | 4 ++-- yarn-project/p2p/src/services/libp2p/libp2p_logger.ts | 0 yarn-project/p2p/src/services/libp2p/libp2p_service.ts | 1 - yarn-project/yarn.lock | 1 + 5 files changed, 4 insertions(+), 3 deletions(-) delete mode 100644 yarn-project/p2p/src/services/libp2p/libp2p_logger.ts diff --git a/yarn-project/foundation/package.json b/yarn-project/foundation/package.json index 97aa9dae7e41..d284594f165d 100644 --- a/yarn-project/foundation/package.json +++ b/yarn-project/foundation/package.json @@ -132,6 +132,7 @@ }, "devDependencies": { "@jest/globals": "^29.5.0", + "@libp2p/interface": "1.3.1", "@types/bn.js": "^5.1.3", "@types/debug": "^4.1.7", "@types/detect-node": "^2.0.0", diff --git a/yarn-project/foundation/src/log/libp2p_logger.ts b/yarn-project/foundation/src/log/libp2p_logger.ts index 3877d7ac137d..b90de4c6db01 100644 --- a/yarn-project/foundation/src/log/libp2p_logger.ts +++ b/yarn-project/foundation/src/log/libp2p_logger.ts @@ -24,9 +24,9 @@ function createLibp2pLogger(component: string): Logger { return Object.assign(logFn, { enabled: log.isLevelEnabled('debug'), - error(message: string, ...args: unknown[]) { - log.error(message, ...args); + // We write error outputs as debug as they are often expected, e.g. connection errors can happen in happy paths + log.debug(message, ...args); }, debug(message: string, ...args: unknown[]) { diff --git a/yarn-project/p2p/src/services/libp2p/libp2p_logger.ts b/yarn-project/p2p/src/services/libp2p/libp2p_logger.ts deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/yarn-project/p2p/src/services/libp2p/libp2p_service.ts b/yarn-project/p2p/src/services/libp2p/libp2p_service.ts index 79dc9675e8bd..45a5697d29be 100644 --- a/yarn-project/p2p/src/services/libp2p/libp2p_service.ts +++ b/yarn-project/p2p/src/services/libp2p/libp2p_service.ts @@ -267,7 +267,6 @@ export class LibP2PService extends WithTracer implement connectionManager: components.connectionManager, }), }, - // Fix the peer id in libp2p logs so we can see the source of the log logger: createLibp2pComponentLogger(logger.module), }); diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 948ec03aacf0..48bb0b62a28c 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -759,6 +759,7 @@ __metadata: "@aztec/bb.js": "portal:../../barretenberg/ts" "@jest/globals": "npm:^29.5.0" "@koa/cors": "npm:^5.0.0" + "@libp2p/interface": "npm:1.3.1" "@noble/curves": "npm:^1.2.0" "@types/bn.js": "npm:^5.1.3" "@types/debug": "npm:^4.1.7" From 0a6c981351c48929207bf1f68acdfa0219f00bf5 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Mon, 17 Feb 2025 18:36:05 +0000 Subject: [PATCH 6/7] chore: include entire transaction in block proposal --- .../aztec-node/src/aztec-node/server.ts | 2 +- .../circuit-types/src/p2p/block_proposal.ts | 8 +- .../src/p2p/consensus_payload.ts | 88 +++++++++++++++++++ yarn-project/circuit-types/src/p2p/mocks.ts | 24 ++++- .../end-to-end/src/e2e_p2p/reex.test.ts | 5 +- .../src/job/epoch-proving-job.test.ts | 6 +- .../src/sequencer/sequencer.test.ts | 12 ++- .../src/sequencer/sequencer.ts | 9 +- .../simulator/src/public/public_processor.ts | 7 +- .../src/duties/validation_service.ts | 16 ++-- .../validator-client/src/validator.test.ts | 25 +++--- .../validator-client/src/validator.ts | 59 +++++++------ 12 files changed, 194 insertions(+), 67 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 8c07c81fdc6f..7edc2614acaa 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -878,7 +878,7 @@ export class AztecNodeService implements AztecNode, Traceable { const processor = publicProcessorFactory.create(fork, newGlobalVariables, skipFeeEnforcement); // REFACTOR: Consider merging ProcessReturnValues into ProcessedTx - const [processedTxs, failedTxs, returns] = await processor.process([tx]); + const [processedTxs, failedTxs, _txs, returns] = await processor.process([tx]); // REFACTOR: Consider returning the error rather than throwing if (failedTxs.length) { this.log.warn(`Simulated tx ${txHash} fails: ${failedTxs[0].error}`, { txHash }); diff --git a/yarn-project/circuit-types/src/p2p/block_proposal.ts b/yarn-project/circuit-types/src/p2p/block_proposal.ts index f6acc39b1706..e5d9ee703668 100644 --- a/yarn-project/circuit-types/src/p2p/block_proposal.ts +++ b/yarn-project/circuit-types/src/p2p/block_proposal.ts @@ -5,7 +5,7 @@ import { Signature } from '@aztec/foundation/eth-signature'; import { type Fr } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { ConsensusPayload } from './consensus_payload.js'; +import { BlockProposalPayload } from './consensus_payload.js'; import { Gossipable } from './gossipable.js'; import { SignatureDomainSeparator, @@ -33,7 +33,7 @@ export class BlockProposal extends Gossipable { constructor( /** The payload of the message, and what the signature is over */ - public readonly payload: ConsensusPayload, + public readonly payload: BlockProposalPayload, /** The signer of the BlockProposal over the header of the new block*/ public readonly signature: Signature, @@ -58,7 +58,7 @@ export class BlockProposal extends Gossipable { } static async createProposalFromSigner( - payload: ConsensusPayload, + payload: BlockProposalPayload, payloadSigner: (payload: Buffer32) => Promise, ) { const hashed = await getHashedSignaturePayload(payload, SignatureDomainSeparator.blockProposal); @@ -93,7 +93,7 @@ export class BlockProposal extends Gossipable { static fromBuffer(buf: Buffer | BufferReader): BlockProposal { const reader = BufferReader.asReader(buf); - return new BlockProposal(reader.readObject(ConsensusPayload), reader.readObject(Signature)); + return new BlockProposal(reader.readObject(BlockProposalPayload), reader.readObject(Signature)); } getSize(): number { diff --git a/yarn-project/circuit-types/src/p2p/consensus_payload.ts b/yarn-project/circuit-types/src/p2p/consensus_payload.ts index f9cc5de5deef..be1a1455406a 100644 --- a/yarn-project/circuit-types/src/p2p/consensus_payload.ts +++ b/yarn-project/circuit-types/src/p2p/consensus_payload.ts @@ -7,9 +7,97 @@ import { type FieldsOf } from '@aztec/foundation/types'; import { encodeAbiParameters, parseAbiParameters } from 'viem'; import { z } from 'zod'; +import { Tx } from '../tx/tx.js'; import { TxHash } from '../tx/tx_hash.js'; import { type Signable, type SignatureDomainSeparator } from './signature_utils.js'; +export class BlockProposalPayload implements Signable { + private size: number | undefined; + + constructor( + /** The block header the attestation is made over */ + public readonly header: BlockHeader, + // TODO(https://github.com/AztecProtocol/aztec-packages/pull/7727#discussion_r1713670830): temporary + public readonly archive: Fr, + /** The sequence of transactions in the block */ + public readonly txs: Tx[], + ) {} + + static get schema() { + return z + .object({ + header: BlockHeader.schema, + archive: Fr.schema, + txs: z.array(Tx.schema), + }) + .transform(obj => new BlockProposalPayload(obj.header, obj.archive, obj.txs)); + } + + static getFields(fields: FieldsOf) { + return [fields.header, fields.archive, fields.txs] as const; + } + + async getPayloadToSign(domainSeparator: SignatureDomainSeparator): Promise { + const abi = parseAbiParameters('uint8, (bytes32, bytes32, (uint256), bytes, bytes32[])'); + const txArray = this.txs.map(tx => tx.toBuffer().toString('hex') as `0x${string}`); + const encodedData = encodeAbiParameters(abi, [ + domainSeparator, + [ + this.archive.toString(), + (await this.header.hash()).toString(), + [0n] /* @todo See #9963 */, + this.header.toString(), + txArray, + ], + ] as const); + + return hexToBuffer(encodedData); + } + + toBuffer(): Buffer { + const buffer = serializeToBuffer([this.header, this.archive, this.txs.length, this.txs]); + this.size = buffer.length; + return buffer; + } + + static fromBuffer(buf: Buffer | BufferReader): BlockProposalPayload { + const reader = BufferReader.asReader(buf); + return new BlockProposalPayload( + reader.readObject(BlockHeader), + reader.readObject(Fr), + reader.readArray(reader.readNumber(), Tx), + ); + } + + static fromFields(fields: FieldsOf): BlockProposalPayload { + return new BlockProposalPayload(fields.header, fields.archive, fields.txs); + } + + static empty(): BlockProposalPayload { + return new BlockProposalPayload(BlockHeader.empty(), Fr.ZERO, []); + } + + /** + * Get the size of the block proposal payload in bytes. + * @returns The size of the block proposal payload. + */ + getSize(): number { + // We cache size to avoid recalculating it + if (this.size) { + return this.size; + } + this.size = this.toBuffer().length; + return this.size; + } + + // Convert from the block proposal payload to the consensus payload + // This version does not include the entire transaction bodies + async toConsensusPayload(): Promise { + const txHashes = await Promise.all(this.txs.map(tx => tx.getTxHash())); + return new ConsensusPayload(this.header, this.archive, txHashes); + } +} + export class ConsensusPayload implements Signable { private size: number | undefined; diff --git a/yarn-project/circuit-types/src/p2p/mocks.ts b/yarn-project/circuit-types/src/p2p/mocks.ts index ff9fd3f6a0fd..ba1577b61b48 100644 --- a/yarn-project/circuit-types/src/p2p/mocks.ts +++ b/yarn-project/circuit-types/src/p2p/mocks.ts @@ -3,10 +3,11 @@ import { makeHeader } from '@aztec/circuits.js/testing'; import { Secp256k1Signer } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; +import { Tx } from '../tx/tx.js'; import { TxHash } from '../tx/tx_hash.js'; import { BlockAttestation } from './block_attestation.js'; import { BlockProposal } from './block_proposal.js'; -import { ConsensusPayload } from './consensus_payload.js'; +import { BlockProposalPayload, ConsensusPayload } from './consensus_payload.js'; import { SignatureDomainSeparator, getHashedSignaturePayloadEthSignedMessage } from './signature_utils.js'; export interface MakeConsensusPayloadOptions { @@ -39,8 +40,27 @@ const makeAndSignConsensusPayload = async ( return { payload, signature }; }; +const makeAndSignBlockProposalPayload = async ( + domainSeparator: SignatureDomainSeparator, + options?: MakeConsensusPayloadOptions, +) => { + const txs = await Promise.all(Array.from({ length: 6 }, () => Tx.random())); + const { signer = Secp256k1Signer.random(), header = makeHeader(1), archive = Fr.random() } = options ?? {}; + + const payload = BlockProposalPayload.fromFields({ + header, + archive, + txs, + }); + + const hash = await getHashedSignaturePayloadEthSignedMessage(payload, domainSeparator); + const signature = signer.sign(hash); + + return { payload, signature }; +}; + export const makeBlockProposal = async (options?: MakeConsensusPayloadOptions): Promise => { - const { payload, signature } = await makeAndSignConsensusPayload(SignatureDomainSeparator.blockProposal, options); + const { payload, signature } = await makeAndSignBlockProposalPayload(SignatureDomainSeparator.blockProposal, options); return new BlockProposal(payload, signature); }; diff --git a/yarn-project/end-to-end/src/e2e_p2p/reex.test.ts b/yarn-project/end-to-end/src/e2e_p2p/reex.test.ts index eb6fcdf94f42..f4182032e773 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/reex.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/reex.test.ts @@ -121,10 +121,11 @@ describe('e2e_p2p_reex', () => { jest.spyOn((node as any).p2pClient, 'broadcastProposal').mockImplementation(async (...args: unknown[]) => { // We remove one of the transactions, therefore the block root will be different! const proposal = args[0] as BlockProposal; - const { txHashes } = proposal.payload; + // TODO: reex + const { txs } = proposal.payload; // We need to mutate the proposal, so we cast to any - (proposal.payload as any).txHashes = txHashes.slice(0, txHashes.length - 1); + (proposal.payload as any).txs = txs.slice(0, txs.length - 1); // We sign over the proposal using the node's signing key // Abusing javascript to access the nodes signing key diff --git a/yarn-project/prover-node/src/job/epoch-proving-job.test.ts b/yarn-project/prover-node/src/job/epoch-proving-job.test.ts index d7555df10b4d..2c83959790c9 100644 --- a/yarn-project/prover-node/src/job/epoch-proving-job.test.ts +++ b/yarn-project/prover-node/src/job/epoch-proving-job.test.ts @@ -100,7 +100,7 @@ describe('epoch-proving-job', () => { const processedTxs = await Promise.all( txsArray.map(async tx => mock({ hash: await tx.getTxHash() })), ); - return [processedTxs, [], []]; + return [processedTxs, [], [], []]; }); }); @@ -120,7 +120,7 @@ describe('epoch-proving-job', () => { publicProcessor.process.mockImplementation(async txs => { const txsArray = await toArray(txs); const errors = txsArray.map(tx => ({ error: new Error('Failed to process tx'), tx })); - return [[], errors, []]; + return [[], errors, [], []]; }); const job = createJob(); @@ -131,7 +131,7 @@ describe('epoch-proving-job', () => { }); it('fails if does not process all txs for a block', async () => { - publicProcessor.process.mockImplementation(_txs => Promise.resolve([[], [], []])); + publicProcessor.process.mockImplementation(_txs => Promise.resolve([[], [], [], []])); const job = createJob(); await job.run(); diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index bb7118130e5f..4534888af00a 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -2,6 +2,7 @@ import { BlockAttestation, type BlockBuilder, BlockProposal, + BlockProposalPayload, Body, ConsensusPayload, type L1ToL2MessageSource, @@ -10,7 +11,7 @@ import { type MerkleTreeId, type MerkleTreeReadOperations, type MerkleTreeWriteOperations, - type Tx, + Tx, TxHash, WorldStateRunningState, type WorldStateSynchronizer, @@ -98,8 +99,9 @@ describe('sequencer', () => { return [attestation]; }; - const createBlockProposal = () => { - return new BlockProposal(new ConsensusPayload(block.header, archive, [TxHash.random()]), mockedSig); + const createBlockProposal = async () => { + const tx = await mockTxForRollup(); + return new BlockProposal(new BlockProposalPayload(block.header, archive, [tx]), mockedSig); }; const processTxs = async (txs: Tx[]) => { @@ -213,7 +215,7 @@ describe('sequencer', () => { const txs = await toArray(txsIter); const processed = await processTxs(txs); logger.verbose(`Processed ${txs.length} txs`, { txHashes: txs.map(tx => tx.getTxHash()) }); - return [processed, [], []]; + return [processed, [], [], []]; }); publicProcessorFactory = mock({ @@ -377,6 +379,7 @@ describe('sequencer', () => { await processTxs(validTxs), [{ tx: invalidTx, error: new Error() }], [], + [], ]); await sequencer.doRealWork(); @@ -595,6 +598,7 @@ class TestSubject extends Sequencer { numTxs: number; numFailedTxs: number; blockBuildingTimer: Timer; + txs: Tx[]; }> { return super.buildBlock(pendingTxs, newGlobalVariables, opts); } diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index a554323f5306..9efdaf43a2c4 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -464,7 +464,7 @@ export class Sequencer { maxBlockGas: this.maxBlockGas, }; const limits = opts.validateOnly ? { deadline } : { deadline, ...proposerLimits }; - const [publicProcessorDuration, [processedTxs, failedTxs]] = await elapsed(() => + const [publicProcessorDuration, [processedTxs, failedTxs, usedTxs]] = await elapsed(() => processor.process(pendingTxs, limits, validators), ); @@ -504,6 +504,7 @@ export class Sequencer { block, publicGas, publicProcessorDuration, + txs: usedTxs, numMsgs: l1ToL2Messages.length, numTxs: processedTxs.length, numFailedTxs: failedTxs.length, @@ -586,7 +587,7 @@ export class Sequencer { this.log.debug('Collecting attestations'); const stopCollectingAttestationsTimer = this.metrics.startCollectingAttestationsTimer(); - const attestations = await this.collectAttestations(block, txHashes); + const attestations = await this.collectAttestations(block, buildBlockRes.txs); if (attestations !== undefined) { this.log.verbose(`Collected ${attestations.length} attestations`, { blockHash, blockNumber }); } @@ -604,7 +605,7 @@ export class Sequencer { [Attributes.BLOCK_ARCHIVE]: block.archive.toString(), [Attributes.BLOCK_TXS_COUNT]: txHashes.length, })) - protected async collectAttestations(block: L2Block, txHashes: TxHash[]): Promise { + protected async collectAttestations(block: L2Block, txs: Tx[]): Promise { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7962): inefficient to have a round trip in here - this should be cached const committee = await this.publisher.getCurrentEpochCommittee(); @@ -626,7 +627,7 @@ export class Sequencer { this.setState(SequencerState.COLLECTING_ATTESTATIONS, slotNumber); this.log.debug('Creating block proposal for validators'); - const proposal = await this.validatorClient.createBlockProposal(block.header, block.archive.root, txHashes); + const proposal = await this.validatorClient.createBlockProposal(block.header, block.archive.root, txs); if (!proposal) { const msg = `Failed to create block proposal`; throw new Error(msg); diff --git a/yarn-project/simulator/src/public/public_processor.ts b/yarn-project/simulator/src/public/public_processor.ts index 23a0de010d60..0eee703f3897 100644 --- a/yarn-project/simulator/src/public/public_processor.ts +++ b/yarn-project/simulator/src/public/public_processor.ts @@ -149,9 +149,11 @@ export class PublicProcessor implements Traceable { postprocessValidator?: TxValidator; nullifierCache?: { addNullifiers: (nullifiers: Buffer[]) => void }; } = {}, - ): Promise<[ProcessedTx[], FailedTx[], NestedProcessReturnValues[]]> { + ): Promise<[ProcessedTx[], FailedTx[], Tx[], NestedProcessReturnValues[]]> { const { maxTransactions, maxBlockSize, deadline, maxBlockGas } = limits; const { preprocessValidator, postprocessValidator, nullifierCache } = validators; + // exp(#12055): for now just returning the tx from this funciton to help with the block proposal construction, but this all needs a bit of a cleanup + const usedTxs: Tx[] = []; const result: ProcessedTx[] = []; const failed: FailedTx[] = []; const timer = new Timer(); @@ -259,6 +261,7 @@ export class PublicProcessor implements Traceable { await this.commitTxState(processedTx); nullifierCache?.addNullifiers(processedTx.txEffect.nullifiers.map(n => n.toBuffer())); result.push(processedTx); + usedTxs.push(tx); returns = returns.concat(returnValues); totalPublicGas = totalPublicGas.add(processedTx.gasUsed.publicGas); @@ -289,7 +292,7 @@ export class PublicProcessor implements Traceable { totalSizeInBytes, }); - return [result, failed, returns]; + return [result, failed, usedTxs, returns]; } @trackSpan('PublicProcessor.processTx', async tx => ({ [Attributes.TX_HASH]: (await tx.getTxHash()).toString() })) diff --git a/yarn-project/validator-client/src/duties/validation_service.ts b/yarn-project/validator-client/src/duties/validation_service.ts index d269ac7144f0..19666bb2d8f1 100644 --- a/yarn-project/validator-client/src/duties/validation_service.ts +++ b/yarn-project/validator-client/src/duties/validation_service.ts @@ -1,9 +1,10 @@ import { BlockAttestation, BlockProposal, - ConsensusPayload, + BlockProposalPayload, + type ConsensusPayload, SignatureDomainSeparator, - type TxHash, + Tx, } from '@aztec/circuit-types'; import { type BlockHeader } from '@aztec/circuits.js'; import { Buffer32 } from '@aztec/foundation/buffer'; @@ -24,10 +25,10 @@ export class ValidationService { * * @returns A block proposal signing the above information (not the current implementation!!!) */ - createBlockProposal(header: BlockHeader, archive: Fr, txs: TxHash[]): Promise { + createBlockProposal(header: BlockHeader, archive: Fr, txs: Tx[]): Promise { const payloadSigner = (payload: Buffer32) => this.keyStore.signMessage(payload); - return BlockProposal.createProposalFromSigner(new ConsensusPayload(header, archive, txs), payloadSigner); + return BlockProposal.createProposalFromSigner(new BlockProposalPayload(header, archive, txs), payloadSigner); } /** @@ -40,12 +41,13 @@ export class ValidationService { * @returns attestation */ async attestToProposal(proposal: BlockProposal): Promise { - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7961): check that the current validator is correct + // Remove the txs from the attestation payload, we only include all of the txs in the initial proposal, not the attestation + const consensusPayload: ConsensusPayload = await proposal.payload.toConsensusPayload(); const buf = Buffer32.fromBuffer( - keccak256(await proposal.payload.getPayloadToSign(SignatureDomainSeparator.blockAttestation)), + keccak256(await consensusPayload.getPayloadToSign(SignatureDomainSeparator.blockAttestation)), ); const sig = await this.keyStore.signMessage(buf); - return new BlockAttestation(proposal.payload, sig); + return new BlockAttestation(consensusPayload, sig); } } diff --git a/yarn-project/validator-client/src/validator.test.ts b/yarn-project/validator-client/src/validator.test.ts index 3f6e8d21755b..f825aa868b8e 100644 --- a/yarn-project/validator-client/src/validator.test.ts +++ b/yarn-project/validator-client/src/validator.test.ts @@ -11,6 +11,7 @@ import { TestDateProvider } from '@aztec/foundation/timer'; import { type P2P } from '@aztec/p2p'; import { describe, expect, it } from '@jest/globals'; +import exp from 'constants'; import { type MockProxy, mock } from 'jest-mock-extended'; import { type PrivateKeyAccount, generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; @@ -67,7 +68,8 @@ describe('ValidationService', () => { it('Should create a valid block proposal', async () => { const header = makeHeader(); const archive = Fr.random(); - const txs = [1, 2, 3, 4, 5].map(() => TxHash.random()); + // const txs = [1, 2, 3, 4, 5].map(() => TxHash.random()); + const txs = await Promise.all([mockTx(), mockTx(), mockTx(), mockTx(), mockTx()]); const blockProposal = await validatorClient.createBlockProposal(header, archive, txs); @@ -85,18 +87,19 @@ describe('ValidationService', () => { ); }); - it('Should throw an error if the transactions are not available', async () => { - const proposal = await makeBlockProposal(); + // exp(#12055): disabled temp + // it('Should throw an error if the transactions are not available', async () => { + // const proposal = await makeBlockProposal(); - // mock the p2pClient.getTxStatus to return undefined for all transactions - p2pClient.getTxStatus.mockResolvedValue(undefined); - // Mock the p2pClient.requestTxs to return undefined for all transactions - p2pClient.requestTxs.mockImplementation(() => Promise.resolve([undefined])); + // // mock the p2pClient.getTxStatus to return undefined for all transactions + // p2pClient.getTxStatus.mockResolvedValue(undefined); + // // Mock the p2pClient.requestTxs to return undefined for all transactions + // p2pClient.requestTxs.mockImplementation(() => Promise.resolve([undefined])); - await expect(validatorClient.ensureTransactionsAreAvailable(proposal)).rejects.toThrow( - TransactionsNotAvailableError, - ); - }); + // await expect(validatorClient.ensureTransactionsAreAvailable(proposal)).rejects.toThrow( + // TransactionsNotAvailableError, + // ); + // }); it('Should not return an attestation if re-execution fails', async () => { const proposal = await makeBlockProposal(); diff --git a/yarn-project/validator-client/src/validator.ts b/yarn-project/validator-client/src/validator.ts index 9a0d3d604078..ee16ea138f7c 100644 --- a/yarn-project/validator-client/src/validator.ts +++ b/yarn-project/validator-client/src/validator.ts @@ -7,7 +7,7 @@ import { createLogger } from '@aztec/foundation/log'; import { RunningPromise } from '@aztec/foundation/running-promise'; import { sleep } from '@aztec/foundation/sleep'; import { DateProvider, type Timer } from '@aztec/foundation/timer'; -import { type P2P } from '@aztec/p2p'; +import { type P2P, type TxPool } from '@aztec/p2p'; import { BlockProposalValidator } from '@aztec/p2p/msg_validators'; import { type TelemetryClient, WithTracer, getTelemetryClient } from '@aztec/telemetry-client'; @@ -49,7 +49,7 @@ export interface Validator { registerBlockBuilder(blockBuilder: BlockBuilderCallback): void; // Block validation responsiblities - createBlockProposal(header: BlockHeader, archive: Fr, txs: TxHash[]): Promise; + createBlockProposal(header: BlockHeader, archive: Fr, txs: Tx[]): Promise; attestToProposal(proposal: BlockProposal): void; broadcastBlockProposal(proposal: BlockProposal): void; @@ -174,8 +174,8 @@ export class ValidatorClient extends WithTracer implements Validator { slotNumber, blockNumber: proposal.payload.header.globalVariables.blockNumber.toNumber(), archive: proposal.payload.archive.toString(), - txCount: proposal.payload.txHashes.length, - txHashes: proposal.payload.txHashes.map(txHash => txHash.toString()), + txCount: proposal.payload.txs.length, + txHashes: (await Promise.all(proposal.payload.txs.map(tx => tx.getTxHash()))).map(txHash => txHash.toString()), }; this.log.verbose(`Received request to attest for slot ${slotNumber}`); @@ -195,12 +195,17 @@ export class ValidatorClient extends WithTracer implements Validator { // Check that all of the tranasctions in the proposal are available in the tx pool before attesting this.log.verbose(`Processing attestation for slot ${slotNumber}`, proposalInfo); try { - await this.ensureTransactionsAreAvailable(proposal); + // exp(#12055): No need to make sure they are available if they exist within the block proposal + // await this.ensureTransactionsAreAvailable(proposal); if (this.config.validatorReexecute) { this.log.verbose(`Re-executing transactions in the proposal before attesting`); await this.reExecuteTransactions(proposal); } + + // exp(#12055): Temp method to add txs to pool and make them available + // TODO: handle duplication logic + ((this.p2pClient as any).txPool as TxPool).addTxs(proposal.payload.txs); } catch (error: any) { // If the transactions are not available, then we should not attempt to attest if (error instanceof TransactionsNotAvailableError) { @@ -225,16 +230,16 @@ export class ValidatorClient extends WithTracer implements Validator { * @param proposal - The proposal to re-execute */ async reExecuteTransactions(proposal: BlockProposal) { - const { header, txHashes } = proposal.payload; + const { header, txs } = proposal.payload; - const txs = (await Promise.all(txHashes.map(tx => this.p2pClient.getTxByHash(tx)))).filter( - tx => tx !== undefined, - ) as Tx[]; + // const txs = (await Promise.all(txHashes.map(tx => this.p2pClient.getTxByHash(tx)))).filter( + // tx => tx !== undefined, + // ) as Tx[]; // If we cannot request all of the transactions, then we should fail - if (txs.length !== txHashes.length) { - throw new TransactionsNotAvailableError(txHashes); - } + // if (txs.length !== txHashes.length) { + // throw new TransactionsNotAvailableError(txHashes); + // } // Assertion: This check will fail if re-execution is not enabled if (this.blockBuilder === undefined) { @@ -255,7 +260,7 @@ export class ValidatorClient extends WithTracer implements Validator { throw new ReExFailedTxsError(numFailedTxs); } - if (block.body.txEffects.length !== txHashes.length) { + if (block.body.txEffects.length !== txs.length) { await this.metrics.recordFailedReexecution(proposal); throw new ReExTimeoutError(); } @@ -275,25 +280,25 @@ export class ValidatorClient extends WithTracer implements Validator { * 3. If we cannot retrieve them from the network, throw an error * @param proposal - The proposal to attest to */ - async ensureTransactionsAreAvailable(proposal: BlockProposal) { - const txHashes: TxHash[] = proposal.payload.txHashes; - const transactionStatuses = await Promise.all(txHashes.map(txHash => this.p2pClient.getTxStatus(txHash))); + // async ensureTransactionsAreAvailable(proposal: BlockProposal) { + // const txHashes: TxHash[] = proposal.payload.txHashes; + // const transactionStatuses = await Promise.all(txHashes.map(txHash => this.p2pClient.getTxStatus(txHash))); - const missingTxs = txHashes.filter((_, index) => !['pending', 'mined'].includes(transactionStatuses[index] ?? '')); + // const missingTxs = txHashes.filter((_, index) => !['pending', 'mined'].includes(transactionStatuses[index] ?? '')); - if (missingTxs.length === 0) { - return; // All transactions are available - } + // if (missingTxs.length === 0) { + // return; // All transactions are available + // } - this.log.verbose(`Missing ${missingTxs.length} transactions in the tx pool, requesting from the network`); + // this.log.verbose(`Missing ${missingTxs.length} transactions in the tx pool, requesting from the network`); - const requestedTxs = await this.p2pClient.requestTxs(missingTxs); - if (requestedTxs.some(tx => tx === undefined)) { - throw new TransactionsNotAvailableError(missingTxs); - } - } + // const requestedTxs = await this.p2pClient.requestTxs(missingTxs); + // if (requestedTxs.some(tx => tx === undefined)) { + // throw new TransactionsNotAvailableError(missingTxs); + // } + // } - async createBlockProposal(header: BlockHeader, archive: Fr, txs: TxHash[]): Promise { + async createBlockProposal(header: BlockHeader, archive: Fr, txs: Tx[]): Promise { if (this.previousProposal?.slotNumber.equals(header.globalVariables.slotNumber)) { this.log.verbose(`Already made a proposal for the same slot, skipping proposal`); return Promise.resolve(undefined); From 626ba48bfe2f65fddbbd6d0c6aa9e5fe88f0c72b Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 18 Feb 2025 12:46:02 +0000 Subject: [PATCH 7/7] fix: hacky ignore duplicate kv errors --- .../circuit-types/src/p2p/block_proposal.test.ts | 14 +++++++++----- .../circuit-types/src/p2p/consensus_payload.ts | 4 +++- .../end-to-end/src/e2e_p2p/gossip_network.test.ts | 6 ++++++ .../sequencer-client/src/sequencer/sequencer.ts | 1 + yarn-project/validator-client/src/validator.ts | 11 ++++++++++- 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/yarn-project/circuit-types/src/p2p/block_proposal.test.ts b/yarn-project/circuit-types/src/p2p/block_proposal.test.ts index 3db49eabadeb..a2df9e789d13 100644 --- a/yarn-project/circuit-types/src/p2p/block_proposal.test.ts +++ b/yarn-project/circuit-types/src/p2p/block_proposal.test.ts @@ -5,9 +5,12 @@ import { BlockProposal } from './block_proposal.js'; import { makeBlockProposal } from './mocks.js'; describe('Block Proposal serialization / deserialization', () => { - const checkEquivalence = (serialized: BlockProposal, deserialized: BlockProposal) => { - expect(deserialized.getSize()).toEqual(serialized.getSize()); - expect(deserialized).toEqual(serialized); + const checkEquivalence = async (original: BlockProposal, deserialized: BlockProposal) => { + // tmp + // force compute tx hashes - this is not done in the deserialization + await Promise.all(deserialized.payload.txs.map(tx => tx.getTxHash())); + expect(deserialized.getSize()).toEqual(original.getSize()); + expect(deserialized).toEqual(original); }; it('Should serialize / deserialize', async () => { @@ -15,7 +18,8 @@ describe('Block Proposal serialization / deserialization', () => { const serialized = proposal.toBuffer(); const deserialized = BlockProposal.fromBuffer(serialized); - checkEquivalence(proposal, deserialized); + + await checkEquivalence(proposal, deserialized); }); it('Should serialize / deserialize + recover sender', async () => { @@ -25,7 +29,7 @@ describe('Block Proposal serialization / deserialization', () => { const serialized = proposal.toBuffer(); const deserialized = BlockProposal.fromBuffer(serialized); - checkEquivalence(proposal, deserialized); + await checkEquivalence(proposal, deserialized); // Recover signature const sender = await deserialized.getSender(); diff --git a/yarn-project/circuit-types/src/p2p/consensus_payload.ts b/yarn-project/circuit-types/src/p2p/consensus_payload.ts index be1a1455406a..595eaec75d55 100644 --- a/yarn-project/circuit-types/src/p2p/consensus_payload.ts +++ b/yarn-project/circuit-types/src/p2p/consensus_payload.ts @@ -39,7 +39,9 @@ export class BlockProposalPayload implements Signable { async getPayloadToSign(domainSeparator: SignatureDomainSeparator): Promise { const abi = parseAbiParameters('uint8, (bytes32, bytes32, (uint256), bytes, bytes32[])'); - const txArray = this.txs.map(tx => tx.toBuffer().toString('hex') as `0x${string}`); + + // Sign over the tx hashes + const txArray = (await Promise.all(this.txs.map(tx => tx.getTxHash()))).map(tx => tx.toString()); const encodedData = encodeAbiParameters(abi, [ domainSeparator, [ diff --git a/yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts index f9cbc273adfc..84eff1806fde 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts @@ -41,6 +41,12 @@ describe('e2e_p2p_network', () => { numberOfNodes: NUM_NODES, basePort: BOOT_NODE_UDP_PORT, metricsPort: shouldCollectMetrics(), + // TODO(md): put in central location - part of different pr + // initialConfig: { + // aztecEpochDuration: 8, + // aztecSlotDuration: 18, + // ethereumSlotDuration: 6, + // }, }); await t.setupAccount(); diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 9efdaf43a2c4..6c08a4cffd18 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -662,6 +662,7 @@ export class Sequencer { attestations?: Signature[], txHashes?: TxHash[], ): Promise { + this.log.info('txhashes', txHashes); // Publishes new block to the network and awaits the tx to be mined this.setState(SequencerState.PUBLISHING_BLOCK, block.header.globalVariables.slotNumber.toBigInt()); diff --git a/yarn-project/validator-client/src/validator.ts b/yarn-project/validator-client/src/validator.ts index ee16ea138f7c..62c30fa409de 100644 --- a/yarn-project/validator-client/src/validator.ts +++ b/yarn-project/validator-client/src/validator.ts @@ -205,7 +205,7 @@ export class ValidatorClient extends WithTracer implements Validator { // exp(#12055): Temp method to add txs to pool and make them available // TODO: handle duplication logic - ((this.p2pClient as any).txPool as TxPool).addTxs(proposal.payload.txs); + this.addProposalTxsToPool(proposal.payload.txs); } catch (error: any) { // If the transactions are not available, then we should not attempt to attest if (error instanceof TransactionsNotAvailableError) { @@ -225,6 +225,15 @@ export class ValidatorClient extends WithTracer implements Validator { return this.validationService.attestToProposal(proposal); } + private async addProposalTxsToPool(txs: Tx[]): Promise { + try { + await ((this.p2pClient as any).txPool as TxPool).addTxs(txs); + } catch (error: any) { + // If the transactions are not available, then we should not attempt to attest + // do nothing, commonly getting kv error here - but i dont care rn + } + } + /** * Re-execute the transactions in the proposal and check that the state updates match the header state * @param proposal - The proposal to re-execute