@ -65,6 +65,11 @@ type HtlcScript interface {
// Script returns the htlc script.
Script ( ) [ ] byte
// lockingConditions return the address, pkScript and sigScript (if
// required) for a htlc script.
lockingConditions ( HtlcOutputType , * chaincfg . Params ) ( btcutil . Address ,
[ ] byte , [ ] byte , error )
// MaxSuccessWitnessSize returns the maximum witness size for the
// success case witness.
MaxSuccessWitnessSize ( ) int
@ -190,14 +195,36 @@ func NewHtlc(version ScriptVersion, cltvExpiry int32,
return nil , err
}
var pkScript , sigScript [ ] byte
var address btcutil . Address
address , pkScript , sigScript , err := htlc . lockingConditions (
outputType , chainParams ,
)
if err != nil {
return nil , fmt . Errorf ( "could not get address: %w" , err )
}
return & Htlc {
HtlcScript : htlc ,
Hash : hash ,
Version : version ,
PkScript : pkScript ,
OutputType : outputType ,
ChainParams : chainParams ,
Address : address ,
SigScript : sigScript ,
} , nil
}
// segwitV0LockingConditions provides the address, pkScript and sigScript (if
// required) for the segwit v0 script and output type provided.
func segwitV0LockingConditions ( outputType HtlcOutputType ,
chainParams * chaincfg . Params , script [ ] byte ) ( btcutil . Address ,
[ ] byte , [ ] byte , error ) {
switch outputType {
case HtlcNP2WSH :
p2wshPkScript , err := input . WitnessScriptHash ( htlc . Script ( ) )
p2wshPkScript , err := input . WitnessScriptHash ( script )
if err != nil {
return nil , err
return nil , nil , nil , err
}
// Generate p2sh script for p2wsh (nested).
@ -210,78 +237,54 @@ func NewHtlc(version ScriptVersion, cltvExpiry int32,
builder . AddData ( hash160 )
builder . AddOp ( txscript . OP_EQUAL )
pkScript , err = builder . Script ( )
pkScript , err : = builder . Script ( )
if err != nil {
return nil , err
return nil , nil , nil , err
}
// Generate a valid sigScript that will allow us to spend the
// p2sh output. The sigScript will contain only a single push of
// the p2wsh witness program corresponding to the matching
// public key of this address.
sigScript , err = txscript . NewScriptBuilder ( ) .
sigScript , err : = txscript . NewScriptBuilder ( ) .
AddData ( p2wshPkScript ) .
Script ( )
if err != nil {
return nil , err
return nil , nil , nil , err
}
address , err = btcutil . NewAddressScriptHash (
address , err : = btcutil . NewAddressScriptHash (
p2wshPkScript , chainParams ,
)
if err != nil {
return nil , err
return nil , nil , nil , err
}
return address , pkScript , sigScript , nil
case HtlcP2WSH :
pkScript , err = input . WitnessScriptHash ( htlc . Script ( ) )
pkScript , err := input . WitnessScriptHash ( script )
if err != nil {
return nil , err
return nil , nil , nil , err
}
address , err = btcutil . NewAddressWitnessScriptHash (
address , err : = btcutil . NewAddressWitnessScriptHash (
pkScript [ 2 : ] ,
chainParams ,
)
if err != nil {
return nil , err
}
case HtlcP2TR :
// Confirm we have a v3 htlc.
trHtlc , ok := htlc . ( * HtlcScriptV3 )
if ! ok {
return nil , ErrInvalidOutputSelected
}
// Generate a tapscript address from our HTLC's taptree.
address , err = btcutil . NewAddressTaproot (
schnorr . SerializePubKey ( trHtlc . TaprootKey ) , chainParams ,
)
if err != nil {
return nil , err
return nil , nil , nil , err
}
// Generate locking script.
pkScript , err = txscript . PayToAddrScript ( address )
if err != nil {
return nil , err
}
// Pay to witness script hash (segwit v0) does not need a
// sigScript (we provide it in the witness instead), so we
// return nil for our sigScript.
return address , pkScript , nil , nil
default :
return nil , errors . New ( "unknown output type" )
return nil , nil , nil , fmt . Errorf ( "unexpected output type: %d" ,
outputType )
}
return & Htlc {
HtlcScript : htlc ,
Hash : hash ,
Version : version ,
PkScript : pkScript ,
OutputType : outputType ,
ChainParams : chainParams ,
Address : address ,
SigScript : sigScript ,
} , nil
}
// GenSuccessWitness returns the success script to spend this htlc with
@ -491,6 +494,14 @@ func (h *HtlcScriptV1) SuccessSequence() uint32 {
return 0
}
// lockingConditions return the address, pkScript and sigScript (if
// required) for a htlc script.
func ( h * HtlcScriptV1 ) lockingConditions ( htlcOutputType HtlcOutputType ,
params * chaincfg . Params ) ( btcutil . Address , [ ] byte , [ ] byte , error ) {
return segwitV0LockingConditions ( htlcOutputType , params , h . script )
}
// HtlcScriptV2 encapsulates the htlc v2 script.
type HtlcScriptV2 struct {
script [ ] byte
@ -625,6 +636,14 @@ func (h *HtlcScriptV2) SuccessSequence() uint32 {
return 1
}
// lockingConditions return the address, pkScript and sigScript (if
// required) for a htlc script.
func ( h * HtlcScriptV2 ) lockingConditions ( htlcOutputType HtlcOutputType ,
params * chaincfg . Params ) ( btcutil . Address , [ ] byte , [ ] byte , error ) {
return segwitV0LockingConditions ( htlcOutputType , params , h . script )
}
// HtlcScriptV3 encapsulates the htlc v3 script.
type HtlcScriptV3 struct {
// The final locking script for the timeout path which is available to
@ -861,3 +880,34 @@ func (h *HtlcScriptV3) MaxTimeoutWitnessSize() int {
func ( h * HtlcScriptV3 ) SuccessSequence ( ) uint32 {
return 1
}
// lockingConditions return the address, pkScript and sigScript (if required)
// for a htlc script.
func ( h * HtlcScriptV3 ) lockingConditions ( outputType HtlcOutputType ,
chainParams * chaincfg . Params ) ( btcutil . Address , [ ] byte , [ ] byte , error ) {
// HtlcV3 can only have taproot output type, because we utilize
// tapscript claim paths.
if outputType != HtlcP2TR {
return nil , nil , nil , fmt . Errorf ( "htlc v3 only supports P2TR " +
"outputs, got: %v" , outputType )
}
// Generate a tapscript address from our tree.
address , err := btcutil . NewAddressTaproot (
schnorr . SerializePubKey ( h . TaprootKey ) , chainParams ,
)
if err != nil {
return nil , nil , nil , err
}
// Generate locking script.
pkScript , err := txscript . PayToAddrScript ( address )
if err != nil {
return nil , nil , nil , err
}
// Taproot (segwit v1) does not need a sigScript (we provide it in the
// witness instead), so we return nil for our sigScript.
return address , pkScript , nil , nil
}