1
1
use {
2
- crate :: { encryption:: MintAmountCiphertext , errors:: TokenProofGenerationError , try_split_u64} ,
2
+ crate :: {
3
+ encryption:: MintAmountCiphertext , errors:: TokenProofGenerationError ,
4
+ try_combine_lo_hi_ciphertexts, try_split_u64,
5
+ } ,
3
6
solana_zk_sdk:: {
4
- encryption:: { elgamal:: ElGamalPubkey , pedersen:: Pedersen } ,
7
+ encryption:: {
8
+ auth_encryption:: { AeCiphertext , AeKey } ,
9
+ elgamal:: { ElGamalCiphertext , ElGamalKeypair , ElGamalPubkey } ,
10
+ pedersen:: Pedersen ,
11
+ } ,
5
12
zk_elgamal_proof_program:: proof_data:: {
6
- BatchedGroupedCiphertext3HandlesValidityProofData , BatchedRangeProofU64Data ,
13
+ BatchedGroupedCiphertext3HandlesValidityProofData , BatchedRangeProofU128Data ,
14
+ CiphertextCommitmentEqualityProofData ,
7
15
} ,
8
16
} ,
9
17
} ;
10
18
19
+ const NEW_SUPPLY_BIT_LENGTH : usize = 64 ;
11
20
const MINT_AMOUNT_LO_BIT_LENGTH : usize = 16 ;
12
21
const MINT_AMOUNT_HI_BIT_LENGTH : usize = 32 ;
13
22
/// The padding bit length in range proofs to make the bit-length power-of-2
14
23
const RANGE_PROOF_PADDING_BIT_LENGTH : usize = 16 ;
15
24
16
25
/// The proof data required for a confidential mint instruction
17
26
pub struct MintProofData {
27
+ pub equality_proof_data : CiphertextCommitmentEqualityProofData ,
18
28
pub ciphertext_validity_proof_data : BatchedGroupedCiphertext3HandlesValidityProofData ,
19
- pub range_proof_data : BatchedRangeProofU64Data ,
29
+ pub range_proof_data : BatchedRangeProofU128Data ,
20
30
}
21
31
22
32
pub fn mint_split_proof_data (
33
+ current_supply_ciphertext : & ElGamalCiphertext ,
34
+ current_decryptable_supply : & AeCiphertext ,
23
35
mint_amount : u64 ,
36
+ supply_elgamal_keypair : & ElGamalKeypair ,
37
+ supply_aes_key : & AeKey ,
24
38
destination_elgamal_pubkey : & ElGamalPubkey ,
25
39
auditor_elgamal_pubkey : & ElGamalPubkey ,
26
- supply_elgamal_pubkey : & ElGamalPubkey ,
27
40
) -> Result < MintProofData , TokenProofGenerationError > {
28
41
// split the mint amount into low and high bits
29
42
let ( mint_amount_lo, mint_amount_hi) = try_split_u64 ( mint_amount, MINT_AMOUNT_LO_BIT_LENGTH )
@@ -35,21 +48,62 @@ pub fn mint_split_proof_data(
35
48
mint_amount_lo,
36
49
destination_elgamal_pubkey,
37
50
auditor_elgamal_pubkey,
38
- supply_elgamal_pubkey ,
51
+ supply_elgamal_keypair . pubkey ( ) ,
39
52
) ;
40
53
41
54
let ( mint_amount_grouped_ciphertext_hi, mint_amount_opening_hi) = MintAmountCiphertext :: new (
42
55
mint_amount_hi,
43
56
destination_elgamal_pubkey,
44
57
auditor_elgamal_pubkey,
45
- supply_elgamal_pubkey ,
58
+ supply_elgamal_keypair . pubkey ( ) ,
46
59
) ;
47
60
61
+ // compute the new supply ciphertext
62
+ let mint_amount_ciphertext_supply_lo = mint_amount_grouped_ciphertext_lo
63
+ . 0
64
+ . to_elgamal_ciphertext ( 2 )
65
+ . unwrap ( ) ;
66
+ let mint_amount_ciphertext_supply_hi = mint_amount_grouped_ciphertext_hi
67
+ . 0
68
+ . to_elgamal_ciphertext ( 2 )
69
+ . unwrap ( ) ;
70
+
71
+ #[ allow( clippy:: arithmetic_side_effects) ]
72
+ let new_supply_ciphertext = current_supply_ciphertext
73
+ + try_combine_lo_hi_ciphertexts (
74
+ & mint_amount_ciphertext_supply_lo,
75
+ & mint_amount_ciphertext_supply_hi,
76
+ MINT_AMOUNT_LO_BIT_LENGTH ,
77
+ )
78
+ . ok_or ( TokenProofGenerationError :: IllegalAmountBitLength ) ?;
79
+
80
+ // decrypt the current supply
81
+ let current_supply = current_decryptable_supply
82
+ . decrypt ( supply_aes_key)
83
+ . ok_or ( TokenProofGenerationError :: IllegalAmountBitLength ) ?;
84
+
85
+ // compute the new supply
86
+ let new_supply = current_supply
87
+ . checked_add ( mint_amount)
88
+ . ok_or ( TokenProofGenerationError :: IllegalAmountBitLength ) ?;
89
+
90
+ let ( new_supply_commitment, new_supply_opening) = Pedersen :: new ( new_supply) ;
91
+
92
+ // generate equality proof data
93
+ let equality_proof_data = CiphertextCommitmentEqualityProofData :: new (
94
+ supply_elgamal_keypair,
95
+ & new_supply_ciphertext,
96
+ & new_supply_commitment,
97
+ & new_supply_opening,
98
+ new_supply,
99
+ )
100
+ . map_err ( TokenProofGenerationError :: from) ?;
101
+
48
102
// generate ciphertext validity proof data
49
103
let ciphertext_validity_proof_data = BatchedGroupedCiphertext3HandlesValidityProofData :: new (
50
104
destination_elgamal_pubkey,
51
105
auditor_elgamal_pubkey,
52
- supply_elgamal_pubkey ,
106
+ supply_elgamal_keypair . pubkey ( ) ,
53
107
& mint_amount_grouped_ciphertext_lo. 0 ,
54
108
& mint_amount_grouped_ciphertext_hi. 0 ,
55
109
mint_amount_lo,
@@ -61,19 +115,22 @@ pub fn mint_split_proof_data(
61
115
62
116
// generate range proof data
63
117
let ( padding_commitment, padding_opening) = Pedersen :: new ( 0_u64 ) ;
64
- let range_proof_data = BatchedRangeProofU64Data :: new (
118
+ let range_proof_data = BatchedRangeProofU128Data :: new (
65
119
vec ! [
120
+ & new_supply_commitment,
66
121
mint_amount_grouped_ciphertext_lo. get_commitment( ) ,
67
122
mint_amount_grouped_ciphertext_hi. get_commitment( ) ,
68
123
& padding_commitment,
69
124
] ,
70
- vec ! [ mint_amount_lo, mint_amount_hi, 0 ] ,
125
+ vec ! [ new_supply , mint_amount_lo, mint_amount_hi, 0 ] ,
71
126
vec ! [
127
+ NEW_SUPPLY_BIT_LENGTH ,
72
128
MINT_AMOUNT_LO_BIT_LENGTH ,
73
129
MINT_AMOUNT_HI_BIT_LENGTH ,
74
130
RANGE_PROOF_PADDING_BIT_LENGTH ,
75
131
] ,
76
132
vec ! [
133
+ & new_supply_opening,
77
134
& mint_amount_opening_lo,
78
135
& mint_amount_opening_hi,
79
136
& padding_opening,
@@ -82,6 +139,7 @@ pub fn mint_split_proof_data(
82
139
. map_err ( TokenProofGenerationError :: from) ?;
83
140
84
141
Ok ( MintProofData {
142
+ equality_proof_data,
85
143
ciphertext_validity_proof_data,
86
144
range_proof_data,
87
145
} )
0 commit comments