Skip to content

Commit

Permalink
feat: Remove entrypoint collection (#2148)
Browse files Browse the repository at this point in the history
Attempt at removing the horrifying `EntrypointCollection` class. This
allows us to remove the `{ sender: address }` option when sending a tx,
and instead just rely on the `Wallet` attached to the Contract instance
to decide which sender to use. In other words, there is now only one way
to choose which account sends a tx, following ethers conventions, rather
than web3js. It also allows us to clean up some utils that are no longer
necessary.

---------

Co-authored-by: PhilWindle <60546371+PhilWindle@users.noreply.github.com>
Co-authored-by: Maddiaa <47148561+Maddiaa0@users.noreply.github.com>
  • Loading branch information
3 people authored Sep 11, 2023
1 parent 2643f66 commit e97c94d
Show file tree
Hide file tree
Showing 41 changed files with 309 additions and 533 deletions.
29 changes: 11 additions & 18 deletions yarn-project/aztec-sandbox/src/examples/private_token_contract.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import {
AccountWallet,
AztecAddress,
Contract,
Fr,
GrumpkinScalar,
Wallet,
createAccounts,
createAztecRpcClient,
createRecipient,
getUnsafeSchnorrAccount,
} from '@aztec/aztec.js';
import { createDebugLogger } from '@aztec/foundation/log';
import { SchnorrSingleKeyAccountContractAbi } from '@aztec/noir-contracts/artifacts';
import { PrivateTokenContract } from '@aztec/noir-contracts/types';

const logger = createDebugLogger('aztec:http-rpc-client');
Expand All @@ -18,7 +17,7 @@ export const privateKey = GrumpkinScalar.fromString('ac0974bec39a17e36ba4a6b4d23
const url = 'http://localhost:8080';

const aztecRpcClient = createAztecRpcClient(url);
let wallet: Wallet;
let wallet: AccountWallet;

const INITIAL_BALANCE = 333n;
const SECONDARY_AMOUNT = 33n;
Expand All @@ -30,10 +29,7 @@ const SECONDARY_AMOUNT = 33n;
*/
async function deployZKContract(owner: AztecAddress) {
logger('Deploying L2 contract...');
const tx = PrivateTokenContract.deploy(aztecRpcClient, INITIAL_BALANCE, owner).send();
const receipt = await tx.getReceipt();
const contract = await PrivateTokenContract.at(receipt.contractAddress!, wallet);
await tx.isMined();
const contract = await PrivateTokenContract.deploy(aztecRpcClient, INITIAL_BALANCE, owner).send().deployed();
logger('L2 contract deployed');
return contract;
}
Expand All @@ -54,10 +50,9 @@ async function getBalance(contract: Contract, ownerAddress: AztecAddress) {
async function main() {
logger('Running ZK contract test on HTTP interface.');

wallet = await createAccounts(aztecRpcClient, SchnorrSingleKeyAccountContractAbi, privateKey, Fr.random(), 2);
const accounts = await aztecRpcClient.getAccounts();
const [owner, account2] = accounts;
logger(`Created ${accounts.length} accounts`);
wallet = await getUnsafeSchnorrAccount(aztecRpcClient, privateKey).waitDeploy();
const owner = wallet.getCompleteAddress();
const recipient = await createRecipient(aztecRpcClient);

logger(`Created Owner account ${owner.toString()}`);

Expand All @@ -67,17 +62,15 @@ async function main() {

// Mint more tokens
logger(`Minting ${SECONDARY_AMOUNT} more coins`);
const mintTx = zkContract.methods.mint(SECONDARY_AMOUNT, owner.address).send({ origin: owner.address });
await mintTx.isMined({ interval: 0.5 });
await zkContract.methods.mint(SECONDARY_AMOUNT, owner.address).send().wait({ interval: 0.5 });
const balanceAfterMint = await getBalance(zkContract, owner.address);
logger(`Owner's balance is now: ${balanceAfterMint}`);

// Perform a transfer
logger(`Transferring ${SECONDARY_AMOUNT} tokens from owner to another account.`);
const transferTx = zkContract.methods.transfer(SECONDARY_AMOUNT, account2.address).send({ origin: owner.address });
await transferTx.isMined({ interval: 0.5 });
await zkContract.methods.transfer(SECONDARY_AMOUNT, recipient.address).send().wait({ interval: 0.5 });
const balanceAfterTransfer = await getBalance(zkContract, owner.address);
const receiverBalance = await getBalance(zkContract, account2.address);
const receiverBalance = await getBalance(zkContract, recipient.address);
logger(`Owner's balance is now ${balanceAfterTransfer}`);
logger(`The transfer receiver's balance is ${receiverBalance}`);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import {
AccountWallet,
AztecAddress,
EthAddress,
Fr,
Wallet,
computeMessageSecretHash,
createAccounts,
createAztecRpcClient,
createRecipient,
getL1ContractAddresses,
getUnsafeSchnorrAccount,
} from '@aztec/aztec.js';
import { GrumpkinScalar } from '@aztec/circuits.js';
import { createDebugLogger } from '@aztec/foundation/log';
import { UniswapPortalAbi, UniswapPortalBytecode } from '@aztec/l1-artifacts';
import { SchnorrSingleKeyAccountContractAbi } from '@aztec/noir-contracts/artifacts';
import { NonNativeTokenContract, UniswapContract } from '@aztec/noir-contracts/types';
import { AztecRPC, TxStatus } from '@aztec/types';

Expand Down Expand Up @@ -56,7 +56,7 @@ if (Number(await publicClient.getBlockNumber()) < EXPECTED_FORKED_BLOCK) {
const ethAccount = EthAddress.fromString((await walletClient.getAddresses())[0]);

const aztecRpcClient = createAztecRpcClient(aztecRpcUrl);
let wallet: Wallet;
let wallet: AccountWallet;

/**
* Deploys all l1 / l2 contracts
Expand Down Expand Up @@ -153,7 +153,7 @@ const transferWethOnL2 = async (
receiver: AztecAddress,
transferAmount: bigint,
) => {
const transferTx = wethL2Contract.methods.transfer(transferAmount, receiver).send({ origin: ownerAddress });
const transferTx = wethL2Contract.methods.transfer(transferAmount, receiver).send();
await transferTx.isMined({ interval: 0.5 });
const transferReceipt = await transferTx.getReceipt();
// expect(transferReceipt.status).toBe(TxStatus.MINED);
Expand All @@ -166,9 +166,9 @@ const transferWethOnL2 = async (
async function main() {
logger('Running L1/L2 messaging test on HTTP interface.');

wallet = await createAccounts(aztecRpcClient, SchnorrSingleKeyAccountContractAbi, privateKey!, Fr.random(), 2);
const accounts = await wallet.getAccounts();
const [owner, receiver] = accounts;
wallet = await getUnsafeSchnorrAccount(aztecRpcClient, privateKey).waitDeploy();
const owner = wallet.getCompleteAddress();
const receiver = await createRecipient(aztecRpcClient);

const result = await deployAllContracts(owner.address);
const {
Expand Down Expand Up @@ -220,7 +220,7 @@ async function main() {
// Call the mint tokens function on the noir contract
const consumptionTx = wethL2Contract.methods
.mint(wethAmountToBridge, owner.address, messageKey, secret, ethAccount.toField())
.send({ origin: owner.address });
.send();
await consumptionTx.isMined({ interval: 0.5 });
const consumptionReceipt = await consumptionTx.getReceipt();
// expect(consumptionReceipt.status).toBe(TxStatus.MINED);
Expand Down Expand Up @@ -250,7 +250,7 @@ async function main() {
ethAccount.toField(),
ethAccount.toField(),
)
.send({ origin: owner.address });
.send();
await withdrawTx.isMined({ interval: 0.5 });
const withdrawReceipt = await withdrawTx.getReceipt();
// expect(withdrawReceipt.status).toBe(TxStatus.MINED);
Expand Down Expand Up @@ -301,7 +301,7 @@ async function main() {
// Call the mint tokens function on the noir contract
const daiMintTx = daiL2Contract.methods
.mint(daiAmountToBridge, owner.address, depositDaiMessageKey, secret, ethAccount.toField())
.send({ origin: owner.address });
.send();
await daiMintTx.isMined({ interval: 0.5 });
const daiMintTxReceipt = await daiMintTx.getReceipt();
// expect(daiMintTxReceipt.status).toBe(TxStatus.MINED);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import SchnorrAuthWitnessAccountContractAbi from '../../abis/schnorr_auth_witnes
import { generatePublicKey } from '../../index.js';
import { DEFAULT_CHAIN_ID, DEFAULT_VERSION } from '../../utils/defaults.js';
import { buildPayload, hashPayload } from './entrypoint_payload.js';
import { CreateTxRequestOpts, Entrypoint } from './index.js';
import { Entrypoint } from './index.js';

/**
* Account contract implementation that uses a single key for signing and encryption. This public key is not
Expand Down Expand Up @@ -59,21 +59,14 @@ export class AuthWitnessAccountEntrypoint implements Entrypoint {
* @param opts - The options
* @returns The TxRequest, the auth witness to insert in db and the message signed
*/
async createTxExecutionRequestWithWitness(
executions: FunctionCall[],
opts: CreateTxRequestOpts = {},
): Promise<{
async createTxExecutionRequestWithWitness(executions: FunctionCall[]): Promise<{
/** The transaction request */
txRequest: TxExecutionRequest;
/** The auth witness */
witness: Fr[];
/** The message signed */
message: Buffer;
}> {
if (opts.origin && !opts.origin.equals(this.address)) {
throw new Error(`Sender ${opts.origin.toString()} does not match account address ${this.address.toString()}`);
}

const { payload, packedArguments: callsPackedArguments } = await buildPayload(executions);
const message = await hashPayload(payload);
const witness = await this.createAuthWitness(message);
Expand All @@ -92,7 +85,7 @@ export class AuthWitnessAccountEntrypoint implements Entrypoint {
return { txRequest, message, witness };
}

createTxExecutionRequest(executions: FunctionCall[], _opts: CreateTxRequestOpts = {}): Promise<TxExecutionRequest> {
createTxExecutionRequest(_executions: FunctionCall[]): Promise<TxExecutionRequest> {
throw new Error(`Not implemented, use createTxExecutionRequestWithWitness instead`);
}

Expand Down

This file was deleted.

12 changes: 2 additions & 10 deletions yarn-project/aztec.js/src/account/entrypoint/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
import { AztecAddress } from '@aztec/circuits.js';
import { FunctionCall, TxExecutionRequest } from '@aztec/types';

export * from './entrypoint_collection.js';
export * from './auth_witness_account_entrypoint.js';
export * from './entrypoint_payload.js';
export * from './entrypoint_utils.js';
export * from './single_key_account_entrypoint.js';
export * from './stored_key_account_entrypoint.js';
export * from './auth_witness_account_entrypoint.js';

/** Options for creating a tx request out of a set of function calls. */
export type CreateTxRequestOpts = {
/** Origin of the tx. Needs to be an address managed by this account. */
origin?: AztecAddress;
};

// docs:start:entrypoint-interface
/**
Expand All @@ -26,6 +18,6 @@ export interface Entrypoint {
* @param opts - Options.
* @returns The authenticated transaction execution request.
*/
createTxExecutionRequest(executions: FunctionCall[], opts?: CreateTxRequestOpts): Promise<TxExecutionRequest>;
createTxExecutionRequest(executions: FunctionCall[]): Promise<TxExecutionRequest>;
}
// docs:end:entrypoint-interface
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import SchnorrSingleKeyAccountContractAbi from '../../abis/schnorr_single_key_ac
import { generatePublicKey } from '../../index.js';
import { DEFAULT_CHAIN_ID, DEFAULT_VERSION } from '../../utils/defaults.js';
import { buildPayload, hashPayload } from './entrypoint_payload.js';
import { CreateTxRequestOpts, Entrypoint } from './index.js';
import { Entrypoint } from './index.js';

/**
* Account contract implementation that uses a single key for signing and encryption. This public key is not
Expand All @@ -23,14 +23,7 @@ export class SingleKeyAccountEntrypoint implements Entrypoint {
private version: number = DEFAULT_VERSION,
) {}

async createTxExecutionRequest(
executions: FunctionCall[],
opts: CreateTxRequestOpts = {},
): Promise<TxExecutionRequest> {
if (opts.origin && !opts.origin.equals(this.address)) {
throw new Error(`Sender ${opts.origin.toString()} does not match account address ${this.address.toString()}`);
}

async createTxExecutionRequest(executions: FunctionCall[]): Promise<TxExecutionRequest> {
const { payload, packedArguments: callsPackedArguments } = await buildPayload(executions);
const message = await hashPayload(payload);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { FunctionCall, PackedArguments, TxExecutionRequest } from '@aztec/types'
import EcdsaAccountContractAbi from '../../abis/ecdsa_account_contract.json' assert { type: 'json' };
import { DEFAULT_CHAIN_ID, DEFAULT_VERSION } from '../../utils/defaults.js';
import { buildPayload, hashPayload } from './entrypoint_payload.js';
import { CreateTxRequestOpts, Entrypoint } from './index.js';
import { Entrypoint } from './index.js';

/**
* Account contract implementation that keeps a signing public key in storage, and is retrieved on
Expand All @@ -25,14 +25,7 @@ export class StoredKeyAccountEntrypoint implements Entrypoint {
this.log = createDebugLogger('aztec:client:accounts:stored_key');
}

async createTxExecutionRequest(
executions: FunctionCall[],
opts: CreateTxRequestOpts = {},
): Promise<TxExecutionRequest> {
if (opts.origin && !opts.origin.equals(this.address)) {
throw new Error(`Sender ${opts.origin.toString()} does not match account address ${this.address.toString()}`);
}

async createTxExecutionRequest(executions: FunctionCall[]): Promise<TxExecutionRequest> {
const { payload, packedArguments: callsPackedArguments } = await buildPayload(executions);
const message = await hashPayload(payload);
const signature = this.sign(message).toBuffer();
Expand Down
18 changes: 6 additions & 12 deletions yarn-project/aztec.js/src/aztec_rpc_client/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
TxReceipt,
} from '@aztec/types';

import { AuthWitnessAccountEntrypoint, CreateTxRequestOpts, Entrypoint } from '../account/entrypoint/index.js';
import { AuthWitnessAccountEntrypoint, Entrypoint } from '../account/entrypoint/index.js';
import { CompleteAddress } from '../index.js';

/**
Expand All @@ -30,7 +30,7 @@ export type Wallet = Entrypoint & AztecRPC;
export abstract class BaseWallet implements Wallet {
constructor(protected readonly rpc: AztecRPC) {}

abstract createTxExecutionRequest(execs: FunctionCall[], opts?: CreateTxRequestOpts): Promise<TxExecutionRequest>;
abstract createTxExecutionRequest(execs: FunctionCall[]): Promise<TxExecutionRequest>;

registerAccount(privKey: GrumpkinPrivateKey, partialAddress: PartialAddress): Promise<void> {
return this.rpc.registerAccount(privKey, partialAddress);
Expand Down Expand Up @@ -110,8 +110,8 @@ export class EntrypointWallet extends BaseWallet {
constructor(rpc: AztecRPC, protected accountImpl: Entrypoint) {
super(rpc);
}
createTxExecutionRequest(executions: FunctionCall[], opts: CreateTxRequestOpts = {}): Promise<TxExecutionRequest> {
return this.accountImpl.createTxExecutionRequest(executions, opts);
createTxExecutionRequest(executions: FunctionCall[]): Promise<TxExecutionRequest> {
return this.accountImpl.createTxExecutionRequest(executions);
}
}

Expand All @@ -136,14 +136,8 @@ export class AuthWitnessEntrypointWallet extends BaseWallet {
* @param opts - The options.
* @returns - The TxRequest
*/
async createTxExecutionRequest(
executions: FunctionCall[],
opts: CreateTxRequestOpts = {},
): Promise<TxExecutionRequest> {
const { txRequest, message, witness } = await this.accountImpl.createTxExecutionRequestWithWitness(
executions,
opts,
);
async createTxExecutionRequest(executions: FunctionCall[]): Promise<TxExecutionRequest> {
const { txRequest, message, witness } = await this.accountImpl.createTxExecutionRequestWithWitness(executions);
await this.rpc.addAuthWitness(Fr.fromBuffer(message), witness);
return txRequest;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { AztecAddress } from '@aztec/circuits.js';
import { AztecRPC, Tx, TxExecutionRequest } from '@aztec/types';

import { SentTx } from './sent_tx.js';
Expand All @@ -8,10 +7,6 @@ import { SentTx } from './sent_tx.js';
* Allows the user to specify the sender address and nonce for a transaction.
*/
export interface SendMethodOptions {
/**
* Sender's address initiating the transaction.
*/
origin?: AztecAddress;
/**
* Wether to skip the simulation of the public part of the transaction.
*/
Expand Down
Loading

0 comments on commit e97c94d

Please sign in to comment.