-
Notifications
You must be signed in to change notification settings - Fork 234
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
refactor: refactor key rotate and address comments from 6405 #6450
Changes from all commits
7d4ace4
a49681c
9b1eb35
034948d
f6902d0
3d10f31
0e738f7
5ac568e
49652b5
50a3909
29b70fd
06fb183
7853a03
c9e0a05
b206b7c
c602171
d33e54f
a3a503d
eaaf567
11b9e89
f595765
41b99f4
6e9a0d3
7309988
6777c35
0d2bdd3
42a0551
e26e04b
924b901
6044733
3378ac0
62ccede
cb500ec
7bbed9e
0225544
0fecfc2
3e9e018
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
import { type PXE } from '@aztec/circuit-types'; | ||
|
||
import { type AccountInterface } from './interface.js'; | ||
import { type AccountInterface, type AccountKeyRotationInterface } from './interface.js'; | ||
|
||
/** | ||
* The wallet interface. | ||
*/ | ||
export type Wallet = AccountInterface & PXE; | ||
export type Wallet = AccountInterface & PXE & AccountKeyRotationInterface; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
import { type AuthWitness, type FunctionCall, type PXE, type TxExecutionRequest } from '@aztec/circuit-types'; | ||
import { type AztecAddress, Fr } from '@aztec/circuits.js'; | ||
import { AztecAddress, CANONICAL_KEY_REGISTRY_ADDRESS, Fq, Fr, derivePublicKeyFromSecretKey } from '@aztec/circuits.js'; | ||
import { type ABIParameterVisibility, type FunctionAbi, FunctionType } from '@aztec/foundation/abi'; | ||
|
||
import { type AccountInterface } from '../account/interface.js'; | ||
|
@@ -165,6 +165,30 @@ export class AccountWallet extends BaseWallet { | |
return { isValidInPrivate, isValidInPublic }; | ||
} | ||
|
||
/** | ||
* Rotates the account master nullifier key pair. | ||
* @param newNskM - The new master nullifier secret key we want to use. | ||
* @remarks - This function also calls the canonical key registry with the account's new derived master nullifier public key. | ||
* We are doing it this way to avoid user error, in the case that a user rotates their keys in the key registry, | ||
* but fails to do so in the key store. This leads to unspendable notes. | ||
* | ||
* This does not hinder our ability to spend notes tied to a previous master nullifier public key, provided we have the master nullifier secret key for it. | ||
*/ | ||
public async rotateNullifierKeys(newNskM: Fq = Fq.random()): Promise<void> { | ||
// We rotate our secret key in the keystore first, because if the subsequent interaction fails, there are no bad side-effects. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the cases that it happens a lot it might use a lot of storage. But it can quite easily be "cleaned" later by looping over the keys and simply checking which either maps the address preimage or that the matching public was in the registry at some point, but don't think it is meaningful for us to really look into now 🤷 |
||
// If vice versa (the key registry is called first), but the call to the PXE fails, we will end up in a situation with unspendable notes, as we have not committed our | ||
// nullifier secret key to our wallet. | ||
await this.pxe.rotateNskM(this.getAddress(), newNskM); | ||
const interaction = new ContractFunctionInteraction( | ||
this, | ||
AztecAddress.fromBigInt(CANONICAL_KEY_REGISTRY_ADDRESS), | ||
this.getRotateNpkMAbi(), | ||
[this.getAddress(), derivePublicKeyFromSecretKey(newNskM), Fr.ZERO], | ||
); | ||
|
||
await interaction.send().wait(); | ||
} | ||
|
||
/** | ||
* Returns a function interaction to cancel a message hash as authorized in this account. | ||
* @param messageHashOrIntent - The message or the caller and action to authorize/revoke | ||
|
@@ -268,4 +292,39 @@ export class AccountWallet extends BaseWallet { | |
returnTypes: [{ kind: 'array', length: 2, type: { kind: 'boolean' } }], | ||
}; | ||
} | ||
|
||
private getRotateNpkMAbi(): FunctionAbi { | ||
return { | ||
name: 'rotate_npk_m', | ||
isInitializer: false, | ||
functionType: FunctionType.PUBLIC, | ||
isInternal: false, | ||
isStatic: false, | ||
parameters: [ | ||
{ | ||
name: 'address', | ||
type: { | ||
fields: [{ name: 'inner', type: { kind: 'field' } }], | ||
kind: 'struct', | ||
path: 'authwit::aztec::protocol_types::address::aztec_address::AztecAddress', | ||
}, | ||
visibility: 'private' as ABIParameterVisibility, | ||
}, | ||
{ | ||
name: 'new_npk_m', | ||
type: { | ||
fields: [ | ||
{ name: 'x', type: { kind: 'field' } }, | ||
{ name: 'y', type: { kind: 'field' } }, | ||
], | ||
kind: 'struct', | ||
path: 'authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint', | ||
}, | ||
visibility: 'private' as ABIParameterVisibility, | ||
}, | ||
{ name: 'nonce', type: { kind: 'field' }, visibility: 'private' as ABIParameterVisibility }, | ||
], | ||
returnTypes: [], | ||
}; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -54,6 +54,8 @@ export abstract class BaseWallet implements Wallet { | |
}, | ||
): Promise<AuthWitness>; | ||
|
||
abstract rotateNullifierKeys(newNskM: Fq): Promise<void>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is abstract so this can still implement wallet |
||
|
||
getAddress() { | ||
return this.getCompleteAddress().address; | ||
} | ||
|
@@ -69,8 +71,8 @@ export abstract class BaseWallet implements Wallet { | |
registerAccount(secretKey: Fr, partialAddress: PartialAddress): Promise<CompleteAddress> { | ||
return this.pxe.registerAccount(secretKey, partialAddress); | ||
} | ||
rotateMasterNullifierKey(account: AztecAddress, secretKey: Fq): Promise<void> { | ||
return this.pxe.rotateMasterNullifierKey(account, secretKey); | ||
rotateNskM(address: AztecAddress, secretKey: Fq) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is gross but here because wallet implements PXE. |
||
return this.pxe.rotateNskM(address, secretKey); | ||
} | ||
registerRecipient(account: CompleteAddress): Promise<void> { | ||
return this.pxe.registerRecipient(account); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be similar to the authwitprovider?
KeyRotationInterface
and then have the usual AccountInterface also implement that?So it is something that it possible from all of the accounts, so might be similar to the authwit in that sense 🤷
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if I like it right now as this makes AccountInterface requires access to the PXE / key store and we'd have to change a lot. Probably would be better refactored when we figure out exactly how we want our classes to look like here because there is a lot of jank as is.