-
Notifications
You must be signed in to change notification settings - Fork 598
feat(SimulateTx): simulate constrained transaction execution with return values #5432
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
Changes from all commits
8cf5474
24be74b
874886b
ca2a445
9ee5750
9db9927
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| import { type FunctionCall, type TxExecutionRequest } from '@aztec/circuit-types'; | ||
| import { type AztecAddress, FunctionData } from '@aztec/circuits.js'; | ||
| import { type FunctionCall, PackedArguments, TxExecutionRequest } from '@aztec/circuit-types'; | ||
| import { type AztecAddress, FunctionData, TxContext } from '@aztec/circuits.js'; | ||
| import { type FunctionAbi, FunctionType, encodeArguments } from '@aztec/foundation/abi'; | ||
|
|
||
| import { type Wallet } from '../account/wallet.js'; | ||
|
|
@@ -8,10 +8,11 @@ import { BaseContractInteraction, SendMethodOptions } from './base_contract_inte | |
| export { SendMethodOptions }; | ||
|
|
||
| /** | ||
| * Represents the options for a view method in a contract function interaction. | ||
| * Represents the options for simulating a contract function interaction. | ||
| * Allows specifying the address from which the view method should be called. | ||
| * Disregarded for simulation of public functions | ||
| */ | ||
| export type ViewMethodOptions = { | ||
| export type SimulateMethodOptions = { | ||
| /** | ||
| * The sender's Aztec address. | ||
| */ | ||
|
|
@@ -63,18 +64,48 @@ export class ContractFunctionInteraction extends BaseContractInteraction { | |
| } | ||
|
|
||
| /** | ||
| * Execute a view (read-only) transaction on an unconstrained function. | ||
| * This method is used to call functions that do not modify the contract state and only return data. | ||
| * Throws an error if called on a non-unconstrained function. | ||
| * Simulate a transaction and get its return values | ||
| * Differs from prove in a few important ways: | ||
| * 1. It returns the values of the function execution | ||
| * 2. It supports `unconstrained`, `private` and `public` functions | ||
| * 3. For `private` execution it: | ||
| * 3.a SKIPS the entrypoint and starts directly at the function | ||
| * 3.b SKIPS public execution entirely | ||
| * 4. For `public` execution it: | ||
| * 4.a Removes the `txRequest` value after ended simulation | ||
| * 4.b Ignores the `from` in the options | ||
| * | ||
| * @param options - An optional object containing additional configuration for the transaction. | ||
| * @returns The result of the view transaction as returned by the contract function. | ||
| * @returns The result of the transaction as returned by the contract function. | ||
| */ | ||
| public view(options: ViewMethodOptions = {}) { | ||
| if (this.functionDao.functionType !== FunctionType.UNCONSTRAINED) { | ||
| throw new Error('Can only call `view` on an unconstrained function.'); | ||
| public async simulate(options: SimulateMethodOptions = {}): Promise<any> { | ||
| if (this.functionDao.functionType == FunctionType.UNCONSTRAINED) { | ||
| return this.wallet.viewTx(this.functionDao.name, this.args, this.contractAddress, options.from); | ||
| } | ||
|
|
||
| const { from } = options; | ||
| return this.wallet.viewTx(this.functionDao.name, this.args, this.contractAddress, from); | ||
| // TODO: If not unconstrained, we return a size 4 array of fields. | ||
| // TODO: It should instead return the correctly decoded value | ||
| // TODO: The return type here needs to be fixed! @LHerskind | ||
|
|
||
| if (this.functionDao.functionType == FunctionType.SECRET) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Having
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is just straight up horrible and old tech debt. Added #5538 |
||
| const nodeInfo = await this.wallet.getNodeInfo(); | ||
| const packedArgs = PackedArguments.fromArgs(encodeArguments(this.functionDao, this.args)); | ||
|
|
||
| const txRequest = TxExecutionRequest.from({ | ||
| argsHash: packedArgs.hash, | ||
| origin: this.contractAddress, | ||
| functionData: FunctionData.fromAbi(this.functionDao), | ||
| txContext: TxContext.empty(nodeInfo.chainId, nodeInfo.protocolVersion), | ||
| packedArguments: [packedArgs], | ||
| authWitnesses: [], | ||
| }); | ||
| const simulatedTx = await this.pxe.simulateTx(txRequest, false, options.from ?? this.wallet.getAddress()); | ||
| return simulatedTx.privateReturnValues?.[0]; | ||
| } else { | ||
| const txRequest = await this.create(); | ||
| const simulatedTx = await this.pxe.simulateTx(txRequest, true); | ||
| this.txRequest = undefined; | ||
| return simulatedTx.publicReturnValues?.[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.
Could you add here a comment describing what we are trying to achieve with this indirect function?