Skip to content

Commit

Permalink
Merge branch 'master' into 05-03-feat_making_keys_fresh_oracles_complete
Browse files Browse the repository at this point in the history
  • Loading branch information
sklppy88 authored May 3, 2024
2 parents 3a12391 + 4a43fab commit 7c759ad
Show file tree
Hide file tree
Showing 19 changed files with 1,454 additions and 179 deletions.
5 changes: 4 additions & 1 deletion cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"bbmalloc",
"benesjan",
"Bincode",
"bincoded",
"bleurgh",
"bodyparser",
"bootnode",
Expand Down Expand Up @@ -98,6 +99,7 @@
"gitrepo",
"grumpkin",
"gtest",
"gzipped",
"hackmd",
"hardfork",
"hardlinks",
Expand Down Expand Up @@ -181,6 +183,7 @@
"productionify",
"protobuf",
"protogalaxy",
"proverless",
"proxied",
"proxified",
"proxify",
Expand Down Expand Up @@ -287,4 +290,4 @@
"flagWords": [
"anonymous"
]
}
}
5 changes: 4 additions & 1 deletion yarn-project/end-to-end/src/benchmarks/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ export async function waitNewPXESynced(
contract: BenchmarkingContract,
startingBlock: number = INITIAL_L2_BLOCK_NUM,
): Promise<PXEService> {
const pxe = await createPXEService(node, { l2BlockPollingIntervalMS: 100, l2StartingBlock: startingBlock });
const pxe = await createPXEService(node, {
l2BlockPollingIntervalMS: 100,
l2StartingBlock: startingBlock,
});
await pxe.registerContract(contract);
await retryUntil(() => pxe.isGlobalStateSynchronized(), 'pxe-global-sync');
return pxe;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { type Tx } from '@aztec/aztec.js';
import { type ClientProtocolArtifact } from '@aztec/noir-protocol-circuits-types';
import { type BBNativeProofCreator } from '@aztec/pxe';

import { ClientProverTest } from './client_prover_test.js';

const TIMEOUT = 300_000;

async function verifyProof(_1: ClientProtocolArtifact, _2: Tx, _3: BBNativeProofCreator) {
// TODO(@PhilWindle): Will verify proof once the circuits are fixed
await Promise.resolve();
//const result = await proofCreator.verifyProof(circuitType, tx.proof);
expect(true).toBeTruthy();
}

describe('client_prover_integration', () => {
const t = new ClientProverTest('transfer_private');
let { provenAsset, accounts, tokenSim, logger, proofCreator } = t;

beforeAll(async () => {
await t.applyBaseSnapshots();
await t.applyMintSnapshot();
await t.setup();
({ provenAsset, accounts, tokenSim, logger, proofCreator } = t);
});

afterAll(async () => {
await t.teardown();
});

afterEach(async () => {
await t.tokenSim.check();
});

it(
'private transfer less than balance',
async () => {
logger.info(
`Starting test using function: ${provenAsset.address}:${provenAsset.methods.balance_of_private.selector}`,
);
const balance0 = await provenAsset.methods.balance_of_private(accounts[0].address).simulate();
const amount = balance0 / 2n;
expect(amount).toBeGreaterThan(0n);
const interaction = provenAsset.methods.transfer(accounts[0].address, accounts[1].address, amount, 0);
const provenTx = await interaction.prove();

// This will recursively verify all app and kernel circuits involved in the private stage of this transaction!
logger.info(`Verifying kernel tail proof`);
await verifyProof('PrivateKernelTailArtifact', provenTx, proofCreator!);

await interaction.send().wait();
tokenSim.transferPrivate(accounts[0].address, accounts[1].address, amount);
},
TIMEOUT,
);

it(
'public transfer less than balance',
async () => {
logger.info(
`Starting test using function: ${provenAsset.address}:${provenAsset.methods.balance_of_public.selector}`,
);
const balance0 = await provenAsset.methods.balance_of_public(accounts[0].address).simulate();
const amount = balance0 / 2n;
expect(amount).toBeGreaterThan(0n);
const interaction = provenAsset.methods.transfer(accounts[0].address, accounts[1].address, amount, 0);
const provenTx = await interaction.prove();

// This will recursively verify all app and kernel circuits involved in the private stage of this transaction!
logger.info(`Verifying kernel tail to public proof`);
await verifyProof('PrivateKernelTailToPublicArtifact', provenTx, proofCreator!);

await interaction.send().wait();
tokenSim.transferPublic(accounts[0].address, accounts[1].address, amount);
},
TIMEOUT,
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
import { SchnorrAccountContractArtifact, getSchnorrAccount } from '@aztec/accounts/schnorr';
import {
type AccountWalletWithSecretKey,
type AztecNode,
type CompleteAddress,
type DebugLogger,
ExtendedNote,
type Fq,
Fr,
Note,
type TxHash,
computeSecretHash,
createDebugLogger,
} from '@aztec/aztec.js';
import { TokenContract } from '@aztec/noir-contracts.js';
import { BBNativeProofCreator, type PXEService } from '@aztec/pxe';

import * as fs from 'fs/promises';

import { waitRegisteredAccountSynced } from '../benchmarks/utils.js';
import {
SnapshotManager,
type SubsystemsContext,
addAccounts,
publicDeployAccounts,
} from '../fixtures/snapshot_manager.js';
import { getBBConfig, setupPXEService } from '../fixtures/utils.js';
import { TokenSimulator } from '../simulators/token_simulator.js';

const { E2E_DATA_PATH: dataPath } = process.env;

const SALT = 1;

/**
* Largely taken from the e2e_token_contract test file. We deploy 2 accounts and a token contract.
* However, we then setup a second PXE with a full prover instance.
* We configure this instance with all of the accounts and contracts.
* We then prove and verify transactions created via this full prover PXE.
*/

export class ClientProverTest {
static TOKEN_NAME = 'Aztec Token';
static TOKEN_SYMBOL = 'AZT';
static TOKEN_DECIMALS = 18n;
private snapshotManager: SnapshotManager;
logger: DebugLogger;
keys: Array<[Fr, Fq]> = [];
wallets: AccountWalletWithSecretKey[] = [];
accounts: CompleteAddress[] = [];
asset!: TokenContract;
tokenSim!: TokenSimulator;
aztecNode!: AztecNode;
pxe!: PXEService;
fullProverPXE!: PXEService;
provenAsset!: TokenContract;
provenPXETeardown?: () => Promise<void>;
private directoryToCleanup?: string;
proofCreator?: BBNativeProofCreator;

constructor(testName: string) {
this.logger = createDebugLogger(`aztec:client_prover_test:${testName}`);
this.snapshotManager = new SnapshotManager(`client_prover_integration/${testName}`, dataPath);
}

/**
* Adds two state shifts to snapshot manager.
* 1. Add 2 accounts.
* 2. Publicly deploy accounts, deploy token contract
*/
async applyBaseSnapshots() {
await this.snapshotManager.snapshot('2_accounts', addAccounts(2, this.logger), async ({ accountKeys }, { pxe }) => {
this.keys = accountKeys;
const accountManagers = accountKeys.map(ak => getSchnorrAccount(pxe, ak[0], ak[1], SALT));
this.wallets = await Promise.all(accountManagers.map(a => a.getWallet()));
this.accounts = await pxe.getRegisteredAccounts();
this.wallets.forEach((w, i) => this.logger.verbose(`Wallet ${i} address: ${w.getAddress()}`));
});

await this.snapshotManager.snapshot(
'client_prover_integration',
async () => {
// Create the token contract state.
// Move this account thing to addAccounts above?
this.logger.verbose(`Public deploy accounts...`);
await publicDeployAccounts(this.wallets[0], this.accounts.slice(0, 2));

this.logger.verbose(`Deploying TokenContract...`);
const asset = await TokenContract.deploy(
this.wallets[0],
this.accounts[0],
ClientProverTest.TOKEN_NAME,
ClientProverTest.TOKEN_SYMBOL,
ClientProverTest.TOKEN_DECIMALS,
)
.send()
.deployed();
this.logger.verbose(`Token deployed to ${asset.address}`);

return { tokenContractAddress: asset.address };
},
async ({ tokenContractAddress }) => {
// Restore the token contract state.
this.asset = await TokenContract.at(tokenContractAddress, this.wallets[0]);
this.logger.verbose(`Token contract address: ${this.asset.address}`);

this.tokenSim = new TokenSimulator(
this.asset,
this.logger,
this.accounts.map(a => a.address),
);

expect(await this.asset.methods.admin().simulate()).toBe(this.accounts[0].address.toBigInt());
},
);
}

async setup() {
const context = await this.snapshotManager.setup();
({ pxe: this.pxe, aztecNode: this.aztecNode } = context);

// Configure a full prover PXE
const bbConfig = await getBBConfig(this.logger);
this.directoryToCleanup = bbConfig?.directoryToCleanup;

if (!bbConfig?.bbWorkingDirectory || !bbConfig?.expectedBBPath) {
throw new Error(`Test must be run with BB native configuration`);
}

this.proofCreator = new BBNativeProofCreator(bbConfig?.expectedBBPath, bbConfig?.bbWorkingDirectory);

this.logger.debug(`Main setup completed, initializing full prover PXE...`);
({ pxe: this.fullProverPXE, teardown: this.provenPXETeardown } = await setupPXEService(
0,
this.aztecNode,
{
proverEnabled: false,
bbBinaryPath: bbConfig?.expectedBBPath,
bbWorkingDirectory: bbConfig?.bbWorkingDirectory,
},
undefined,
true,
this.proofCreator,
));
this.logger.debug(`Contract address ${this.asset.address}`);
await this.fullProverPXE.registerContract(this.asset);

for (let i = 0; i < 2; i++) {
await waitRegisteredAccountSynced(
this.fullProverPXE,
this.keys[i][0],
this.wallets[i].getCompleteAddress().partialAddress,
);

await waitRegisteredAccountSynced(this.pxe, this.keys[i][0], this.wallets[i].getCompleteAddress().partialAddress);
}

const account = getSchnorrAccount(this.fullProverPXE, this.keys[0][0], this.keys[0][1], SALT);

await this.fullProverPXE.registerContract({
instance: account.getInstance(),
artifact: SchnorrAccountContractArtifact,
});

const provenWallet = await account.getWallet();
this.provenAsset = await TokenContract.at(this.asset.address, provenWallet);
this.logger.debug(`Full prover PXE started!!`);
return this;
}

snapshot = <T>(
name: string,
apply: (context: SubsystemsContext) => Promise<T>,
restore: (snapshotData: T, context: SubsystemsContext) => Promise<void> = () => Promise.resolve(),
): Promise<void> => this.snapshotManager.snapshot(name, apply, restore);

async teardown() {
await this.snapshotManager.teardown();

// Cleanup related to the second 'full prover' PXE
await this.provenPXETeardown?.();

if (this.directoryToCleanup) {
await fs.rm(this.directoryToCleanup, { recursive: true, force: true });
}
}

async addPendingShieldNoteToPXE(accountIndex: number, amount: bigint, secretHash: Fr, txHash: TxHash) {
const note = new Note([new Fr(amount), secretHash]);
const extendedNote = new ExtendedNote(
note,
this.accounts[accountIndex].address,
this.asset.address,
TokenContract.storage.pending_shields.slot,
TokenContract.notes.TransparentNote.id,
txHash,
);
await this.wallets[accountIndex].addNote(extendedNote);
}

async applyMintSnapshot() {
await this.snapshotManager.snapshot(
'mint',
async () => {
const { asset, accounts } = this;
const amount = 10000n;

this.logger.verbose(`Minting ${amount} publicly...`);
await asset.methods.mint_public(accounts[0].address, amount).send().wait();

this.logger.verbose(`Minting ${amount} privately...`);
const secret = Fr.random();
const secretHash = computeSecretHash(secret);
const receipt = await asset.methods.mint_private(amount, secretHash).send().wait();

await this.addPendingShieldNoteToPXE(0, amount, secretHash, receipt.txHash);
const txClaim = asset.methods.redeem_shield(accounts[0].address, amount, secret).send();
await txClaim.wait({ debug: true });
this.logger.verbose(`Minting complete.`);

return { amount };
},
async ({ amount }) => {
const {
asset,
accounts: [{ address }],
tokenSim,
} = this;
tokenSim.mintPublic(address, amount);

const publicBalance = await asset.methods.balance_of_public(address).simulate();
this.logger.verbose(`Public balance of wallet 0: ${publicBalance}`);
expect(publicBalance).toEqual(this.tokenSim.balanceOfPublic(address));

tokenSim.mintPrivate(amount);
tokenSim.redeemShield(address, amount);
const privateBalance = await asset.methods.balance_of_private(address).simulate();
this.logger.verbose(`Private balance of wallet 0: ${privateBalance}`);
expect(privateBalance).toEqual(tokenSim.balanceOfPrivate(address));

const totalSupply = await asset.methods.total_supply().simulate();
this.logger.verbose(`Total supply: ${totalSupply}`);
expect(totalSupply).toEqual(tokenSim.totalSupply);

return Promise.resolve();
},
);
}
}
Loading

0 comments on commit 7c759ad

Please sign in to comment.