@@ -4268,6 +4268,93 @@ void run_eckey_edge_case_test(void) {
42684268 secp256k1_context_set_illegal_callback (ctx , NULL , NULL );
42694269}
42704270
4271+ void test_xonly_pubkey (void ) {
4272+ unsigned char sk [32 ] = { 0 };
4273+ unsigned char garbage [32 ];
4274+ secp256k1_pubkey signed_pk ;
4275+ secp256k1_xonly_pubkey xonly_pk ;
4276+ secp256k1_xonly_pubkey xonly_pk_tmp ;
4277+ secp256k1_ge pk1 ;
4278+ secp256k1_ge pk2 ;
4279+ secp256k1_fe y ;
4280+ unsigned char buf32 [32 ];
4281+
4282+ /* sk = 0 should fail */
4283+ CHECK (secp256k1_xonly_pubkey_create (ctx , & xonly_pk , sk ) == 0 );
4284+
4285+ /* Check that X coordinate of normal pubkey and x-only pubkey matches
4286+ * and that due to choice of secret key the Y coordinates are each others
4287+ * additive inverse. */
4288+ sk [0 ] = 6 ;
4289+ CHECK (secp256k1_ec_pubkey_create (ctx , & signed_pk , sk ) == 1 );
4290+ CHECK (secp256k1_xonly_pubkey_create (ctx , & xonly_pk , sk ) == 1 );
4291+ secp256k1_pubkey_load (ctx , & pk1 , & signed_pk );
4292+ secp256k1_pubkey_load (ctx , & pk2 , (secp256k1_pubkey * ) & xonly_pk );
4293+ CHECK (secp256k1_fe_equal (& pk1 .x , & pk2 .x ) == 1 );
4294+ secp256k1_fe_negate (& y , & pk2 .y , 1 );
4295+ CHECK (secp256k1_fe_equal (& pk1 .y , & y ) == 1 );
4296+
4297+ /* Serialization and parse roundtrip */
4298+ CHECK (secp256k1_xonly_pubkey_create (ctx , & xonly_pk , sk ) == 1 );
4299+ CHECK (secp256k1_xonly_pubkey_serialize (ctx , buf32 , & xonly_pk ) == 1 );
4300+ CHECK (secp256k1_xonly_pubkey_parse (ctx , & xonly_pk_tmp , buf32 ) == 1 );
4301+ CHECK (memcmp (& xonly_pk , & xonly_pk_tmp , sizeof (xonly_pk )) == 0 );
4302+
4303+ /* Can't parse a byte string that's not a valid X coordinate */
4304+ memset (garbage , 0 , sizeof (garbage ));
4305+ CHECK (secp256k1_xonly_pubkey_parse (ctx , & xonly_pk_tmp , garbage ) == 0 );
4306+ }
4307+
4308+ void test_xonly_pubkey_api (void ) {
4309+ secp256k1_xonly_pubkey pk ;
4310+ unsigned char sk [32 ];
4311+ unsigned char buf32 [32 ];
4312+
4313+ /** setup **/
4314+ secp256k1_context * none = secp256k1_context_create (SECP256K1_CONTEXT_NONE );
4315+ secp256k1_context * sign = secp256k1_context_create (SECP256K1_CONTEXT_SIGN );
4316+ secp256k1_context * vrfy = secp256k1_context_create (SECP256K1_CONTEXT_VERIFY );
4317+ int ecount ;
4318+
4319+ secp256k1_context_set_error_callback (none , counting_illegal_callback_fn , & ecount );
4320+ secp256k1_context_set_error_callback (sign , counting_illegal_callback_fn , & ecount );
4321+ secp256k1_context_set_error_callback (vrfy , counting_illegal_callback_fn , & ecount );
4322+ secp256k1_context_set_illegal_callback (none , counting_illegal_callback_fn , & ecount );
4323+ secp256k1_context_set_illegal_callback (sign , counting_illegal_callback_fn , & ecount );
4324+ secp256k1_context_set_illegal_callback (vrfy , counting_illegal_callback_fn , & ecount );
4325+
4326+ secp256k1_rand256 (sk );
4327+ ecount = 0 ;
4328+ CHECK (secp256k1_xonly_pubkey_create (none , & pk , sk ) == 0 );
4329+ CHECK (ecount == 1 );
4330+ CHECK (secp256k1_xonly_pubkey_create (sign , & pk , sk ) == 1 );
4331+ CHECK (secp256k1_xonly_pubkey_create (vrfy , & pk , sk ) == 0 );
4332+ CHECK (ecount == 2 );
4333+ CHECK (secp256k1_xonly_pubkey_create (sign , NULL , sk ) == 0 );
4334+ CHECK (ecount == 3 );
4335+ CHECK (secp256k1_xonly_pubkey_create (sign , & pk , NULL ) == 0 );
4336+ CHECK (ecount == 4 );
4337+
4338+ ecount = 0 ;
4339+ CHECK (secp256k1_xonly_pubkey_create (sign , & pk , sk ) == 1 );
4340+ CHECK (secp256k1_xonly_pubkey_serialize (none , buf32 , & pk ) == 1 );
4341+ CHECK (secp256k1_xonly_pubkey_serialize (none , NULL , & pk ) == 0 );
4342+ CHECK (ecount == 1 );
4343+ CHECK (secp256k1_xonly_pubkey_serialize (none , buf32 , NULL ) == 0 );
4344+ CHECK (ecount == 2 );
4345+
4346+ ecount = 0 ;
4347+ CHECK (secp256k1_xonly_pubkey_parse (none , & pk , buf32 ) == 1 );
4348+ CHECK (secp256k1_xonly_pubkey_parse (none , NULL , buf32 ) == 0 );
4349+ CHECK (ecount == 1 );
4350+ CHECK (secp256k1_xonly_pubkey_parse (none , & pk , NULL ) == 0 );
4351+ CHECK (ecount == 2 );
4352+
4353+ secp256k1_context_destroy (none );
4354+ secp256k1_context_destroy (sign );
4355+ secp256k1_context_destroy (vrfy );
4356+ }
4357+
42714358void random_sign (secp256k1_scalar * sigr , secp256k1_scalar * sigs , const secp256k1_scalar * key , const secp256k1_scalar * msg , int * recid ) {
42724359 secp256k1_scalar nonce ;
42734360 do {
@@ -5438,6 +5525,10 @@ int main(int argc, char **argv) {
54385525 /* EC key edge cases */
54395526 run_eckey_edge_case_test ();
54405527
5528+ /* Positive key test cases */
5529+ test_xonly_pubkey ();
5530+ test_xonly_pubkey_api ();
5531+
54415532#ifdef ENABLE_MODULE_ECDH
54425533 /* ecdh tests */
54435534 run_ecdh_tests ();
0 commit comments