Skip to content

Commit 1f2589f

Browse files
authored
chore: more AVM proving tests and benches along with test refactors (#16474)
## What's done 1. Adapt public tx simulator test helpers for token and AMM so they can also be used by proving tests. AMM takes long, so it is **skipped**. 2. Pull bulk test into a test helper for reuse in simulator, proving, and ivc integration 3. Create new **skipped** (manually run) mega bulk test that runs bulk 16 times and proves it 4. Add **skipped** (manually run) proving tests for "gadgets". In particular, sha, keccak and poseidon hashes of large enough size that they nearly run out of gas. 5. Add token proving test to benchmarks ## One concern This PR's test refactor substantially reduces code duplication, but it relies on one ugly thing. I'm passing a `(b: boolean) => expect(b).toBe(true)` to test helpers because I don't want the simulator's exports to depend on jest. IMO it's worth it despite not being pretty. _Note that this is no longer done for bulk and megabulk, only token and amm that run multiple txs._
2 parents 7761fe8 + 9713e66 commit 1f2589f

34 files changed

+621
-546
lines changed

noir-projects/noir-contracts/contracts/test/avm_gadgets_test_contract/src/main.nr

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ contract AvmGadgetsTest {
99
keccak256::keccak256(data, data.len())
1010
}
1111

12+
#[public]
13+
fn keccak_hash_2400(data: [u8; 2400]) -> [u8; 32] {
14+
keccak256::keccak256(data, data.len())
15+
}
16+
1217
#[public]
1318
fn keccak_f1600(data: [u64; 25]) -> [u64; 25] {
1419
std::hash::keccakf1600(data)
@@ -19,6 +24,11 @@ contract AvmGadgetsTest {
1924
poseidon::poseidon2::Poseidon2::hash(data, data.len())
2025
}
2126

27+
#[public]
28+
fn poseidon2_hash_2000fields(data: [Field; 2000]) -> Field {
29+
poseidon::poseidon2::Poseidon2::hash(data, data.len())
30+
}
31+
2232
#[public]
2333
fn sha256_hash_10(data: [u8; 10]) -> [u8; 32] {
2434
sha256::sha256_var(data, data.len() as u64)
@@ -81,6 +91,11 @@ contract AvmGadgetsTest {
8191
sha256::sha256_var(data, data.len() as u64)
8292
}
8393

94+
#[public]
95+
fn sha256_hash_2500(data: [u8; 2500]) -> [u8; 32] {
96+
sha256::sha256_var(data, data.len() as u64)
97+
}
98+
8499
#[public]
85100
fn pedersen_hash(data: [Field; 10]) -> Field {
86101
std::hash::pedersen_hash(data)

noir-projects/noir-contracts/contracts/test/avm_test_contract/src/main.nr

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,7 @@ pub contract AvmTest {
661661
expected_deployer: AztecAddress,
662662
expected_class_id: ContractClassId,
663663
expected_initialization_hash: Field,
664+
skip_strictly_limited_side_effects: bool,
664665
) {
665666
dep::aztec::oracle::debug_log::debug_log("biwise_ops");
666667
let num = get_block_number();
@@ -718,20 +719,24 @@ pub contract AvmTest {
718719
let _ = get_l2_gas_left();
719720
dep::aztec::oracle::debug_log::debug_log("get_da_gas_left");
720721
let _ = get_da_gas_left();
721-
dep::aztec::oracle::debug_log::debug_log("emit_public_log");
722-
let _ = emit_public_log();
722+
if !skip_strictly_limited_side_effects {
723+
dep::aztec::oracle::debug_log::debug_log("emit_public_log");
724+
let _ = emit_public_log();
725+
}
723726
dep::aztec::oracle::debug_log::debug_log("note_hash_exists");
724727
let _ = note_hash_exists(1, 2);
725728
dep::aztec::oracle::debug_log::debug_log("new_note_hash");
726729
let _ = new_note_hash(1);
727730
dep::aztec::oracle::debug_log::debug_log("new_nullifier");
728-
let _ = new_nullifier(1);
731+
let _ = new_nullifier(args_field[0]);
729732
dep::aztec::oracle::debug_log::debug_log("nullifier_exists");
730733
let _ = nullifier_exists(1);
731734
dep::aztec::oracle::debug_log::debug_log("l1_to_l2_msg_exists");
732735
let _ = l1_to_l2_msg_exists(1, 2);
733-
dep::aztec::oracle::debug_log::debug_log("send_l2_to_l1_msg");
734-
let _ = send_l2_to_l1_msg(EthAddress::from_field(0x2020), 1);
736+
if !skip_strictly_limited_side_effects {
737+
dep::aztec::oracle::debug_log::debug_log("send_l2_to_l1_msg");
738+
let _ = send_l2_to_l1_msg(EthAddress::from_field(0x2020), 1);
739+
}
735740
dep::aztec::oracle::debug_log::debug_log("storage_read_and_write");
736741
set_storage_single(read_storage_single());
737742
dep::aztec::oracle::debug_log::debug_log("nested_call_to_add");
Lines changed: 13 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,21 @@
1-
import { Fr } from '@aztec/foundation/fields';
21
import { createLogger } from '@aztec/foundation/log';
3-
import { AvmTestContractArtifact } from '@aztec/noir-test-contracts.js/AvmTest';
4-
import { TestExecutorMetrics, defaultGlobals } from '@aztec/simulator/public/fixtures';
5-
import { AztecAddress } from '@aztec/stdlib/aztec-address';
6-
import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
2+
import { TestExecutorMetrics, bulkTest, defaultGlobals } from '@aztec/simulator/public/fixtures';
73

84
import { mkdirSync, writeFileSync } from 'fs';
95
import path from 'path';
106

117
import { AvmProvingTester } from './avm_proving_tester.js';
128

13-
describe('AVM bulk test', () => {
14-
const sender = AztecAddress.fromNumber(42);
15-
let avmTestContractInstance: ContractInstanceWithAddress;
9+
const TIMEOUT = 180_000;
10+
11+
describe('AVM proven bulk test', () => {
12+
const logger = createLogger('avm-bulk-test');
1613
const metrics = new TestExecutorMetrics();
1714
let tester: AvmProvingTester;
18-
const logger = createLogger('avm-bulk-test');
1915

2016
beforeEach(async () => {
17+
// FULL PROVING! Not check-circuit.
2118
tester = await AvmProvingTester.new(/*checkCircuitOnly=*/ false, /*globals=*/ defaultGlobals(), metrics);
22-
avmTestContractInstance = await tester.registerAndDeployContract(
23-
/*constructorArgs=*/ [],
24-
/*deployer=*/ AztecAddress.fromNumber(420),
25-
AvmTestContractArtifact,
26-
);
2719
});
2820

2921
afterAll(() => {
@@ -38,39 +30,11 @@ describe('AVM bulk test', () => {
3830
}
3931
});
4032

41-
it('Prove and verify', async () => {
42-
// Get a deployed contract instance to pass to the contract
43-
// for it to use as "expected" values when testing contract instance retrieval.
44-
const expectContractInstance = avmTestContractInstance;
45-
const argsField = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(x => new Fr(x));
46-
const argsU8 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(x => new Fr(x));
47-
const args = [
48-
argsField,
49-
argsU8,
50-
/*getInstanceForAddress=*/ expectContractInstance.address.toField(),
51-
/*expectedDeployer=*/ expectContractInstance.deployer.toField(),
52-
/*expectedClassId=*/ expectContractInstance.currentContractClassId.toField(),
53-
/*expectedInitializationHash=*/ expectContractInstance.initializationHash.toField(),
54-
];
55-
56-
await tester.simProveVerify(
57-
sender,
58-
/*setupCalls=*/ [],
59-
/*appCalls=*/ [{ address: avmTestContractInstance.address, fnName: 'bulk_testing', args }],
60-
/*teardownCall=*/ undefined,
61-
/*expectRevert=*/ false,
62-
/*feePayer*/ undefined,
63-
/*privateInsertions=*/ {
64-
nonRevertible: {
65-
nullifiers: [new Fr(420000)],
66-
noteHashes: [new Fr(420001)],
67-
},
68-
revertible: {
69-
nullifiers: [new Fr(420002)],
70-
noteHashes: [new Fr(420003)],
71-
},
72-
},
73-
'bulk_test',
74-
);
75-
}, 180_000);
33+
it(
34+
'Prove and verify',
35+
async () => {
36+
await bulkTest(tester, logger, (b: boolean) => expect(b).toBe(true));
37+
},
38+
TIMEOUT,
39+
);
7640
});

yarn-project/bb-prover/src/avm_proving_tests/avm_check_circuit1.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
1212

1313
import { AvmProvingTester } from './avm_proving_tester.js';
1414

15-
const TIMEOUT = 300_000;
15+
const TIMEOUT = 100_000;
1616

17-
describe.skip('AVM WitGen & Circuit – check circuit', () => {
17+
describe.skip('AVM check-circuit – unhappy paths 1', () => {
1818
let avmTestContractInstance: ContractInstanceWithAddress;
1919
let tester: AvmProvingTester;
2020

yarn-project/bb-prover/src/avm_proving_tests/avm_check_circuit2.test.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
55

66
import { AvmProvingTester } from './avm_proving_tester.js';
77

8-
const TIMEOUT = 300_000;
8+
const TIMEOUT = 100_000;
99

10-
describe.skip('AVM WitGen & Circuit – check circuit', () => {
10+
describe.skip('AVM check-circuit – unhappy paths 2', () => {
1111
const sender = AztecAddress.fromNumber(42);
1212
let avmTestContractInstance: ContractInstanceWithAddress;
1313
let tester: AvmProvingTester;
@@ -43,8 +43,8 @@ describe.skip('AVM WitGen & Circuit – check circuit', () => {
4343
// },
4444
// TIMEOUT,
4545
// );
46-
// FIXME(dbanks12): fails with "Lookup PERM_MAIN_ALU failed."
47-
it.skip('top-level exceptional halts due to a non-existent contract in app-logic and teardown', async () => {
46+
47+
it('top-level exceptional halts due to a non-existent contract in app-logic and teardown', async () => {
4848
// don't insert contracts into trees, and make sure retrieval fails
4949
const tester = await AvmProvingTester.new(/*checkCircuitOnly=*/ true);
5050
await tester.simProveVerify(
@@ -61,6 +61,7 @@ describe.skip('AVM WitGen & Circuit – check circuit', () => {
6161
/*expectRevert=*/ true,
6262
);
6363
});
64+
6465
it(
6566
'enqueued calls in every phase, with enqueued calls that depend on each other',
6667
async () => {

yarn-project/bb-prover/src/avm_proving_tests/avm_check_circuit3.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
55

66
import { AvmProvingTester } from './avm_proving_tester.js';
77

8-
const TIMEOUT = 300_000;
8+
const TIMEOUT = 100_000;
99

10-
describe.skip('AVM WitGen & Circuit – check circuit', () => {
10+
describe.skip('AVM check-circuit – unhappy paths 3', () => {
1111
const sender = AztecAddress.fromNumber(42);
1212
let avmTestContractInstance: ContractInstanceWithAddress;
1313
let tester: AvmProvingTester;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { createLogger } from '@aztec/foundation/log';
2+
import { TestExecutorMetrics, ammTest, defaultGlobals } from '@aztec/simulator/public/fixtures';
3+
4+
import { mkdirSync, writeFileSync } from 'fs';
5+
import path from 'path';
6+
7+
import { AvmProvingTester } from './avm_proving_tester.js';
8+
9+
const TIMEOUT = 300_000;
10+
11+
// TODO: unskip when check-circuit works for AMM. Confirm that it is fast enough to run in CI.
12+
describe.skip('AVM proven AMM', () => {
13+
const logger = createLogger('avm-proven-tests-amm');
14+
const metrics = new TestExecutorMetrics();
15+
let tester: AvmProvingTester;
16+
17+
beforeEach(async () => {
18+
// Check-circuit only (no full proving).
19+
tester = await AvmProvingTester.new(/*checkCircuitOnly=*/ true, /*globals=*/ defaultGlobals(), metrics);
20+
});
21+
22+
afterAll(() => {
23+
if (process.env.BENCH_OUTPUT) {
24+
mkdirSync(path.dirname(process.env.BENCH_OUTPUT), { recursive: true });
25+
writeFileSync(process.env.BENCH_OUTPUT, metrics.toGithubActionBenchmarkJSON());
26+
} else if (process.env.BENCH_OUTPUT_MD) {
27+
writeFileSync(process.env.BENCH_OUTPUT_MD, metrics.toPrettyString());
28+
} else {
29+
logger.info(`\n`); // sometimes jest tests obscure the last line(s)
30+
logger.info(metrics.toPrettyString());
31+
}
32+
});
33+
34+
it(
35+
'proven AMM operations: addLiquidity, swap, removeLiquidity (simulates constructors, set_minter)',
36+
async () => {
37+
await ammTest(tester, logger, (b: boolean) => expect(b).toBe(true));
38+
},
39+
TIMEOUT,
40+
);
41+
});
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { createLogger } from '@aztec/foundation/log';
2+
import { TestExecutorMetrics, defaultGlobals, tokenTest } from '@aztec/simulator/public/fixtures';
3+
4+
import { mkdirSync, writeFileSync } from 'fs';
5+
import path from 'path';
6+
7+
import { AvmProvingTester } from './avm_proving_tester.js';
8+
9+
const TIMEOUT = 60_000;
10+
11+
describe('AVM proven TokenContract', () => {
12+
const logger = createLogger('avm-proven-tests-token');
13+
const metrics = new TestExecutorMetrics();
14+
let tester: AvmProvingTester;
15+
16+
beforeAll(async () => {
17+
// Check-circuit only (no full proving).
18+
tester = await AvmProvingTester.new(/*checkCircuitOnly=*/ true, /*globals=*/ defaultGlobals(), metrics);
19+
});
20+
21+
afterAll(() => {
22+
if (process.env.BENCH_OUTPUT) {
23+
mkdirSync(path.dirname(process.env.BENCH_OUTPUT), { recursive: true });
24+
writeFileSync(process.env.BENCH_OUTPUT, metrics.toGithubActionBenchmarkJSON());
25+
} else if (process.env.BENCH_OUTPUT_MD) {
26+
writeFileSync(process.env.BENCH_OUTPUT_MD, metrics.toPrettyString());
27+
} else {
28+
logger.info(`\n`); // sometimes jest tests obscure the last line(s)
29+
logger.info(metrics.toPrettyString());
30+
}
31+
});
32+
33+
it(
34+
'proven token transfer (simulates constructor, mint, burn, check balance)',
35+
async () => {
36+
await tokenTest(tester, logger, (b: boolean) => expect(b).toBe(true));
37+
},
38+
TIMEOUT,
39+
);
40+
});

yarn-project/bb-prover/src/avm_proving_tests/avm_contract_class_limits.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { AvmProvingTester } from './avm_proving_tester.js';
88

99
const TIMEOUT = 300_000;
1010

11-
describe('AVM WitGen & Circuit – check circuit - contract class limits', () => {
11+
describe('AVM check-circuit - contract class limits', () => {
1212
const deployer = AztecAddress.fromNumber(42);
1313
let instances: ContractInstanceWithAddress[];
1414
let tester: AvmProvingTester;

yarn-project/bb-prover/src/avm_proving_tests/avm_contract_updates.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ import type { UInt64 } from '@aztec/stdlib/types';
1313

1414
import { AvmProvingTester } from './avm_proving_tester.js';
1515

16-
const TIMEOUT = 300_000;
16+
const TIMEOUT = 60_000;
1717

18-
describe.skip('AVM WitGen & Circuit - contract updates', () => {
18+
describe('AVM check-circuit - contract updates', () => {
1919
const sender = AztecAddress.fromNumber(42);
2020

2121
const avmTestContractClassSeed = 0;

0 commit comments

Comments
 (0)