feat(aztec-nr)!: add msg_sender to the utility context#24062
Conversation
|
|
||
| if handshake.is_initialized() { | ||
| Option::some(handshake.view_note().siloed_for(caller)) | ||
| Option::some(handshake.view_note().siloed_for(self.msg_sender())) |
There was a problem hiding this comment.
What if an app invokes this function directly, with an arbitrary from? Wouldn't we be then exposing all of the siloed secrets to the app for all from contracts, letting the app find all onchain activity?
There was a problem hiding this comment.
Yes, but isn't it the responsibility of the wallet to prevent that from happening? I mean, an app could also try to get balances for all tokens and accounts, right?
| throw new Error(`Cannot run ${entryPointArtifact.functionType} function as private`); | ||
| } | ||
|
|
||
| if (request.origin !== contractAddress) { |
There was a problem hiding this comment.
We are now simply avoiding the extra param and doing:
const contractAddress = request.origin;
| } | ||
|
|
||
| /** The address of the contract whose function is being executed, from the call context. */ | ||
| protected get contractAddress(): AztecAddress { |
There was a problem hiding this comment.
Added this to avoid changing over 50 this.contractAddress to this.callContext.contractAddress
| export type PrivateExecutionOracleArgs = UtilityExecutionOracleArgs & { | ||
| argsHash: Fr; | ||
| txContext: TxContext; | ||
| callContext: CallContext; |
There was a problem hiding this comment.
Moved into UtilityOracle
| * The caller address: it becomes the utility's `msg_sender` and determines which notes and keys are visible | ||
| * during execution. Pass `NO_FROM` when there is no acting account. | ||
| */ | ||
| from: AztecAddress | NoFrom; |
There was a problem hiding this comment.
Made this change to keep it consistent with proveTx and simulateTx
Why we are doing this
Utility functions had no notion of
msg_sender, so a utility that wanted to know its caller had to accept it as a forgeable parameter.HandshakeRegistry::get_app_siloed_secrettook an explicitcallerargument and siloed the returned secret by it, so a hostile contract could lie aboutcallerand read another app's siloed secret.Our fix
UtilityContextnow carries a realmsg_sender, set by the simulator on dispatch: nested calls (utility-to-utility or private-to-utility) observe the calling contract's address, and top-level calls observe thefromsupplied for the simulation. It is exposed asself.msg_sender()andself.context.maybe_msg_sender(), mirroring the private and public contexts..simulate({ from })on a utility now sets the top-levelmsg_senderin addition to determining note/key visibility.Wallet.executeUtilitytakes{ from, additionalScopes }instead of{ scopes }.HandshakeRegistry::get_app_siloed_secretdrops the forgeablecallerparameter and silos byself.msg_sender().Migration
Covered in the new migration_notes.md entry:
TestEnvironment::execute_utility/execute_utility_optstake a leadingfrom, andWallet.executeUtilityoptions change from{ scopes }to{ from, additionalScopes }.Fixes F-671