-
Notifications
You must be signed in to change notification settings - Fork 284
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: handle calls to non-existent contracts in AVM witgen #10862
Conversation
if (contract_bytecode.bytecode.size() == 0) { | ||
vinfo("Excluding non-existent contract from bytecode hash columns..."); | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the only real diff here. We are assuming that if the hinted bytecode is empty, the contract doesn't exist and should therefore be omitted from the bytecode hashing.
trace_builder.allocate_gas_for_call(l2_gas_allocated_to_enqueued_call, da_gas_allocated_to_enqueued_call); | ||
// Find the bytecode based on contract address of the public call request | ||
std::vector<uint8_t> bytecode = | ||
trace_builder.get_bytecode(trace_builder.current_ext_call_ctx.contract_address, check_bytecode_membership); | ||
std::vector<uint8_t> bytecode; | ||
try { | ||
bytecode = | ||
trace_builder.get_bytecode(trace_builder.current_ext_call_ctx.contract_address, check_bytecode_membership); | ||
} catch ([[maybe_unused]] const std::runtime_error& e) { | ||
info("AVM enqueued call exceptionally halted. Error: No bytecode found for enqueued call"); | ||
// FIXME: properly handle case when bytecode is not found! | ||
// For now, we add a dummy row in main trace to mutate later. | ||
// Dummy row in main trace to mutate afterwards. | ||
// This error was encountered before any opcodes were executed, but | ||
// we need at least one row in the execution trace to then mutate and say "it halted and consumed all gas!" | ||
trace_builder.op_add(0, 0, 0, 0, OpCode::ADD_8); | ||
trace_builder.handle_exceptional_halt(); | ||
return AvmError::NO_BYTECODE_FOUND; | ||
; | ||
} | ||
|
||
trace_builder.allocate_gas_for_call(l2_gas_allocated_to_enqueued_call, da_gas_allocated_to_enqueued_call); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i COULD have had get_bytecode
return [byteode, error]
... but this is way simpler...
// FIXME: properly handle case when an instruction fails parsing | ||
// especially first instruction in bytecode | ||
if (!is_ok(error)) { | ||
info("AVM failed to deserialize bytecode at pc: ", pc); | ||
// FIXME: properly handle case when an instruction fails parsing! | ||
// For now, we add a dummy row in main trace to mutate later. | ||
// This error was encountered before any opcodes were executed, but | ||
// we need at least one row in the execution trace to then mutate and say "it halted and consumed all gas!" | ||
trace_builder.op_add(0, 0, 0, 0, OpCode::ADD_8); | ||
error = parse_error; | ||
break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't tested this yet, but it should work! We can write a test for deserialization failures in a follow-up
.internal_return_ptr_stack = {}, | ||
.tree_snapshot = {}, | ||
}; | ||
if (is_ok(error)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just moved into if is ok
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can probably move some tests into the bulk test. But we can't do that with tests that are expected to revert....
const merkleTrees = await (await MerkleTrees.new(openTmpStore(), telemetry)).fork(); | ||
const contractDataSource = new MockedAvmTestContractDataSource(); | ||
const contractDataSource = new MockedAvmTestContractDataSource(skipContractDeployments); | ||
const worldStateDB = new WorldStateDB(merkleTrees, contractDataSource); | ||
|
||
const contractInstance = contractDataSource.contractInstance; | ||
const contractAddressNullifier = siloNullifier( | ||
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS), | ||
contractInstance.address.toField(), | ||
); | ||
await merkleTrees.batchInsert(MerkleTreeId.NULLIFIER_TREE, [contractAddressNullifier.toBuffer()], 0); | ||
// other contract address used by the bulk test's GETCONTRACTINSTANCE test | ||
const otherContractAddressNullifier = siloNullifier( | ||
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS), | ||
contractDataSource.otherContractInstance.address.toField(), | ||
); | ||
await merkleTrees.batchInsert(MerkleTreeId.NULLIFIER_TREE, [otherContractAddressNullifier.toBuffer()], 0); | ||
|
||
if (!skipContractDeployments) { | ||
const contractAddressNullifier = siloNullifier( | ||
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS), | ||
contractInstance.address.toField(), | ||
); | ||
await merkleTrees.batchInsert(MerkleTreeId.NULLIFIER_TREE, [contractAddressNullifier.toBuffer()], 0); | ||
// other contract address used by the bulk test's GETCONTRACTINSTANCE test | ||
const otherContractAddressNullifier = siloNullifier( | ||
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS), | ||
contractDataSource.otherContractInstance.address.toField(), | ||
); | ||
await merkleTrees.batchInsert(MerkleTreeId.NULLIFIER_TREE, [otherContractAddressNullifier.toBuffer()], 0); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Skip contract deployment completely when we want to fail at the top-level due to bytecode not found.
Exceptionally halt & consume all gas on a call to a non-existent contract. Should be able to prove.
Hacked this to work for top-level/enqueued-calls by adding a dummy row (
op_add
) and then raising an exceptional halt.Resolves #10373
Resolves #10044
Follow-up work: