Skip to content

Commit

Permalink
test: refactor nested contract test for speed (#6117)
Browse files Browse the repository at this point in the history
Fixes #6114. Approx from 500 -> 120 seconds.

---------

Co-authored-by: Jan Beneš <[email protected]>
  • Loading branch information
LHerskind and benesjan authored May 2, 2024
1 parent ae5cb21 commit b346a2f
Show file tree
Hide file tree
Showing 7 changed files with 295 additions and 159 deletions.
158 changes: 0 additions & 158 deletions yarn-project/end-to-end/src/e2e_nested_contract.test.ts

This file was deleted.

45 changes: 45 additions & 0 deletions yarn-project/end-to-end/src/e2e_nested_contract/importer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { ImportTestContract, TestContract } from '@aztec/noir-contracts.js';

import { NestedContractTest } from './nested_contract_test.js';

describe('e2e_nested_contract manual', () => {
const t = new NestedContractTest('manual');
let testContract: TestContract;
let importerContract: ImportTestContract;
let { wallets, logger } = t;

beforeAll(async () => {
await t.applyBaseSnapshots();
await t.setup();
({ wallets, logger } = t);
});

beforeEach(async () => {
importerContract = await ImportTestContract.deploy(wallets[0]).send().deployed();
testContract = await TestContract.deploy(wallets[0]).send().deployed();
});

afterAll(async () => {
await t.teardown();
});

it('calls a method with multiple arguments', async () => {
logger.info(`Calling main on importer contract`);
await importerContract.methods.main_contract(testContract.address).send().wait();
});

it('calls a method no arguments', async () => {
logger.info(`Calling noargs on importer contract`);
await importerContract.methods.call_no_args(testContract.address).send().wait();
});

it('calls an open function', async () => {
logger.info(`Calling openfn on importer contract`);
await importerContract.methods.call_open_fn(testContract.address).send().wait();
});

it('calls an open function from an open function', async () => {
logger.info(`Calling pub openfn on importer contract`);
await importerContract.methods.pub_call_open_fn(testContract.address).send().wait();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { NestedContractTest } from './nested_contract_test.js';

describe('e2e_nested_contract manual', () => {
const t = new NestedContractTest('manual');
let { parentContract, childContract } = t;

beforeAll(async () => {
await t.applyBaseSnapshots();
await t.applyManualSnapshots();
await t.setup();
({ parentContract, childContract } = t);
});

afterAll(async () => {
await t.teardown();
});

it('performs nested calls', async () => {
await parentContract.methods.entry_point(childContract.address, childContract.methods.value.selector).send().wait();
});

it('fails simulation if calling a function not allowed to be called externally', async () => {
await expect(
parentContract.methods
.entry_point(childContract.address, (childContract.methods as any).value_internal.selector)
.prove(),
).rejects.toThrow(/Assertion failed: Function value_internal can only be called internally/);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { type AztecAddress, Fr } from '@aztec/aztec.js';
import { ChildContract, ParentContract } from '@aztec/noir-contracts.js';

import { NestedContractTest } from './nested_contract_test.js';

describe('e2e_nested_contract manual_enqueue', () => {
const t = new NestedContractTest('manual_enqueue');
let { wallets, pxe, parentContract, childContract } = t;

const getChildStoredValue = (child: { address: AztecAddress }) => pxe.getPublicStorageAt(child.address, new Fr(1));

beforeAll(async () => {
await t.applyBaseSnapshots();
// We don't have the manual snapshot because every test requires a fresh setup and teardown
await t.setup();
({ wallets, pxe } = t);
});

beforeEach(async () => {
parentContract = await ParentContract.deploy(wallets[0]).send().deployed();
childContract = await ChildContract.deploy(wallets[0]).send().deployed();
});

afterAll(async () => {
await t.teardown();
});

it('enqueues a single public call', async () => {
await parentContract.methods
.enqueue_call_to_child(childContract.address, childContract.methods.pub_inc_value.selector, 42n)
.send()
.wait();
expect(await getChildStoredValue(childContract)).toEqual(new Fr(42n));
});

it('fails simulation if calling a public function not allowed to be called externally', async () => {
await expect(
parentContract.methods
.enqueue_call_to_child(
childContract.address,
(childContract.methods as any).pub_inc_value_internal.selector,
42n,
)
.prove(),
).rejects.toThrow(/Assertion failed: Function pub_inc_value_internal can only be called internally/);
});

it('enqueues multiple public calls', async () => {
await parentContract.methods
.enqueue_call_to_child_twice(childContract.address, childContract.methods.pub_inc_value.selector, 42n)
.send()
.wait();
expect(await getChildStoredValue(childContract)).toEqual(new Fr(85n));
});

it('enqueues a public call with nested public calls', async () => {
await parentContract.methods
.enqueue_call_to_pub_entry_point(childContract.address, childContract.methods.pub_inc_value.selector, 42n)
.send()
.wait();
expect(await getChildStoredValue(childContract)).toEqual(new Fr(42n));
});

it('enqueues multiple public calls with nested public calls', async () => {
await parentContract.methods
.enqueue_calls_to_pub_entry_point(childContract.address, childContract.methods.pub_inc_value.selector, 42n)
.send()
.wait();
expect(await getChildStoredValue(childContract)).toEqual(new Fr(85n));
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { type AztecAddress, BatchCall, Fr, type Wallet, toBigIntBE } from '@aztec/aztec.js';

import { NestedContractTest } from './nested_contract_test.js';

describe('e2e_nested_contract manual', () => {
const t = new NestedContractTest('manual');
let wallet: Wallet;
let { wallets, pxe, parentContract, childContract } = t;

const getChildStoredValue = (child: { address: AztecAddress }) => pxe.getPublicStorageAt(child.address, new Fr(1));

beforeAll(async () => {
await t.applyBaseSnapshots();
await t.applyManualSnapshots();
await t.setup();
({ wallets, pxe, parentContract, childContract } = t);
wallet = wallets[0];
});

afterAll(async () => {
await t.teardown();
});

it('performs public nested calls', async () => {
await parentContract.methods
.pub_entry_point(childContract.address, childContract.methods.pub_get_value.selector, 42n)
.send()
.wait();
});

// Regression for https://github.com/AztecProtocol/aztec-packages/issues/640
it('reads fresh value after write within the same tx', async () => {
await parentContract.methods
.pub_entry_point_twice(childContract.address, childContract.methods.pub_inc_value.selector, 42n)
.send()
.wait();
expect(await getChildStoredValue(childContract)).toEqual(new Fr(84n));
});

// Regression for https://github.com/AztecProtocol/aztec-packages/issues/1645
// Executes a public call first and then a private call (which enqueues another public call)
// through the account contract, if the account entrypoint behaves properly, it will honor
// this order and not run the private call first which results in the public calls being inverted.
it('executes public calls in expected order', async () => {
const pubSetValueSelector = childContract.methods.pub_set_value.selector;
const actions = [
childContract.methods.pub_set_value(20n).request(),
parentContract.methods.enqueue_call_to_child(childContract.address, pubSetValueSelector, 40n).request(),
];

const tx = await new BatchCall(wallet, actions).send().wait();
const extendedLogs = (
await wallet.getUnencryptedLogs({
fromBlock: tx.blockNumber!,
})
).logs;
const processedLogs = extendedLogs.map(extendedLog => toBigIntBE(extendedLog.log.data));
expect(processedLogs).toEqual([20n, 40n]);
expect(await getChildStoredValue(childContract)).toEqual(new Fr(40n));
});
});
Loading

0 comments on commit b346a2f

Please sign in to comment.