@@ -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: %v" ,
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
@@ -495,6 +498,14 @@ func (h *HtlcScriptV1) SuccessSequence() uint32 {
495498 return 0
496499}
497500
501+ // lockingConditions return the address, pkScript and sigScript (if
502+ // required) for a htlc script.
503+ func (h * HtlcScriptV1 ) lockingConditions (htlcOutputType HtlcOutputType ,
504+ params * chaincfg.Params ) (btcutil.Address , []byte , []byte , error ) {
505+
506+ return segwitV0LockingConditions (htlcOutputType , params , h .script )
507+ }
508+
498509// HtlcScriptV2 encapsulates the htlc v2 script.
499510type HtlcScriptV2 struct {
500511 script []byte
@@ -629,6 +640,14 @@ func (h *HtlcScriptV2) SuccessSequence() uint32 {
629640 return 1
630641}
631642
643+ // lockingConditions return the address, pkScript and sigScript (if
644+ // required) for a htlc script.
645+ func (h * HtlcScriptV2 ) lockingConditions (htlcOutputType HtlcOutputType ,
646+ params * chaincfg.Params ) (btcutil.Address , []byte , []byte , error ) {
647+
648+ return segwitV0LockingConditions (htlcOutputType , params , h .script )
649+ }
650+
632651// HtlcScriptV3 encapsulates the htlc v3 script.
633652type HtlcScriptV3 struct {
634653 // The final locking script for the timeout path which is available to
@@ -865,3 +884,35 @@ func (h *HtlcScriptV3) MaxTimeoutWitnessSize() int {
865884func (h * HtlcScriptV3 ) SuccessSequence () uint32 {
866885 return 1
867886}
887+
888+ // lockingConditions return the address, pkScript and sigScript (if required)
889+ // for a htlc script.
890+ func (h * HtlcScriptV3 ) lockingConditions (outputType HtlcOutputType ,
891+ chainParams * chaincfg.Params ) (btcutil.Address , []byte , []byte , error ) {
892+
893+ // HtlcV3 can only have taproot output type, because we utilize
894+ // tapscript claim paths.
895+ if outputType != HtlcP2TR {
896+ return nil , nil , nil , fmt .Errorf ("htlc v3 only supports P2TR " +
897+ "outputs, got: %v" , outputType )
898+ }
899+
900+ // Generate a tapscript address from our tree.
901+ address , err := btcutil .NewAddressTaproot (
902+ schnorr .SerializePubKey (h .TaprootKey ),
903+ chainParams ,
904+ )
905+ if err != nil {
906+ return nil , nil , nil , err
907+ }
908+
909+ // Generate locking script.
910+ pkScript , err := txscript .PayToAddrScript (address )
911+ if err != nil {
912+ return nil , nil , nil , err
913+ }
914+
915+ // Taproot (segwit v1) does not need a sigScript (we provide it in the
916+ // witness instead), so we return nil for our sigScript.
917+ return address , pkScript , nil , nil
918+ }
0 commit comments