sign: Add CreateMuSig2Nonce
This commit is contained in:
1 parent
82ea67c607
commit
512b17fc56
7 files changed
+88
-1
No files matched your search
+34
@@ -13,6 +13,7 @@
|
|||||||
#include <secp256k1.h>
|
#include <secp256k1.h>
|
||||||
#include <secp256k1_ellswift.h>
|
#include <secp256k1_ellswift.h>
|
||||||
#include <secp256k1_extrakeys.h>
|
#include <secp256k1_extrakeys.h>
|
||||||
|
#include <secp256k1_musig.h>
|
||||||
#include <secp256k1_recovery.h>
|
#include <secp256k1_recovery.h>
|
||||||
#include <secp256k1_schnorrsig.h>
|
#include <secp256k1_schnorrsig.h>
|
||||||
|
|
||||||
@@ -349,6 +350,39 @@ KeyPair CKey::ComputeKeyPair(const uint256* merkle_root) const
|
|||||||
return KeyPair(*this, merkle_root);
|
return KeyPair(*this, merkle_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> CKey::CreateMuSig2Nonce(MuSig2SecNonce& secnonce, const uint256& sighash, const CPubKey& aggregate_pubkey, const std::vector<CPubKey>& pubkeys)
|
||||||
|
{
|
||||||
|
// Get the keyagg cache and aggregate pubkey
|
||||||
|
secp256k1_musig_keyagg_cache keyagg_cache;
|
||||||
|
if (!MuSig2AggregatePubkeys(pubkeys, keyagg_cache, aggregate_pubkey)) return {};
|
||||||
|
|
||||||
|
// Parse participant pubkey
|
||||||
|
CPubKey our_pubkey = GetPubKey();
|
||||||
|
secp256k1_pubkey pubkey;
|
||||||
|
if (!secp256k1_ec_pubkey_parse(secp256k1_context_static, &pubkey, our_pubkey.data(), our_pubkey.size())) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate randomness for nonce
|
||||||
|
uint256 rand;
|
||||||
|
GetStrongRandBytes(rand);
|
||||||
|
|
||||||
|
// Generate nonce
|
||||||
|
secp256k1_musig_pubnonce pubnonce;
|
||||||
|
if (!secp256k1_musig_nonce_gen(secp256k1_context_sign, secnonce.Get(), &pubnonce, rand.data(), UCharCast(begin()), &pubkey, sighash.data(), &keyagg_cache, nullptr)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize pubnonce
|
||||||
|
std::vector<uint8_t> out;
|
||||||
|
out.resize(MUSIG2_PUBNONCE_SIZE);
|
||||||
|
if (!secp256k1_musig_pubnonce_serialize(secp256k1_context_static, out.data(), &pubnonce)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
CKey GenerateRandomKey(bool compressed) noexcept
|
CKey GenerateRandomKey(bool compressed) noexcept
|
||||||
{
|
{
|
||||||
CKey key;
|
CKey key;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#ifndef BITCOIN_KEY_H
|
#ifndef BITCOIN_KEY_H
|
||||||
#define BITCOIN_KEY_H
|
#define BITCOIN_KEY_H
|
||||||
|
|
||||||
|
#include <musig.h>
|
||||||
#include <pubkey.h>
|
#include <pubkey.h>
|
||||||
#include <serialize.h>
|
#include <serialize.h>
|
||||||
#include <support/allocators/secure.h>
|
#include <support/allocators/secure.h>
|
||||||
@@ -220,6 +221,8 @@ public:
|
|||||||
* Merkle root of the script tree).
|
* Merkle root of the script tree).
|
||||||
*/
|
*/
|
||||||
KeyPair ComputeKeyPair(const uint256* merkle_root) const;
|
KeyPair ComputeKeyPair(const uint256* merkle_root) const;
|
||||||
|
|
||||||
|
std::vector<uint8_t> CreateMuSig2Nonce(MuSig2SecNonce& secnonce, const uint256& sighash, const CPubKey& aggregate_pubkey, const std::vector<CPubKey>& pubkeys);
|
||||||
};
|
};
|
||||||
|
|
||||||
CKey GenerateRandomKey(bool compressed = true) noexcept;
|
CKey GenerateRandomKey(bool compressed = true) noexcept;
|
||||||
|
|||||||
@@ -111,3 +111,10 @@ bool MuSig2SecNonce::IsValid()
|
|||||||
{
|
{
|
||||||
return m_impl->IsValid();
|
return m_impl->IsValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint256 MuSig2SessionID(const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256& sighash)
|
||||||
|
{
|
||||||
|
HashWriter hasher;
|
||||||
|
hasher << script_pubkey << part_pubkey << sighash;
|
||||||
|
return hasher.GetSHA256();
|
||||||
|
}
|
||||||
@@ -18,6 +18,8 @@ struct secp256k1_musig_secnonce;
|
|||||||
using namespace util::hex_literals;
|
using namespace util::hex_literals;
|
||||||
constexpr uint256 MUSIG_CHAINCODE{"868087ca02a6f974c4598924c36b57762d32cb45717167e300622c7167e38965"_hex_u8};
|
constexpr uint256 MUSIG_CHAINCODE{"868087ca02a6f974c4598924c36b57762d32cb45717167e300622c7167e38965"_hex_u8};
|
||||||
|
|
||||||
|
constexpr size_t MUSIG2_PUBNONCE_SIZE{66};
|
||||||
|
|
||||||
//! Compute the full aggregate pubkey from the given participant pubkeys in their current order.
|
//! Compute the full aggregate pubkey from the given participant pubkeys in their current order.
|
||||||
//! Outputs the secp256k1_musig_keyagg_cache and validates that the computed aggregate pubkey matches an expected aggregate pubkey.
|
//! Outputs the secp256k1_musig_keyagg_cache and validates that the computed aggregate pubkey matches an expected aggregate pubkey.
|
||||||
//! This is necessary for most MuSig2 operations.
|
//! This is necessary for most MuSig2 operations.
|
||||||
@@ -58,4 +60,6 @@ public:
|
|||||||
bool IsValid();
|
bool IsValid();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint256 MuSig2SessionID(const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256& sighash);
|
||||||
|
|
||||||
#endif // BITCOIN_MUSIG_H
|
#endif // BITCOIN_MUSIG_H
|
||||||
+1
-1
@@ -794,7 +794,7 @@ struct PSBTInput
|
|||||||
|
|
||||||
std::vector<uint8_t> pubnonce;
|
std::vector<uint8_t> pubnonce;
|
||||||
s >> pubnonce;
|
s >> pubnonce;
|
||||||
if (pubnonce.size() != 66) {
|
if (pubnonce.size() != MUSIG2_PUBNONCE_SIZE) {
|
||||||
throw std::ios_base::failure("Input musig2 pubnonce value is not 66 bytes");
|
throw std::ios_base::failure("Input musig2 pubnonce value is not 66 bytes");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,10 @@
|
|||||||
|
|
||||||
#include <consensus/amount.h>
|
#include <consensus/amount.h>
|
||||||
#include <key.h>
|
#include <key.h>
|
||||||
|
#include <musig.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
#include <primitives/transaction.h>
|
#include <primitives/transaction.h>
|
||||||
|
#include <random.h>
|
||||||
#include <script/keyorigin.h>
|
#include <script/keyorigin.h>
|
||||||
#include <script/miniscript.h>
|
#include <script/miniscript.h>
|
||||||
#include <script/script.h>
|
#include <script/script.h>
|
||||||
@@ -100,6 +102,34 @@ bool MutableTransactionSignatureCreator::CreateSchnorrSig(const SigningProvider&
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> MutableTransactionSignatureCreator::CreateMuSig2Nonce(const SigningProvider& provider, const CPubKey& aggregate_pubkey, const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256* leaf_hash, const uint256* merkle_root, SigVersion sigversion, const SignatureData& sigdata) const
|
||||||
|
{
|
||||||
|
assert(sigversion == SigVersion::TAPROOT || sigversion == SigVersion::TAPSCRIPT);
|
||||||
|
|
||||||
|
// Retrieve the private key
|
||||||
|
CKey key;
|
||||||
|
if (!provider.GetKey(part_pubkey.GetID(), key)) return {};
|
||||||
|
|
||||||
|
// Retrieve participant pubkeys
|
||||||
|
auto it = sigdata.musig2_pubkeys.find(aggregate_pubkey);
|
||||||
|
if (it == sigdata.musig2_pubkeys.end()) return {};
|
||||||
|
const std::vector<CPubKey>& pubkeys = it->second;
|
||||||
|
if (std::find(pubkeys.begin(), pubkeys.end(), part_pubkey) == pubkeys.end()) return {};
|
||||||
|
|
||||||
|
// Compute sighash
|
||||||
|
std::optional<uint256> sighash = ComputeSchnorrSignatureHash(leaf_hash, sigversion);
|
||||||
|
if (!sighash.has_value()) return {};
|
||||||
|
|
||||||
|
MuSig2SecNonce secnonce;
|
||||||
|
std::vector<uint8_t> out = key.CreateMuSig2Nonce(secnonce, *sighash, aggregate_pubkey, pubkeys);
|
||||||
|
if (out.empty()) return {};
|
||||||
|
|
||||||
|
// Store the secnonce in the SigningProvider
|
||||||
|
provider.SetMuSig2SecNonce(MuSig2SessionID(script_pubkey, part_pubkey, *sighash), std::move(secnonce));
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
static bool GetCScript(const SigningProvider& provider, const SignatureData& sigdata, const CScriptID& scriptid, CScript& script)
|
static bool GetCScript(const SigningProvider& provider, const SignatureData& sigdata, const CScriptID& scriptid, CScript& script)
|
||||||
{
|
{
|
||||||
if (provider.GetCScript(scriptid, script)) {
|
if (provider.GetCScript(scriptid, script)) {
|
||||||
@@ -755,6 +785,12 @@ public:
|
|||||||
sig.assign(64, '\000');
|
sig.assign(64, '\000');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
std::vector<uint8_t> CreateMuSig2Nonce(const SigningProvider& provider, const CPubKey& aggregate_pubkey, const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256* leaf_hash, const uint256* merkle_root, SigVersion sigversion, const SignatureData& sigdata) const override
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> out;
|
||||||
|
out.assign(MUSIG2_PUBNONCE_SIZE, '\000');
|
||||||
|
return out;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class SigningProvider;
|
|||||||
|
|
||||||
struct bilingual_str;
|
struct bilingual_str;
|
||||||
struct CMutableTransaction;
|
struct CMutableTransaction;
|
||||||
|
struct SignatureData;
|
||||||
|
|
||||||
/** Interface for signature creators. */
|
/** Interface for signature creators. */
|
||||||
class BaseSignatureCreator {
|
class BaseSignatureCreator {
|
||||||
@@ -33,6 +34,7 @@ public:
|
|||||||
/** Create a singular (non-script) signature. */
|
/** Create a singular (non-script) signature. */
|
||||||
virtual bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const =0;
|
virtual bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const =0;
|
||||||
virtual bool CreateSchnorrSig(const SigningProvider& provider, std::vector<unsigned char>& sig, const XOnlyPubKey& pubkey, const uint256* leaf_hash, const uint256* merkle_root, SigVersion sigversion) const =0;
|
virtual bool CreateSchnorrSig(const SigningProvider& provider, std::vector<unsigned char>& sig, const XOnlyPubKey& pubkey, const uint256* leaf_hash, const uint256* merkle_root, SigVersion sigversion) const =0;
|
||||||
|
virtual std::vector<uint8_t> CreateMuSig2Nonce(const SigningProvider& provider, const CPubKey& aggregate_pubkey, const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256* leaf_hash, const uint256* merkle_root, SigVersion sigversion, const SignatureData& sigdata) const =0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A signature creator for transactions. */
|
/** A signature creator for transactions. */
|
||||||
@@ -53,6 +55,7 @@ public:
|
|||||||
const BaseSignatureChecker& Checker() const override { return checker; }
|
const BaseSignatureChecker& Checker() const override { return checker; }
|
||||||
bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override;
|
bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override;
|
||||||
bool CreateSchnorrSig(const SigningProvider& provider, std::vector<unsigned char>& sig, const XOnlyPubKey& pubkey, const uint256* leaf_hash, const uint256* merkle_root, SigVersion sigversion) const override;
|
bool CreateSchnorrSig(const SigningProvider& provider, std::vector<unsigned char>& sig, const XOnlyPubKey& pubkey, const uint256* leaf_hash, const uint256* merkle_root, SigVersion sigversion) const override;
|
||||||
|
std::vector<uint8_t> CreateMuSig2Nonce(const SigningProvider& provider, const CPubKey& aggregate_pubkey, const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256* leaf_hash, const uint256* merkle_root, SigVersion sigversion, const SignatureData& sigdata) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A signature checker that accepts all signatures */
|
/** A signature checker that accepts all signatures */
|
||||||
|
|||||||
Reference in new issue
Block a user