Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
sklppy88 committed Oct 31, 2024
1 parent 9f52cbb commit 857791d
Show file tree
Hide file tree
Showing 13 changed files with 2 additions and 260 deletions.
21 changes: 0 additions & 21 deletions docs/docs/aztec/concepts/accounts/keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,27 +25,6 @@ However, since Aztec supports native [account abstraction](../accounts/index.md#
Instead it's up to the account contract developer to implement it.
:::

## Public keys retrieval

The keys can be retrieved from the [Private eXecution Environment (PXE)](../pxe/index.md) using the following getter in Aztec.nr:

```
fn get_public_keys(account: AztecAddress) -> PublicKeys;
```

It is necessary to first register the user as a recipient in our PXE, providing their public keys.

First we need to get a hold of recipient's [complete address](#complete-address).
Below are some ways how we could instantiate it after getting the information in a string form from a recipient:

#include_code instantiate-complete-address /yarn-project/circuits.js/src/structs/complete_address.test.ts rust

Then to register the recipient's [complete address](#complete-address) in PXE we would call `registerRecipient` PXE endpoint using Aztec.js.

#include_code register-recipient /yarn-project/aztec.js/src/wallet/create_recipient.ts rust

During private function execution these keys are obtained via an oracle call from PXE.

## Scoped keys

To minimize damage of potential key leaks the keys are scoped (also called app-siloed) to the contract that requests them.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,6 @@ Unlike on Ethereum, there are 2 types of events supported by Aztec: [encrypted](

## Encrypted Events

### Register a recipient

Encrypted events can only be emitted by private functions and are encrypted using a public key of a recipient.
For this reason it is necessary to register a recipient in the Private Execution Environment (PXE) before encrypting the events for them.

First we need to get a hold of recipient's complete address.
Below are some ways how we could instantiate it after getting the information in a string form from a recipient:

#include_code instantiate-complete-address /yarn-project/circuits.js/src/structs/complete_address.test.ts rust

Then to register the recipient's complete address in PXE we would call `registerRecipient` PXE endpoint using Aztec.js

#include_code register-recipient /yarn-project/aztec.js/src/wallet/create_recipient.ts rust

:::info
If a note recipient is one of the accounts inside the PXE, we don't need to register it as a recipient because we already have the public key available. You can register a recipient as shown [here](../how_to_deploy_contract.md)
:::

### Call emit

To emit encrypted logs you can import the `encode_and_encrypt` or `encode_and_encrypt_with_keys` functions and pass them into the `emit` function after inserting a note. An example can be seen in the reference token contract's transfer function:
Expand Down
9 changes: 0 additions & 9 deletions yarn-project/aztec.js/src/wallet/base_wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,21 +81,12 @@ export abstract class BaseWallet implements Wallet {
registerAccount(secretKey: Fr, partialAddress: PartialAddress): Promise<CompleteAddress> {
return this.pxe.registerAccount(secretKey, partialAddress);
}
registerRecipient(account: CompleteAddress): Promise<void> {
return this.pxe.registerRecipient(account);
}
getRegisteredAccounts(): Promise<CompleteAddress[]> {
return this.pxe.getRegisteredAccounts();
}
getRegisteredAccount(address: AztecAddress): Promise<CompleteAddress | undefined> {
return this.pxe.getRegisteredAccount(address);
}
getRecipients(): Promise<CompleteAddress[]> {
return this.pxe.getRecipients();
}
getRecipient(address: AztecAddress): Promise<CompleteAddress | undefined> {
return this.pxe.getRecipient(address);
}
registerContract(contract: {
/** Instance */ instance: ContractInstanceWithAddress;
/** Associated artifact */ artifact?: ContractArtifact;
Expand Down
15 changes: 0 additions & 15 deletions yarn-project/aztec.js/src/wallet/create_recipient.ts

This file was deleted.

29 changes: 0 additions & 29 deletions yarn-project/circuit-types/src/interfaces/pxe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,20 +73,6 @@ export interface PXE {
*/
registerAccount(secretKey: Fr, partialAddress: PartialAddress): Promise<CompleteAddress>;

/**
* Registers a recipient in PXE. This is required when sending encrypted notes to
* a user who hasn't deployed their account contract yet. Since their account is not deployed, their
* encryption public key has not been broadcasted, so we need to manually register it on the PXE Service
* in order to be able to encrypt data for this recipient.
*
* @param recipient - The complete address of the recipient
* @remarks Called recipient because we can only send notes to this account and not receive them via this PXE Service.
* This is because we don't have the associated private key and for this reason we can't decrypt
* the recipient's notes. We can send notes to this account because we can encrypt them with the recipient's
* public key.
*/
registerRecipient(recipient: CompleteAddress): Promise<void>;

/**
* Retrieves the user accounts registered on this PXE Service.
* @returns An array of the accounts registered on this PXE Service.
Expand All @@ -102,21 +88,6 @@ export interface PXE {
*/
getRegisteredAccount(address: AztecAddress): Promise<CompleteAddress | undefined>;

/**
* Retrieves the recipients added to this PXE Service.
* @returns An array of recipients registered on this PXE Service.
*/
getRecipients(): Promise<CompleteAddress[]>;

/**
* Retrieves the complete address of the recipient corresponding to the provided aztec address.
* Complete addresses include the address, the partial address, and the encryption public key.
*
* @param address - The aztec address of the recipient.
* @returns The complete address of the requested recipient.
*/
getRecipient(address: AztecAddress): Promise<CompleteAddress | undefined>;

/**
* Registers a contract class in the PXE without registering any associated contract instance with it.
*
Expand Down
14 changes: 0 additions & 14 deletions yarn-project/cli/src/cmds/pxe/get_recipient.ts

This file was deleted.

15 changes: 0 additions & 15 deletions yarn-project/cli/src/cmds/pxe/get_recipients.ts

This file was deleted.

36 changes: 0 additions & 36 deletions yarn-project/cli/src/cmds/pxe/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
parseOptionalInteger,
parseOptionalLogId,
parseOptionalTxHash,
parsePartialAddress,
parsePublicKey,
pxeOption,
} from '../../utils/commands.js';
Expand Down Expand Up @@ -91,22 +90,6 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: DebugL
await getLogs(txHash, fromBlock, toBlock, afterLog, contractAddress, rpcUrl, follow, debugLogger, log);
});

program
.command('register-recipient')
.description('Register a recipient in the PXE.')
.requiredOption('-a, --address <aztecAddress>', "The account's Aztec address.", parseAztecAddress)
.requiredOption('-p, --public-key <publicKey>', 'The account public key.', parsePublicKey)
.requiredOption(
'-pa, --partial-address <partialAddress>',
'The partially computed address of the account contract.',
parsePartialAddress,
)
.addOption(pxeOption)
.action(async ({ address, publicKey, partialAddress, rpcUrl }) => {
const { registerRecipient } = await import('./register_recipient.js');
await registerRecipient(address, publicKey, partialAddress, rpcUrl, debugLogger, log);
});

program
.command('get-accounts')
.description('Gets all the Aztec accounts stored in the PXE.')
Expand All @@ -127,25 +110,6 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: DebugL
await getAccount(address, options.rpcUrl, debugLogger, log);
});

program
.command('get-recipients')
.description('Gets all the recipients stored in the PXE.')
.addOption(pxeOption)
.action(async (options: any) => {
const { getRecipients } = await import('./get_recipients.js');
await getRecipients(options.rpcUrl, debugLogger, log);
});

program
.command('get-recipient')
.description('Gets a recipient given its Aztec address.')
.argument('<address>', 'The Aztec address to get recipient for', parseAztecAddress)
.addOption(pxeOption)
.action(async (address, options) => {
const { getRecipient } = await import('./get_recipient.js');
await getRecipient(address, options.rpcUrl, debugLogger, log);
});

program
.command('block-number')
.description('Gets the current Aztec L2 block number.')
Expand Down
18 changes: 0 additions & 18 deletions yarn-project/cli/src/cmds/pxe/register_recipient.ts

This file was deleted.

4 changes: 0 additions & 4 deletions yarn-project/end-to-end/src/composed/e2e_persistence.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,6 @@ describe('Aztec persistence', () => {
await context.teardown();
});

it('pxe does not have the owner account', async () => {
await expect(context.pxe.getRecipient(ownerAddress.address)).resolves.toBeUndefined();
});

it('the node has the contract', async () => {
await expect(context.aztecNode.getContract(contractAddress)).resolves.toBeDefined();
});
Expand Down
27 changes: 0 additions & 27 deletions yarn-project/pxe/src/pxe_service/pxe_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,33 +221,6 @@ export class PXEService implements PXE {
return Promise.resolve(account);
}

public async registerRecipient(recipient: CompleteAddress): Promise<void> {
const wasAdded = await this.db.addCompleteAddress(recipient);

if (wasAdded) {
this.log.info(`Added recipient:\n ${recipient.toReadableString()}`);
} else {
this.log.info(`Recipient:\n "${recipient.toReadableString()}"\n already registered.`);
}
}

public async getRecipients(): Promise<CompleteAddress[]> {
// Get complete addresses of both the recipients and the accounts
const completeAddresses = await this.db.getCompleteAddresses();
// Filter out the addresses corresponding to accounts
const accounts = await this.keyStore.getAccounts();
const recipients = completeAddresses.filter(
completeAddress => !accounts.find(account => account.equals(completeAddress.address)),
);
return recipients;
}

public async getRecipient(address: AztecAddress): Promise<CompleteAddress | undefined> {
const result = await this.getRecipients();
const recipient = result.find(r => r.address.equals(address));
return Promise.resolve(recipient);
}

public async registerContractClass(artifact: ContractArtifact): Promise<void> {
const contractClassId = computeContractClassId(getContractClassFromArtifact(artifact));
await this.db.addContractArtifact(contractClassId, artifact);
Expand Down
54 changes: 1 addition & 53 deletions yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,7 @@ import {
randomContractInstanceWithAddress,
randomDeployedContract,
} from '@aztec/circuit-types';
import {
AztecAddress,
CompleteAddress,
Fr,
INITIAL_L2_BLOCK_NUM,
Point,
PublicKeys,
getContractClassFromArtifact,
} from '@aztec/circuits.js';
import { AztecAddress, Fr, INITIAL_L2_BLOCK_NUM, getContractClassFromArtifact } from '@aztec/circuits.js';

export const pxeTestSuite = (testName: string, pxeSetup: () => Promise<PXE>) => {
describe(testName, () => {
Expand All @@ -29,33 +21,11 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise<PXE>) =>

// Check that the account is correctly registered using the getAccounts and getRecipients methods
const accounts = await pxe.getRegisteredAccounts();
const recipients = await pxe.getRecipients();
expect(accounts).toContainEqual(completeAddress);
expect(recipients).not.toContainEqual(completeAddress);

// Check that the account is correctly registered using the getAccount and getRecipient methods
const account = await pxe.getRegisteredAccount(completeAddress.address);
const recipient = await pxe.getRecipient(completeAddress.address);
expect(account).toEqual(completeAddress);
expect(recipient).toBeUndefined();
});

it('registers a recipient and returns it as a recipient only and not as an account', async () => {
const completeAddress = CompleteAddress.random();

await pxe.registerRecipient(completeAddress);

// Check that the recipient is correctly registered using the getAccounts and getRecipients methods
const accounts = await pxe.getRegisteredAccounts();
const recipients = await pxe.getRecipients();
expect(accounts).not.toContainEqual(completeAddress);
expect(recipients).toContainEqual(completeAddress);

// Check that the recipient is correctly registered using the getAccount and getRecipient methods
const account = await pxe.getRegisteredAccount(completeAddress.address);
const recipient = await pxe.getRecipient(completeAddress.address);
expect(account).toBeUndefined();
expect(recipient).toEqual(completeAddress);
});

it('does not throw when registering the same account twice (just ignores the second attempt)', async () => {
Expand All @@ -66,28 +36,6 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise<PXE>) =>
await pxe.registerAccount(randomSecretKey, randomPartialAddress);
});

// Disabled as CompleteAddress constructor now performs preimage validation.
it.skip('cannot register a recipient with the same aztec address but different pub key or partial address', async () => {
const recipient1 = CompleteAddress.random();
const recipient2 = new CompleteAddress(
recipient1.address,
new PublicKeys(Point.random(), Point.random(), Point.random(), Point.random()),
Fr.random(),
);

await pxe.registerRecipient(recipient1);
await expect(() => pxe.registerRecipient(recipient2)).rejects.toThrow(
`Complete address with aztec address ${recipient1.address}`,
);
});

it('does not throw when registering the same recipient twice (just ignores the second attempt)', async () => {
const completeAddress = CompleteAddress.random();

await pxe.registerRecipient(completeAddress);
await pxe.registerRecipient(completeAddress);
});

it('successfully adds a contract', async () => {
const contracts = [randomDeployedContract(), randomDeployedContract()];
for (const contract of contracts) {
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/pxe/src/simulator_oracle/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export class SimulatorOracle implements DBOracle {
if (!completeAddress) {
throw new Error(
`No public key registered for address ${account}.
Register it by calling pxe.registerRecipient(...) or pxe.registerAccount(...).\nSee docs for context: https://docs.aztec.network/reference/common_errors/aztecnr-errors#simulation-error-no-public-key-registered-for-address-0x0-register-it-by-calling-pxeregisterrecipient-or-pxeregisteraccount`,
Register it by calling pxe.registerAccount(...).\nSee docs for context: https://docs.aztec.network/reference/common_errors/aztecnr-errors#simulation-error-no-public-key-registered-for-address-0x0-register-it-by-calling-pxeregisterrecipient-or-pxeregisteraccount`,
);
}
return completeAddress;
Expand Down

0 comments on commit 857791d

Please sign in to comment.