github.com/ethereum/go-ethereum@v1.16.1/crypto/secp256k1/libsecp256k1/src/modules/musig/keyagg_impl.h (about)

     1  /***********************************************************************
     2   * Distributed under the MIT software license, see the accompanying    *
     3   * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
     4   ***********************************************************************/
     5  
     6  #ifndef SECP256K1_MODULE_MUSIG_KEYAGG_IMPL_H
     7  #define SECP256K1_MODULE_MUSIG_KEYAGG_IMPL_H
     8  
     9  #include <string.h>
    10  
    11  #include "keyagg.h"
    12  #include "../../eckey.h"
    13  #include "../../ecmult.h"
    14  #include "../../field.h"
    15  #include "../../group.h"
    16  #include "../../hash.h"
    17  #include "../../util.h"
    18  
    19  static const unsigned char secp256k1_musig_keyagg_cache_magic[4] = { 0xf4, 0xad, 0xbb, 0xdf };
    20  
    21  /* A keyagg cache consists of
    22   * - 4 byte magic set during initialization to allow detecting an uninitialized
    23   *   object.
    24   * - 64 byte aggregate (and potentially tweaked) public key
    25   * - 64 byte "second" public key (set to the point at infinity if not present)
    26   * - 32 byte hash of all public keys
    27   * - 1 byte the parity of the internal key (if tweaked, otherwise 0)
    28   * - 32 byte tweak
    29   */
    30  /* Requires that cache_i->pk is not infinity. */
    31  static void secp256k1_keyagg_cache_save(secp256k1_musig_keyagg_cache *cache, const secp256k1_keyagg_cache_internal *cache_i) {
    32      unsigned char *ptr = cache->data;
    33      memcpy(ptr, secp256k1_musig_keyagg_cache_magic, 4);
    34      ptr += 4;
    35      secp256k1_ge_to_bytes(ptr, &cache_i->pk);
    36      ptr += 64;
    37      secp256k1_ge_to_bytes_ext(ptr, &cache_i->second_pk);
    38      ptr += 64;
    39      memcpy(ptr, cache_i->pks_hash, 32);
    40      ptr += 32;
    41      *ptr = cache_i->parity_acc;
    42      ptr += 1;
    43      secp256k1_scalar_get_b32(ptr, &cache_i->tweak);
    44  }
    45  
    46  static int secp256k1_keyagg_cache_load(const secp256k1_context* ctx, secp256k1_keyagg_cache_internal *cache_i, const secp256k1_musig_keyagg_cache *cache) {
    47      const unsigned char *ptr = cache->data;
    48      ARG_CHECK(secp256k1_memcmp_var(ptr, secp256k1_musig_keyagg_cache_magic, 4) == 0);
    49      ptr += 4;
    50      secp256k1_ge_from_bytes(&cache_i->pk, ptr);
    51      ptr += 64;
    52      secp256k1_ge_from_bytes_ext(&cache_i->second_pk, ptr);
    53      ptr += 64;
    54      memcpy(cache_i->pks_hash, ptr, 32);
    55      ptr += 32;
    56      cache_i->parity_acc = *ptr & 1;
    57      ptr += 1;
    58      secp256k1_scalar_set_b32(&cache_i->tweak, ptr, NULL);
    59      return 1;
    60  }
    61  
    62  /* Initializes SHA256 with fixed midstate. This midstate was computed by applying
    63   * SHA256 to SHA256("KeyAgg list")||SHA256("KeyAgg list"). */
    64  static void secp256k1_musig_keyagglist_sha256(secp256k1_sha256 *sha) {
    65      secp256k1_sha256_initialize(sha);
    66  
    67      sha->s[0] = 0xb399d5e0ul;
    68      sha->s[1] = 0xc8fff302ul;
    69      sha->s[2] = 0x6badac71ul;
    70      sha->s[3] = 0x07c5b7f1ul;
    71      sha->s[4] = 0x9701e2eful;
    72      sha->s[5] = 0x2a72ecf8ul;
    73      sha->s[6] = 0x201a4c7bul;
    74      sha->s[7] = 0xab148a38ul;
    75      sha->bytes = 64;
    76  }
    77  
    78  /* Computes pks_hash = tagged_hash(pk[0], ..., pk[np-1]) */
    79  static int secp256k1_musig_compute_pks_hash(const secp256k1_context *ctx, unsigned char *pks_hash, const secp256k1_pubkey * const* pks, size_t np) {
    80      secp256k1_sha256 sha;
    81      size_t i;
    82  
    83      secp256k1_musig_keyagglist_sha256(&sha);
    84      for (i = 0; i < np; i++) {
    85          unsigned char ser[33];
    86          size_t ser_len = sizeof(ser);
    87          if (!secp256k1_ec_pubkey_serialize(ctx, ser, &ser_len, pks[i], SECP256K1_EC_COMPRESSED)) {
    88              return 0;
    89          }
    90          VERIFY_CHECK(ser_len == sizeof(ser));
    91          secp256k1_sha256_write(&sha, ser, sizeof(ser));
    92      }
    93      secp256k1_sha256_finalize(&sha, pks_hash);
    94      return 1;
    95  }
    96  
    97  /* Initializes SHA256 with fixed midstate. This midstate was computed by applying
    98   * SHA256 to SHA256("KeyAgg coefficient")||SHA256("KeyAgg coefficient"). */
    99  static void secp256k1_musig_keyaggcoef_sha256(secp256k1_sha256 *sha) {
   100      secp256k1_sha256_initialize(sha);
   101  
   102      sha->s[0] = 0x6ef02c5aul;
   103      sha->s[1] = 0x06a480deul;
   104      sha->s[2] = 0x1f298665ul;
   105      sha->s[3] = 0x1d1134f2ul;
   106      sha->s[4] = 0x56a0b063ul;
   107      sha->s[5] = 0x52da4147ul;
   108      sha->s[6] = 0xf280d9d4ul;
   109      sha->s[7] = 0x4484be15ul;
   110      sha->bytes = 64;
   111  }
   112  
   113  /* Compute KeyAgg coefficient which is constant 1 for the second pubkey and
   114   * otherwise tagged_hash(pks_hash, pk) where pks_hash is the hash of public keys.
   115   * second_pk is the point at infinity in case there is no second_pk. Assumes
   116   * that pk is not the point at infinity and that the Y-coordinates of pk and
   117   * second_pk are normalized. */
   118  static void secp256k1_musig_keyaggcoef_internal(secp256k1_scalar *r, const unsigned char *pks_hash, secp256k1_ge *pk, const secp256k1_ge *second_pk) {
   119      VERIFY_CHECK(!secp256k1_ge_is_infinity(pk));
   120  
   121      if (!secp256k1_ge_is_infinity(second_pk)
   122            && secp256k1_ge_eq_var(pk, second_pk)) {
   123          secp256k1_scalar_set_int(r, 1);
   124      } else {
   125          secp256k1_sha256 sha;
   126          unsigned char buf[33];
   127          size_t buflen = sizeof(buf);
   128          int ret;
   129          secp256k1_musig_keyaggcoef_sha256(&sha);
   130          secp256k1_sha256_write(&sha, pks_hash, 32);
   131          ret = secp256k1_eckey_pubkey_serialize(pk, buf, &buflen, 1);
   132  #ifdef VERIFY
   133          /* Serialization does not fail since the pk is not the point at infinity
   134           * (according to this function's precondition). */
   135          VERIFY_CHECK(ret && buflen == sizeof(buf));
   136  #else
   137          (void) ret;
   138  #endif
   139          secp256k1_sha256_write(&sha, buf, sizeof(buf));
   140          secp256k1_sha256_finalize(&sha, buf);
   141          secp256k1_scalar_set_b32(r, buf, NULL);
   142      }
   143  }
   144  
   145  /* Assumes that pk is not the point at infinity and that the Y-coordinates of pk
   146   * and cache_i->second_pk are normalized. */
   147  static void secp256k1_musig_keyaggcoef(secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_ge *pk) {
   148      secp256k1_musig_keyaggcoef_internal(r, cache_i->pks_hash, pk, &cache_i->second_pk);
   149  }
   150  
   151  typedef struct {
   152      const secp256k1_context *ctx;
   153      /* pks_hash is the hash of the public keys */
   154      unsigned char pks_hash[32];
   155      const secp256k1_pubkey * const* pks;
   156      secp256k1_ge second_pk;
   157  } secp256k1_musig_pubkey_agg_ecmult_data;
   158  
   159  /* Callback for batch EC multiplication to compute keyaggcoef_0*P0 + keyaggcoef_1*P1 + ...  */
   160  static int secp256k1_musig_pubkey_agg_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data) {
   161      secp256k1_musig_pubkey_agg_ecmult_data *ctx = (secp256k1_musig_pubkey_agg_ecmult_data *) data;
   162      int ret;
   163      ret = secp256k1_pubkey_load(ctx->ctx, pt, ctx->pks[idx]);
   164  #ifdef VERIFY
   165      /* pubkey_load can't fail because the same pks have already been loaded in
   166       * `musig_compute_pks_hash` (and we test this). */
   167      VERIFY_CHECK(ret);
   168  #else
   169      (void) ret;
   170  #endif
   171      secp256k1_musig_keyaggcoef_internal(sc, ctx->pks_hash, pt, &ctx->second_pk);
   172      return 1;
   173  }
   174  
   175  int secp256k1_musig_pubkey_agg(const secp256k1_context* ctx, secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_pubkey * const* pubkeys, size_t n_pubkeys) {
   176      secp256k1_musig_pubkey_agg_ecmult_data ecmult_data;
   177      secp256k1_gej pkj;
   178      secp256k1_ge pkp;
   179      size_t i;
   180  
   181      VERIFY_CHECK(ctx != NULL);
   182      if (agg_pk != NULL) {
   183          memset(agg_pk, 0, sizeof(*agg_pk));
   184      }
   185      ARG_CHECK(pubkeys != NULL);
   186      ARG_CHECK(n_pubkeys > 0);
   187  
   188      ecmult_data.ctx = ctx;
   189      ecmult_data.pks = pubkeys;
   190  
   191      secp256k1_ge_set_infinity(&ecmult_data.second_pk);
   192      for (i = 1; i < n_pubkeys; i++) {
   193          if (secp256k1_memcmp_var(pubkeys[0], pubkeys[i], sizeof(*pubkeys[0])) != 0) {
   194              secp256k1_ge pk;
   195              if (!secp256k1_pubkey_load(ctx, &pk, pubkeys[i])) {
   196                  return 0;
   197              }
   198              ecmult_data.second_pk = pk;
   199              break;
   200          }
   201      }
   202  
   203      if (!secp256k1_musig_compute_pks_hash(ctx, ecmult_data.pks_hash, pubkeys, n_pubkeys)) {
   204          return 0;
   205      }
   206      /* TODO: actually use optimized ecmult_multi algorithms by providing a
   207       * scratch space */
   208      if (!secp256k1_ecmult_multi_var(&ctx->error_callback, NULL, &pkj, NULL, secp256k1_musig_pubkey_agg_callback, (void *) &ecmult_data, n_pubkeys)) {
   209          /* In order to reach this line with the current implementation of
   210           * ecmult_multi_var one would need to provide a callback that can
   211           * fail. */
   212          return 0;
   213      }
   214      secp256k1_ge_set_gej(&pkp, &pkj);
   215      secp256k1_fe_normalize_var(&pkp.y);
   216      /* The resulting public key is infinity with negligible probability */
   217      VERIFY_CHECK(!secp256k1_ge_is_infinity(&pkp));
   218      if (keyagg_cache != NULL) {
   219          secp256k1_keyagg_cache_internal cache_i = { 0 };
   220          cache_i.pk = pkp;
   221          cache_i.second_pk = ecmult_data.second_pk;
   222          memcpy(cache_i.pks_hash, ecmult_data.pks_hash, sizeof(cache_i.pks_hash));
   223          secp256k1_keyagg_cache_save(keyagg_cache, &cache_i);
   224      }
   225  
   226      if (agg_pk != NULL) {
   227          secp256k1_extrakeys_ge_even_y(&pkp);
   228          secp256k1_xonly_pubkey_save(agg_pk, &pkp);
   229      }
   230      return 1;
   231  }
   232  
   233  int secp256k1_musig_pubkey_get(const secp256k1_context* ctx, secp256k1_pubkey *agg_pk, const secp256k1_musig_keyagg_cache *keyagg_cache) {
   234      secp256k1_keyagg_cache_internal cache_i;
   235      VERIFY_CHECK(ctx != NULL);
   236      ARG_CHECK(agg_pk != NULL);
   237      memset(agg_pk, 0, sizeof(*agg_pk));
   238      ARG_CHECK(keyagg_cache != NULL);
   239  
   240      if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) {
   241          return 0;
   242      }
   243      secp256k1_pubkey_save(agg_pk, &cache_i.pk);
   244      return 1;
   245  }
   246  
   247  static int secp256k1_musig_pubkey_tweak_add_internal(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32, int xonly) {
   248      secp256k1_keyagg_cache_internal cache_i;
   249      int overflow = 0;
   250      secp256k1_scalar tweak;
   251  
   252      VERIFY_CHECK(ctx != NULL);
   253      if (output_pubkey != NULL) {
   254          memset(output_pubkey, 0, sizeof(*output_pubkey));
   255      }
   256      ARG_CHECK(keyagg_cache != NULL);
   257      ARG_CHECK(tweak32 != NULL);
   258  
   259      if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) {
   260          return 0;
   261      }
   262      secp256k1_scalar_set_b32(&tweak, tweak32, &overflow);
   263      if (overflow) {
   264          return 0;
   265      }
   266      if (xonly && secp256k1_extrakeys_ge_even_y(&cache_i.pk)) {
   267          cache_i.parity_acc ^= 1;
   268          secp256k1_scalar_negate(&cache_i.tweak, &cache_i.tweak);
   269      }
   270      secp256k1_scalar_add(&cache_i.tweak, &cache_i.tweak, &tweak);
   271      if (!secp256k1_eckey_pubkey_tweak_add(&cache_i.pk, &tweak)) {
   272          return 0;
   273      }
   274      /* eckey_pubkey_tweak_add fails if cache_i.pk is infinity */
   275      VERIFY_CHECK(!secp256k1_ge_is_infinity(&cache_i.pk));
   276      secp256k1_keyagg_cache_save(keyagg_cache, &cache_i);
   277      if (output_pubkey != NULL) {
   278          secp256k1_pubkey_save(output_pubkey, &cache_i.pk);
   279      }
   280      return 1;
   281  }
   282  
   283  int secp256k1_musig_pubkey_ec_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32) {
   284      return secp256k1_musig_pubkey_tweak_add_internal(ctx, output_pubkey, keyagg_cache, tweak32, 0);
   285  }
   286  
   287  int secp256k1_musig_pubkey_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32) {
   288      return secp256k1_musig_pubkey_tweak_add_internal(ctx, output_pubkey, keyagg_cache, tweak32, 1);
   289  }
   290  
   291  #endif