@@ -7,14 +7,18 @@ import { ed25519GenListOfRandom } from "../utils";
77import { EncryptedAmount } from "./encryptedAmount" ;
88import { AVAILABLE_BALANCE_CHUNK_COUNT , CHUNK_BITS } from "./chunkedAmount" ;
99import { Aptos , SimpleTransaction , AccountAddressInput , InputGenerateTransactionOptions } from "@aptos-labs/ts-sdk" ;
10-
11- /** Stub type — sigma proof is not yet implemented. */
12- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
13- export type ConfidentialNormalizationSigmaProof = { } ;
10+ import type { SigmaProtocolProof } from "./sigmaProtocol" ;
11+ import { proveNormalization } from "./sigmaProtocolWithdraw" ;
1412
1513export type CreateConfidentialNormalizationOpArgs = {
1614 decryptionKey : TwistedEd25519PrivateKey ;
1715 unnormalizedAvailableBalance : EncryptedAmount ;
16+ /** 32-byte sender address */
17+ senderAddress : Uint8Array ;
18+ /** 32-byte token address */
19+ tokenAddress : Uint8Array ;
20+ /** Optional auditor encryption key */
21+ auditorEncryptionKey ?: TwistedEd25519PublicKey ;
1822 randomness ?: bigint [ ] ;
1923} ;
2024
@@ -25,16 +29,33 @@ export class ConfidentialNormalization {
2529
2630 normalizedEncryptedAvailableBalance : EncryptedAmount ;
2731
32+ /** Optional: normalized balance encrypted under auditor key */
33+ auditorEncryptedNormalizedBalance ?: EncryptedAmount ;
34+
2835 randomness : bigint [ ] ;
2936
37+ senderAddress : Uint8Array ;
38+
39+ tokenAddress : Uint8Array ;
40+
41+ auditorEncryptionKey ?: TwistedEd25519PublicKey ;
42+
3043 constructor ( args : {
3144 decryptionKey : TwistedEd25519PrivateKey ;
3245 unnormalizedEncryptedAvailableBalance : EncryptedAmount ;
3346 normalizedEncryptedAvailableBalance : EncryptedAmount ;
47+ auditorEncryptedNormalizedBalance ?: EncryptedAmount ;
48+ senderAddress : Uint8Array ;
49+ tokenAddress : Uint8Array ;
50+ auditorEncryptionKey ?: TwistedEd25519PublicKey ;
3451 } ) {
3552 this . decryptionKey = args . decryptionKey ;
3653 this . unnormalizedEncryptedAvailableBalance = args . unnormalizedEncryptedAvailableBalance ;
3754 this . normalizedEncryptedAvailableBalance = args . normalizedEncryptedAvailableBalance ;
55+ this . auditorEncryptedNormalizedBalance = args . auditorEncryptedNormalizedBalance ;
56+ this . senderAddress = args . senderAddress ;
57+ this . tokenAddress = args . tokenAddress ;
58+ this . auditorEncryptionKey = args . auditorEncryptionKey ;
3859 const randomness = this . normalizedEncryptedAvailableBalance . getRandomness ( ) ;
3960 if ( ! randomness ) {
4061 throw new Error ( "Randomness is not set" ) ;
@@ -43,7 +64,13 @@ export class ConfidentialNormalization {
4364 }
4465
4566 static async create ( args : CreateConfidentialNormalizationOpArgs ) {
46- const { decryptionKey, randomness = ed25519GenListOfRandom ( AVAILABLE_BALANCE_CHUNK_COUNT ) } = args ;
67+ const {
68+ decryptionKey,
69+ randomness = ed25519GenListOfRandom ( AVAILABLE_BALANCE_CHUNK_COUNT ) ,
70+ senderAddress,
71+ tokenAddress,
72+ auditorEncryptionKey,
73+ } = args ;
4774
4875 const unnormalizedEncryptedAvailableBalance = args . unnormalizedAvailableBalance ;
4976
@@ -52,31 +79,62 @@ export class ConfidentialNormalization {
5279 publicKey : decryptionKey . publicKey ( ) ,
5380 randomness,
5481 } ) ;
82+
83+ // If auditor is set, encrypt the normalized balance under the auditor key with the same randomness
84+ let auditorEncryptedNormalizedBalance : EncryptedAmount | undefined ;
85+ if ( auditorEncryptionKey ) {
86+ auditorEncryptedNormalizedBalance = EncryptedAmount . fromAmountAndPublicKey ( {
87+ amount : unnormalizedEncryptedAvailableBalance . getAmount ( ) ,
88+ publicKey : auditorEncryptionKey ,
89+ randomness,
90+ } ) ;
91+ }
92+
5593 return new ConfidentialNormalization ( {
5694 decryptionKey,
5795 unnormalizedEncryptedAvailableBalance,
5896 normalizedEncryptedAvailableBalance,
97+ auditorEncryptedNormalizedBalance,
98+ senderAddress,
99+ tokenAddress,
100+ auditorEncryptionKey,
59101 } ) ;
60102 }
61103
62- /** Returns an empty sigma proof (stub — sigma proof is not yet implemented). */
63- static serializeSigmaProof ( ) : Uint8Array {
64- return new Uint8Array ( 0 ) ;
65- }
66-
67- /** Stub — always returns an empty sigma proof. */
68- async genSigmaProof ( ) : Promise < ConfidentialNormalizationSigmaProof > {
69- return { } as ConfidentialNormalizationSigmaProof ;
70- }
104+ /**
105+ * Generate the sigma protocol proof for normalization.
106+ * Normalization is the same as withdrawal with v = 0.
107+ */
108+ genSigmaProof ( ) : SigmaProtocolProof {
109+ const oldCipherTexts = this . unnormalizedEncryptedAvailableBalance . getCipherText ( ) ;
110+ const newCipherTexts = this . normalizedEncryptedAvailableBalance . getCipherText ( ) ;
111+
112+ const oldBalanceC = oldCipherTexts . map ( ( ct ) => ct . C ) ;
113+ const oldBalanceD = oldCipherTexts . map ( ( ct ) => ct . D ) ;
114+ const newBalanceC = newCipherTexts . map ( ( ct ) => ct . C ) ;
115+ const newBalanceD = newCipherTexts . map ( ( ct ) => ct . D ) ;
116+
117+ let auditorEncryptionKey : TwistedEd25519PublicKey | undefined ;
118+ let newBalanceDAud : import ( "." ) . RistPoint [ ] | undefined ;
119+ if ( this . auditorEncryptionKey && this . auditorEncryptedNormalizedBalance ) {
120+ auditorEncryptionKey = this . auditorEncryptionKey ;
121+ newBalanceDAud = this . auditorEncryptedNormalizedBalance . getCipherText ( ) . map ( ( ct ) => ct . D ) ;
122+ }
71123
72- /** Stub — always returns true. */
73- static verifySigmaProof ( _opts : {
74- publicKey : TwistedEd25519PublicKey ;
75- sigmaProof : ConfidentialNormalizationSigmaProof ;
76- unnormalizedEncryptedBalance : EncryptedAmount ;
77- normalizedEncryptedBalance : EncryptedAmount ;
78- } ) : boolean {
79- return true ;
124+ return proveNormalization ( {
125+ dk : this . decryptionKey ,
126+ senderAddress : this . senderAddress ,
127+ tokenAddress : this . tokenAddress ,
128+ amount : 0n ,
129+ oldBalanceC,
130+ oldBalanceD,
131+ newBalanceC,
132+ newBalanceD,
133+ newAmountChunks : this . normalizedEncryptedAvailableBalance . getAmountChunks ( ) ,
134+ newRandomness : this . randomness ,
135+ auditorEncryptionKey,
136+ newBalanceDAud,
137+ } ) ;
80138 }
81139
82140 async genRangeProof ( ) : Promise < Uint8Array > {
@@ -104,11 +162,21 @@ export class ConfidentialNormalization {
104162 } ) ;
105163 }
106164
107- async authorizeNormalization ( ) : Promise < [ { sigmaProof : Uint8Array ; rangeProof : Uint8Array } , EncryptedAmount ] > {
108- const sigmaProof = ConfidentialNormalization . serializeSigmaProof ( ) ;
165+ async authorizeNormalization ( ) : Promise <
166+ [
167+ { sigmaProof : SigmaProtocolProof ; rangeProof : Uint8Array } ,
168+ EncryptedAmount ,
169+ EncryptedAmount | undefined ,
170+ ]
171+ > {
172+ const sigmaProof = this . genSigmaProof ( ) ;
109173 const rangeProof = await this . genRangeProof ( ) ;
110174
111- return [ { sigmaProof, rangeProof } , this . normalizedEncryptedAvailableBalance ] ;
175+ return [
176+ { sigmaProof, rangeProof } ,
177+ this . normalizedEncryptedAvailableBalance ,
178+ this . auditorEncryptedNormalizedBalance ,
179+ ] ;
112180 }
113181
114182 async createTransaction ( args : {
@@ -119,18 +187,25 @@ export class ConfidentialNormalization {
119187 withFeePayer ?: boolean ;
120188 options ?: InputGenerateTransactionOptions ;
121189 } ) : Promise < SimpleTransaction > {
122- const [ { rangeProof } , normalizedCB ] = await this . authorizeNormalization ( ) ;
190+ const [ { sigmaProof, rangeProof } , normalizedCB , auditorCB ] = await this . authorizeNormalization ( ) ;
191+
192+ // Build auditor A components (D points encrypted under auditor key)
193+ const newBalanceA = auditorCB
194+ ? auditorCB . getCipherText ( ) . map ( ( ct ) => ct . D . toRawBytes ( ) )
195+ : ( [ ] as Uint8Array [ ] ) ;
123196
124197 return args . client . transaction . build . simple ( {
125198 ...args ,
126199 data : {
127200 function : `${ args . confidentialAssetModuleAddress } ::${ MODULE_NAME } ::normalize_raw` ,
128201 functionArguments : [
129202 args . tokenAddress ,
130- normalizedCB . getCipherTextBytes ( ) ,
203+ normalizedCB . getCipherText ( ) . map ( ( ct ) => ct . C . toRawBytes ( ) ) , // new_balance_C
204+ normalizedCB . getCipherText ( ) . map ( ( ct ) => ct . D . toRawBytes ( ) ) , // new_balance_D
205+ newBalanceA , // new_balance_A
131206 rangeProof ,
132- [ ] as Uint8Array [ ] , // sigma_proto_comm (stub)
133- [ ] as Uint8Array [ ] , // sigma_proto_resp (stub)
207+ sigmaProof . commitment ,
208+ sigmaProof . response ,
134209 ] ,
135210 } ,
136211 options : args . options ,
0 commit comments