@@ -29,6 +29,24 @@ export {
2929 CallForest ,
3030} ;
3131
32+ /**
33+ * Signs a zkApp command JSON object with the provided private key.
34+ *
35+ * This function applies a Schnorr signature to the fee payer and any account
36+ * updates within the command that require signatures and are owned by the same
37+ * public key.
38+ *
39+ * If this method is not called as the fee payer (i.e. the private key provided
40+ * does not match the fee payer's public key), the fee payer authorization will
41+ * remain unsigned after this method returns. This behavior allows for collaborative
42+ * construction of zkApp commands where two different users sign the account update
43+ * and pay the fee.
44+ *
45+ * @param zkappCommand_ - The zkApp command in JSON format, before signatures.
46+ * @param privateKeyBase58 - The Base58-encoded private key used for signing.
47+ * @param networkId - The network identifier that determines the signature domain.
48+ * @returns The signed zkApp command in JSON format.
49+ */
3250function signZkappCommand (
3351 zkappCommand_ : Json . ZkappCommand ,
3452 privateKeyBase58 : string ,
@@ -38,11 +56,14 @@ function signZkappCommand(
3856
3957 let { commitment, fullCommitment } = transactionCommitments ( zkappCommand , networkId ) ;
4058 let privateKey = PrivateKey . fromBase58 ( privateKeyBase58 ) ;
41- let publicKey = zkappCommand . feePayer . body . publicKey ;
59+ let publicKey = PrivateKey . toPublicKey ( privateKey ) ;
4260
43- // sign fee payer
4461 let signature = signFieldElement ( fullCommitment , privateKey , networkId ) ;
45- zkappCommand . feePayer . authorization = Signature . toBase58 ( signature ) ;
62+
63+ // sign fee payer whenever the public key matches
64+ if ( PublicKey . equal ( zkappCommand . feePayer . body . publicKey , publicKey ) ) {
65+ zkappCommand . feePayer . authorization = Signature . toBase58 ( signature ) ;
66+ }
4667
4768 // sign other updates with the same public key that require a signature
4869 for ( let update of zkappCommand . accountUpdates ) {
@@ -56,19 +77,39 @@ function signZkappCommand(
5677 return ZkappCommand . toJSON ( zkappCommand ) ;
5778}
5879
80+ /**
81+ * Verifies the signature of a zkApp command JSON object.
82+ *
83+ * This function verifies the signatures of the fee payer and any account
84+ * updates within the command that require signatures and are owned by the
85+ * same public key.
86+ *
87+ * @param zkappCommand_ - The zkApp command in JSON format, after signatures.
88+ * @param publicKeyBase58 - The Base58-encoded public key used for verification.
89+ * @param networkId - The network identifier that determines the signature domain.
90+ * @param feePayerPublicKeyBase58 - Optional Base58-encoded public key of the fee
91+ * payer, required if the provided public key does not
92+ * match the fee payer's public key.
93+ * @returns True if the signature is valid, false otherwise.
94+ *
95+ * @warning To verify the zkApp command signature, the public key must match the
96+ * fee payer's public key, or the parameter `feePayerPublicKey` must be provided.
97+ */
5998function verifyZkappCommandSignature (
6099 zkappCommand_ : Json . ZkappCommand ,
61100 publicKeyBase58 : string ,
62- networkId : NetworkId
101+ networkId : NetworkId ,
102+ feePayerPublicKeyBase58 ?: string
63103) {
64104 let zkappCommand = ZkappCommand . fromJSON ( zkappCommand_ ) ;
65105
66106 let { commitment, fullCommitment } = transactionCommitments ( zkappCommand , networkId ) ;
67107 let publicKey = PublicKey . fromBase58 ( publicKeyBase58 ) ;
68108
69- // verify fee payer signature
109+ // verify fee payer signature when public keys match
110+ let feePayerPublicKey = feePayerPublicKeyBase58 ? PublicKey . fromBase58 ( feePayerPublicKeyBase58 ) : publicKey ;
70111 let signature = Signature . fromBase58 ( zkappCommand . feePayer . authorization ) ;
71- let ok = verifyFieldElement ( signature , fullCommitment , publicKey , networkId ) ;
112+ let ok = verifyFieldElement ( signature , fullCommitment , feePayerPublicKey , networkId ) && PublicKey . equal ( zkappCommand . feePayer . body . publicKey , feePayerPublicKey ) ;
72113 if ( ! ok ) return false ;
73114
74115 // verify other signatures for the same public key
0 commit comments