@@ -144,6 +144,81 @@ bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild
144144 return ret;
145145}
146146
147+ bool CKey::PartialSigningNonce (const uint256& hash, std::vector<unsigned char >& pubnonceout) const {
148+ if (!fValid )
149+ return false ;
150+ secp256k1_pubkey_t pubnonce;
151+ unsigned char secnonce[32 ];
152+ LockObject (secnonce);
153+ int ret = secp256k1_schnorr_generate_nonce_pair (secp256k1_context, hash.begin (), begin (), secp256k1_nonce_function_rfc6979, NULL , &pubnonce, secnonce);
154+ UnlockObject (secnonce);
155+ if (!ret)
156+ return false ;
157+ pubnonceout.resize (33 + 64 );
158+ int publen = 33 ;
159+ secp256k1_ec_pubkey_serialize (secp256k1_context, &pubnonceout[0 ], &publen, &pubnonce, true );
160+ // Sign the hash + pubnonce with a full signature, to prove possession of the corresponding private key.
161+ uint256 hash2;
162+ CSHA256 ().Write (hash.begin (), 32 ).Write (&pubnonceout[0 ], 33 ).Finalize (hash2.begin ());
163+ return secp256k1_schnorr_sign (secp256k1_context, hash2.begin (), &pubnonceout[33 ], begin (), secp256k1_nonce_function_rfc6979, NULL );
164+ }
165+
166+ static bool CombinePubNonces (const uint256& hash, const std::vector<std::vector<unsigned char > >& pubnonces, const std::vector<CPubKey>& pubkeys, secp256k1_pubkey_t & out) {
167+ bool ret = pubnonces.size () > 0 ;
168+ ret = ret && (pubnonces.size () == pubkeys.size ());
169+ std::vector<secp256k1_pubkey_t > parsed_pubnonces;
170+ std::vector<const secp256k1_pubkey_t *> parsed_pubnonce_pointers;
171+ parsed_pubnonces.reserve (pubnonces.size ());
172+ parsed_pubnonce_pointers.reserve (pubnonces.size ());
173+ std::vector<CPubKey>::const_iterator pit = pubkeys.begin ();
174+ for (std::vector<std::vector<unsigned char > >::const_iterator it = pubnonces.begin (); it != pubnonces.end (); ++it, ++pit) {
175+ secp256k1_pubkey_t other_pubnonce;
176+ ret = ret && (it->size () == 33 + 64 );
177+ ret = ret && secp256k1_ec_pubkey_parse (secp256k1_context, &other_pubnonce, &(*it)[0 ], 33 );
178+ // Verify the signature on the pubnonce.
179+ uint256 hash2;
180+ secp256k1_pubkey_t pubkey;
181+ CSHA256 ().Write (hash.begin (), 32 ).Write (&(*it)[0 ], 33 ).Finalize (hash2.begin ());
182+ ret = ret && secp256k1_ec_pubkey_parse (secp256k1_context, &pubkey, &(*pit)[0 ], pit->size ());
183+ ret = ret && secp256k1_schnorr_verify (secp256k1_context, hash2.begin (), &(*it)[33 ], &pubkey);
184+ if (ret) {
185+ parsed_pubnonces.push_back (other_pubnonce);
186+ parsed_pubnonce_pointers.push_back (&parsed_pubnonces.back ());
187+ }
188+ }
189+ return (ret && secp256k1_ec_pubkey_combine (secp256k1_context, &out, parsed_pubnonces.size (), &parsed_pubnonce_pointers[0 ]));
190+ }
191+
192+ bool CKey::PartialSign (const uint256& hash, const std::vector<std::vector<unsigned char > >& other_pubnonces_in, const std::vector<CPubKey>& other_pubkeys_in, const std::vector<unsigned char >& my_pubnonce_in, std::vector<unsigned char >& vchPartialSig) const {
193+ if (!fValid )
194+ return false ;
195+ secp256k1_pubkey_t pubnonce, my_pubnonce, other_pubnonces;
196+ unsigned char secnonce[32 ];
197+ LockObject (secnonce);
198+ int ret = my_pubnonce_in.size () == 33 + 64 && secp256k1_ec_pubkey_parse (secp256k1_context, &my_pubnonce, &my_pubnonce_in[0 ], 33 );
199+ ret = ret && secp256k1_schnorr_generate_nonce_pair (secp256k1_context, hash.begin (), begin (), secp256k1_nonce_function_rfc6979, NULL , &pubnonce, secnonce);
200+ ret = ret && memcmp (&pubnonce, &my_pubnonce, sizeof (pubnonce)) == 0 ;
201+ ret = ret && CombinePubNonces (hash, other_pubnonces_in, other_pubkeys_in, other_pubnonces);
202+ if (ret) {
203+ vchPartialSig.resize (64 );
204+ ret = secp256k1_schnorr_partial_sign (secp256k1_context, hash.begin (), &vchPartialSig[0 ], begin (), secnonce, &other_pubnonces);
205+ }
206+ UnlockObject (secnonce);
207+ return ret;
208+ }
209+
210+ bool CombinePartialSignatures (const std::vector<std::vector<unsigned char > >& input, std::vector<unsigned char >& output) {
211+ std::vector<const unsigned char *> sig_pointers;
212+ sig_pointers.reserve (input.size ());
213+ for (std::vector<std::vector<unsigned char > >::const_iterator it = input.begin (); it != input.end (); ++it) {
214+ if (it->size () != 64 ) return false ;
215+ sig_pointers.push_back (&((*it)[0 ]));
216+ }
217+ output.resize (64 );
218+ bool ret = !!secp256k1_schnorr_partial_combine (secp256k1_context, &output[0 ], sig_pointers.size (), &sig_pointers[0 ]);
219+ return ret;
220+ }
221+
147222bool CExtKey::Derive (CExtKey &out, unsigned int nChild) const {
148223 out.nDepth = nDepth + 1 ;
149224 CKeyID id = key.GetPubKey ().GetID ();
@@ -205,7 +280,7 @@ bool ECC_InitSanityCheck() {
205280void ECC_Start () {
206281 assert (secp256k1_context == NULL );
207282
208- secp256k1_context_t *ctx = secp256k1_context_create (SECP256K1_CONTEXT_SIGN);
283+ secp256k1_context_t *ctx = secp256k1_context_create (SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY );
209284 assert (ctx != NULL );
210285
211286 {
0 commit comments