Skip to content
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

Add access permission to accounts #500

Merged
merged 28 commits into from
Jan 18, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8339069
add implicit account creation fee
mitschabaude May 4, 2022
76ce986
generated types
mitschabaude Oct 20, 2022
40c963d
fix ts & replace manual types with generated ones
mitschabaude Oct 20, 2022
89356e8
put access permission on example token contracts
mitschabaude Oct 20, 2022
51ffa4c
move rejected token access example to a unit test
mitschabaude Oct 20, 2022
449b57d
update bindings
mitschabaude Oct 20, 2022
82147c7
Merge branch 'main' into feature/add-access-permission
mrmr1993 Oct 31, 2022
19b7257
Merge commit '018f2ba8169efab78e14088e68d8197c3b89f2dd' into feature/…
mrmr1993 Nov 16, 2022
b70aa0e
Merge branch 'berkeley' into feature/add-access-permission
mitschabaude Nov 21, 2022
efadaec
regenerate types
mitschabaude Nov 21, 2022
182c437
Merge branch 'main' into feature/add-access-permission
mitschabaude Nov 21, 2022
bc199d2
add access permission
mitschabaude Nov 21, 2022
728d111
fix generation of test vectors
mitschabaude Nov 21, 2022
992d4cc
update bindings
mitschabaude Nov 21, 2022
36c99ad
Merge branch 'berkeley' into feature/add-access-permission
mitschabaude Nov 22, 2022
6dc97d0
Merge commit '980202eeed2827fec3e4d604cd9ee07d22432ba3' into feature/…
mrmr1993 Dec 1, 2022
9d0ee52
Fixup tests
mrmr1993 Dec 2, 2022
0adcfca
Merge branch 'feature/add-access-permission' into feature/add-access-…
mrmr1993 Dec 2, 2022
c81eea6
Merge commit '483baff2ac71c65f757c6717754de4ef152bc6a2' into HEAD
mrmr1993 Dec 15, 2022
0aefb8d
Merge commit 'aa750aec4c862c8422dbde902dd3f0e9cec4f631' into HEAD
mrmr1993 Dec 21, 2022
e04491b
Merge branch 'berkeley' into feature/add-access-permission
mitschabaude Dec 21, 2022
8086e00
update bindings
mitschabaude Dec 21, 2022
627aa65
Merge commit 'aa750aec4c862c8422dbde902dd3f0e9cec4f631' into feature/…
mrmr1993 Dec 21, 2022
7082c28
Update test vector
mrmr1993 Dec 22, 2022
ce678aa
Ah good, now we have 2 copies of everything
mrmr1993 Dec 22, 2022
1dcb867
Merge commit '0aefb8db9de82556dcd15c3556cbcd507947d10b' into HEAD
mrmr1993 Jan 17, 2023
afd778e
Merge branch 'feature/implicit-account-creation-fee' into feature/add…
mitschabaude Jan 18, 2023
5a89fd3
update bindings
mitschabaude Jan 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 0 additions & 65 deletions src/examples/zkapps/dex/arbitrary_token_interaction.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/examples/zkapps/dex/dex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ class TokenContract extends SmartContract {
...Permissions.default(),
send: Permissions.proof(),
receive: Permissions.proof(),
access: Permissions.proofOrSignature(),
});
}
@method init() {
Expand Down
1 change: 1 addition & 0 deletions src/examples/zkapps/dex/erc20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ class TrivialCoin extends SmartContract implements Erc20 {
...Permissions.default(),
setVerificationKey: Permissions.impossible(),
setPermissions: Permissions.impossible(),
access: Permissions.proofOrSignature(),
});
}

Expand Down
3 changes: 1 addition & 2 deletions src/examples/zkapps/token_with_proofs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class TokenContract extends SmartContract {
this.setPermissions({
...Permissions.default(),
send: Permissions.proof(),
access: Permissions.proofOrSignature(),
});
this.balance.addInPlace(UInt64.fromNumber(initialBalance));
}
Expand Down Expand Up @@ -180,7 +181,6 @@ tx = await Local.transaction(feePayer, () => {
});
console.log('authorize send (proof)');
await tx.prove();
console.log('send (proof)');
await tx.send();

console.log(
Expand All @@ -202,7 +202,6 @@ tx = await Local.transaction(feePayer, () => {
});
console.log('authorize send (proof)');
await tx.prove();
console.log('send (proof)');
await tx.send();

console.log(
Expand Down
27 changes: 14 additions & 13 deletions src/lib/account_update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,13 @@ interface Permissions extends Permissions_ {
// TODO: doccomments
incrementNonce: Permission;
setVotingFor: Permission;

/**
* Permission to control the ability to include _any_ account update for this account in a transaction. Note that this is more restrictive than
* all other permissions combined. For normal accounts it can safely be set to `none`, but for token contracts this has to be more restrictive, to
* prevent unauthorized token interactions -- for example, it could be `proofOrSignature`.
*/
access: Permission;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any thoughts on how we default this to non-none somehow when working with tokens? Happy path needs to be the secure one

Copy link
Contributor Author

@mitschabaude mitschabaude Oct 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could export a TokenContract which is SmartContract but with defaults changed to be secure for token contracts

And have all our examples and docs for tokens point to this

}
let Permissions = {
...Permission,
Expand Down Expand Up @@ -249,6 +256,7 @@ let Permissions = {
setTokenSymbol: Permission.signature(),
incrementNonce: Permissions.signature(),
setVotingFor: Permission.signature(),
access: Permission.none(),
}),

initial: (): Permissions => ({
Expand All @@ -263,6 +271,7 @@ let Permissions = {
setTokenSymbol: Permission.signature(),
incrementNonce: Permissions.signature(),
setVotingFor: Permission.signature(),
access: Permission.none(),
}),

fromString: (permission: AuthRequired): Permission => {
Expand All @@ -284,19 +293,11 @@ let Permissions = {
}
},

fromJSON: (permissions: {
editState: AuthRequired;
send: AuthRequired;
receive: AuthRequired;
setDelegate: AuthRequired;
setPermissions: AuthRequired;
setVerificationKey: AuthRequired;
setZkappUri: AuthRequired;
editSequenceState: AuthRequired;
setTokenSymbol: AuthRequired;
incrementNonce: AuthRequired;
setVotingFor: AuthRequired;
}): Permissions => {
fromJSON: (
permissions: NonNullable<
Types.Json.AccountUpdate['body']['update']['permissions']
>
): Permissions => {
return Object.fromEntries(
Object.entries(permissions).map(([k, v]) => [
k,
Expand Down
23 changes: 4 additions & 19 deletions src/lib/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import 'isomorphic-fetch';
import { Bool, Field, Ledger } from '../snarky.js';
import { UInt32, UInt64 } from './int.js';
import {
TokenId,
Permission,
Permissions,
ZkappStateLength,
} from './account_update.js';
import { TokenId, Permissions, ZkappStateLength } from './account_update.js';
import { PublicKey } from './signature.js';
import { NetworkValue } from './precondition.js';
import { Types } from '../snarky/types.js';
Expand Down Expand Up @@ -127,19 +122,9 @@ type FetchedAccount = {
zkappState: string[] | null;
receiptChainHash?: string;
balance: { total: string };
permissions?: {
editState: AuthRequired;
send: AuthRequired;
receive: AuthRequired;
setDelegate: AuthRequired;
setPermissions: AuthRequired;
setVerificationKey: AuthRequired;
setZkappUri: AuthRequired;
editSequenceState: AuthRequired;
setTokenSymbol: AuthRequired;
incrementNonce: AuthRequired;
setVotingFor: AuthRequired;
};
permissions?: NonNullable<
Types.Json.AccountUpdate['body']['update']['permissions']
>;
delegateAccount?: { publicKey: string };
sequenceEvents?: string[] | null;
verificationKey?: { verificationKey: string };
Expand Down
15 changes: 15 additions & 0 deletions src/lib/token.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class TokenContract extends SmartContract {
this.setPermissions({
...Permissions.default(),
editState: Permissions.proofOrSignature(),
access: Permissions.proofOrSignature(),
});
}

Expand Down Expand Up @@ -192,6 +193,20 @@ describe('Token', () => {
expect(e).toBeDefined();
});
});

it('should reject tx if user bypasses the token contract by using an empty account update', async () => {
let tx = await Mina.transaction(feePayer, () => {
// pay fees for creating user's token X account
AccountUpdate.fundNewAccount(feePayer);
// 😈😈😈 mint tokens without authorization 😈😈😈
zkapp.experimental.token.mint({
address: tokenAccount1,
amount: UInt64.from(100_000),
});
AccountUpdate.attachToTransaction(zkapp.self);
});
await expect(tx.send()).rejects.toThrow(/Update_not_permitted_access/);
});
});

describe('Burn token', () => {
Expand Down
19 changes: 6 additions & 13 deletions src/snarky.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { Types } from './index.js';

export {
Field,
Bool,
Expand Down Expand Up @@ -743,6 +745,7 @@ type UInt64_ = { value: Field };
type PublicKey_ = { x: Field; isOdd: Bool };

// this closely corresponds to Mina_base.Account.t
// TODO: auto-generate from the OCaml type
interface Account {
publicKey: PublicKey_;
balance: UInt64_;
Expand All @@ -760,19 +763,9 @@ interface Account {
lastSequenceSlot: number;
provedState: boolean;
};
permissions: {
editState: AuthRequired;
send: AuthRequired;
receive: AuthRequired;
setDelegate: AuthRequired;
setPermissions: AuthRequired;
setVerificationKey: AuthRequired;
setZkappUri: AuthRequired;
editSequenceState: AuthRequired;
setTokenSymbol: AuthRequired;
incrementNonce: AuthRequired;
setVotingFor: AuthRequired;
};
permissions: NonNullable<
Types.Json.AccountUpdate['body']['update']['permissions']
>;
}

// TODO would be nice to document these, at least the parts that end up being used in the public API
Expand Down
6 changes: 6 additions & 0 deletions src/snarky/gen/js-layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ let jsLayout = {
docs: null,
keys: [
'editState',
'access',
'send',
'receive',
'setDelegate',
Expand All @@ -136,6 +137,7 @@ let jsLayout = {
],
entries: {
editState: { type: 'AuthRequired' },
access: { type: 'AuthRequired' },
send: { type: 'AuthRequired' },
receive: { type: 'AuthRequired' },
setDelegate: { type: 'AuthRequired' },
Expand All @@ -149,6 +151,7 @@ let jsLayout = {
},
docEntries: {
editState: null,
access: null,
send: null,
receive: null,
setDelegate: null,
Expand Down Expand Up @@ -822,6 +825,7 @@ let jsLayout = {
docs: null,
keys: [
'editState',
'access',
'send',
'receive',
'setDelegate',
Expand All @@ -835,6 +839,7 @@ let jsLayout = {
],
entries: {
editState: { type: 'AuthRequired' },
access: { type: 'AuthRequired' },
send: { type: 'AuthRequired' },
receive: { type: 'AuthRequired' },
setDelegate: { type: 'AuthRequired' },
Expand All @@ -848,6 +853,7 @@ let jsLayout = {
},
docEntries: {
editState: null,
access: null,
send: null,
receive: null,
setDelegate: null,
Expand Down
2 changes: 2 additions & 0 deletions src/snarky/gen/transaction-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type ZkappCommand = {
} | null;
permissions: {
editState: AuthRequired;
access: AuthRequired;
send: AuthRequired;
receive: AuthRequired;
setDelegate: AuthRequired;
Expand Down Expand Up @@ -171,6 +172,7 @@ type AccountUpdate = {
} | null;
permissions: {
editState: AuthRequired;
access: AuthRequired;
send: AuthRequired;
receive: AuthRequired;
setDelegate: AuthRequired;
Expand Down
2 changes: 2 additions & 0 deletions src/snarky/gen/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ type ZkappCommand = {
isSome: Bool;
value: {
editState: AuthRequired;
access: AuthRequired;
send: AuthRequired;
receive: AuthRequired;
setDelegate: AuthRequired;
Expand Down Expand Up @@ -280,6 +281,7 @@ type AccountUpdate = {
isSome: Bool;
value: {
editState: AuthRequired;
access: AuthRequired;
send: AuthRequired;
receive: AuthRequired;
setDelegate: AuthRequired;
Expand Down