Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
benesjan committed Aug 31, 2023
1 parent c7d5190 commit e7cebfa
Show file tree
Hide file tree
Showing 45 changed files with 227 additions and 219 deletions.
13 changes: 6 additions & 7 deletions yarn-project/acir-simulator/src/client/private_execution.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
L1_TO_L2_MSG_TREE_HEIGHT,
MAX_NEW_COMMITMENTS_PER_CALL,
PRIVATE_DATA_TREE_HEIGHT,
PrivateKey,
PublicCallRequest,
TxContext,
} from '@aztec/circuits.js';
Expand Down Expand Up @@ -66,7 +65,7 @@ describe('Private Execution test suite', () => {
let logger: DebugLogger;

const defaultContractAddress = AztecAddress.random();
const ownerPk = PrivateKey.fromString('5e30a2f886b4b6a11aea03bf4910fbd5b24e61aa27ea4d05c393b3ab592a8d33');
const ownerPk = Fr.fromString('5e30a2f886b4b6a11aea03bf4910fbd5b24e61aa27ea4d05c393b3ab592a8d33');

const treeHeights: { [name: string]: number } = {
privateData: PRIVATE_DATA_TREE_HEIGHT,
Expand Down Expand Up @@ -168,7 +167,7 @@ describe('Private Execution test suite', () => {

describe('private token airdrop contract', () => {
const contractAddress = defaultContractAddress;
const recipientPk = PrivateKey.fromString('0c9ed344548e8f9ba8aa3c9f8651eaa2853130f6c1e9c050ccf198f7ea18a7ec');
const recipientPk = Fr.fromString('0c9ed344548e8f9ba8aa3c9f8651eaa2853130f6c1e9c050ccf198f7ea18a7ec');
const mockFirstNullifier = new Fr(1111);
let owner: AztecAddress;
let recipient: AztecAddress;
Expand Down Expand Up @@ -233,7 +232,7 @@ describe('Private Execution test suite', () => {
const siloedNoteHash = siloCommitment(circuitsWasm, contractAddress, innerNoteHash);
const uniqueSiloedNoteHash = computeUniqueCommitment(circuitsWasm, note.nonce, siloedNoteHash);
const innerNullifier = Fr.fromBuffer(
pedersenPlookupCommitInputs(circuitsWasm, [uniqueSiloedNoteHash.toBuffer(), ownerPk.value]),
pedersenPlookupCommitInputs(circuitsWasm, [uniqueSiloedNoteHash.toBuffer(), ownerPk.toBuffer()]),
);

const result = await acirSimulator.computeNoteHashAndNullifier(
Expand Down Expand Up @@ -400,7 +399,7 @@ describe('Private Execution test suite', () => {

describe('private token contract', () => {
const contractAddress = defaultContractAddress;
const recipientPk = PrivateKey.fromString('0c9ed344548e8f9ba8aa3c9f8651eaa2853130f6c1e9c050ccf198f7ea18a7ec');
const recipientPk = Fr.fromString('0c9ed344548e8f9ba8aa3c9f8651eaa2853130f6c1e9c050ccf198f7ea18a7ec');
const mockFirstNullifier = new Fr(1111);
let owner: AztecAddress;
let recipient: AztecAddress;
Expand Down Expand Up @@ -465,7 +464,7 @@ describe('Private Execution test suite', () => {
const siloedNoteHash = siloCommitment(circuitsWasm, contractAddress, innerNoteHash);
const uniqueSiloedNoteHash = computeUniqueCommitment(circuitsWasm, note.nonce, siloedNoteHash);
const innerNullifier = Fr.fromBuffer(
pedersenPlookupCommitInputs(circuitsWasm, [uniqueSiloedNoteHash.toBuffer(), ownerPk.value]),
pedersenPlookupCommitInputs(circuitsWasm, [uniqueSiloedNoteHash.toBuffer(), ownerPk.toBuffer()]),
);

const result = await acirSimulator.computeNoteHashAndNullifier(
Expand Down Expand Up @@ -680,7 +679,7 @@ describe('Private Execution test suite', () => {

describe('consuming messages', () => {
const contractAddress = defaultContractAddress;
const recipientPk = PrivateKey.fromString('0c9ed344548e8f9ba8aa3c9f8651eaa2853130f6c1e9c050ccf198f7ea18a7ec');
const recipientPk = Fr.fromString('0c9ed344548e8f9ba8aa3c9f8651eaa2853130f6c1e9c050ccf198f7ea18a7ec');

let recipient: AztecAddress;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CompleteAddress, FunctionData, HistoricBlockData, PrivateKey } from '@aztec/circuits.js';
import { CompleteAddress, FunctionData, HistoricBlockData } from '@aztec/circuits.js';
import { FunctionSelector, encodeArguments } from '@aztec/foundation/abi';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { EthAddress } from '@aztec/foundation/eth-address';
Expand All @@ -21,7 +21,7 @@ describe('Unconstrained Execution test suite', () => {
});

describe('private token contract', () => {
const ownerPk = PrivateKey.fromString('5e30a2f886b4b6a11aea03bf4910fbd5b24e61aa27ea4d05c393b3ab592a8d33');
const ownerPk = Fr.fromString('5e30a2f886b4b6a11aea03bf4910fbd5b24e61aa27ea4d05c393b3ab592a8d33');

let owner: AztecAddress;

Expand Down
20 changes: 10 additions & 10 deletions yarn-project/aztec-cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { JsonStringify } from '@aztec/foundation/json-rpc';
import { DebugLogger, LogFn } from '@aztec/foundation/log';
import { compileContract } from '@aztec/noir-compiler/cli';
import { SchnorrAccountContractAbi } from '@aztec/noir-contracts/artifacts';
import { CompleteAddress, ContractData, L2BlockL2Logs, PrivateKey, TxHash } from '@aztec/types';
import { CompleteAddress, ContractData, L2BlockL2Logs, TxHash } from '@aztec/types';

import { Command } from 'commander';
import { readFileSync } from 'fs';
Expand Down Expand Up @@ -93,7 +93,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command {

program
.command('generate-private-key')
.description('Generates a 32-byte private key.')
.description('Generates a private key which fits into the field used by Grumpkin curve.')
.option(
'-m, --mnemonic',
'An optional mnemonic string used for the private key generation. If not provided, random private key will be generated.',
Expand All @@ -103,11 +103,13 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command {
let publicKey;
if (options.mnemonic) {
const acc = mnemonicToAccount(options.mnemonic);
const key = Buffer.from(acc.getHdKey().privateKey!);
privKey = key.toString('hex');
publicKey = await generatePublicKey(new PrivateKey(key));
// Given that the mnemonicToAccount is a function from viem/accounts, it works with Ethereum private keys.
// Ethereum private keys are 256 bits and for this reason we need to fit it to Fr as that is the canonical
// representation of a private key used with Grumpkin curve.
const key = Fr.fromBufferWithWrapping(Buffer.from(acc.getHdKey().privateKey!));
publicKey = await generatePublicKey(key);
} else {
const key = PrivateKey.random();
const key = Fr.random();
privKey = key.toString();
publicKey = await generatePublicKey(key);
}
Expand All @@ -128,9 +130,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command {
.option('-u, --rpc-url <string>', 'URL of the Aztec RPC', AZTEC_RPC_HOST || 'http://localhost:8080')
.action(async options => {
const client = await createCompatibleClient(options.rpcUrl, debugLogger);
const privateKey = options.privateKey
? PrivateKey.fromString(stripLeadingHex(options.privateKey))
: PrivateKey.random();
const privateKey = options.privateKey ? Fr.fromString(stripLeadingHex(options.privateKey)) : Fr.random();

const account = getSchnorrAccount(client, privateKey, privateKey, accountCreationSalt);
const wallet = await account.waitDeploy();
Expand Down Expand Up @@ -379,7 +379,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command {
);
}

const privateKey = PrivateKey.fromString(stripLeadingHex(options.privateKey));
const privateKey = Fr.fromString(stripLeadingHex(options.privateKey));

const client = await createCompatibleClient(options.rpcUrl, debugLogger);
const wallet = await getAccountWallets(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
ContractData,
ExtendedContractData,
L2BlockL2Logs,
PrivateKey,
Tx,
TxExecutionRequest,
TxHash,
Expand Down Expand Up @@ -36,7 +35,6 @@ export function getHttpRpcServer(aztecRpcServer: AztecRPC): JsonRpcServer {
TxHash,
EthAddress,
Point,
PrivateKey,
Fr,
},
{ Tx, TxReceipt, L2BlockL2Logs },
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/aztec-rpc/src/synchroniser/synchroniser.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CompleteAddress, Fr, HistoricBlockData, PrivateKey } from '@aztec/circuits.js';
import { CompleteAddress, Fr, HistoricBlockData } from '@aztec/circuits.js';
import { Grumpkin } from '@aztec/circuits.js/barretenberg';
import { TestKeyStore } from '@aztec/key-store';
import { AztecNode, L2Block, MerkleTreeId } from '@aztec/types';
Expand Down Expand Up @@ -103,7 +103,7 @@ describe('Synchroniser', () => {

// Manually adding account to database so that we can call synchroniser.isAccountStateSynchronised
const keyStore = new TestKeyStore(await Grumpkin.new());
const privateKey = PrivateKey.random();
const privateKey = Fr.random();
keyStore.addAccount(privateKey);
const completeAddress = await CompleteAddress.fromPrivateKeyAndPartialAddress(privateKey, Fr.random());
await database.addCompleteAddress(completeAddress);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { AztecAddress, Contract, Fr, PrivateKey, Wallet, createAccounts, createAztecRpcClient } from '@aztec/aztec.js';
import { AztecAddress, Contract, Fr, Wallet, createAccounts, createAztecRpcClient } 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');

export const privateKey = PrivateKey.fromString('ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80');
export const privateKey = Fr.fromString('ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80');

const url = 'http://localhost:8080';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
createAztecRpcClient,
getL1ContractAddresses,
} from '@aztec/aztec.js';
import { PrivateKey } from '@aztec/circuits.js';
import { createDebugLogger } from '@aztec/foundation/log';
import { UniswapPortalAbi, UniswapPortalBytecode } from '@aztec/l1-artifacts';
import { SchnorrSingleKeyAccountContractAbi } from '@aztec/noir-contracts/artifacts';
Expand Down Expand Up @@ -37,7 +36,7 @@ const aztecRpcUrl = 'http://localhost:8080';
const ethRpcUrl = 'http://localhost:8545';

const hdAccount = mnemonicToAccount(MNEMONIC);
const privateKey = new PrivateKey(Buffer.from(hdAccount.getHdKey().privateKey!));
const privateKey = Fr.fromBuffer(Buffer.from(hdAccount.getHdKey().privateKey!));

const walletClient = createWalletClient({
account: hdAccount,
Expand Down
3 changes: 1 addition & 2 deletions yarn-project/aztec-sandbox/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec/aztec-node';
import { createAztecRPCServer, getConfigEnvVars as getRpcConfigEnvVars } from '@aztec/aztec-rpc';
import { deployInitialSandboxAccounts } from '@aztec/aztec.js';
import { PrivateKey } from '@aztec/circuits.js';
import { deployL1Contracts } from '@aztec/ethereum';
import { createDebugLogger } from '@aztec/foundation/log';
import { retryUntil } from '@aztec/foundation/retry';
Expand Down Expand Up @@ -72,7 +71,7 @@ async function main() {
logger.info(`Setting up Aztec Sandbox v${version}, please stand by...`);
logger.info('Deploying rollup contracts to L1...');
const deployedL1Contracts = await waitThenDeploy(aztecNodeConfig.rpcUrl, hdAccount);
aztecNodeConfig.publisherPrivateKey = new PrivateKey(Buffer.from(privKey!));
aztecNodeConfig.publisherPrivateKey = Buffer.from(privKey!).toString('hex');
aztecNodeConfig.rollupContract = deployedL1Contracts.rollupAddress;
aztecNodeConfig.contractDeploymentEmitterContract = deployedL1Contracts.contractDeploymentEmitterAddress;
aztecNodeConfig.inboxContract = deployedL1Contracts.inboxAddress;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import { Ecdsa } from '@aztec/circuits.js/barretenberg';
import { ContractAbi } from '@aztec/foundation/abi';
import { CompleteAddress, NodeInfo, PrivateKey } from '@aztec/types';
import { CompleteAddress, NodeInfo } from '@aztec/types';

import EcdsaAccountContractAbi from '../../abis/ecdsa_account_contract.json' assert { type: 'json' };
import { StoredKeyAccountEntrypoint } from '../entrypoint/stored_key_account_entrypoint.js';
import { EcdsaStoredKeyAccountEntrypoint } from '../index.js';
import { AccountContract } from './index.js';

/**
* Account contract that authenticates transactions using ECDSA signatures
* verified against a secp256k1 public key stored in an immutable encrypted note.
*/ export class EcdsaAccountContract implements AccountContract {
constructor(private signingPrivateKey: PrivateKey) {}
constructor(private signingPrivateKey: Buffer) {}

public async getDeploymentArgs() {
const signingPublicKey = await Ecdsa.new().then(e => e.computePublicKey(this.signingPrivateKey));
return [signingPublicKey.subarray(0, 32), signingPublicKey.subarray(32, 64)];
}

public async getEntrypoint({ address }: CompleteAddress, { chainId, version }: NodeInfo) {
return new StoredKeyAccountEntrypoint(address, this.signingPrivateKey, await Ecdsa.new(), chainId, version);
return new EcdsaStoredKeyAccountEntrypoint(address, this.signingPrivateKey, await Ecdsa.new(), chainId, version);
}

public getContractAbi(): ContractAbi {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ContractAbi } from '@aztec/foundation/abi';
import { CompleteAddress, NodeInfo, PrivateKey } from '@aztec/types';

import SchnorrAccountContractAbi from '../../abis/schnorr_account_contract.json' assert { type: 'json' };
import { StoredKeyAccountEntrypoint } from '../entrypoint/stored_key_account_entrypoint.js';
import { SchnorrStoredKeyAccountEntrypoint } from '../entrypoint/schnorr_stored_key_account_entrypoint.js';
import { AccountContract } from './index.js';

/**
Expand All @@ -19,7 +19,13 @@ export class SchnorrAccountContract implements AccountContract {
}

public async getEntrypoint({ address }: CompleteAddress, { chainId, version }: NodeInfo) {
return new StoredKeyAccountEntrypoint(address, this.signingPrivateKey, await Schnorr.new(), chainId, version);
return new SchnorrStoredKeyAccountEntrypoint(
address,
this.signingPrivateKey,
await Schnorr.new(),
chainId,
version,
);
}

public getContractAbi(): ContractAbi {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { AztecAddress, FunctionData, TxContext } from '@aztec/circuits.js';
import { Ecdsa } from '@aztec/circuits.js/barretenberg';
import { ContractAbi, encodeArguments } from '@aztec/foundation/abi';
import { DebugLogger, createDebugLogger } from '@aztec/foundation/log';
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';

/**
* Account contract implementation that keeps a signing public key in storage, and is retrieved on
* every new request in order to validate the payload signature.
*/
export class EcdsaStoredKeyAccountEntrypoint implements Entrypoint {
private log: DebugLogger;

constructor(
private address: AztecAddress,
private privateKey: Buffer,
private signer: Ecdsa,
private chainId: number = DEFAULT_CHAIN_ID,
private version: number = DEFAULT_VERSION,
) {
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()}`);
}

const { payload, packedArguments: callsPackedArguments } = await buildPayload(executions);
const message = await hashPayload(payload);
const signature = this.signer.constructSignature(message, this.privateKey).toBuffer();
this.log(`Signed challenge ${message.toString('hex')} as ${signature.toString('hex')}`);

const args = [payload, signature];
const abi = this.getEntrypointAbi();
const packedArgs = await PackedArguments.fromArgs(encodeArguments(abi, args));
const txRequest = TxExecutionRequest.from({
argsHash: packedArgs.hash,
origin: this.address,
functionData: FunctionData.fromAbi(abi),
txContext: TxContext.empty(this.chainId, this.version),
packedArguments: [...callsPackedArguments, packedArgs],
});

return txRequest;
}

private getEntrypointAbi() {
// We use the EcdsaAccountContractAbi because it implements the interface we need, but ideally
// we should have an interface that defines the entrypoint for StoredKeyAccountContracts and
// load the abi from it.
const abi = (EcdsaAccountContractAbi as any as ContractAbi).functions.find(f => f.name === 'entrypoint');
if (!abi) throw new Error(`Entrypoint abi for account contract not found`);
return abi;
}
}
2 changes: 1 addition & 1 deletion yarn-project/aztec.js/src/account/entrypoint/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export * from './entrypoint_collection.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 './ecdsa_stored_key_account_entrypoint.js';

/** Options for creating a tx request out of a set of function calls. */
export type CreateTxRequestOpts = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AztecAddress, FunctionData, PrivateKey, TxContext } from '@aztec/circuits.js';
import { Signer } from '@aztec/circuits.js/barretenberg';
import { Schnorr } from '@aztec/circuits.js/barretenberg';
import { ContractAbi, encodeArguments } from '@aztec/foundation/abi';
import { DebugLogger, createDebugLogger } from '@aztec/foundation/log';
import { FunctionCall, PackedArguments, TxExecutionRequest } from '@aztec/types';
Expand All @@ -10,16 +10,16 @@ import { buildPayload, hashPayload } from './entrypoint_payload.js';
import { CreateTxRequestOpts, Entrypoint } from './index.js';

/**
* Account contract implementation that keeps a signing public key in storage, and is retrieved on
* Account contract implementation that keeps a Schnorr signing public key in storage, and is retrieved on
* every new request in order to validate the payload signature.
*/
export class StoredKeyAccountEntrypoint implements Entrypoint {
export class SchnorrStoredKeyAccountEntrypoint implements Entrypoint {
private log: DebugLogger;

constructor(
private address: AztecAddress,
private privateKey: PrivateKey,
private signer: Signer,
private signer: Schnorr,
private chainId: number = DEFAULT_CHAIN_ID,
private version: number = DEFAULT_VERSION,
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AztecAddress, FunctionData, PartialAddress, PrivateKey, TxContext } from '@aztec/circuits.js';
import { Signer } from '@aztec/circuits.js/barretenberg';
import { Schnorr } from '@aztec/circuits.js/barretenberg';
import { ContractAbi, encodeArguments } from '@aztec/foundation/abi';
import { FunctionCall, PackedArguments, TxExecutionRequest } from '@aztec/types';

Expand All @@ -19,7 +19,7 @@ export class SingleKeyAccountEntrypoint implements Entrypoint {
private address: AztecAddress,
private partialAddress: PartialAddress,
private privateKey: PrivateKey,
private signer: Signer,
private signer: Schnorr,
private chainId: number = DEFAULT_CHAIN_ID,
private version: number = DEFAULT_VERSION,
) {}
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/aztec.js/src/account/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export type Salt = Fr | number | bigint;
export function getEcdsaAccount(
rpc: AztecRPC,
encryptionPrivateKey: PrivateKey,
signingPrivateKey: PrivateKey,
signingPrivateKey: Buffer,
saltOrAddress?: Salt | CompleteAddress,
): Account {
return new Account(rpc, encryptionPrivateKey, new EcdsaAccountContract(signingPrivateKey), saltOrAddress);
Expand Down
Loading

0 comments on commit e7cebfa

Please sign in to comment.