@@ -65,6 +65,11 @@ type HtlcScript interface {
6565 // Script returns the htlc script.
6666 Script () []byte
6767
68+ // lockingConditions return the address, pkScript and sigScript (if
69+ // required) for a htlc script.
70+ lockingConditions (HtlcOutputType , * chaincfg.Params ) (btcutil.Address ,
71+ []byte , []byte , error )
72+
6873 // MaxSuccessWitnessSize returns the maximum witness size for the
6974 // success case witness.
7075 MaxSuccessWitnessSize () int
@@ -190,14 +195,36 @@ func NewHtlc(version ScriptVersion, cltvExpiry int32,
190195 return nil , err
191196 }
192197
193- var pkScript , sigScript []byte
194- var address btcutil.Address
198+ address , pkScript , sigScript , err := htlc .lockingConditions (
199+ outputType , chainParams ,
200+ )
201+ if err != nil {
202+ return nil , fmt .Errorf ("could not get address: %w" , err )
203+ }
204+
205+ return & Htlc {
206+ HtlcScript : htlc ,
207+ Hash : hash ,
208+ Version : version ,
209+ PkScript : pkScript ,
210+ OutputType : outputType ,
211+ ChainParams : chainParams ,
212+ Address : address ,
213+ SigScript : sigScript ,
214+ }, nil
215+ }
216+
217+ // segwitV0LockingConditions provides the address, pkScript and sigScript (if
218+ // required) for the segwit v0 script and output type provided.
219+ func segwitV0LockingConditions (outputType HtlcOutputType ,
220+ chainParams * chaincfg.Params , script []byte ) (btcutil.Address ,
221+ []byte , []byte , error ) {
195222
196223 switch outputType {
197224 case HtlcNP2WSH :
198- p2wshPkScript , err := input .WitnessScriptHash (htlc . Script () )
225+ p2wshPkScript , err := input .WitnessScriptHash (script )
199226 if err != nil {
200- return nil , err
227+ return nil , nil , nil , err
201228 }
202229
203230 // Generate p2sh script for p2wsh (nested).
@@ -210,78 +237,54 @@ func NewHtlc(version ScriptVersion, cltvExpiry int32,
210237 builder .AddData (hash160 )
211238 builder .AddOp (txscript .OP_EQUAL )
212239
213- pkScript , err = builder .Script ()
240+ pkScript , err : = builder .Script ()
214241 if err != nil {
215- return nil , err
242+ return nil , nil , nil , err
216243 }
217244
218245 // Generate a valid sigScript that will allow us to spend the
219246 // p2sh output. The sigScript will contain only a single push of
220247 // the p2wsh witness program corresponding to the matching
221248 // public key of this address.
222- sigScript , err = txscript .NewScriptBuilder ().
249+ sigScript , err : = txscript .NewScriptBuilder ().
223250 AddData (p2wshPkScript ).
224251 Script ()
225252 if err != nil {
226- return nil , err
253+ return nil , nil , nil , err
227254 }
228255
229- address , err = btcutil .NewAddressScriptHash (
256+ address , err : = btcutil .NewAddressScriptHash (
230257 p2wshPkScript , chainParams ,
231258 )
232259 if err != nil {
233- return nil , err
260+ return nil , nil , nil , err
234261 }
235262
263+ return address , pkScript , sigScript , nil
264+
236265 case HtlcP2WSH :
237- pkScript , err = input .WitnessScriptHash (htlc . Script () )
266+ pkScript , err : = input .WitnessScriptHash (script )
238267 if err != nil {
239- return nil , err
268+ return nil , nil , nil , err
240269 }
241270
242- address , err = btcutil .NewAddressWitnessScriptHash (
271+ address , err : = btcutil .NewAddressWitnessScriptHash (
243272 pkScript [2 :],
244273 chainParams ,
245274 )
246275 if err != nil {
247- return nil , err
248- }
249-
250- case HtlcP2TR :
251- // Confirm we have a v3 htlc.
252- trHtlc , ok := htlc .(* HtlcScriptV3 )
253- if ! ok {
254- return nil , ErrInvalidOutputSelected
255- }
256-
257- // Generate a tapscript address from our HTLC's taptree.
258- address , err = btcutil .NewAddressTaproot (
259- schnorr .SerializePubKey (trHtlc .TaprootKey ), chainParams ,
260- )
261- if err != nil {
262- return nil , err
276+ return nil , nil , nil , err
263277 }
264278
265- // Generate locking script.
266- pkScript , err = txscript .PayToAddrScript (address )
267- if err != nil {
268- return nil , err
269- }
279+ // Pay to witness script hash (segwit v0) does not need a
280+ // sigScript (we provide it in the witness instead), so we
281+ // return nil for our sigScript.
282+ return address , pkScript , nil , nil
270283
271284 default :
272- return nil , errors .New ("unknown output type" )
285+ return nil , nil , nil , fmt .Errorf ("unexpected output type: %d" ,
286+ outputType )
273287 }
274-
275- return & Htlc {
276- HtlcScript : htlc ,
277- Hash : hash ,
278- Version : version ,
279- PkScript : pkScript ,
280- OutputType : outputType ,
281- ChainParams : chainParams ,
282- Address : address ,
283- SigScript : sigScript ,
284- }, nil
285288}
286289
287290// GenSuccessWitness returns the success script to spend this htlc with
@@ -491,6 +494,14 @@ func (h *HtlcScriptV1) SuccessSequence() uint32 {
491494 return 0
492495}
493496
497+ // lockingConditions return the address, pkScript and sigScript (if
498+ // required) for a htlc script.
499+ func (h * HtlcScriptV1 ) lockingConditions (htlcOutputType HtlcOutputType ,
500+ params * chaincfg.Params ) (btcutil.Address , []byte , []byte , error ) {
501+
502+ return segwitV0LockingConditions (htlcOutputType , params , h .script )
503+ }
504+
494505// HtlcScriptV2 encapsulates the htlc v2 script.
495506type HtlcScriptV2 struct {
496507 script []byte
@@ -625,6 +636,14 @@ func (h *HtlcScriptV2) SuccessSequence() uint32 {
625636 return 1
626637}
627638
639+ // lockingConditions return the address, pkScript and sigScript (if
640+ // required) for a htlc script.
641+ func (h * HtlcScriptV2 ) lockingConditions (htlcOutputType HtlcOutputType ,
642+ params * chaincfg.Params ) (btcutil.Address , []byte , []byte , error ) {
643+
644+ return segwitV0LockingConditions (htlcOutputType , params , h .script )
645+ }
646+
628647// HtlcScriptV3 encapsulates the htlc v3 script.
629648type HtlcScriptV3 struct {
630649 // The final locking script for the timeout path which is available to
@@ -861,3 +880,34 @@ func (h *HtlcScriptV3) MaxTimeoutWitnessSize() int {
861880func (h * HtlcScriptV3 ) SuccessSequence () uint32 {
862881 return 1
863882}
883+
884+ // lockingConditions return the address, pkScript and sigScript (if required)
885+ // for a htlc script.
886+ func (h * HtlcScriptV3 ) lockingConditions (outputType HtlcOutputType ,
887+ chainParams * chaincfg.Params ) (btcutil.Address , []byte , []byte , error ) {
888+
889+ // HtlcV3 can only have taproot output type, because we utilize
890+ // tapscript claim paths.
891+ if outputType != HtlcP2TR {
892+ return nil , nil , nil , fmt .Errorf ("htlc v3 only supports P2TR " +
893+ "outputs, got: %v" , outputType )
894+ }
895+
896+ // Generate a tapscript address from our tree.
897+ address , err := btcutil .NewAddressTaproot (
898+ schnorr .SerializePubKey (h .TaprootKey ), chainParams ,
899+ )
900+ if err != nil {
901+ return nil , nil , nil , err
902+ }
903+
904+ // Generate locking script.
905+ pkScript , err := txscript .PayToAddrScript (address )
906+ if err != nil {
907+ return nil , nil , nil , err
908+ }
909+
910+ // Taproot (segwit v1) does not need a sigScript (we provide it in the
911+ // witness instead), so we return nil for our sigScript.
912+ return address , pkScript , nil , nil
913+ }
0 commit comments