Skip to content

Commit

Permalink
fix: use simulation to estimate gas used (#11211)
Browse files Browse the repository at this point in the history
Relevant to #10991 but not 'Fixes' because anvil doesn't support
`eth_simulateV1` so we can't yet remove all time-based inputs in L1

Fixes #11341 

- We now try to `simulate` the 'propose' & 'proposeAndClaim'
transactions, using the appropriate timestamp, instead of using
hardcoded 12M gas.
- Also some updates to logging where we 
  1. Try to decode errors from our Rollup ABI
2. truncate large Hexes but still include them in error data so txs can
be investigated
- Update slot duration to 36 for sepolia deployments

Follow-up from this: #11390 #11440

---------

Co-authored-by: Santiago Palladino <[email protected]>
  • Loading branch information
spypsy and spalladino authored Jan 24, 2025
1 parent f589c90 commit 63776f0
Show file tree
Hide file tree
Showing 36 changed files with 625 additions and 259 deletions.
3 changes: 0 additions & 3 deletions package.json

This file was deleted.

5 changes: 4 additions & 1 deletion spartan/aztec-network/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ Service Address Setup Container
- name: OTEL_COLLECTOR_ENDPOINT
value: "{{ .Values.telemetry.otelCollectorEndpoint }}"
- name: EXTERNAL_ETHEREUM_HOST
value: "{{ .Values.ethereum.execution.externalHost }}"
value: "{{ .Values.ethereum.externalHost }}"
- name: ETHEREUM_PORT
value: "{{ .Values.ethereum.execution.service.port }}"
- name: EXTERNAL_BOOT_NODE_HOST
Expand Down Expand Up @@ -192,6 +192,9 @@ nodeSelector:
{{- end -}}

{{- define "aztec-network.waitForEthereum" -}}
if [ -n "${EXTERNAL_ETHEREUM_HOST}" ]; then
export ETHEREUM_HOST="${EXTERNAL_ETHEREUM_HOST}"
fi
echo "Awaiting ethereum node at ${ETHEREUM_HOST}"
until curl -s -X POST -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":67}' \
Expand Down
3 changes: 1 addition & 2 deletions spartan/aztec-network/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,8 @@ ethereum:
# 10 times the default of 131072
maxTxInputSizeBytes: "1310720"
args: ""
externalHost: ""
execution:
externalHost: ""
service:
port: 8545
targetPort: 8545
Expand All @@ -239,7 +239,6 @@ ethereum:
cpu: "1"
storageSize: "80Gi"
beacon:
externalHost: ""
service:
port: 5052
targetPort: 5052
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
telemetry:
enabled: true

aztec:
slotDuration: 36 # in seconds,

network:
setupL2Contracts: false
public: false

ethereum:
execution:
externalHost:
beacon:
externalHost:
chainId: "11155111"
deployL1ContractsPrivateKey:
externalHost:

validator:
l1FixedPriorityFeePerGas: 1
l1GasLimitBufferPercentage: 5
l1FixedPriorityFeePerGas: 2
l1GasLimitBufferPercentage: 15
replicas: 48
validatorKeys:
validatorAddresses:
Expand Down Expand Up @@ -77,4 +77,4 @@ proverNode:
proverPublisherPrivateKey:

bot:
txIntervalSeconds: 5
txIntervalSeconds: 0
2 changes: 1 addition & 1 deletion yarn-project/archiver/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
"lodash.omit": "^4.5.0",
"tsc-watch": "^6.0.0",
"tslib": "^2.5.0",
"viem": "^2.7.15",
"viem": "2.22.8",
"ws": "^8.13.0"
},
"devDependencies": {
Expand Down
96 changes: 62 additions & 34 deletions yarn-project/archiver/src/archiver/archiver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,20 @@ interface MockInboxContractRead {
totalMessagesInserted: () => Promise<bigint>;
}

interface MockRollupContractEvents {
L2BlockProposed: (
filter: any,
range: { fromBlock: bigint; toBlock: bigint },
) => Promise<Log<bigint, number, false, undefined, true, typeof RollupAbi, 'L2BlockProposed'>[]>;
}

interface MockInboxContractEvents {
MessageSent: (
filter: any,
range: { fromBlock: bigint; toBlock: bigint },
) => Promise<Log<bigint, number, false, undefined, true, typeof InboxAbi, 'MessageSent'>[]>;
}

describe('Archiver', () => {
const rollupAddress = EthAddress.ZERO;
const inboxAddress = EthAddress.ZERO;
Expand All @@ -59,8 +73,18 @@ describe('Archiver', () => {
let now: number;
let l1Constants: L1RollupConstants;

let rollupRead: MockProxy<MockRollupContractRead>;
let inboxRead: MockProxy<MockInboxContractRead>;
let mockRollupRead: MockProxy<MockRollupContractRead>;
let mockInboxRead: MockProxy<MockInboxContractRead>;
let mockRollupEvents: MockProxy<MockRollupContractEvents>;
let mockInboxEvents: MockProxy<MockInboxContractEvents>;
let mockRollup: {
read: typeof mockRollupRead;
getEvents: typeof mockRollupEvents;
};
let mockInbox: {
read: typeof mockInboxRead;
getEvents: typeof mockInboxEvents;
};
let archiver: Archiver;
let blocks: L2Block[];

Expand All @@ -79,20 +103,6 @@ describe('Archiver', () => {
getBlock: ((args: any) => ({
timestamp: args.blockNumber * BigInt(DefaultL1ContractsConfig.ethereumSlotDuration) + BigInt(now),
})) as any,
// Return the logs mocked whenever the public client is queried
getLogs: ((args: any) => {
let logs = undefined;
if (args!.event!.name === 'MessageSent') {
logs = l2MessageSentLogs;
} else if (args!.event!.name === 'L2BlockProposed') {
logs = l2BlockProposedLogs;
} else {
throw new Error(`Unknown event: ${args!.event!.name}`);
}
return Promise.resolve(
logs.filter(log => log.blockNumber >= args.fromBlock && log.blockNumber <= args.toBlock),
);
}) as any,
});
blobSinkClient = mock<BlobSinkClientInterface>();

Expand Down Expand Up @@ -126,15 +136,33 @@ describe('Archiver', () => {
});
});

rollupRead = mock<MockRollupContractRead>();
rollupRead.archiveAt.mockImplementation((args: readonly [bigint]) =>
mockRollupRead = mock<MockRollupContractRead>();
mockRollupRead.archiveAt.mockImplementation((args: readonly [bigint]) =>
Promise.resolve(blocks[Number(args[0] - 1n)].archive.root.toString()),
);
mockRollupEvents = mock<MockRollupContractEvents>();
mockRollupEvents.L2BlockProposed.mockImplementation((filter: any, { fromBlock, toBlock }) =>
Promise.resolve(l2BlockProposedLogs.filter(log => log.blockNumber! >= fromBlock && log.blockNumber! <= toBlock)),
);
mockRollup = {
read: mockRollupRead,
getEvents: mockRollupEvents,
};

((archiver as any).rollup as any).read = rollupRead;
(archiver as any).rollup = mockRollup;

inboxRead = mock<MockInboxContractRead>();
((archiver as any).inbox as any).read = inboxRead;
mockInboxRead = mock<MockInboxContractRead>();
mockInboxEvents = mock<MockInboxContractEvents>();
mockInboxEvents.MessageSent.mockImplementation(async (filter: any, { fromBlock, toBlock }) => {
return await Promise.resolve(
l2MessageSentLogs.filter(log => log.blockNumber! >= fromBlock && log.blockNumber! <= toBlock),
);
});
mockInbox = {
read: mockInboxRead,
getEvents: mockInboxEvents,
};
(archiver as any).inbox = mockInbox;

l2MessageSentLogs = [];
l2BlockProposedLogs = [];
Expand All @@ -156,7 +184,7 @@ describe('Archiver', () => {

publicClient.getBlockNumber.mockResolvedValueOnce(2500n).mockResolvedValueOnce(2600n).mockResolvedValueOnce(2700n);

rollupRead.status
mockRollup.read.status
.mockResolvedValueOnce([0n, GENESIS_ROOT, 1n, blocks[0].archive.root.toString(), GENESIS_ROOT])
.mockResolvedValue([
1n,
Expand All @@ -166,7 +194,7 @@ describe('Archiver', () => {
blocks[0].archive.root.toString(),
]);

inboxRead.totalMessagesInserted.mockResolvedValueOnce(2n).mockResolvedValueOnce(6n);
mockInbox.read.totalMessagesInserted.mockResolvedValueOnce(2n).mockResolvedValueOnce(6n);

makeMessageSentEvent(98n, 1n, 0n);
makeMessageSentEvent(99n, 1n, 1n);
Expand Down Expand Up @@ -253,9 +281,9 @@ describe('Archiver', () => {

const badArchive = Fr.random().toString();

rollupRead.status.mockResolvedValue([0n, GENESIS_ROOT, 2n, blocks[1].archive.root.toString(), GENESIS_ROOT]);
mockRollup.read.status.mockResolvedValue([0n, GENESIS_ROOT, 2n, blocks[1].archive.root.toString(), GENESIS_ROOT]);

inboxRead.totalMessagesInserted.mockResolvedValueOnce(2n).mockResolvedValueOnce(2n);
mockInbox.read.totalMessagesInserted.mockResolvedValueOnce(2n).mockResolvedValueOnce(2n);

makeMessageSentEvent(66n, 1n, 0n);
makeMessageSentEvent(68n, 1n, 1n);
Expand Down Expand Up @@ -290,11 +318,11 @@ describe('Archiver', () => {
const rollupTxs = blocks.map(makeRollupTx);

publicClient.getBlockNumber.mockResolvedValueOnce(50n).mockResolvedValueOnce(100n);
rollupRead.status
mockRollup.read.status
.mockResolvedValueOnce([0n, GENESIS_ROOT, 0n, GENESIS_ROOT, GENESIS_ROOT])
.mockResolvedValueOnce([0n, GENESIS_ROOT, 2n, blocks[1].archive.root.toString(), GENESIS_ROOT]);

inboxRead.totalMessagesInserted.mockResolvedValueOnce(0n).mockResolvedValueOnce(2n);
mockInbox.read.totalMessagesInserted.mockResolvedValueOnce(0n).mockResolvedValueOnce(2n);

makeMessageSentEvent(66n, 1n, 0n);
makeMessageSentEvent(68n, 1n, 1n);
Expand Down Expand Up @@ -328,17 +356,17 @@ describe('Archiver', () => {

// We will return status at first to have an empty round, then as if we have 2 pending blocks, and finally
// Just a single pending block returning a "failure" for the expected pending block
rollupRead.status
mockRollup.read.status
.mockResolvedValueOnce([0n, GENESIS_ROOT, 0n, GENESIS_ROOT, GENESIS_ROOT])
.mockResolvedValueOnce([0n, GENESIS_ROOT, 2n, blocks[1].archive.root.toString(), GENESIS_ROOT])
.mockResolvedValueOnce([0n, GENESIS_ROOT, 1n, blocks[0].archive.root.toString(), Fr.ZERO.toString()]);

rollupRead.archiveAt
mockRollup.read.archiveAt
.mockResolvedValueOnce(blocks[0].archive.root.toString())
.mockResolvedValueOnce(blocks[1].archive.root.toString())
.mockResolvedValueOnce(Fr.ZERO.toString());

inboxRead.totalMessagesInserted
mockInbox.read.totalMessagesInserted
.mockResolvedValueOnce(0n)
.mockResolvedValueOnce(2n)
.mockResolvedValueOnce(2n)
Expand Down Expand Up @@ -393,7 +421,7 @@ describe('Archiver', () => {

const rollupTxs = blocks.map(makeRollupTx);
publicClient.getBlockNumber.mockResolvedValueOnce(l1BlockForL2Block);
rollupRead.status.mockResolvedValueOnce([0n, GENESIS_ROOT, 1n, l2Block.archive.root.toString(), GENESIS_ROOT]);
mockRollup.read.status.mockResolvedValueOnce([0n, GENESIS_ROOT, 1n, l2Block.archive.root.toString(), GENESIS_ROOT]);
makeL2BlockProposedEvent(l1BlockForL2Block, 1n, l2Block.archive.root.toString());
rollupTxs.forEach(tx => publicClient.getTransaction.mockResolvedValueOnce(tx));

Expand Down Expand Up @@ -424,7 +452,7 @@ describe('Archiver', () => {

const rollupTxs = blocks.map(makeRollupTx);
publicClient.getBlockNumber.mockResolvedValueOnce(l1BlockForL2Block);
rollupRead.status.mockResolvedValueOnce([0n, GENESIS_ROOT, 1n, l2Block.archive.root.toString(), GENESIS_ROOT]);
mockRollup.read.status.mockResolvedValueOnce([0n, GENESIS_ROOT, 1n, l2Block.archive.root.toString(), GENESIS_ROOT]);
makeL2BlockProposedEvent(l1BlockForL2Block, 1n, l2Block.archive.root.toString());
rollupTxs.forEach(tx => publicClient.getTransaction.mockResolvedValueOnce(tx));

Expand All @@ -449,7 +477,7 @@ describe('Archiver', () => {

logger.info(`Syncing archiver to L1 block ${notLastL1BlockForEpoch}`);
publicClient.getBlockNumber.mockResolvedValueOnce(notLastL1BlockForEpoch);
rollupRead.status.mockResolvedValueOnce([0n, GENESIS_ROOT, 0n, GENESIS_ROOT, GENESIS_ROOT]);
mockRollup.read.status.mockResolvedValueOnce([0n, GENESIS_ROOT, 0n, GENESIS_ROOT, GENESIS_ROOT]);

await archiver.start(true);
expect(await archiver.isEpochComplete(0n)).toBe(false);
Expand All @@ -462,7 +490,7 @@ describe('Archiver', () => {

logger.info(`Syncing archiver to L1 block ${lastL1BlockForEpoch}`);
publicClient.getBlockNumber.mockResolvedValueOnce(lastL1BlockForEpoch);
rollupRead.status.mockResolvedValueOnce([0n, GENESIS_ROOT, 0n, GENESIS_ROOT, GENESIS_ROOT]);
mockRollup.read.status.mockResolvedValueOnce([0n, GENESIS_ROOT, 0n, GENESIS_ROOT, GENESIS_ROOT]);

await archiver.start(true);
expect(await archiver.isEpochComplete(0n)).toBe(true);
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/aztec-faucet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"koa": "^2.14.2",
"koa-bodyparser": "^4.4.1",
"koa-router": "^12.0.0",
"viem": "^2.7.15",
"viem": "2.22.8",
"zod": "^3.23.8"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/aztec.js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
"@aztec/types": "workspace:^",
"axios": "^1.7.2",
"tslib": "^2.4.0",
"viem": "^2.7.15"
"viem": "2.22.8"
},
"devDependencies": {
"@jest/globals": "^29.5.0",
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/aztec/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"commander": "^12.1.0",
"koa": "^2.14.2",
"koa-router": "^12.0.0",
"viem": "^2.7.15"
"viem": "2.22.8"
},
"files": [
"dest",
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/bb-prover/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
"jest-mock-extended": "^3.0.3",
"ts-node": "^10.9.1",
"typescript": "^5.0.4",
"viem": "^2.7.15"
"viem": "2.22.8"
},
"files": [
"dest",
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/circuit-types/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
"lodash.omit": "^4.5.0",
"ts-node": "^10.9.1",
"typescript": "^5.0.4",
"viem": "^2.7.15"
"viem": "2.22.8"
},
"files": [
"dest",
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
"semver": "^7.5.4",
"source-map-support": "^0.5.21",
"tslib": "^2.4.0",
"viem": "^2.7.15"
"viem": "2.22.8"
},
"devDependencies": {
"@aztec/accounts": "workspace:^",
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/end-to-end/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
"tslib": "^2.4.0",
"typescript": "^5.0.4",
"util": "^0.12.5",
"viem": "^2.7.15",
"viem": "2.22.8",
"webpack": "^5.88.2",
"webpack-cli": "^5.1.4",
"zod": "^3.23.8"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -528,17 +528,19 @@ describe('L1Publisher integration', () => {
await expect(publisher.proposeL2Block(block)).resolves.toEqual(false);

// Test for both calls
expect(loggerErrorSpy).toHaveBeenCalledTimes(2);
// NOTE: First error is from the simulate fn, which isn't supported by anvil
expect(loggerErrorSpy).toHaveBeenCalledTimes(3);

// Test first call
expect(loggerErrorSpy).toHaveBeenNthCalledWith(
1,
2,
expect.stringMatching(/^L1 transaction 0x[a-f0-9]{64} reverted$/i),
expect.anything(),
);

// Test second call
expect(loggerErrorSpy).toHaveBeenNthCalledWith(
2,
3,
expect.stringMatching(
/^Rollup process tx reverted\. The contract function "propose" reverted\. Error: Rollup__InvalidInHash/i,
),
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/epoch-cache/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"get-port": "^7.1.0",
"jest-mock-extended": "^3.0.7",
"tslib": "^2.4.0",
"viem": "^2.7.15",
"viem": "2.22.8",
"zod": "^3.23.8"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/ethereum/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"@viem/anvil": "^0.0.10",
"dotenv": "^16.0.3",
"tslib": "^2.4.0",
"viem": "^2.7.15",
"viem": "2.22.8",
"zod": "^3.23.8"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/ethereum/src/contracts/rollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { type L1ReaderConfig } from '../l1_reader.js';
export class RollupContract {
private readonly rollup: GetContractReturnType<typeof RollupAbi, PublicClient<HttpTransport, Chain>>;

constructor(public readonly client: PublicClient, address: Hex) {
constructor(public readonly client: PublicClient<HttpTransport, Chain>, address: Hex) {
this.rollup = getContract({ address, abi: RollupAbi, client });
}

Expand Down
Loading

0 comments on commit 63776f0

Please sign in to comment.