Skip to content

Instantly share code, notes, and snippets.

@jonasnick
Last active March 28, 2020 08:56
Show Gist options
  • Save jonasnick/a122acd8395ac4c6ae7b648450f5ec07 to your computer and use it in GitHub Desktop.
Save jonasnick/a122acd8395ac4c6ae7b648450f5ec07 to your computer and use it in GitHub Desktop.
Taproot Test
/*********************/
/* Current version */
/* */
/*********************/
/* Create output key */
secp256k1_rand256(sk);
CHECK(secp256k1_xonly_pubkey_create(ctx, &internal_pk, sk) == 1);
/* In actual taproot the tweak would be hash of internal_pk */
CHECK(secp256k1_xonly_pubkey_serialize(ctx, tweak, &internal_pk) == 1);
/* Copy internal_pk because tweak_add changes the public key in place */
output_pk = internal_pk;
CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &is_negated, tweak) == 1);
CHECK(secp256k1_xonly_pubkey_serialize(ctx, output_pk_bytes, &output_pk) == 1);
/* Key spend */
secp256k1_rand256(msg);
CHECK(secp256k1_xonly_seckey_tweak_add(ctx, sk, tweak) == 1);
CHECK(secp256k1_schnorrsig_sign(ctx, &sig, msg, sk, NULL, NULL) == 1);
/* Verify key spend */
CHECK(secp256k1_xonly_pubkey_parse(ctx, &output_pk, output_pk_bytes) == 1);
CHECK(secp256k1_schnorrsig_verify(ctx, &sig, msg, &output_pk) == 1);
/* Script spend */
CHECK(secp256k1_xonly_pubkey_serialize(ctx, internal_pk_bytes, &internal_pk) == 1);
/* Verify script spend */
CHECK(secp256k1_xonly_pubkey_parse(ctx, &output_pk, output_pk_bytes) == 1);
CHECK(secp256k1_xonly_pubkey_parse(ctx, &internal_pk, internal_pk_bytes) == 1);
CHECK(secp256k1_xonly_pubkey_tweak_test(ctx, &output_pk_bytes, is_negated, &internal_pk, tweak) == 1);
/*********************/
/* Keep xonly for */
/* verification */
/* */
/*********************/
secp256k1_rand256(sk);
/* Use normal pubkey_create */
CHECK(secp256k1_pubkey_create(ctx, &internal_pk, sk) == 1);
/* Serialize as XONLY (32 bytes) */
CHECK(secp256k1_pubkey_serialize(ctx, tweak, &internal_pk, XONLY) == 1);
output_pk = internal_pk;
/* Can't use normal tweak_add because xonly_pubkey_tweak_add is fundamentally
* differs by negating the input pk. Note that input/output pk would be normal
* pubkeys
*/
CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, tweak) == 1);
CHECK(secp256k1_pubkey_serialize(ctx, output_pk_bytes, &output_pk, COMPRESSED) == 1);
/* Key spend */
secp256k1_rand256(msg);
/* seckey_tweak_add differs from normal seckey_add */
CHECK(secp256k1_xonly_seckey_tweak_add(ctx, sk, tweak) == 1);
CHECK(secp256k1_schnorrsig_sign(ctx, &sig, msg, sk, NULL, NULL) == 1);
/* Parse xonly pubkey and verify */
CHECK(secp256k1_xonly_pubkey_parse(ctx, &output_pk_xonly, output_pk_bytes) == 1);
CHECK(secp256k1_schnorrsig_verify(ctx, &sig, msg, &output_pk_xonly) == 1);
/* Script spend */
CHECK(secp256k1_pubkey_serialize(ctx, internal_pk_bytes, &internal_pk, XONLY) == 1);
/* Verify script spend */
CHECK(secp256k1_xonly_pubkey_parse(ctx, &internal_pk_xonly, internal_pk_bytes) == 1);
/* output_pk is a normal pubkey, internal_pk is an xonly pubkey */
CHECK(secp256k1_xonly_pubkey_tweak_test(ctx, &output_pk_bytes[1], output_pk_bytes[0] - 0x02, &internal_pk_xonly, tweak) == 1);
/*********************/
/* Remove xonly */
/* */
/*********************/
secp256k1_rand256(sk);
CHECK(secp256k1_pubkey_create(ctx, &internal_pk, sk) == 1);
CHECK(secp256k1_pubkey_serialize(ctx, tweak, &internal_pk, XONLY) == 1);
output_pk = internal_pk;
/* Need to keep xonly_pubkey_tweak_add as mentioned above */
CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, tweak) == 1);
CHECK(secp256k1_pubkey_serialize(ctx, output_pk_bytes, &output_pk, XONLY) == 1);
/* Key spend */
secp256k1_rand256(msg);
CHECK(secp256k1_xonly_seckey_tweak_add(ctx, sk, tweak) == 1);
CHECK(secp256k1_schnorrsig_sign(ctx, &sig, msg, sk, NULL, NULL) == 1);
CHECK(secp256k1_pubkey_parse(ctx, &output_pk, output_pk_bytes, XONLY) == 1);
/* Returns 0 if the given pubkey doesn't have an even Y */
CHECK(secp256k1_schnorrsig_verify(ctx, &sig, msg, &output_pk) == 1);
/* Script spend */
CHECK(secp256k1_pubkey_serialize(ctx, internal_pk_bytes, &internal_pk, XONLY) == 1);
CHECK(secp256k1_pubkey_parse(ctx, &output_pk, output_pk_bytes, COMPRESSED) == 1);
CHECK(secp256k1_pubkey_parse(ctx, &internal_pk, internal_pk_bytes, XONLY) == 1);
/* Accepts two public keys, returns 0 if internal_pk doesn't have an even Y */
CHECK(secp256k1_xonly_pubkey_tweak_test(ctx, &output_pk_bytes[1], output_pk_bytes[0] - 0x02, &internal_pk, tweak) == 1);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment