From 034a5a454164595030921895aa3d6d1a808695aa Mon Sep 17 00:00:00 2001 From: Martin Minkov Date: Wed, 3 Aug 2022 12:44:58 -0700 Subject: [PATCH 1/5] Add send method to Party and zkApp --- src/lib/party.ts | 16 ++++++++++++++++ src/lib/zkapp.ts | 5 +++++ 2 files changed, 21 insertions(+) diff --git a/src/lib/party.ts b/src/lib/party.ts index 551d796165..07d62f78dc 100644 --- a/src/lib/party.ts +++ b/src/lib/party.ts @@ -50,6 +50,7 @@ export { Token, CallForest, createChildParty, + SendParams, }; const ZkappStateLength = 8; @@ -670,6 +671,21 @@ class Party implements Types.Party { }; } + send({ to, amount }: Omit) { + let party = this; + let receiverParty = Party.createUnsigned(to); + + // Sub the amount from the sender's account + let i0 = party.body.balanceChange; + party.body.balanceChange = new Int64(i0.magnitude, i0.sgn).sub(amount); + + // Add the amount to send to the receiver's account + let i1 = receiverParty.body.balanceChange; + receiverParty.body.balanceChange = new Int64(i1.magnitude, i1.sgn).add( + amount + ); + } + get balance() { let party = this; diff --git a/src/lib/zkapp.ts b/src/lib/zkapp.ts index 4d2cd461f3..75b1612142 100644 --- a/src/lib/zkapp.ts +++ b/src/lib/zkapp.ts @@ -29,6 +29,7 @@ import { Authorization, CallForest, getDefaultTokenId, + SendParams, } from './party'; import { PrivateKey, PublicKey } from './signature'; import * as Mina from './mina'; @@ -562,6 +563,10 @@ class SmartContract { return this.self.token(); } + send(args: Omit) { + return this.self.send(args); + } + get tokenId() { return this.self.tokenId; } From 7e44c0144cdefe434ae4061b74279a0f1e9a633b Mon Sep 17 00:00:00 2001 From: Martin Minkov Date: Wed, 3 Aug 2022 12:46:21 -0700 Subject: [PATCH 2/5] Fix tokens test --- src/lib/token.test.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lib/token.test.ts b/src/lib/token.test.ts index 05e5bb695a..e0da3e3a07 100644 --- a/src/lib/token.test.ts +++ b/src/lib/token.test.ts @@ -65,7 +65,7 @@ class TokenContract extends SmartContract { }); } - @method send( + @method sendTokens( senderAddress: PublicKey, receiverAddress: PublicKey, amount: UInt64 @@ -253,7 +253,7 @@ describe('Token', () => { ( await Mina.transaction(feePayer, () => { Party.fundNewAccount(feePayer); - zkapp.send(tokenAccount1, tokenAccount2, UInt64.from(10_000)); + zkapp.sendTokens(tokenAccount1, tokenAccount2, UInt64.from(10_000)); zkapp.sign(zkappKey); }) ) @@ -279,7 +279,7 @@ describe('Token', () => { let tx = ( await Mina.transaction(feePayer, () => { - zkapp.send(tokenAccount1, tokenAccount2, UInt64.from(10_000)); + zkapp.sendTokens(tokenAccount1, tokenAccount2, UInt64.from(10_000)); zkapp.sign(zkappKey); }) ).sign([tokenAccount1Key]); @@ -300,7 +300,11 @@ describe('Token', () => { let tx = ( await Mina.transaction(feePayer, () => { - zkapp.send(tokenAccount1, tokenAccount2, UInt64.from(100_000_000)); + zkapp.sendTokens( + tokenAccount1, + tokenAccount2, + UInt64.from(100_000_000) + ); zkapp.sign(zkappKey); }) ).sign([tokenAccount1Key]); From 6eb3b7332680f14297ac65f667ba400707689207 Mon Sep 17 00:00:00 2001 From: Martin Minkov Date: Wed, 3 Aug 2022 12:53:23 -0700 Subject: [PATCH 3/5] Add example script --- src/examples/simple-zkapp-payment.ts | 131 +++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/examples/simple-zkapp-payment.ts diff --git a/src/examples/simple-zkapp-payment.ts b/src/examples/simple-zkapp-payment.ts new file mode 100644 index 0000000000..34b90207ce --- /dev/null +++ b/src/examples/simple-zkapp-payment.ts @@ -0,0 +1,131 @@ +import { + isReady, + method, + Mina, + Party, + PrivateKey, + SmartContract, + PublicKey, + UInt64, + shutdown, + DeployArgs, + Permissions, +} from 'snarkyjs'; + +await isReady; + +class SendMINAExample extends SmartContract { + deploy(args: DeployArgs) { + super.deploy(args); + this.setPermissions({ + ...Permissions.default(), + editState: Permissions.proofOrSignature(), + editSequenceState: Permissions.proofOrSignature(), + }); + this.balance.addInPlace(UInt64.fromNumber(initialBalance)); + } + + @method sendMINA(receiverAddress: PublicKey, amount: UInt64) { + this.send({ + to: receiverAddress, + amount, + }); + } +} + +let Local = Mina.LocalBlockchain(); +Mina.setActiveInstance(Local); + +// a test account that pays all the fees, and puts additional funds into the zkapp +let feePayer = Local.testAccounts[0].privateKey; + +// the zkapp account +let zkappKey = PrivateKey.random(); +let zkappAddress = zkappKey.toPublicKey(); + +let account1Key = PrivateKey.random(); +let account1Address = account1Key.toPublicKey(); + +let account2Key = PrivateKey.random(); +let account2Address = account2Key.toPublicKey(); + +let zkapp = new SendMINAExample(zkappAddress); +let initialBalance = 10_000_000_000; +let tx; + +console.log('deploy'); +tx = await Mina.transaction(feePayer, () => { + Party.fundNewAccount(feePayer, { initialBalance }); + zkapp.deploy({ zkappKey }); +}); +tx.send(); + +console.log(`zkApp balance: ${Mina.getBalance(zkappAddress)} MINA`); + +console.log('----------MINA sending----------'); +tx = await Local.transaction(feePayer, () => { + Party.fundNewAccount(feePayer); + zkapp.sendMINA(account1Address, UInt64.from(1_000_000)); + zkapp.sign(zkappKey); +}); +tx.send(); + +console.log(`zkApp balance: ${Mina.getBalance(zkappAddress)} MINA`); +console.log( + `account1Address balance: ${Mina.getBalance(account1Address)} MINA` +); + +console.log('----------MINA sending (with signed)----------'); +tx = await Local.transaction(feePayer, () => { + Party.fundNewAccount(feePayer); + let party = Party.createSigned(zkappKey); + party.send({ to: account2Address, amount: UInt64.from(1_000_000) }); + zkapp.sign(zkappKey); + zkapp.account.nonce.assertEquals(zkapp.account.nonce.get().add(1)); +}); +tx.send(); + +console.log(`zkApp balance: ${Mina.getBalance(zkappAddress)} MINA`); +console.log( + `account1Address balance: ${Mina.getBalance(account1Address)} MINA` +); +console.log( + `account2Address balance: ${Mina.getBalance(account2Address)} MINA` +); + +console.log('----------MINA sending (with unsigned)----------'); +tx = await Local.transaction(feePayer, () => { + let party = Party.createUnsigned(zkappAddress); + party.signInPlace(zkappKey); + party.send({ to: account2Address, amount: UInt64.from(1_000_000) }); + zkapp.sign(zkappKey); + zkapp.account.nonce.assertEquals(zkapp.account.nonce.get().add(1)); +}); +tx.send(); + +console.log(`zkApp balance: ${Mina.getBalance(zkappAddress)} MINA`); +console.log( + `account1Address balance: ${Mina.getBalance(account1Address)} MINA` +); +console.log( + `account2Address balance: ${Mina.getBalance(account2Address)} MINA` +); + +console.log('----------MINA sending (with proof)----------'); +tx = await Local.transaction(feePayer, () => { + let party = Party.createSigned(zkappKey); + party.send({ to: account2Address, amount: UInt64.from(1_000_000) }); + zkapp.account.nonce.assertEquals(zkapp.account.nonce.get().add(1)); +}); +await tx.prove(); +tx.send(); + +console.log(`zkApp balance: ${Mina.getBalance(zkappAddress)} MINA`); +console.log( + `account1Address balance: ${Mina.getBalance(account1Address)} MINA` +); +console.log( + `account2Address balance: ${Mina.getBalance(account2Address)} MINA` +); + +shutdown(); From ee23a8742391c61b98237a1a24ef49d04ca5c873 Mon Sep 17 00:00:00 2001 From: Martin Minkov Date: Wed, 3 Aug 2022 16:01:05 -0700 Subject: [PATCH 4/5] Make receiverParty a child of zkApp --- src/lib/party.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib/party.ts b/src/lib/party.ts index 07d62f78dc..60b637dcfe 100644 --- a/src/lib/party.ts +++ b/src/lib/party.ts @@ -673,7 +673,10 @@ class Party implements Types.Party { send({ to, amount }: Omit) { let party = this; - let receiverParty = Party.createUnsigned(to); + let receiverParty = createChildParty(party, to, { + tokenId: party.body.tokenId, + caller: party.body.tokenId, + }); // Sub the amount from the sender's account let i0 = party.body.balanceChange; From 2fce81bd05931ef57008649ff506ef35e412e542 Mon Sep 17 00:00:00 2001 From: Martin Minkov Date: Thu, 4 Aug 2022 09:38:36 -0700 Subject: [PATCH 5/5] Move payment script under examples/zkApps dir --- .../{simple-zkapp-payment.ts => zkapps/simple_zkapp_payment.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/examples/{simple-zkapp-payment.ts => zkapps/simple_zkapp_payment.ts} (100%) diff --git a/src/examples/simple-zkapp-payment.ts b/src/examples/zkapps/simple_zkapp_payment.ts similarity index 100% rename from src/examples/simple-zkapp-payment.ts rename to src/examples/zkapps/simple_zkapp_payment.ts