-
Notifications
You must be signed in to change notification settings - Fork 296
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
feat: pay fee when deploying account contracts #5540
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
90f4dbc
to
e951798
Compare
Benchmark resultsMetrics with a significant change:
Detailed resultsAll benchmarks are run on txs on the This benchmark source data is available in JSON format on S3 here. Values are compared against data from master at commit L2 block published to L1Each column represents the number of txs on an L2 block published to L1.
L2 chain processingEach column represents the number of blocks on the L2 chain where each block has 16 txs.
Circuits statsStats on running time and I/O sizes collected for every circuit run across all benchmarks.
Tree insertion statsThe duration to insert a fixed batch of leaves into each tree type.
MiscellaneousTransaction sizes based on how many contract classes are registered in the tx.
Transaction size based on fee payment method
Transaction processing duration by data writes.
|
51ed6a1
to
f61f732
Compare
4d98bc8
to
1bbdc57
Compare
1bbdc57
to
086911b
Compare
Looks like boxes use the published versions of aztec.js & accounts instead of what's in the current workspace so the their tests will fail. We can either disable them temporarily until the next release or find a way to link them against the workspace's packages. |
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.
Looks good! I left a few comments but we can address those later. I was about to comment on how it'd be nice to be able to publicly deploy and initialize simultaneously, when I remembered that you just mentioned that on Slack heh.
#[aztec(private)] | ||
#[aztec(initializer)] | ||
fn constructor() { | ||
let actions = AccountActions::private(&mut context, ACCOUNT_ACTIONS_STORAGE_SLOT, is_valid_impl); | ||
actions.initialize_account_contract(); | ||
} |
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.
Let's remove this: this account contract does not need initialization at all.
@@ -54,6 +56,17 @@ impl AccountActions { | |||
) | |||
} | |||
|
|||
pub fn initialize_account_contract(self) { |
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'd rename this to something like "execute_fee_payload_for_init", since it's not actually initializing the contract.
let fee_payload = FeePayload::deserialize(pop_capsule()); | ||
let fee_hash = fee_payload.hash(); |
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 think I'm starting to agree with Joe on this use case for capsules. The fee_payload
should be an argument to this function and not something that shows up magically, and what we really need is a way to say "this argument is not part of the initialization hash". But we can change that in a future PR.
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 think the tasks for this would be:
- Add a
noinitargcheck
attribute in Noir for the argument to be skipped - Make sure the attribute is emitted in the abi
- Compute a separate args hash for initialization preimage check if there are any noinitargcheck
- Change the address computation so it ignores args marked as
noinitargcheck
when computing the initialization hash in the address preimage (this will be the most annoying bit I think) - Ensure the deploy method does not ignore them when actually executing the initialization
It's quite a lot unfortunately, but feels cleaner..?
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 think I'm starting to agree with Joe on this use case for capsules
lol same, but I was actually thinking of going the protocol contract route instead of adding a new macro 😅
#[aztec(private)] | ||
#[aztec(initializer)] | ||
fn constructor() { | ||
let actions = AccountActions::private(&mut context, ACCOUNT_ACTIONS_STORAGE_SLOT, is_valid_impl); | ||
actions.initialize_account_contract(); | ||
} |
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.
Let's remove this one as well
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.
Whoa, when was entrypoints
moved to a package of its own?
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 creates the entrypoints package during the offsite. In hindsight I think a better approach would've been to expose it as aztec.js/entrypoints
.
if (!this.initializerArtifact) { | ||
throw new Error('Account contract can not be initialized without an initializer'); | ||
} |
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.
Let's extend this to support account contracts without initializers, in which case we should just publicly deploy the instance.
const deployWallet = new SignerlessWallet(this.pxe); | ||
const deployer = new ContractDeployer( | ||
this.accountContract.getContractArtifact(), | ||
deployWallet, | ||
const args = this.accountContract.getDeploymentArgs() ?? []; | ||
this.deployMethod = new DeployAccountMethod( | ||
this.pxe, | ||
this.accountContract.getAuthWitnessProvider(this.getCompleteAddress()), | ||
encryptionPublicKey, | ||
this.accountContract.getContractArtifact(), | ||
args, | ||
() => this.#register(), | ||
); | ||
const args = this.accountContract.getDeploymentArgs() ?? []; | ||
this.deployMethod = deployer.deploy(...args); |
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.
Looks a lot nicer!
/** | ||
* The function calls to execute | ||
* @internal | ||
*/ | ||
get function_calls() { | ||
return this.#functionCalls; | ||
} |
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.
Let's add a comment why this snake_case property is needed
/** | ||
* Contract interaction for deploying an account contract. Handles fee preparation and contract initialization. | ||
*/ | ||
export class DeployAccountMethod<TContract extends ContractBase = Contract> extends BaseContractInteraction { |
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.
Let's rename to InitializeAccount
, since it doesn't have the capability to publicly deploy.
Superseded by #5601 |
This PR enables accounts to pay tx fees when they're deployed. To achieve this a new deployment method was added that's used by the `AccountManager` class to optionally register/publicly deploy and initialize the target account contract. Entrypoint classes now accept authwits/packed arguments alongside the normal function calls from before. This is needed so that authwits could be created in a parent context and then passed along as transient authwits to the transaction (see `ExecutionRequestInit` wrapper type) Initializing an account contract can use any of the three existing payment methods: - using bridged gas token from L1 - paying privately through a fee payment contract - paying publicly through a fee payment contract In order to use fee payment contracts this PR adds `noinitcheck` to `spend_private_authwit` and `spend_public_authwit` because it's not possible to read the init nullifier in the current tx (protocol limitation). Instead the contract relies on the note containing the public key to exist to validate that the contract has been initialized correctly. An extra payment flow is tested as well: a third party takes the account's public keys and deploys and initializes the account while paying the associated fee. This simulates the flow where a deployment service is used that takes payment through a side chain (e.g. fiat). Breaking change: moved `DefaultMultiCallEntrypoint` to aztec.js This PR supersedes #5540 and #5543. Fix #5190 #5191 #5544.
This PR enables account contracts to pay for tx fees when they're deployed.
Fix #5190