github.com/decred/dcrlnd@v0.7.6/input/test_utils.go (about)

     1  package input
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"fmt"
     7  
     8  	"github.com/decred/dcrd/chaincfg/chainhash"
     9  	"github.com/decred/dcrd/chaincfg/v3"
    10  	"github.com/decred/dcrd/dcrec"
    11  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    12  	"github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
    13  	"github.com/decred/dcrd/dcrutil/v4"
    14  	"github.com/decred/dcrd/txscript/v4"
    15  	"github.com/decred/dcrd/txscript/v4/sign"
    16  	"github.com/decred/dcrd/txscript/v4/stdaddr"
    17  	"github.com/decred/dcrd/txscript/v4/stdscript"
    18  	"github.com/decred/dcrd/wire"
    19  )
    20  
    21  var (
    22  	// For simplicity a single priv key controls all of our test outputs.
    23  	testWalletPrivKey = []byte{
    24  		0x2b, 0xd8, 0x06, 0xc9, 0x7f, 0x0e, 0x00, 0xaf,
    25  		0x1a, 0x1f, 0xc3, 0x32, 0x8f, 0xa7, 0x63, 0xa9,
    26  		0x26, 0x97, 0x23, 0xc8, 0xdb, 0x8f, 0xac, 0x4f,
    27  		0x93, 0xaf, 0x71, 0xdb, 0x18, 0x6d, 0x6e, 0x90,
    28  	}
    29  
    30  	// We're alice :)
    31  	bobsPrivKey = []byte{
    32  		0x81, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda,
    33  		0x63, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
    34  		0xd, 0xe7, 0x95, 0xe4, 0xb7, 0x25, 0xb8, 0x4d,
    35  		0x1e, 0xb, 0x4c, 0xfd, 0x9e, 0xc5, 0x8c, 0xe9,
    36  	}
    37  
    38  	// Use a hard-coded HD seed.
    39  	testHdSeed = chainhash.Hash{
    40  		0xb7, 0x94, 0x38, 0x5f, 0x2d, 0x1e, 0xf7, 0xab,
    41  		0x4d, 0x92, 0x73, 0xd1, 0x90, 0x63, 0x81, 0xb4,
    42  		0x4f, 0x2f, 0x6f, 0x25, 0x88, 0xa3, 0xef, 0xb9,
    43  		0x6a, 0x49, 0x18, 0x83, 0x31, 0x98, 0x47, 0x53,
    44  	}
    45  )
    46  
    47  // MockSigner is a simple implementation of the Signer interface. Each one has
    48  // a set of private keys in a slice and can sign messages using the appropriate
    49  // one.
    50  type MockSigner struct {
    51  	Privkeys  []*secp256k1.PrivateKey
    52  	NetParams *chaincfg.Params
    53  }
    54  
    55  // SignOutputRaw generates a signature for the passed transaction according to
    56  // the data within the passed SignDescriptor.
    57  func (m *MockSigner) SignOutputRaw(tx *wire.MsgTx,
    58  	signDesc *SignDescriptor) (Signature, error) {
    59  
    60  	pubkey := signDesc.KeyDesc.PubKey
    61  	switch {
    62  	case signDesc.SingleTweak != nil:
    63  		pubkey = TweakPubKeyWithTweak(pubkey, signDesc.SingleTweak)
    64  	case signDesc.DoubleTweak != nil:
    65  		pubkey = DeriveRevocationPubkey(pubkey, signDesc.DoubleTweak.PubKey())
    66  	}
    67  
    68  	hash160 := dcrutil.Hash160(pubkey.SerializeCompressed())
    69  	privKey := m.findKey(hash160, signDesc.SingleTweak, signDesc.DoubleTweak)
    70  	if privKey == nil {
    71  		return nil, fmt.Errorf("mock signer does not have key")
    72  	}
    73  
    74  	sig, err := sign.RawTxInSignature(tx, signDesc.InputIndex,
    75  		signDesc.WitnessScript, signDesc.HashType, privKey.Serialize(),
    76  		dcrec.STEcdsaSecp256k1)
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  
    81  	return ecdsa.ParseDERSignature(sig[:len(sig)-1])
    82  }
    83  
    84  func (m *MockSigner) ComputeInputScript(tx *wire.MsgTx, signDesc *SignDescriptor) (*Script, error) {
    85  	scriptType, addresses := stdscript.ExtractAddrs(
    86  		signDesc.Output.Version, signDesc.Output.PkScript, m.NetParams)
    87  
    88  	if len(addresses) != 1 {
    89  		return nil, fmt.Errorf("unexpected nb of addresses (got %d, want %d)",
    90  			len(addresses), 1)
    91  	}
    92  
    93  	switch scriptType {
    94  	case stdscript.STPubKeyHashEcdsaSecp256k1:
    95  		privKey := m.findKey(addresses[0].(stdaddr.Hash160er).Hash160()[:], signDesc.SingleTweak,
    96  			signDesc.DoubleTweak)
    97  		if privKey == nil {
    98  			return nil, fmt.Errorf("mock signer does not have key for "+
    99  				"address %v", addresses[0])
   100  		}
   101  
   102  		sigScript, err := sign.SignatureScript(
   103  			tx, signDesc.InputIndex, signDesc.Output.PkScript,
   104  			txscript.SigHashAll, privKey.Serialize(),
   105  			dcrec.STEcdsaSecp256k1, true,
   106  		)
   107  		if err != nil {
   108  			return nil, err
   109  		}
   110  
   111  		return &Script{SigScript: sigScript}, nil
   112  
   113  	default:
   114  		return nil, fmt.Errorf("unexpected script type: %v", scriptType)
   115  	}
   116  }
   117  
   118  // findKey searches through all stored private keys and returns one
   119  // corresponding to the hashed pubkey if it can be found. The public key may
   120  // either correspond directly to the private key or to the private key with a
   121  // tweak applied.
   122  func (m *MockSigner) findKey(needleHash160 []byte, singleTweak []byte,
   123  	doubleTweak *secp256k1.PrivateKey) *secp256k1.PrivateKey {
   124  
   125  	for _, privkey := range m.Privkeys {
   126  		// First check whether public key is directly derived from private key.
   127  		hash160 := dcrutil.Hash160(privkey.PubKey().SerializeCompressed())
   128  		if bytes.Equal(hash160, needleHash160) {
   129  			return privkey
   130  		}
   131  
   132  		// Otherwise check if public key is derived from tweaked private key.
   133  		switch {
   134  		case singleTweak != nil:
   135  			privkey = TweakPrivKey(privkey, singleTweak)
   136  		case doubleTweak != nil:
   137  			privkey = DeriveRevocationPrivKey(privkey, doubleTweak)
   138  		default:
   139  			continue
   140  		}
   141  		hash160 = dcrutil.Hash160(privkey.PubKey().SerializeCompressed())
   142  		if bytes.Equal(hash160, needleHash160) {
   143  			return privkey
   144  		}
   145  	}
   146  	return nil
   147  }
   148  
   149  // pubkeyFromHex parses a Decred public key from a hex encoded string.
   150  func pubkeyFromHex(keyHex string) (*secp256k1.PublicKey, error) {
   151  	bytes, err := hex.DecodeString(keyHex)
   152  	if err != nil {
   153  		return nil, err
   154  	}
   155  	return secp256k1.ParsePubKey(bytes)
   156  }
   157  
   158  // privkeyFromHex parses a Decred private key from a hex encoded string.
   159  func privkeyFromHex(keyHex string) (*secp256k1.PrivateKey, error) {
   160  	bytes, err := hex.DecodeString(keyHex)
   161  	if err != nil {
   162  		return nil, err
   163  	}
   164  	key := secp256k1.PrivKeyFromBytes(bytes)
   165  	return key, nil
   166  
   167  }
   168  
   169  // pubkeyToHex serializes a Decred public key to a hex encoded string.
   170  func pubkeyToHex(key *secp256k1.PublicKey) string {
   171  	return hex.EncodeToString(key.SerializeCompressed())
   172  }
   173  
   174  // privkeyFromHex serializes a Decred private key to a hex encoded string.
   175  func privkeyToHex(key *secp256k1.PrivateKey) string {
   176  	return hex.EncodeToString(key.Serialize())
   177  }