Skip to content
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
8 changes: 7 additions & 1 deletion noir-projects/aztec-nr/aztec/src/authwit/account.nr
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,13 @@ impl AccountActions<&mut PrivateContext> {
pub fn entrypoint(self, app_payload: AppPayload, fee_payment_method: u8, cancellable: bool) {
let valid_fn = self.is_valid_impl;

assert(valid_fn(self.context, app_payload.hash()));
let message_hash = compute_authwit_message_hash(
self.context.this_address(),
self.context.chain_id(),
self.context.version(),
app_payload.hash(),
);
assert(valid_fn(self.context, message_hash));

if fee_payment_method == AccountFeePaymentMethodOptions.PREEXISTING_FEE_JUICE {
self.context.set_as_fee_payer();
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/aztec.js/src/account/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ export class BaseAccount implements Account {
return this.entrypoint.createTxExecutionRequest(exec, gasSettings, chainInfo, options);
}

wrapExecutionPayload(exec: ExecutionPayload, options?: any): Promise<ExecutionPayload> {
return this.entrypoint.wrapExecutionPayload(exec, options);
wrapExecutionPayload(exec: ExecutionPayload, chainInfo: ChainInfo, options?: any): Promise<ExecutionPayload> {
return this.entrypoint.wrapExecutionPayload(exec, chainInfo, options);
}

async createAuthWit(messageHashOrIntent: CallIntent | IntentInnerHash, chainInfo: ChainInfo): Promise<AuthWitness> {
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/aztec.js/src/account/account_with_secret_key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ export class AccountWithSecretKey implements Account {
return this.account.createTxExecutionRequest(exec, gasSettings, chainInfo, options);
}

wrapExecutionPayload(exec: ExecutionPayload, options?: any): Promise<ExecutionPayload> {
return this.account.wrapExecutionPayload(exec, options);
wrapExecutionPayload(exec: ExecutionPayload, chainInfo: ChainInfo, options?: any): Promise<ExecutionPayload> {
return this.account.wrapExecutionPayload(exec, chainInfo, options);
}
createAuthWit(intent: IntentInnerHash | CallIntent, chainInfo: ChainInfo): Promise<AuthWitness> {
return this.account.createAuthWit(intent, chainInfo);
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/aztec.js/src/account/signerless_account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ export class SignerlessAccount implements Account {
return this.entrypoint.createTxExecutionRequest(exec, gasSettings, chainInfo);
}

wrapExecutionPayload(exec: ExecutionPayload, options?: any): Promise<ExecutionPayload> {
return this.entrypoint.wrapExecutionPayload(exec, options);
wrapExecutionPayload(exec: ExecutionPayload, chainInfo: ChainInfo, options?: any): Promise<ExecutionPayload> {
return this.entrypoint.wrapExecutionPayload(exec, chainInfo, options);
}

createAuthWit(_intent: Fr | Buffer | IntentInnerHash | CallIntent): Promise<AuthWitness> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { AccountFeePaymentMethodOptions } from '@aztec/entrypoints/account';
import type { ChainInfo } from '@aztec/entrypoints/interfaces';
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
import { AztecAddress } from '@aztec/stdlib/aztec-address';
import type { GasSettings } from '@aztec/stdlib/gas';
Expand All @@ -25,6 +26,7 @@ import type { FeePaymentMethod } from '../fee/fee_payment_method.js';
export class AccountEntrypointMetaPaymentMethod implements FeePaymentMethod {
constructor(
private account: Account,
private chainInfo: ChainInfo,
private paymentMethod?: FeePaymentMethod,
private feeEntrypointOptions?: any,
) {}
Expand Down Expand Up @@ -61,7 +63,7 @@ export class AccountEntrypointMetaPaymentMethod implements FeePaymentMethod {
}

// Use the generic wrapping mechanism from the account interface
return this.account.wrapExecutionPayload(innerPayload, options);
return this.account.wrapExecutionPayload(innerPayload, this.chainInfo, options);
}

getFeePayer(): Promise<AztecAddress> {
Expand Down
10 changes: 7 additions & 3 deletions yarn-project/aztec.js/src/wallet/deploy_account_method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,12 @@ export class DeployAccountMethod<TContract extends ContractBase = Contract> exte
* @param feeEntrypointOptions - Optional entrypoint-specific options for wrapping. If not provided, will be auto-computed based on the payment method.
* @returns A FeePaymentMethod that routes the original one through the account's entrypoint (AccountEntrypointMetaPaymentMethod)
*/
private getSelfFeePaymentMethod(originalPaymentMethod?: FeePaymentMethod, feeEntrypointOptions?: any) {
private async getSelfFeePaymentMethod(originalPaymentMethod?: FeePaymentMethod, feeEntrypointOptions?: any) {
if (!this.address) {
throw new Error('Instance is not yet constructed. This is a bug!');
}
return new AccountEntrypointMetaPaymentMethod(this.account, originalPaymentMethod, feeEntrypointOptions);
const chainInfo = await this.wallet.getChainInfo();
return new AccountEntrypointMetaPaymentMethod(this.account, chainInfo, originalPaymentMethod, feeEntrypointOptions);
}

/**
Expand All @@ -128,7 +129,10 @@ export class DeployAccountMethod<TContract extends ContractBase = Contract> exte
const executionPayloads = [deploymentExecutionPayload];
// If this is a self-deployment, manage the fee accordingly
if (opts?.deployer?.equals(AztecAddress.ZERO)) {
const feePaymentMethod = this.getSelfFeePaymentMethod(opts?.fee?.paymentMethod, opts?.fee?.feeEntrypointOptions);
const feePaymentMethod = await this.getSelfFeePaymentMethod(
opts?.fee?.paymentMethod,
opts?.fee?.feeEntrypointOptions,
);
const feeExecutionPayload = await feePaymentMethod.getExecutionPayload();
// Notice they are reversed (fee payment usually goes first):
// this is because we need to construct the contract BEFORE it can pay for its own fee
Expand Down
17 changes: 13 additions & 4 deletions yarn-project/entrypoints/src/account_entrypoint.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Fr } from '@aztec/foundation/curves/bn254';
import { type FunctionAbi, FunctionCall, FunctionSelector, encodeArguments } from '@aztec/stdlib/abi';
import { computeOuterAuthWitHash } from '@aztec/stdlib/auth-witness';
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
import type { GasSettings } from '@aztec/stdlib/gas';
import { ExecutionPayload, HashedValues, TxContext, TxExecutionRequest } from '@aztec/stdlib/tx';
Expand Down Expand Up @@ -66,7 +67,7 @@ export class DefaultAccountEntrypoint implements EntrypointInterface {
options: DefaultAccountEntrypointOptions,
): Promise<TxExecutionRequest> {
const { authWitnesses, capsules, extraHashedArgs } = exec;
const callData = await this.#buildEntrypointCallData(exec, options);
const callData = await this.#buildEntrypointCallData(exec, chainInfo, options);
const entrypointHashedArgs = await HashedValues.fromArgs(callData.encodedArgs);
const txRequest = TxExecutionRequest.from({
firstCallArgsHash: entrypointHashedArgs.hash,
Expand All @@ -84,10 +85,11 @@ export class DefaultAccountEntrypoint implements EntrypointInterface {

async wrapExecutionPayload(
exec: ExecutionPayload,
chainInfo: ChainInfo,
options: DefaultAccountEntrypointOptions,
): Promise<ExecutionPayload> {
const { authWitnesses, capsules, extraHashedArgs, feePayer } = exec;
const callData = await this.#buildEntrypointCallData(exec, options);
const callData = await this.#buildEntrypointCallData(exec, chainInfo, options);

// Build the entrypoint function call
const entrypointCall = FunctionCall.from({
Expand All @@ -114,10 +116,15 @@ export class DefaultAccountEntrypoint implements EntrypointInterface {
* Builds the shared data needed for both creating a tx execution request and wrapping an execution payload.
* This includes encoding calls, building entrypoint arguments, and creating the authwitness.
* @param exec - The execution payload containing calls to encode
* @param chainInfo - Chain information (chainId and version) for replay protection
* @param options - Account entrypoint options including tx nonce and fee payment method
* @returns Encoded call data, ABI, function selector, and auth witness
*/
async #buildEntrypointCallData(exec: ExecutionPayload, options: DefaultAccountEntrypointOptions) {
async #buildEntrypointCallData(
exec: ExecutionPayload,
chainInfo: ChainInfo,
options: DefaultAccountEntrypointOptions,
) {
const { calls } = exec;
const { cancellable, txNonce, feePaymentMethodOptions } = options;

Expand All @@ -129,7 +136,9 @@ export class DefaultAccountEntrypoint implements EntrypointInterface {

const functionSelector = await FunctionSelector.fromNameAndParameters(abi.name, abi.parameters);

const payloadAuthWitness = await this.auth.createAuthWit(await encodedCalls.hash());
const payloadHash = await encodedCalls.hash();
const messageHash = await computeOuterAuthWitHash(this.address, chainInfo.chainId, chainInfo.version, payloadHash);
const payloadAuthWitness = await this.auth.createAuthWit(messageHash);

return {
encodedCalls,
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/entrypoints/src/default_entrypoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class DefaultEntrypoint implements EntrypointInterface {
);
}

async wrapExecutionPayload(exec: ExecutionPayload, _options?: any): Promise<ExecutionPayload> {
async wrapExecutionPayload(exec: ExecutionPayload, _chainInfo: ChainInfo, _options?: any): Promise<ExecutionPayload> {
if (exec.calls.length !== 1) {
throw new Error(`DefaultEntrypoint can only wrap a single call, got ${exec.calls.length}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class DefaultMultiCallEntrypoint implements EntrypointInterface {
return Promise.resolve(txRequest);
}

async wrapExecutionPayload(exec: ExecutionPayload, _options?: any): Promise<ExecutionPayload> {
async wrapExecutionPayload(exec: ExecutionPayload, _chainInfo: ChainInfo, _options?: any): Promise<ExecutionPayload> {
const { authWitnesses, capsules, extraHashedArgs } = exec;
const callData = await this.#buildEntrypointCallData(exec);
const entrypointCall = FunctionCall.from({
Expand Down
3 changes: 2 additions & 1 deletion yarn-project/entrypoints/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,12 @@ export interface EntrypointInterface {
* of a single entrypoint call.
*
* @param exec - The execution payload to wrap
* @param chainInfo - Chain information (chainId and version) for replay protection
* @param options - Implementation-specific options
* @returns A new execution payload with a single call to this entrypoint
* @throws Error if the payload cannot be wrapped (e.g., exceeds call limit)
*/
wrapExecutionPayload(exec: ExecutionPayload, options?: any): Promise<ExecutionPayload>;
wrapExecutionPayload(exec: ExecutionPayload, chainInfo: ChainInfo, options?: any): Promise<ExecutionPayload>;
}

/** Creates authorization witnesses. */
Expand Down
Loading