mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-02-23 06:35:07 +01:00
In this commit, we modify the musig2 interfaces to instead use an explicit value for the local nonces. Before this commit, we used the functional option, but we want to also support specifying this value over RPC for the remote signer. The functional option pattern is opaque, so we can't get the nonce value we need. To get around this, we'll just make this an explicit pointer, then map this to the functional option at the very last moment.
136 lines
4.3 KiB
Go
136 lines
4.3 KiB
Go
package wtmock
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"sync"
|
|
|
|
"github.com/btcsuite/btcd/btcec/v2"
|
|
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
|
"github.com/btcsuite/btcd/btcec/v2/schnorr"
|
|
"github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
|
|
"github.com/btcsuite/btcd/txscript"
|
|
"github.com/btcsuite/btcd/wire"
|
|
"github.com/lightningnetwork/lnd/input"
|
|
"github.com/lightningnetwork/lnd/keychain"
|
|
)
|
|
|
|
// MockSigner is an input.Signer that allows one to add arbitrary private keys
|
|
// and sign messages by passing the assigned keychain.KeyLocator.
|
|
type MockSigner struct {
|
|
mu sync.Mutex
|
|
|
|
index uint32
|
|
keys map[keychain.KeyLocator]*btcec.PrivateKey
|
|
}
|
|
|
|
// NewMockSigner returns a fresh MockSigner.
|
|
func NewMockSigner() *MockSigner {
|
|
return &MockSigner{
|
|
keys: make(map[keychain.KeyLocator]*btcec.PrivateKey),
|
|
}
|
|
}
|
|
|
|
// SignOutputRaw signs an input on the passed transaction using the input index
|
|
// in the sign descriptor. The returned signature is the raw DER-encoded
|
|
// signature without the signhash flag.
|
|
func (s *MockSigner) SignOutputRaw(tx *wire.MsgTx,
|
|
signDesc *input.SignDescriptor) (input.Signature, error) {
|
|
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
|
|
witnessScript := signDesc.WitnessScript
|
|
amt := signDesc.Output.Value
|
|
|
|
privKey, ok := s.keys[signDesc.KeyDesc.KeyLocator]
|
|
if !ok {
|
|
panic("cannot sign w/ unknown key")
|
|
}
|
|
|
|
sig, err := txscript.RawTxInWitnessSignature(
|
|
tx, signDesc.SigHashes, signDesc.InputIndex, amt,
|
|
witnessScript, signDesc.HashType, privKey,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return ecdsa.ParseDERSignature(sig[:len(sig)-1])
|
|
}
|
|
|
|
// ComputeInputScript is not implemented.
|
|
func (s *MockSigner) ComputeInputScript(tx *wire.MsgTx,
|
|
signDesc *input.SignDescriptor) (*input.Script, error) {
|
|
panic("not implemented")
|
|
}
|
|
|
|
// MuSig2CreateSession creates a new MuSig2 signing session using the local
|
|
// key identified by the key locator. The complete list of all public keys of
|
|
// all signing parties must be provided, including the public key of the local
|
|
// signing key. If nonces of other parties are already known, they can be
|
|
// submitted as well to reduce the number of method calls necessary later on.
|
|
func (s *MockSigner) MuSig2CreateSession(input.MuSig2Version,
|
|
keychain.KeyLocator, []*btcec.PublicKey, *input.MuSig2Tweaks,
|
|
[][musig2.PubNonceSize]byte,
|
|
*musig2.Nonces) (*input.MuSig2SessionInfo, error) {
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
// MuSig2RegisterNonces registers one or more public nonces of other signing
|
|
// participants for a session identified by its ID. This method returns true
|
|
// once we have all nonces for all other signing participants.
|
|
func (s *MockSigner) MuSig2RegisterNonces(input.MuSig2SessionID,
|
|
[][musig2.PubNonceSize]byte) (bool, error) {
|
|
|
|
return false, nil
|
|
}
|
|
|
|
// MuSig2Sign creates a partial signature using the local signing key
|
|
// that was specified when the session was created. This can only be
|
|
// called when all public nonces of all participants are known and have
|
|
// been registered with the session. If this node isn't responsible for
|
|
// combining all the partial signatures, then the cleanup parameter
|
|
// should be set, indicating that the session can be removed from memory
|
|
// once the signature was produced.
|
|
func (s *MockSigner) MuSig2Sign(input.MuSig2SessionID,
|
|
[sha256.Size]byte, bool) (*musig2.PartialSignature, error) {
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
// MuSig2CombineSig combines the given partial signature(s) with the
|
|
// local one, if it already exists. Once a partial signature of all
|
|
// participants is registered, the final signature will be combined and
|
|
// returned.
|
|
func (s *MockSigner) MuSig2CombineSig(input.MuSig2SessionID,
|
|
[]*musig2.PartialSignature) (*schnorr.Signature, bool, error) {
|
|
|
|
return nil, false, nil
|
|
}
|
|
|
|
// MuSig2Cleanup removes a session from memory to free up resources.
|
|
func (s *MockSigner) MuSig2Cleanup(input.MuSig2SessionID) error {
|
|
return nil
|
|
}
|
|
|
|
// AddPrivKey records the passed privKey in the MockSigner's registry of keys it
|
|
// can sign with in the future. A unique key locator is returned, allowing the
|
|
// caller to sign with this key when presented via an input.SignDescriptor.
|
|
func (s *MockSigner) AddPrivKey(privKey *btcec.PrivateKey) keychain.KeyLocator {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
|
|
keyLoc := keychain.KeyLocator{
|
|
Index: s.index,
|
|
}
|
|
s.index++
|
|
|
|
s.keys[keyLoc] = privKey
|
|
|
|
return keyLoc
|
|
}
|
|
|
|
// Compile-time constraint ensuring the MockSigner implements the input.Signer
|
|
// interface.
|
|
var _ input.Signer = (*MockSigner)(nil)
|