Skip to content

Commit

Permalink
Merge pull request #1639 from o1-labs/feature/vk-permissions-wrapper
Browse files Browse the repository at this point in the history
Verification key permissions: better-named wrappers
  • Loading branch information
mitschabaude committed May 9, 2024
2 parents c8a9c00 + 045c90b commit 23cdfa3
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 57 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased](https://github.com/o1-labs/o1js/compare/4a17de857...HEAD)

### Added

- `Permissions.VerificationKey`, a namespace for verification key permissions https://github.com/o1-labs/o1js/pull/1639
- Includes more accurate names for the `impossible` and `proof` permissions for verification keys, which are now called `impossibleDuringCurrentVersion` and `proofDuringCurrentVersion` respectively.

### Fixes

- Fix absolute imports which prevented compilation in some TS projects that used o1js https://github.com/o1-labs/o1js/pull/1628
Expand Down
7 changes: 2 additions & 5 deletions src/examples/zkapps/dex/erc20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
TokenContract,
AccountUpdateForest,
Struct,
TransactionVersion,
} from 'o1js';

export { Erc20Like, TrivialCoin };
Expand Down Expand Up @@ -79,10 +78,8 @@ class TrivialCoin extends TokenContract implements Erc20Like {
// make account non-upgradable forever
this.account.permissions.set({
...Permissions.default(),
setVerificationKey: {
auth: Permissions.impossible(),
txnVersion: TransactionVersion.current(),
},
setVerificationKey:
Permissions.VerificationKey.impossibleDuringCurrentVersion(),
setPermissions: Permissions.impossible(),
access: Permissions.proofOrSignature(),
});
Expand Down
15 changes: 3 additions & 12 deletions src/examples/zkapps/dex/upgradability.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import { expect } from 'expect';
import {
AccountUpdate,
Mina,
Permissions,
PrivateKey,
UInt64,
TransactionVersion,
} from 'o1js';
import { AccountUpdate, Mina, Permissions, PrivateKey, UInt64 } from 'o1js';
import { getProfiler } from '../../utils/profiler.js';
import { TokenContract, addresses, createDex, keys, tokenIds } from './dex.js';

Expand Down Expand Up @@ -446,10 +439,8 @@ async function upgradeabilityTests({ withVesting }: { withVesting: boolean }) {
let update = AccountUpdate.createSigned(addresses.dex);
update.account.permissions.set({
...Permissions.initial(),
setVerificationKey: {
auth: Permissions.impossible(),
txnVersion: TransactionVersion.current(),
},
setVerificationKey:
Permissions.VerificationKey.impossibleDuringCurrentVersion(),
});
});
await tx.prove();
Expand Down
5 changes: 0 additions & 5 deletions src/examples/zkapps/voting/dummy-contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
method,
DeployArgs,
Permissions,
TransactionVersion,
} from 'o1js';

export class DummyContract extends SmartContract {
Expand All @@ -19,10 +18,6 @@ export class DummyContract extends SmartContract {
editState: Permissions.proofOrSignature(),
editActionState: Permissions.proofOrSignature(),
setPermissions: Permissions.proofOrSignature(),
setVerificationKey: {
auth: Permissions.signature(),
txnVersion: TransactionVersion.current(),
},
incrementNonce: Permissions.proofOrSignature(),
});
this.sum.set(Field(0));
Expand Down
6 changes: 1 addition & 5 deletions src/examples/zkapps/voting/membership.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
provablePure,
AccountUpdate,
Provable,
TransactionVersion,
} from 'o1js';
import { Member } from './member.js';
import { ParticipantPreconditions } from './preconditions.js';
Expand Down Expand Up @@ -76,10 +75,7 @@ export class Membership_ extends SmartContract {
editState: Permissions.proofOrSignature(),
editActionState: Permissions.proofOrSignature(),
setPermissions: Permissions.proofOrSignature(),
setVerificationKey: {
auth: Permissions.proofOrSignature(),
txnVersion: TransactionVersion.current(),
},
setVerificationKey: Permissions.VerificationKey.proofOrSignature(),
incrementNonce: Permissions.proofOrSignature(),
});
}
Expand Down
6 changes: 1 addition & 5 deletions src/examples/zkapps/voting/voting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
provablePure,
AccountUpdate,
Provable,
TransactionVersion,
} from 'o1js';

import { Member } from './member.js';
Expand Down Expand Up @@ -103,10 +102,7 @@ export class Voting_ extends SmartContract {
editState: Permissions.proofOrSignature(),
editActionState: Permissions.proofOrSignature(),
incrementNonce: Permissions.proofOrSignature(),
setVerificationKey: {
auth: Permissions.none(),
txnVersion: TransactionVersion.current(),
},
setVerificationKey: Permissions.VerificationKey.none(),
setPermissions: Permissions.proofOrSignature(),
});
this.accumulatedVotes.set(Reducer.initialActionState);
Expand Down
7 changes: 2 additions & 5 deletions src/examples/zkapps/zkapp-self-update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,15 @@ import {
Mina,
AccountUpdate,
Provable,
TransactionVersion,
} from 'o1js';

class SelfUpdater extends SmartContract {
init() {
super.init();
this.account.permissions.set({
...Permissions.default(),
setVerificationKey: {
auth: Permissions.proof(),
txnVersion: TransactionVersion.current(),
},
setVerificationKey:
Permissions.VerificationKey.proofDuringCurrentVersion(),
});
}

Expand Down
97 changes: 77 additions & 20 deletions src/lib/mina/account-update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,18 @@ const False = () => Bool(false);
* documentation on those methods to learn more.
*/
type Permission = Types.AuthRequired;

class VerificationKeyPermission {
constructor(public auth: Permission, public txnVersion: UInt32) {}

// TODO this class could be made incompatible with a plain object (breaking change)
// private _ = undefined;

static withCurrentVersion(perm: Permission) {
return new VerificationKeyPermission(perm, TransactionVersion.current());
}
}

let Permission = {
/**
* Modification is impossible.
Expand Down Expand Up @@ -197,6 +209,64 @@ let Permission = {
signatureNecessary: False(),
signatureSufficient: True(),
}),

/**
* Special Verification key permissions.
*
* The difference to normal permissions is that `Permission.proof` and `Permission.impossible` are replaced by less restrictive permissions:
* - `impossible` is replaced by `impossibleDuringCurrentVersion`
* - `proof` is replaced by `proofDuringCurrentVersion`
*
* The issue is that a future hardfork which changes the proof system could mean that old verification keys can no longer
* be used to verify proofs in the new proof system, and the zkApp would have to be redeployed to adapt the verification key.
*
* Having either `impossible` or `proof` would mean that these zkApps can't be upgraded after this hypothetical hardfork, and would become unusable.
*
* Such a future hardfork would manifest as an increment in the "transaction version" of zkApps, which you can check with {@link TransactionVersion.current()}.
*
* The `impossibleDuringCurrentVersion` and `proofDuringCurrentVersion` have an additional `txnVersion` field.
* These permissions follow the same semantics of not upgradable, or only upgradable with proofs,
* _as long as_ the current transaction version is the same as the one on the permission.
*
* Once the current transaction version is higher than the one on the permission, the permission is treated as `signature`,
* and the zkApp can be redeployed with a signature of the original account owner.
*/
VerificationKey: {
/**
* Modification is impossible, as long as the network accepts the current {@link TransactionVersion}.
*
* After a hardfork that increments the transaction version, the permission is treated as `signature`.
*/
impossibleDuringCurrentVersion: () =>
VerificationKeyPermission.withCurrentVersion(Permission.impossible()),

/**
* Modification is always permitted
*/
none: () => VerificationKeyPermission.withCurrentVersion(Permission.none()),

/**
* Modification is permitted by zkapp proofs only; as long as the network accepts the current {@link TransactionVersion}.
*
* After a hardfork that increments the transaction version, the permission is treated as `signature`.
*/
proofDuringCurrentVersion: () =>
VerificationKeyPermission.withCurrentVersion(Permission.proof()),

/**
* Modification is permitted by signatures only, using the private key of the zkapp account
*/
signature: () =>
VerificationKeyPermission.withCurrentVersion(Permission.signature()),

/**
* Modification is permitted by zkapp proofs or signatures
*/
proofOrSignature: () =>
VerificationKeyPermission.withCurrentVersion(
Permission.proofOrSignature()
),
},
};

// TODO: we could replace the interface below if we could bridge annotations from OCaml
Expand Down Expand Up @@ -242,10 +312,7 @@ interface Permissions extends Permissions_ {
* key associated with the circuit tied to this account. Effectively
* "upgradeability" of the smart contract.
*/
setVerificationKey: {
auth: Permission;
txnVersion: UInt32;
};
setVerificationKey: VerificationKeyPermission;

/**
* The {@link Permission} corresponding to the ability to set the zkapp uri
Expand Down Expand Up @@ -283,6 +350,7 @@ interface Permissions extends Permissions_ {
}
let Permissions = {
...Permission,

/**
* Default permissions are:
*
Expand Down Expand Up @@ -311,10 +379,7 @@ let Permissions = {
receive: Permission.none(),
setDelegate: Permission.signature(),
setPermissions: Permission.signature(),
setVerificationKey: {
auth: Permission.signature(),
txnVersion: TransactionVersion.current(),
},
setVerificationKey: Permission.VerificationKey.signature(),
setZkappUri: Permission.signature(),
editActionState: Permission.proof(),
setTokenSymbol: Permission.signature(),
Expand All @@ -330,10 +395,7 @@ let Permissions = {
receive: Permission.none(),
setDelegate: Permission.signature(),
setPermissions: Permission.signature(),
setVerificationKey: {
auth: Permission.signature(),
txnVersion: TransactionVersion.current(),
},
setVerificationKey: Permission.VerificationKey.signature(),
setZkappUri: Permission.signature(),
editActionState: Permission.signature(),
setTokenSymbol: Permission.signature(),
Expand All @@ -350,10 +412,7 @@ let Permissions = {
access: Permission.none(),
setDelegate: Permission.none(),
setPermissions: Permission.none(),
setVerificationKey: {
auth: Permission.signature(),
txnVersion: TransactionVersion.current(),
},
setVerificationKey: Permission.VerificationKey.none(),
setZkappUri: Permission.none(),
editActionState: Permission.none(),
setTokenSymbol: Permission.none(),
Expand All @@ -369,10 +428,8 @@ let Permissions = {
access: Permission.impossible(),
setDelegate: Permission.impossible(),
setPermissions: Permission.impossible(),
setVerificationKey: {
auth: Permission.signature(),
txnVersion: TransactionVersion.current(),
},
setVerificationKey:
Permission.VerificationKey.impossibleDuringCurrentVersion(),
setZkappUri: Permission.impossible(),
editActionState: Permission.impossible(),
setTokenSymbol: Permission.impossible(),
Expand Down
3 changes: 3 additions & 0 deletions src/lib/mina/precondition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
ZkappUri,
} from '../../bindings/mina-transaction/transaction-leaves.js';
import type { Types } from '../../bindings/mina-transaction/types.js';
import type { Permissions } from './account-update.js';
import { ZkappStateLength } from './mina-instance.js';

export {
Expand Down Expand Up @@ -615,6 +616,8 @@ type UpdateValueOriginal = {
type UpdateValue = {
[K in keyof Update_]: K extends 'zkappUri' | 'tokenSymbol'
? string
: K extends 'permissions'
? Permissions
: Update_[K]['value'];
};

Expand Down

0 comments on commit 23cdfa3

Please sign in to comment.