github.com/decred/dcrlnd@v0.7.6/watchtower/wtmock/signer.go (about)

     1  package wtmock
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/decred/dcrd/dcrec"
     7  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
     8  	"github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
     9  	"github.com/decred/dcrd/txscript/v4/sign"
    10  	"github.com/decred/dcrd/wire"
    11  	"github.com/decred/dcrlnd/input"
    12  	"github.com/decred/dcrlnd/keychain"
    13  )
    14  
    15  // MockSigner is an input.Signer that allows one to add arbitrary private keys
    16  // and sign messages by passing the assigned keychain.KeyLocator.
    17  type MockSigner struct {
    18  	mu sync.Mutex
    19  
    20  	index uint32
    21  	keys  map[keychain.KeyLocator]*secp256k1.PrivateKey
    22  }
    23  
    24  // NewMockSigner returns a fresh MockSigner.
    25  func NewMockSigner() *MockSigner {
    26  	return &MockSigner{
    27  		keys: make(map[keychain.KeyLocator]*secp256k1.PrivateKey),
    28  	}
    29  }
    30  
    31  // SignOutputRaw signs an input on the passed transaction using the input index
    32  // in the sign descriptor. The returned signature is the raw DER-encoded
    33  // signature without the signhash flag.
    34  func (s *MockSigner) SignOutputRaw(tx *wire.MsgTx,
    35  	signDesc *input.SignDescriptor) (input.Signature, error) {
    36  	s.mu.Lock()
    37  	defer s.mu.Unlock()
    38  
    39  	witnessScript := signDesc.WitnessScript
    40  
    41  	privKey, ok := s.keys[signDesc.KeyDesc.KeyLocator]
    42  	if !ok {
    43  		panic("cannot sign w/ unknown key")
    44  	}
    45  
    46  	sig, err := sign.RawTxInSignature(
    47  		tx, signDesc.InputIndex,
    48  		witnessScript, signDesc.HashType, privKey.Serialize(),
    49  		dcrec.STEcdsaSecp256k1,
    50  	)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  
    55  	return ecdsa.ParseDERSignature(sig[:len(sig)-1])
    56  }
    57  
    58  // ComputeInputScript is not implemented.
    59  func (s *MockSigner) ComputeInputScript(tx *wire.MsgTx,
    60  	signDesc *input.SignDescriptor) (*input.Script, error) {
    61  	panic("not implemented")
    62  }
    63  
    64  // AddPrivKey records the passed privKey in the MockSigner's registry of keys it
    65  // can sign with in the future. A unique key locator is returned, allowing the
    66  // caller to sign with this key when presented via an input.SignDescriptor.
    67  func (s *MockSigner) AddPrivKey(privKey *secp256k1.PrivateKey) keychain.KeyLocator {
    68  	s.mu.Lock()
    69  	defer s.mu.Unlock()
    70  
    71  	keyLoc := keychain.KeyLocator{
    72  		Index: s.index,
    73  	}
    74  	s.index++
    75  
    76  	s.keys[keyLoc] = privKey
    77  
    78  	return keyLoc
    79  }
    80  
    81  // Compile-time constraint ensuring the MockSigner implements the input.Signer
    82  // interface.
    83  var _ input.Signer = (*MockSigner)(nil)