@@ -111,6 +111,74 @@ int secp256k1_silentpayments_send_create_shared_secret(const secp256k1_context *
111
111
return 1 ;
112
112
}
113
113
114
+ int secp256k1_silentpayments_create_public_tweak_data (const secp256k1_context * ctx , unsigned char * tweak_data33 , const secp256k1_pubkey * plain_pubkeys , size_t n_plain_pubkeys , const secp256k1_xonly_pubkey * xonly_pubkeys , size_t n_xonly_pubkeys , const unsigned char * outpoints_hash32 ) {
115
+ size_t i ;
116
+ secp256k1_pubkey A_tweaked ;
117
+ size_t outputlen = 33 ;
118
+
119
+ /* Sanity check inputs */
120
+ VERIFY_CHECK (ctx != NULL );
121
+ ARG_CHECK (tweak_data33 != NULL );
122
+ memset (tweak_data33 , 0 , 33 );
123
+ ARG_CHECK (plain_pubkeys == NULL || n_plain_pubkeys >= 1 );
124
+ ARG_CHECK (xonly_pubkeys == NULL || n_xonly_pubkeys >= 1 );
125
+ ARG_CHECK ((plain_pubkeys != NULL ) || (xonly_pubkeys != NULL ));
126
+ ARG_CHECK ((n_plain_pubkeys + n_xonly_pubkeys ) >= 1 );
127
+ ARG_CHECK (outpoints_hash32 != NULL );
128
+
129
+ /* Compute input public keys tweak: A_tweaked = (A_0 + A_1 + ... + A_n) * outpoints_hash */
130
+ for (i = 0 ; i < n_plain_pubkeys ; i ++ ) {
131
+ secp256k1_pubkey combined ;
132
+ const secp256k1_pubkey * addends [2 ];
133
+ if (i == 0 ) {
134
+ A_tweaked = plain_pubkeys [0 ];
135
+ continue ;
136
+ }
137
+ addends [0 ] = & A_tweaked ;
138
+ addends [1 ] = & plain_pubkeys [i ];
139
+ if (!secp256k1_ec_pubkey_combine (ctx , & combined , addends , 2 )) {
140
+ return 0 ;
141
+ }
142
+ A_tweaked = combined ;
143
+ }
144
+ /* X-only public keys have to be converted to regular public keys (assuming even parity) */
145
+ for (i = 0 ; i < n_xonly_pubkeys ; i ++ ) {
146
+ unsigned char pubkey_to_add_ser [33 ];
147
+ secp256k1_pubkey combined , pubkey_to_add ;
148
+ const secp256k1_pubkey * addends [2 ];
149
+
150
+ pubkey_to_add_ser [0 ] = 0x02 ;
151
+ if (!secp256k1_xonly_pubkey_serialize (ctx , & pubkey_to_add_ser [1 ], & xonly_pubkeys [i ])) {
152
+ return 0 ;
153
+ }
154
+ if (!secp256k1_ec_pubkey_parse (ctx , & pubkey_to_add , pubkey_to_add_ser , 33 )) {
155
+ return 0 ;
156
+ }
157
+
158
+ if (i == 0 && n_plain_pubkeys == 0 ) {
159
+ A_tweaked = pubkey_to_add ;
160
+ continue ;
161
+ }
162
+ addends [0 ] = & A_tweaked ;
163
+ addends [1 ] = & pubkey_to_add ;
164
+ if (!secp256k1_ec_pubkey_combine (ctx , & combined , addends , 2 )) {
165
+ return 0 ;
166
+ }
167
+ A_tweaked = combined ;
168
+ }
169
+
170
+ if (!secp256k1_ec_pubkey_tweak_mul (ctx , & A_tweaked , outpoints_hash32 )) {
171
+ return 0 ;
172
+ }
173
+
174
+ /* Serialize tweak_data */
175
+ if (!secp256k1_ec_pubkey_serialize (ctx , tweak_data33 , & outputlen , & A_tweaked , SECP256K1_EC_COMPRESSED )) {
176
+ return 0 ;
177
+ }
178
+
179
+ return 1 ;
180
+ }
181
+
114
182
/* TODO: implement functions for receiver side. */
115
183
116
184
#endif
0 commit comments