github.com/decred/dcrlnd@v0.7.6/input/signdescriptor.go (about) 1 package input 2 3 import ( 4 "encoding/binary" 5 "errors" 6 "io" 7 8 "github.com/decred/dcrd/dcrec/secp256k1/v4" 9 "github.com/decred/dcrd/txscript/v4" 10 "github.com/decred/dcrd/wire" 11 "github.com/decred/dcrlnd/keychain" 12 ) 13 14 var ( 15 // ErrTweakOverdose signals a SignDescriptor is invalid because both of its 16 // SingleTweak and DoubleTweak are non-nil. 17 ErrTweakOverdose = errors.New("sign descriptor should only have one tweak") 18 ) 19 20 // SignDescriptor houses the necessary information required to successfully sign 21 // a given output. This struct is used by the Signer interface in order to gain 22 // access to critical data needed to generate a valid signature. 23 type SignDescriptor struct { 24 // KeyDesc is a descriptor that precisely describes *which* key to use 25 // for signing. This may provide the raw public key directly, or 26 // require the Signer to re-derive the key according to the populated 27 // derivation path. 28 KeyDesc keychain.KeyDescriptor 29 30 // SingleTweak is a scalar value that will be added to the private key 31 // corresponding to the above public key to obtain the private key to 32 // be used to sign this input. This value is typically derived via the 33 // following computation: 34 // 35 // * derivedKey = privkey + sha256(perCommitmentPoint || pubKey) mod N 36 // 37 // NOTE: If this value is nil, then the input can be signed using only 38 // the above public key. Either a SingleTweak should be set or a 39 // DoubleTweak, not both. 40 SingleTweak []byte 41 42 // DoubleTweak is a private key that will be used in combination with 43 // its corresponding private key to derive the private key that is to 44 // be used to sign the target input. Within the Lightning protocol, 45 // this value is typically the commitment secret from a previously 46 // revoked commitment transaction. This value is in combination with 47 // two hash values, and the original private key to derive the private 48 // key to be used when signing. 49 // 50 // * k = (privKey*sha256(pubKey || tweakPub) + 51 // tweakPriv*sha256(tweakPub || pubKey)) mod N 52 // 53 // NOTE: If this value is nil, then the input can be signed using only 54 // the above public key. Either a SingleTweak should be set or a 55 // DoubleTweak, not both. 56 DoubleTweak *secp256k1.PrivateKey 57 58 // WitnessScript is the full script required to properly redeem the 59 // output. This field will only be populated if a p2sh 60 // output is being signed. 61 // 62 // On Decred this is usually referred to as the "redeemScript". 63 WitnessScript []byte 64 65 // Output is the target output which should be signed. The PkScript and 66 // Value fields within the output should be properly populated, 67 // otherwise an invalid signature may be generated. 68 Output *wire.TxOut 69 70 // HashType is the target sighash type that should be used when 71 // generating the final sighash, and signature. 72 HashType txscript.SigHashType 73 74 // InputIndex is the target input within the transaction that should be 75 // signed. 76 InputIndex int 77 } 78 79 // WriteSignDescriptor serializes a SignDescriptor struct into the passed 80 // io.Writer stream. 81 // 82 // NOTE: We assume the SigHashes and InputIndex fields haven't been assigned 83 // yet, since that is usually done just before broadcast by the witness 84 // generator. 85 func WriteSignDescriptor(w io.Writer, sd *SignDescriptor) error { 86 err := binary.Write(w, binary.BigEndian, sd.KeyDesc.Family) 87 if err != nil { 88 return err 89 } 90 err = binary.Write(w, binary.BigEndian, sd.KeyDesc.Index) 91 if err != nil { 92 return err 93 } 94 95 err = binary.Write(w, binary.BigEndian, sd.KeyDesc.PubKey != nil) 96 if err != nil { 97 return err 98 } 99 100 if sd.KeyDesc.PubKey != nil { 101 serializedPubKey := sd.KeyDesc.PubKey.SerializeCompressed() 102 if err := wire.WriteVarBytes(w, 0, serializedPubKey); err != nil { 103 return err 104 } 105 } 106 107 if err := wire.WriteVarBytes(w, 0, sd.SingleTweak); err != nil { 108 return err 109 } 110 111 var doubleTweakBytes []byte 112 if sd.DoubleTweak != nil { 113 doubleTweakBytes = sd.DoubleTweak.Serialize() 114 } 115 if err := wire.WriteVarBytes(w, 0, doubleTweakBytes); err != nil { 116 return err 117 } 118 119 if err := wire.WriteVarBytes(w, 0, sd.WitnessScript); err != nil { 120 return err 121 } 122 123 if err := writeTxOut(w, sd.Output); err != nil { 124 return err 125 } 126 127 var scratch [4]byte 128 binary.BigEndian.PutUint32(scratch[:], uint32(sd.HashType)) 129 if _, err := w.Write(scratch[:]); err != nil { 130 return err 131 } 132 133 return nil 134 } 135 136 // ReadSignDescriptor deserializes a SignDescriptor struct from the passed 137 // io.Reader stream. 138 func ReadSignDescriptor(r io.Reader, sd *SignDescriptor) error { 139 err := binary.Read(r, binary.BigEndian, &sd.KeyDesc.Family) 140 if err != nil { 141 return err 142 } 143 err = binary.Read(r, binary.BigEndian, &sd.KeyDesc.Index) 144 if err != nil { 145 return err 146 } 147 148 var hasKey bool 149 err = binary.Read(r, binary.BigEndian, &hasKey) 150 if err != nil { 151 return err 152 } 153 154 if hasKey { 155 pubKeyBytes, err := wire.ReadVarBytes(r, 0, 34, "pubkey") 156 if err != nil { 157 return err 158 } 159 sd.KeyDesc.PubKey, err = secp256k1.ParsePubKey(pubKeyBytes) 160 if err != nil { 161 return err 162 } 163 } 164 165 singleTweak, err := wire.ReadVarBytes(r, 0, 32, "singleTweak") 166 if err != nil { 167 return err 168 } 169 170 // Serializing a SignDescriptor with a nil-valued SingleTweak results 171 // in deserializing a zero-length slice. Since a nil-valued SingleTweak 172 // has special meaning and a zero-length slice for a SingleTweak is 173 // invalid, we can use the zero-length slice as the flag for a 174 // nil-valued SingleTweak. 175 if len(singleTweak) == 0 { 176 sd.SingleTweak = nil 177 } else { 178 sd.SingleTweak = singleTweak 179 } 180 181 doubleTweakBytes, err := wire.ReadVarBytes(r, 0, 32, "doubleTweak") 182 if err != nil { 183 return err 184 } 185 186 // Serializing a SignDescriptor with a nil-valued DoubleTweak results 187 // in deserializing a zero-length slice. Since a nil-valued DoubleTweak 188 // has special meaning and a zero-length slice for a DoubleTweak is 189 // invalid, we can use the zero-length slice as the flag for a 190 // nil-valued DoubleTweak. 191 if len(doubleTweakBytes) == 0 { 192 sd.DoubleTweak = nil 193 } else { 194 sd.DoubleTweak = secp256k1.PrivKeyFromBytes(doubleTweakBytes) 195 } 196 197 // Only one tweak should ever be set, fail if both are present. 198 if sd.SingleTweak != nil && sd.DoubleTweak != nil { 199 return ErrTweakOverdose 200 } 201 202 witnessScript, err := wire.ReadVarBytes(r, 0, 500, "witnessScript") 203 if err != nil { 204 return err 205 } 206 sd.WitnessScript = witnessScript 207 208 txOut := &wire.TxOut{} 209 if err := readTxOut(r, txOut); err != nil { 210 return err 211 } 212 sd.Output = txOut 213 214 var hashType [4]byte 215 if _, err := io.ReadFull(r, hashType[:]); err != nil { 216 return err 217 } 218 sd.HashType = txscript.SigHashType(binary.BigEndian.Uint32(hashType[:])) 219 220 return nil 221 }