Skip to content

Commit

Permalink
Rename authorize to approve (#534)
Browse files Browse the repository at this point in the history
* Rename 'authorize' to 'approve'

We rename 'authorize' to approve in the aims to take advantage of the
concept of 'approve' in Ethereum. We hope that developers will
intuitively understand what it means to 'approve' a AccountUpdate given
that a smart contract in Ethereum must get approval to spend tokens.

* Changelog

* Update tokens test
  • Loading branch information
MartinMinkov committed Nov 9, 2022
1 parent 027514c commit e151439
Show file tree
Hide file tree
Showing 12 changed files with 71 additions and 71 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added `VerificationKey`, which is a `Struct` with auxiliary data, to pass verification keys to a `@method`
- BREAKING CHANGE: Change names related to circuit types: `AsFieldsAndAux<T>` -> `Provable<T>`, `AsFieldElement<T>` -> `ProvablePure<T>`, `circuitValue` -> `provable`
- BREAKING CHANGE: Change all `ofFields` and `ofBits` methods on circuit types to `fromFields` and `fromBits`
- `SmartContract.experimental.authorize()` to authorize a tree of child account updates https://github.com/o1-labs/snarkyjs/pull/428
- AccountUpdates are now valid `@method` arguments, and `authorize()` is intended to be used on them when passed to a method
- `SmartContract.experimental.approve()` to approve a tree of child account updates https://github.com/o1-labs/snarkyjs/pull/428
- AccountUpdates are now valid `@method` arguments, and `approve()` is intended to be used on them when passed to a method
- Also replaces `Experimental.accountUpdateFromCallback()`
- `Circuit.log()` to easily log Fields and other provable types inside a method, with the same API as `console.log()`
- `AccountUpdate.attachToTransaction()` for explicitly adding an account update to the current transaction. This replaces some previous behaviour where an account update got attached implicitly.
Expand Down
26 changes: 13 additions & 13 deletions src/examples/zkapps/dex/dex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,12 @@ function createDex({
* The transaction needs to be signed by the user's private key.
*/
@method redeemLiquidity(user: PublicKey, dl: UInt64) {
// call the token X holder inside a token X-authorized callback
// call the token X holder inside a token X-approved callback
let tokenX = new TokenContract(this.tokenX);
let dexX = new DexTokenHolder(this.address, tokenX.experimental.token.id);
let dxdy = dexX.redeemLiquidity(user, dl, this.tokenY);
let dx = dxdy[0];
tokenX.authorizeUpdateAndSend(dexX.self, user, dx);
tokenX.approveUpdateAndSend(dexX.self, user, dx);
return dxdy;
}

Expand All @@ -171,7 +171,7 @@ function createDex({
let tokenY = new TokenContract(this.tokenY);
let dexY = new DexTokenHolder(this.address, tokenY.experimental.token.id);
let dy = dexY.swap(user, dx, this.tokenX);
tokenY.authorizeUpdateAndSend(dexY.self, user, dy);
tokenY.approveUpdateAndSend(dexY.self, user, dy);
return dy;
}

Expand All @@ -187,12 +187,12 @@ function createDex({
let tokenX = new TokenContract(this.tokenX);
let dexX = new DexTokenHolder(this.address, tokenX.experimental.token.id);
let dx = dexX.swap(user, dy, this.tokenY);
tokenX.authorizeUpdateAndSend(dexX.self, user, dx);
tokenX.approveUpdateAndSend(dexX.self, user, dx);
return dx;
}

/**
* helper method to authorize burning of user's liquidity.
* helper method to approve burning of user's liquidity.
* this just burns user tokens, so there is no incentive to call this directly.
* instead, the dex token holders call this and in turn pay back tokens.
*
Expand Down Expand Up @@ -222,7 +222,7 @@ function createDex({
// see the more complicated method `redeemLiquidity` below which gives back both tokens, by calling this method,
// for the other token, in a callback
@method redeemLiquidityPartial(user: PublicKey, dl: UInt64): UInt64x2 {
// user burns dl, authorized by the Dex main contract
// user burns dl, approved by the Dex main contract
let dex = new Dex(addresses.dex);
let l = dex.burnLiquidity(user, dl);

Expand All @@ -234,7 +234,7 @@ function createDex({
// just subtract the balance, user gets their part one level higher
this.balance.subInPlace(dy);

// this can't be a delegate call, or it won't be authorized by the token owner
// this can't be a delegate call, or it won't be approved by the token owner
this.self.isDelegateCall = Bool(false);

// return l, dy so callers don't have to walk their child account updates to get it
Expand All @@ -247,13 +247,13 @@ function createDex({
dl: UInt64,
otherTokenAddress: PublicKey
): UInt64x2 {
// first call the Y token holder, authorized by the Y token contract; this makes sure we get dl, the user's lqXY
// first call the Y token holder, approved by the Y token contract; this makes sure we get dl, the user's lqXY
let tokenY = new TokenContract(otherTokenAddress);
let dexY = new DexTokenHolder(this.address, tokenY.experimental.token.id);
let result = dexY.redeemLiquidityPartial(user, dl);
let l = result[0];
let dy = result[1];
tokenY.authorizeUpdateAndSend(dexY.self, user, dy);
tokenY.approveUpdateAndSend(dexY.self, user, dy);

// in return for dl, we give back dx, the X token part
let x = this.account.balance.get();
Expand All @@ -262,7 +262,7 @@ function createDex({
// just subtract the balance, user gets their part one level higher
this.balance.subInPlace(dx);

// this can't be a delegate call, or it won't be authorized by the token owner
// this can't be a delegate call, or it won't be approved by the token owner
this.self.isDelegateCall = Bool(false);

return [dx, dy];
Expand Down Expand Up @@ -396,7 +396,7 @@ class TokenContract extends SmartContract {
@method deployZkapp(address: PublicKey, verificationKey: VerificationKey) {
let tokenId = this.experimental.token.id;
let zkapp = AccountUpdate.defaultAccountUpdate(address, tokenId);
this.experimental.authorize(zkapp);
this.experimental.approve(zkapp);
AccountUpdate.setValue(zkapp.update.permissions, {
...Permissions.default(),
send: Permissions.proof(),
Expand All @@ -406,12 +406,12 @@ class TokenContract extends SmartContract {
}

// let a zkapp send tokens to someone, provided the token supply stays constant
@method authorizeUpdateAndSend(
@method approveUpdateAndSend(
zkappUpdate: AccountUpdate,
to: PublicKey,
amount: UInt64
) {
this.experimental.authorize(zkappUpdate);
this.experimental.approve(zkappUpdate);

// see if balance change cancels the amount sent
let balanceChange = Int64.fromObject(zkappUpdate.body.balanceChange);
Expand Down
10 changes: 5 additions & 5 deletions src/examples/zkapps/dex/erc20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,12 @@ class TrivialCoin extends SmartContract implements Erc20 {
from: PublicKey,
to: PublicKey,
value: UInt64,
authorize: Experimental.Callback<any>
approve: Experimental.Callback<any>
): Bool {
// TODO: need to be able to witness a certain layout of account updates, in this case
// tokenContract --> sender --> receiver
let fromUpdate = this.experimental.authorize(
authorize,
let fromUpdate = this.experimental.approve(
approve,
AccountUpdate.Layout.NoChildren
);

Expand Down Expand Up @@ -215,8 +215,8 @@ class TrivialCoin extends SmartContract implements Erc20 {
// for letting a zkapp do whatever it wants, as long as no tokens are transfered
// TODO: atm, we have to restrict the zkapp to have no children
// -> need to be able to witness a general layout of account updates
@method authorizeZkapp(callback: Experimental.Callback<any>) {
let zkappUpdate = this.experimental.authorize(
@method approveZkapp(callback: Experimental.Callback<any>) {
let zkappUpdate = this.experimental.approve(
callback,
AccountUpdate.Layout.NoChildren
);
Expand Down
4 changes: 2 additions & 2 deletions src/examples/zkapps/dex/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,9 +296,9 @@ async function main({ withVesting }: { withVesting: boolean }) {
send: Permissions.impossible(),
});
tokenXtokenAccount.sign();
// token X owner authorizes w/ signature so we don't need another method for this test
// token X owner approves w/ signature so we don't need another method for this test
let tokenX = AccountUpdate.create(addresses.tokenX);
tokenX.authorize(tokenXtokenAccount);
tokenX.approve(tokenXtokenAccount);
tokenX.sign();
});
await tx.prove();
Expand Down
26 changes: 13 additions & 13 deletions src/examples/zkapps/token_with_proofs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class TokenContract extends SmartContract {
receiverAddress: PublicKey,
callback: Experimental.Callback<any>
) {
let senderAccountUpdate = this.experimental.authorize(
let senderAccountUpdate = this.experimental.approve(
callback,
AccountUpdate.Layout.AnyChildren
);
Expand All @@ -84,14 +84,14 @@ class TokenContract extends SmartContract {
}

class ZkAppB extends SmartContract {
@method authorizeSend() {
@method approveSend() {
let amount = UInt64.from(1_000);
this.balance.subInPlace(amount);
}
}

class ZkAppC extends SmartContract {
@method authorizeSend() {
@method approveSend() {
let amount = UInt64.from(1_000);
this.balance.subInPlace(amount);
}
Expand Down Expand Up @@ -168,17 +168,17 @@ tx = await Local.transaction(feePayer, () => {
await tx.prove();
await tx.send();

console.log('authorize send from zkAppB');
console.log('approve send from zkAppB');
tx = await Local.transaction(feePayer, () => {
let authorizeSendingCallback = Experimental.Callback.create(
let approveSendingCallback = Experimental.Callback.create(
zkAppB,
'authorizeSend',
'approveSend',
[]
);
// we call the token contract with the callback
tokenZkApp.sendTokens(zkAppBAddress, zkAppCAddress, authorizeSendingCallback);
tokenZkApp.sendTokens(zkAppBAddress, zkAppCAddress, approveSendingCallback);
});
console.log('authorize send (proof)');
console.log('approve send (proof)');
await tx.prove();
console.log('send (proof)');
await tx.send();
Expand All @@ -188,19 +188,19 @@ console.log(
Mina.getBalance(zkAppCAddress, tokenId).value.toBigInt()
);

console.log('authorize send from zkAppC');
console.log('approve send from zkAppC');
tx = await Local.transaction(feePayer, () => {
// Pay for tokenAccount1's account creation
AccountUpdate.fundNewAccount(feePayer);
let authorizeSendingCallback = Experimental.Callback.create(
let approveSendingCallback = Experimental.Callback.create(
zkAppC,
'authorizeSend',
'approveSend',
[]
);
// we call the token contract with the callback
tokenZkApp.sendTokens(zkAppCAddress, tokenAccount1, authorizeSendingCallback);
tokenZkApp.sendTokens(zkAppCAddress, tokenAccount1, approveSendingCallback);
});
console.log('authorize send (proof)');
console.log('approve send (proof)');
await tx.prove();
console.log('send (proof)');
await tx.send();
Expand Down
4 changes: 2 additions & 2 deletions src/examples/zkapps/voting/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,14 +260,14 @@ try {
);

/*
if we now call authorizeVoters, which invokes publish on both membership contracts,
if we now call approveVoters, which invokes publish on both membership contracts,
we will also update the committed members!
and since we keep track of voters and candidates in our off-chain storage,
both the on-chain committedMembers variable and the off-chain merkle tree root need to be equal
*/

tx = await Mina.transaction(feePayer, () => {
contracts.voting.authorizeRegistrations();
contracts.voting.approveRegistrations();
if (!params.doProofs) contracts.voting.sign(votingKey);
});

Expand Down
8 changes: 4 additions & 4 deletions src/examples/zkapps/voting/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ export async function testSet(

try {
let tx = await Mina.transaction(sequenceOverflowSet.feePayer, () => {
sequenceOverflowSet.voting.authorizeRegistrations();
sequenceOverflowSet.voting.approveRegistrations();
});
await tx.prove();
await tx.send();
Expand Down Expand Up @@ -568,7 +568,7 @@ export async function testSet(

/*
test case description:
authorize registrations, invoked publish on both membership SCs
approve registrations, invoked publish on both membership SCs
preconditions:
- votes and candidates were registered previously
Expand All @@ -588,12 +588,12 @@ export async function testSet(
true,
() => {
// register new candidate
voting.authorizeRegistrations();
voting.approveRegistrations();
},
feePayer
);

// authorizeVoters updates the committed members on both contracts by invoking the publish method.
// approve updates the committed members on both contracts by invoking the publish method.
// We check if offchain storage merkle roots match both on-chain committedMembers for voters and candidates

if (!voting.committedVotes.get().equals(initialRoot).toBoolean()) {
Expand Down
2 changes: 1 addition & 1 deletion src/examples/zkapps/voting/voting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ export class Voting_ extends SmartContract {
* Calls the `publish()` method of the Candidate-Membership and Voter-Membership contract.
*/
@method
authorizeRegistrations() {
approveRegistrations() {
// Invokes the publish method of both Voter and Candidate Membership contracts.
let VoterContract: Membership_ = new Membership_(voterAddress);
VoterContract.publish();
Expand Down
14 changes: 7 additions & 7 deletions src/lib/account_update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,7 @@ class AccountUpdate implements Types.AccountUpdate {
amount: number | bigint | UInt64;
}) {
let receiver = AccountUpdate.defaultAccountUpdate(address, this.id);
thisAccountUpdate.authorize(receiver);
thisAccountUpdate.approve(receiver);
// Add the amount to mint to the receiver's account
receiver.body.balanceChange = Int64.fromObject(
receiver.body.balanceChange
Expand All @@ -725,7 +725,7 @@ class AccountUpdate implements Types.AccountUpdate {
amount: number | bigint | UInt64;
}) {
let sender = AccountUpdate.defaultAccountUpdate(address, this.id);
thisAccountUpdate.authorize(sender);
thisAccountUpdate.approve(sender);
sender.body.useFullCommitment = Bool(true);

// Sub the amount to burn from the sender's account
Expand All @@ -748,7 +748,7 @@ class AccountUpdate implements Types.AccountUpdate {
}) {
// Create a new accountUpdate for the sender to send the amount to the receiver
let sender = AccountUpdate.defaultAccountUpdate(from, this.id);
thisAccountUpdate.authorize(sender);
thisAccountUpdate.approve(sender);
sender.body.useFullCommitment = Bool(true);
sender.body.balanceChange = Int64.fromObject(
sender.body.balanceChange
Expand Down Expand Up @@ -805,7 +805,7 @@ class AccountUpdate implements Types.AccountUpdate {
} else {
receiver = AccountUpdate.defaultAccountUpdate(to, this.body.tokenId);
}
this.authorize(receiver);
this.approve(receiver);

// Sub the amount from the sender's account
this.body.balanceChange = Int64.fromObject(this.body.balanceChange).sub(
Expand All @@ -818,7 +818,7 @@ class AccountUpdate implements Types.AccountUpdate {
).add(amount);
}

authorize(
approve(
childUpdate: AccountUpdate,
layout: AccountUpdatesLayout = AccountUpdate.Layout.NoDelegation
) {
Expand Down Expand Up @@ -1021,15 +1021,15 @@ class AccountUpdate implements Types.AccountUpdate {
static create(publicKey: PublicKey, tokenId?: Field) {
let accountUpdate = AccountUpdate.defaultAccountUpdate(publicKey, tokenId);
if (smartContractContext.has()) {
smartContractContext.get().this.self.authorize(accountUpdate);
smartContractContext.get().this.self.approve(accountUpdate);
} else {
Mina.currentTransaction()?.accountUpdates.push(accountUpdate);
}
return accountUpdate;
}
static attachToTransaction(accountUpdate: AccountUpdate) {
if (smartContractContext.has()) {
smartContractContext.get().this.self.authorize(accountUpdate);
smartContractContext.get().this.self.approve(accountUpdate);
} else {
if (!Mina.currentTransaction.has()) return;
let updates = Mina.currentTransaction.get().accountUpdates;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/mina.ts
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,7 @@ async function verifyAccountUpdate(
checkPermission(p, 'incrementNonce');
}

// this checks for an edge case where an account update can be authorized using proofs but
// this checks for an edge case where an account update can be approved using proofs but
// a) the proof is invalid (bad verification key)
// and b) there are no state changes initiate so no permissions will be checked
// however, if the verification key changes, the proof should still be invalid
Expand Down
Loading

0 comments on commit e151439

Please sign in to comment.