Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
benesjan committed Apr 11, 2024
1 parent b6df7db commit daad843
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,5 @@ global GENERATOR_INDEX__NSK_M = 47;
global GENERATOR_INDEX__IVSK_M = 48;
global GENERATOR_INDEX__OVSK_M = 49;
global GENERATOR_INDEX__TSK_M = 50;
global GENERATOR_INDEX__PUBLIC_KEYS_HASH = 51;
global GENERATOR_INDEX__CONTRACT_ADDRESS_V1 = 52;
32 changes: 17 additions & 15 deletions yarn-project/circuit-types/src/keys/new_key_store.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,38 @@
import { AztecAddress, Fr, PartialAddress, type PublicKey } from '@aztec/circuits.js';
import { type AztecAddress, Fr, PartialAddress, type PublicKey } from '@aztec/circuits.js';

/**
* Represents a secure storage for managing keys.
*/
export interface NewKeyStore {
/**
* Retrieves the master nullifier public key.
* @returns A Promise that resolves to the master nullifier public key.
* Gets the master nullifier public key for a given account.
* @throws If the account does not exist in the key store.
* @param account - The account address for which to retrieve the master nullifier public key.
* @returns The master nullifier public key for the account.
*/
getMasterNullifierPublicKey(): Promise<PublicKey>;
getMasterNullifierPublicKey(account: AztecAddress): Promise<PublicKey>;

/**
* Retrieves the master incoming viewing key.
* @returns A Promise that resolves to the master incoming viewing key.
* Gets the master incoming viewing public key for a given account.
* @throws If the account does not exist in the key store.
* @param account - The account address for which to retrieve the master incoming viewing public key.
* @returns The master incoming viewing public key for the account.
*/
getMasterIncomingViewingPublicKey(): Promise<PublicKey>;
getMasterIncomingViewingPublicKey(account: AztecAddress): Promise<PublicKey>;

/**
* Retrieves the master outgoing viewing key.
* @throws If the account does not exist in the key store.
* @param account - The account to retrieve the master outgoing viewing key for.
* @returns A Promise that resolves to the master outgoing viewing key.
*/
getMasterOutgoingViewingPublicKey(): Promise<PublicKey>;
getMasterOutgoingViewingPublicKey(account: AztecAddress): Promise<PublicKey>;

/**
* Retrieves the master tagging key.
* @throws If the account does not exist in the key store.
* @param account - The account to retrieve the master tagging key for.
* @returns A Promise that resolves to the master tagging key.
*/
getMasterTaggingPublicKey(): Promise<PublicKey>;

/**
* Retrieves the hash of the public keys.
* @returns A Promise that resolves to the hash of the public keys.
*/
getPublicKeysHash(): Promise<PublicKey>;
getMasterTaggingPublicKey(account: AztecAddress): Promise<PublicKey>;
}
2 changes: 2 additions & 0 deletions yarn-project/circuits.js/src/constants.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,6 @@ export enum GeneratorIndex {
IVSK_M = 48,
OVSK_M = 49,
TSK_M = 50,
PUBLIC_KEYS_HASH = 51,
CONTRACT_ADDRESS_V1 = 52,
}
127 changes: 107 additions & 20 deletions yarn-project/key-store/src/new_test_key_store.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,9 @@
import { type NewKeyStore, type KeyPair, type KeyStore, type PublicKey } from '@aztec/circuit-types';
import {
type AztecAddress,
type GrumpkinPrivateKey,
GrumpkinScalar,
Point,
computeNullifierSecretKey,
computeSiloedNullifierSecretKey,
derivePublicKey,
type Fr,
GeneratorIndex,
Fq,
} from '@aztec/circuits.js';
import { type NewKeyStore, type PublicKey } from '@aztec/circuit-types';
import { AztecAddress, Fq, type Fr, GeneratorIndex, type PartialAddress, Point } from '@aztec/circuits.js';
import { type Grumpkin } from '@aztec/circuits.js/barretenberg';
import { poseidonHash } from '@aztec/foundation/crypto';
import { type AztecKVStore, type AztecMap } from '@aztec/kv-store';

import { ConstantKeyPair } from './key_pair.js';
import { poseidonHash } from '@aztec/foundation/crypto';
/**
* TestKeyStore is an implementation of the KeyStore interface, used for managing key pairs in a testing environment.
* It should be utilized in testing scenarios where secure key management is not required, and ease-of-use is prioritized.
Expand All @@ -28,13 +16,112 @@ export class NewTestKeyStore implements NewKeyStore {
this.#keys = database.openMap('key_store');
}

public async addAccount(sk: Fr): Promise<PublicKey> {
public async addAccount(sk: Fr, partialAddress: PartialAddress): Promise<AztecAddress> {
// First we derive the master secret keys
const masterNullifierSecretKey = poseidonHash([sk], GeneratorIndex.NSK_M);
// TODO: Is converting from Fr to Fq an issue? Fr.MODULUS is < Fq.MODULUS so it wont' throw but should we refactor this?
const masterNullifierPublicKey = this.curve.mul(this.curve.generator(), Fq.fromBuffer(masterNullifierSecretKey.toBuffer()))
const masterIncomingViewingSecretKey = poseidonHash([sk], GeneratorIndex.IVSK_M);
const masterOutgoingViewingSecretKey = poseidonHash([sk], GeneratorIndex.OVSK_M);
const masterTaggingSecretKey = poseidonHash([sk], GeneratorIndex.TSK_M);

// Then we derive the master public keys
// TODO: Is converting from Fr to Fq bellow an issue? Fr.MODULUS is < Fq.MODULUS so it shouldn't but should we refactor this anyway?
const masterNullifierPublicKey = this.curve.mul(
this.curve.generator(),
Fq.fromBuffer(masterNullifierSecretKey.toBuffer()),
);
const masterIncomingViewingPublicKey = this.curve.mul(
this.curve.generator(),
Fq.fromBuffer(masterIncomingViewingSecretKey.toBuffer()),
);
const masterOutgoingViewingPublicKey = this.curve.mul(
this.curve.generator(),
Fq.fromBuffer(masterOutgoingViewingSecretKey.toBuffer()),
);
const masterTaggingPublicKey = this.curve.mul(
this.curve.generator(),
Fq.fromBuffer(masterTaggingSecretKey.toBuffer()),
);

// We hash the public keys to get the public keys hash
const publicKeysHash = poseidonHash(
[
masterNullifierPublicKey,
masterIncomingViewingPublicKey,
masterOutgoingViewingPublicKey,
masterTaggingPublicKey,
],
GeneratorIndex.PUBLIC_KEYS_HASH,
);

// We hash the partial address and the public keys hash to get the account address
// TODO: Should GeneratorIndex.CONTRACT_ADDRESS be removed given that we introduced CONTRACT_ADDRESS_V1?
// TODO: Move the following line to AztecAddress class?
const accountAddressFr = poseidonHash([partialAddress, publicKeysHash], GeneratorIndex.CONTRACT_ADDRESS_V1);
const accountAddress = AztecAddress.fromField(accountAddressFr);

// We store the keys in the database
await this.#keys.set(`${accountAddress.toString()}-npk_m`, masterNullifierPublicKey.toBuffer());
await this.#keys.set(`${accountAddress.toString()}-ivpk_m`, masterIncomingViewingPublicKey.toBuffer());
await this.#keys.set(`${accountAddress.toString()}-ovpk_m`, masterOutgoingViewingPublicKey.toBuffer());
await this.#keys.set(`${accountAddress.toString()}-tpk_m`, masterTaggingPublicKey.toBuffer());

// At last, we return the newly derived account address
return Promise.resolve(accountAddress);
}

/**
* Gets the master nullifier public key for a given account.
* @throws If the account does not exist in the key store.
* @param account - The account address for which to retrieve the master nullifier public key.
* @returns The master nullifier public key for the account.
*/
public getMasterNullifierPublicKey(account: AztecAddress): Promise<PublicKey> {
const masterNullifierPublicKeyBuffer = this.#keys.get(`${account.toString()}-npk_m`);
if (!masterNullifierPublicKeyBuffer) {
throw new Error(`Account ${account.toString()} does not exist.`);
}
return Promise.resolve(Point.fromBuffer(masterNullifierPublicKeyBuffer));
}

/**
* Gets the master incoming viewing public key for a given account.
* @throws If the account does not exist in the key store.
* @param account - The account address for which to retrieve the master incoming viewing public key.
* @returns The master incoming viewing public key for the account.
*/
public getMasterIncomingViewingPublicKey(account: AztecAddress): Promise<PublicKey> {
const masterIncomingViewingPublicKeyBuffer = this.#keys.get(`${account.toString()}-ivpk_m`);
if (!masterIncomingViewingPublicKeyBuffer) {
throw new Error(`Account ${account.toString()} does not exist.`);
}
return Promise.resolve(Point.fromBuffer(masterIncomingViewingPublicKeyBuffer));
}

/**
* Retrieves the master outgoing viewing public key.
* @throws If the account does not exist in the key store.
* @param account - The account to retrieve the master outgoing viewing key for.
* @returns A Promise that resolves to the master outgoing viewing key.
*/
public getMasterOutgoingViewingPublicKey(account: AztecAddress): Promise<PublicKey> {
const masterOutgoingViewingPublicKeyBuffer = this.#keys.get(`${account.toString()}-ovpk_m`);
if (!masterOutgoingViewingPublicKeyBuffer) {
throw new Error(`Account ${account.toString()} does not exist.`);
}
return Promise.resolve(Point.fromBuffer(masterOutgoingViewingPublicKeyBuffer));
}

public async getMasterNullifierPublicKey(): Promise<PublicKey> {
return poseidonHash()
/**
* Retrieves the master tagging public key.
* @throws If the account does not exist in the key store.
* @param account - The account to retrieve the master tagging key for.
* @returns A Promise that resolves to the master tagging key.
*/
public getMasterTaggingPublicKey(account: AztecAddress): Promise<PublicKey> {
const masterTaggingPublicKeyBuffer = this.#keys.get(`${account.toString()}-tpk_m`);
if (!masterTaggingPublicKeyBuffer) {
throw new Error(`Account ${account.toString()} does not exist.`);
}
return Promise.resolve(Point.fromBuffer(masterTaggingPublicKeyBuffer));
}
}

0 comments on commit daad843

Please sign in to comment.