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 }