Skip to content
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: Token standard #2069

Merged
merged 29 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
91a5516
feat: add auth entrypoint collection
LHerskind Sep 6, 2023
16637ed
feat: initial token standard ideas
LHerskind Sep 6, 2023
3ee72ab
fix: minor fix on contract
LHerskind Sep 6, 2023
582cfd1
fix: work around no public functions from constructor
LHerskind Sep 7, 2023
de7f1d9
test: add tests and minor fixes
LHerskind Sep 7, 2023
642308e
feat: add designated caller
LHerskind Sep 7, 2023
9e7bdd7
chore: add to ci
LHerskind Sep 7, 2023
b05032f
chore: rebase + rebuild noir
LHerskind Sep 8, 2023
3b7d28a
feat: add nonces
LHerskind Sep 8, 2023
d36a526
refactor: Extend simulator to make checks concise
LHerskind Sep 8, 2023
90a1823
chore: rebase goodies
LHerskind Sep 11, 2023
2811d45
fix: Update code size log on deployment
LHerskind Sep 11, 2023
2d52f0f
refactor: shared context and check response in `account_interface`
LHerskind Sep 11, 2023
889669d
refactor: account contract cleanup for less code duplication
LHerskind Sep 11, 2023
6bd380b
feat: add burn function + tests
LHerskind Sep 11, 2023
64f7e1f
feat: Include contract address in message hash
LHerskind Sep 11, 2023
37ac39a
chore: rebase
LHerskind Sep 11, 2023
4221061
chore: update cli_docs list
LHerskind Sep 11, 2023
d0a97a7
fix: catch public nullifier double-spends early in sequencer
LHerskind Sep 11, 2023
5dafcab
chore: address comments
LHerskind Sep 11, 2023
e368494
chore: fixing some rebase issues
LHerskind Sep 12, 2023
3a70678
chore: address api changes
LHerskind Sep 12, 2023
256d284
chore: fix maddia comments
LHerskind Sep 12, 2023
e225689
fix: remove builder stages from ypb
Maddiaa0 Sep 13, 2023
c337f89
chore: bump contracts
Maddiaa0 Sep 13, 2023
0249c80
Merge branch 'master' into lh/token-standard
Maddiaa0 Sep 13, 2023
d5c8fd0
Merge branch 'master' of github.com:AztecProtocol/aztec-packages into…
Maddiaa0 Sep 13, 2023
40dda48
Revert "fix: remove builder stages from ypb"
Maddiaa0 Sep 13, 2023
fe1e059
fix: add token contract to workspace
Maddiaa0 Sep 13, 2023
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
15 changes: 15 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,19 @@ jobs:
command: ./scripts/cond_run_script end-to-end $JOB_NAME ./scripts/run_tests_local e2e_lending_contract.test.ts
working_directory: yarn-project/end-to-end

e2e-token-contract:
machine:
image: ubuntu-2004:202010-01
resource_class: large
steps:
- *checkout
- *setup_env
- run:
name: "Test"
command: ./scripts/cond_run_script end-to-end $JOB_NAME ./scripts/run_tests_local e2e_token_contract.test.ts
working_directory: yarn-project/end-to-end


e2e-private-token-contract:
machine:
image: ubuntu-2004:202010-01
Expand Down Expand Up @@ -1427,6 +1440,7 @@ workflows:
- e2e-2-rpc-servers: *e2e_test
- e2e-deploy-contract: *e2e_test
- e2e-lending-contract: *e2e_test
- e2e-token-contract: *e2e_test
- e2e-private-token-contract: *e2e_test
- e2e-sandbox-example: *e2e_test
- e2e-multi-transfer-contract: *e2e_test
Expand Down Expand Up @@ -1461,6 +1475,7 @@ workflows:
- e2e-2-rpc-servers
- e2e-deploy-contract
- e2e-lending-contract
- e2e-token-contract
- e2e-private-token-contract
- e2e-sandbox-example
- e2e-multi-transfer-contract
Expand Down
5 changes: 3 additions & 2 deletions yarn-project/acir-simulator/src/client/private_execution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,16 @@ export class PrivateFunctionExecution {
return Promise.resolve(ZERO_ACVM_FIELD);
},
enqueuePublicFunctionCall: async ([acvmContractAddress], [acvmFunctionSelector], [acvmArgsHash]) => {
const selector = FunctionSelector.fromField(fromACVMField(acvmFunctionSelector));
const enqueuedRequest = await this.enqueuePublicFunctionCall(
frToAztecAddress(fromACVMField(acvmContractAddress)),
FunctionSelector.fromField(fromACVMField(acvmFunctionSelector)),
selector,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This takes in the targetContractAddress, why is it called selector?

In executor this name is used again but with different fields

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think I copied it a round because the 32byte strings tilted me on some error codes. Will fix it.

this.context.packedArgsCache.unpack(fromACVMField(acvmArgsHash)),
this.callContext,
);

this.log(
`Enqueued call to public function (with side-effect counter #${enqueuedRequest.sideEffectCounter}) ${acvmContractAddress}:${acvmFunctionSelector}`,
`Enqueued call to public function (with side-effect counter #${enqueuedRequest.sideEffectCounter}) ${acvmContractAddress}:${selector}`,
);
enqueuedPublicFunctionCalls.push(enqueuedRequest);
return toAcvmEnqueuePublicFunctionResult(enqueuedRequest);
Expand Down
5 changes: 3 additions & 2 deletions yarn-project/acir-simulator/src/public/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,11 @@ export class PublicExecutor {
},
callPublicFunction: async ([address], [functionSelector], [argsHash]) => {
const args = packedArgs.unpack(fromACVMField(argsHash));
this.log(`Public function call: addr=${address} selector=${functionSelector} args=${args.join(',')}`);
const selector = FunctionSelector.fromField(fromACVMField(functionSelector));
this.log(`Public function call: addr=${address} selector=${selector} args=${args.join(',')}`);
const childExecutionResult = await this.callPublicFunction(
frToAztecAddress(fromACVMField(address)),
FunctionSelector.fromField(fromACVMField(functionSelector)),
selector,
args,
execution.callContext,
globalVariables,
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/aztec-rpc/src/simulator_oracle/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class SimulatorOracle implements DBOracle {

async getAuthWitness(messageHash: Fr): Promise<Fr[]> {
const witness = await this.db.getAuthWitness(messageHash);
if (!witness) throw new Error(`Unknown auth witness for message hash ${messageHash.toString()}`);
if (!witness) throw new Error(`Unknown auth witness for message hash ${messageHash.toString(true)}`);
return witness;
}

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,50 @@ import { DEFAULT_CHAIN_ID, DEFAULT_VERSION } from '../../utils/defaults.js';
import { buildPayload, hashPayload } from './entrypoint_payload.js';
import { Entrypoint } from './index.js';

/**
* An extended interface for entrypoints that support signing and adding auth witnesses.
*/
export interface IAuthWitnessAccountEntrypoint extends Entrypoint {
/**
* Sign a message hash with the private key.
* @param message - The message hash to sign.
* @returns The signature as a Buffer.
*/
sign(message: Buffer): Buffer;

/**
* Creates an AuthWitness witness for the given message. In this case, witness is the public key, the signature
* and the partial address, to be used for verification.
* @param message - The message hash to sign.
* @param opts - Options.
* @returns [publicKey, signature, partialAddress] as Fr[].
*/
createAuthWitness(message: Buffer): Promise<Fr[]>;

/**
* Returns the transaction request and the auth witness for the given function calls.
* Returning the witness here as a nonce is generated in the buildPayload action.
* @param executions - The function calls to execute
* @param opts - The options
* @returns The TxRequest, the auth witness to insert in db and the message signed
*/
createTxExecutionRequestWithWitness(executions: FunctionCall[]): Promise<{
/** The transaction request */
txRequest: TxExecutionRequest;
/** The auth witness */
witness: Fr[];
/** The message signed */
message: Buffer;
}>;
}

/**
* Account contract implementation that uses a single key for signing and encryption. This public key is not
* stored in the contract, but rather verified against the contract address. Note that this approach is not
* secure and should not be used in real use cases.
* The entrypoint is extended to support signing and creating eip1271-like witnesses.
*/
export class AuthWitnessAccountEntrypoint implements Entrypoint {
export class AuthWitnessAccountEntrypoint implements IAuthWitnessAccountEntrypoint {
constructor(
private address: AztecAddress,
private partialAddress: PartialAddress,
Expand All @@ -25,21 +62,10 @@ export class AuthWitnessAccountEntrypoint implements Entrypoint {
private version: number = DEFAULT_VERSION,
) {}

/**
* Sign a message hash with the private key.
* @param message - The message hash to sign.
* @returns The signature as a Buffer.
*/
public sign(message: Buffer): Buffer {
return this.signer.constructSignature(message, this.privateKey).toBuffer();
}

/**
* Creates an AuthWitness witness for the given message. In this case, witness is the public key, the signature
* and the partial address, to be used for verification.
* @param message - The message hash to sign.
* @returns [publicKey, signature, partialAddress] as Fr[].
*/
async createAuthWitness(message: Buffer): Promise<Fr[]> {
const signature = this.sign(message);
const publicKey = await generatePublicKey(this.privateKey);
Expand Down
25 changes: 23 additions & 2 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, Entrypoint } from '../account/entrypoint/index.js';
import { Entrypoint, IAuthWitnessAccountEntrypoint } from '../account/entrypoint/index.js';
import { CompleteAddress } from '../index.js';

/**
Expand Down Expand Up @@ -121,7 +121,7 @@ export class EntrypointWallet extends BaseWallet {
* to provide authentication data to the contract during execution.
*/
export class AuthWitnessEntrypointWallet extends BaseWallet {
constructor(rpc: AztecRPC, protected accountImpl: AuthWitnessAccountEntrypoint) {
constructor(rpc: AztecRPC, protected accountImpl: IAuthWitnessAccountEntrypoint, protected address: CompleteAddress) {
super(rpc);
}

Expand Down Expand Up @@ -151,12 +151,33 @@ export class AuthWitnessEntrypointWallet extends BaseWallet {
* This is useful for signing messages that are not directly part of the transaction payload, such as
* approvals .
* @param messageHash - The message hash to sign
* @param opts - The options.
*/
async signAndAddAuthWitness(messageHash: Buffer): Promise<void> {
const witness = await this.accountImpl.createAuthWitness(messageHash);
await this.rpc.addAuthWitness(Fr.fromBuffer(messageHash), witness);
return Promise.resolve();
}

/**
* Signs the `messageHash` and adds the witness to the RPC.
* This is useful for signing messages that are not directly part of the transaction payload, such as
* approvals .
* @param messageHash - The message hash to sign
*/
async signAndGetAuthWitness(messageHash: Buffer): Promise<Fr[]> {
return await this.accountImpl.createAuthWitness(messageHash);
}

/** Returns the complete address of the account that implements this wallet. */
public getCompleteAddress() {
return this.address;
}

/** Returns the address of the account that implements this wallet. */
public getAddress() {
return this.address.address;
}
}

/**
Expand Down
1 change: 1 addition & 0 deletions yarn-project/end-to-end/src/cli_docs_sandbox.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ SchnorrAuthWitnessAccountContractAbi
SchnorrHardcodedAccountContractAbi
SchnorrSingleKeyAccountContractAbi
TestContractAbi
TokenContractAbi
UniswapContractAbi
// docs:end:example-contracts
`;
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/end-to-end/src/e2e_account_contracts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ describe('e2e_account_contracts', () => {
await tx.wait();
}
const entryPoint = (await account.getEntrypoint()) as unknown as AuthWitnessAccountEntrypoint;
const wallet = new AuthWitnessEntrypointWallet(rpc, entryPoint);
const wallet = new AuthWitnessEntrypointWallet(rpc, entryPoint, await account.getCompleteAddress());
return { account, wallet };
},
);
Expand Down
23 changes: 13 additions & 10 deletions yarn-project/end-to-end/src/e2e_lending_contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { AztecRPCServer } from '@aztec/aztec-rpc';
import {
Account,
AuthWitnessAccountContract,
AuthWitnessAccountEntrypoint,
AuthWitnessEntrypointWallet,
AztecAddress,
CheatCodes,
Fr,
IAuthWitnessAccountEntrypoint,
computeMessageSecretHash,
} from '@aztec/aztec.js';
import { CircuitsWasm, CompleteAddress, FunctionSelector, GeneratorIndex, GrumpkinScalar } from '@aztec/circuits.js';
Expand Down Expand Up @@ -82,15 +82,18 @@ describe('e2e_lending_contract', () => {
beforeEach(async () => {
({ aztecNode, aztecRpcServer, logger, cheatCodes: cc } = await setup(0));

const privateKey = GrumpkinScalar.random();
const account = new Account(aztecRpcServer, privateKey, new AuthWitnessAccountContract(privateKey));
const entryPoint = (await account.getEntrypoint()) as unknown as AuthWitnessAccountEntrypoint;

const deployTx = await account.deploy();
await deployTx.wait({ interval: 0.1 });

wallet = new AuthWitnessEntrypointWallet(aztecRpcServer, entryPoint);
accounts = await wallet.getAccounts();
{
const privateKey = GrumpkinScalar.random();
const account = new Account(aztecRpcServer, privateKey, new AuthWitnessAccountContract(privateKey));
const deployTx = await account.deploy();
await deployTx.wait({ interval: 0.1 });
wallet = new AuthWitnessEntrypointWallet(
aztecRpcServer,
(await account.getEntrypoint()) as unknown as IAuthWitnessAccountEntrypoint,
await account.getCompleteAddress(),
);
accounts = await wallet.getAccounts();
}
}, 100_000);

afterEach(async () => {
Expand Down
Loading