Module: Secp256k1::MuSig
- Included in:
- Secp256k1
- Defined in:
- lib/secp256k1/musig.rb,
lib/secp256k1/musig/key_agg.rb,
lib/secp256k1/musig/session.rb
Overview
MuSig module
Defined Under Namespace
Classes: KeyAggCache, KeyAggContext, Session
Instance Method Summary collapse
-
#aggregate_musig_nonce(pub_nonces) ⇒ String
Aggregates the nonces of all signers into a single nonce.
-
#aggregate_pubkey(pubkeys) ⇒ Secp2561k::MuSig::KeyAggContext
Aggregate public keys.
-
#generate_musig_nonce(session_id, pk, sk: nil, key_agg_ctx: nil, msg: nil, extra_in: nil) ⇒ Array(String)
Generate nonce pair.
-
#generate_musig_nonce_counter(counter, private_key, key_agg_ctx: nil, msg: nil, extra_in: nil) ⇒ Array(String)
Generate a nonce pair deterministically using a non-repeating counter instead of session randomness.
-
#generate_musig_session_id ⇒ String
Generate fresh session id for musig signing session.
Instance Method Details
#aggregate_musig_nonce(pub_nonces) ⇒ String
Aggregates the nonces of all signers into a single nonce.
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/secp256k1/musig.rb', line 178 def aggregate_musig_nonce(pub_nonces) raise ArgumentError, "pub_nonces must be Array." unless pub_nonces.is_a?(Array) with_context do |context| nonce_ptrs = pub_nonces.map do |pub_nonce| pub_nonce = hex2bin(pub_nonce) validate_string!("pub_nonce", pub_nonce, 66) in66 = FFI::MemoryPointer.new(:uchar, 66).put_bytes(0, pub_nonce) pub_nonce_ptr = FFI::MemoryPointer.new(:uchar, 132) if secp256k1_musig_pubnonce_parse(context, pub_nonce_ptr, in66) == 0 raise Error, "secp256k1_musig_pubnonce_parse error." end pub_nonce_ptr end agg_nonce = FFI::MemoryPointer.new(:uchar, 132) pubnonces = FFI::MemoryPointer.new(:pointer, pub_nonces.length) pubnonces.write_array_of_pointer(nonce_ptrs) result = secp256k1_musig_nonce_agg(context, agg_nonce, pubnonces, pub_nonces.length) raise Error, "nonce aggregation failed." if result == 0 out66 = FFI::MemoryPointer.new(:uchar, 66) secp256k1_musig_aggnonce_serialize(context, out66, agg_nonce) out66.read_string(66).unpack1("H*") end end |
#aggregate_pubkey(pubkeys) ⇒ Secp2561k::MuSig::KeyAggContext
Aggregate public keys.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/secp256k1/musig.rb', line 65 def aggregate_pubkey(pubkeys) raise ArgumentError, "pubkeys must be an array." unless pubkeys.is_a?(Array) with_context do |context| pubkeys_ptrs = pubkeys.map do |pubkey| pubkey = hex2bin(pubkey) validate_string!('pubkey', pubkey, 33) input = FFI::MemoryPointer.new(:uchar, 33).put_bytes(0, pubkey) pubkey_ptr = FFI::MemoryPointer.new(:uchar, 64) raise Error, "pubkey is invalid." unless secp256k1_ec_pubkey_parse(context, pubkey_ptr, input, 33) == 1 pubkey_ptr end pubkeys_ptr = FFI::MemoryPointer.new(:pointer, pubkeys.length) pubkeys_ptr.write_array_of_pointer(pubkeys_ptrs) agg_pubkey = FFI::MemoryPointer.new(:uchar, 64) cache = Secp256k1::MuSig::KeyAggCache.new if secp256k1_musig_pubkey_agg(context, agg_pubkey, cache.pointer, pubkeys_ptr, pubkeys.length) == 0 raise Error, "secp256k1_musig_pubkey_agg argument error." end Secp256k1::MuSig::KeyAggContext.new(cache) end end |
#generate_musig_nonce(session_id, pk, sk: nil, key_agg_ctx: nil, msg: nil, extra_in: nil) ⇒ Array(String)
Generate nonce pair.
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/secp256k1/musig.rb', line 103 def generate_musig_nonce(session_id, pk, sk: nil, key_agg_ctx: nil, msg: nil, extra_in: nil) validate_string!("session_id", session_id, 32) validate_string!("pk", pk, 33) validate_string!("sk", sk, 32) if sk validate_string!("msg", msg, 32) if msg validate_string!("extra_in", extra_in, 32) if extra_in if key_agg_ctx raise ArgumentError, "key_agg must be Secp256k1::MuSig::KeyAggContext." unless key_agg_ctx.is_a?(KeyAggContext) end with_context do |context| pk_ptr = FFI::MemoryPointer.new(:uchar, 33).put_bytes(0, hex2bin(pk)) pubkey = FFI::MemoryPointer.new(:uchar, 64) raise Error, "pk is invalid public key." unless secp256k1_ec_pubkey_parse(context, pubkey, pk_ptr, 33) == 1 pubnonce = FFI::MemoryPointer.new(:uchar, 132) secnonce = FFI::MemoryPointer.new(:uchar, 132) seckey = sk ? FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, hex2bin(sk)) : nil msg32 = msg ? FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, hex2bin(msg)) : nil extra_input32 = extra_in ? FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, hex2bin(extra_in)) : nil session_secrand32 = FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, hex2bin(session_id)) raise Error, "arguments is invalid." unless secp256k1_musig_nonce_gen( context, secnonce, pubnonce, session_secrand32, seckey, pubkey, msg32, key_agg_ctx.pointer, extra_input32) == 1 pub66 = FFI::MemoryPointer.new(:uchar, 66) secp256k1_musig_pubnonce_serialize(context, pub66, pubnonce) [secnonce.read_string(132).unpack1('H*'), pub66.read_string(66).unpack1('H*')] end end |
#generate_musig_nonce_counter(counter, private_key, key_agg_ctx: nil, msg: nil, extra_in: nil) ⇒ Array(String)
Generate a nonce pair deterministically using a non-repeating counter instead of session randomness. The caller must ensure that counter never repeats for the same key pair.
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/secp256k1/musig.rb', line 145 def generate_musig_nonce_counter(counter, private_key, key_agg_ctx: nil, msg: nil, extra_in: nil) raise ArgumentError, "counter must be Integer." unless counter.is_a?(Integer) raise ArgumentError, "counter must be between 0 and 2**64-1." if counter < 0 || counter > (2**64 - 1) validate_string!("private_key", private_key, 32) validate_string!("msg", msg, 32) if msg validate_string!("extra_in", extra_in, 32) if extra_in if key_agg_ctx raise ArgumentError, "key_agg_ctx must be Secp256k1::MuSig::KeyAggContext." unless key_agg_ctx.is_a?(KeyAggContext) end with_context do |context| keypair = [create_keypair(private_key)].pack('H*') keypair_ptr = FFI::MemoryPointer.new(:uchar, 96).put_bytes(0, keypair) pubnonce = FFI::MemoryPointer.new(:uchar, 132) secnonce = FFI::MemoryPointer.new(:uchar, 132) msg32 = msg ? FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, hex2bin(msg)) : nil extra_input32 = extra_in ? FFI::MemoryPointer.new(:uchar, 32).put_bytes(0, hex2bin(extra_in)) : nil cache_ptr = key_agg_ctx ? key_agg_ctx.pointer : nil raise Error, "arguments is invalid." unless secp256k1_musig_nonce_gen_counter( context, secnonce, pubnonce, counter, keypair_ptr, msg32, cache_ptr, extra_input32) == 1 pub66 = FFI::MemoryPointer.new(:uchar, 66) secp256k1_musig_pubnonce_serialize(context, pub66, pubnonce) [secnonce.read_string(132).unpack1('H*'), pub66.read_string(66).unpack1('H*')] end end |
#generate_musig_session_id ⇒ String
Generate fresh session id for musig signing session.
89 90 91 |
# File 'lib/secp256k1/musig.rb', line 89 def generate_musig_session_id SecureRandom.random_bytes(32).unpack1('H*') end |