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

fix(avm-simulator): always set revertReason when reverting #6297

Merged
merged 1 commit into from
May 9, 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
7 changes: 4 additions & 3 deletions yarn-project/end-to-end/src/e2e_avm_simulator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ describe('e2e_avm_simulator', () => {
});
});

describe('ACVM interoperability', () => {
describe.skip('ACVM interoperability', () => {
let avmContract: AvmAcvmInteropTestContract;

beforeEach(async () => {
Expand All @@ -136,7 +136,7 @@ describe('e2e_avm_simulator', () => {
expect(await avmContract.methods.call_avm_from_acvm().simulate()).toEqual(123456n);
});

it.skip('Can call ACVM function from AVM', async () => {
it('Can call ACVM function from AVM', async () => {
expect(await avmContract.methods.call_acvm_from_avm().simulate()).toEqual(123456n);
});

Expand All @@ -146,7 +146,7 @@ describe('e2e_avm_simulator', () => {
await avmContract.methods.assert_unsiloed_nullifier_acvm(nullifier).send().wait();
});

it.skip('AVM nested call to ACVM sees settled nullifiers', async () => {
it('AVM nested call to ACVM sees settled nullifiers', async () => {
const nullifier = new Fr(123456);
await avmContract.methods.new_nullifier(nullifier).send().wait();
await avmContract.methods
Expand All @@ -155,6 +155,7 @@ describe('e2e_avm_simulator', () => {
.wait();
});

// TODO: Enable (or delete) authwit tests once the AVM is fully functional.
describe.skip('Authwit', () => {
it('Works if authwit provided', async () => {
const recipient = AztecAddress.random();
Expand Down
22 changes: 14 additions & 8 deletions yarn-project/simulator/src/avm/avm_machine_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,20 @@ export class AvmMachineState {
throw new Error('Execution results are not ready! Execution is ongoing.');
}
let revertReason = undefined;
if (this.reverted && this.output.length > 0) {
try {
// We remove the first element which is the 'error selector'.
const revertOutput = this.output.slice(1);
// Try to interpret the output as a text string.
revertReason = new Error('Assertion failed: ' + String.fromCharCode(...revertOutput.map(fr => fr.toNumber())));
} catch (e) {
revertReason = new Error('<no output>');
if (this.reverted) {
if (this.output.length === 0) {
revertReason = new Error('Assertion failed.');
} else {
try {
// We remove the first element which is the 'error selector'.
const revertOutput = this.output.slice(1);
// Try to interpret the output as a text string.
revertReason = new Error(
'Assertion failed: ' + String.fromCharCode(...revertOutput.map(fr => fr.toNumber())),
);
} catch (e) {
revertReason = new Error('Assertion failed: <cannot interpret as string>');
}
}
}
return new AvmContractCallResults(this.reverted, this.output, revertReason);
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/simulator/src/avm/avm_simulator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ describe('AVM simulator: transpiled Noir contracts', () => {
const bytecode = getAvmTestContractBytecode('u128_from_integer_overflow');
const results = await new AvmSimulator(initContext()).executeBytecode(bytecode);
expect(results.reverted).toBe(true);
expect(results.revertReason?.message).toEqual(undefined);
expect(results.revertReason?.message).toEqual('Assertion failed.');
// Note: compiler intrinsic messages (like below) are not known to the AVM
//expect(results.revertReason?.message).toEqual("Assertion failed: call to assert_max_bit_size 'self.__assert_max_bit_size(bit_size)'");
});
Expand Down
10 changes: 9 additions & 1 deletion yarn-project/simulator/src/public/abstract_phase_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,10 +283,18 @@ export abstract class AbstractPhaseManager {
)
: current;

// Sanity check for a current upstream assumption.
// Consumers of the result seem to expect "reverted <=> revertReason !== undefined".
const functionSelector = result.execution.functionData.selector.toString();
if (result.reverted && !result.revertReason) {
throw new Error(
`Simulation of ${result.execution.contractAddress.toString()}:${functionSelector} reverted with no reason.`,
);
}

// Accumulate gas used in this execution
gasUsed = gasUsed.add(Gas.from(result.startGasLeft).sub(Gas.from(result.endGasLeft)));

const functionSelector = result.execution.functionData.selector.toString();
if (result.reverted && !PhaseIsRevertible[this.phase]) {
this.log.debug(
`Simulation error on ${result.execution.contractAddress.toString()}:${functionSelector} with reason: ${
Expand Down
4 changes: 0 additions & 4 deletions yarn-project/simulator/src/public/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,6 @@ async function executePublicFunctionAcvm(
})();

if (reverted) {
if (!revertReason) {
throw new Error('Reverted but no revert reason');
}

return {
execution,
returnValues: [],
Expand Down
Loading