decred.org/dcrdex@v1.0.3/dex/networks/btc/script.go (about)

     1  // This code is available on the terms of the project LICENSE.md file,
     2  // also available online at https://blueoakcouncil.org/license/1.0.0.
     3  
     4  package btc
     5  
     6  import (
     7  	"bytes"
     8  	"crypto/sha256"
     9  	"encoding/binary"
    10  	"encoding/hex"
    11  	"errors"
    12  	"fmt"
    13  
    14  	"decred.org/dcrdex/dex"
    15  	"decred.org/dcrdex/server/account"
    16  	"github.com/btcsuite/btcd/btcutil"
    17  	"github.com/btcsuite/btcd/chaincfg"
    18  	"github.com/btcsuite/btcd/txscript"
    19  	"github.com/btcsuite/btcd/wire"
    20  	dcrtxscript "github.com/decred/dcrd/txscript/v4"
    21  )
    22  
    23  const (
    24  	// MaxCLTVScriptNum is the largest usable value for a CLTV lockTime. This
    25  	// will actually be stored in a 5-byte ScriptNum since they have a sign bit,
    26  	// however, it is not 2^39-1 since the spending transaction's nLocktime is
    27  	// an unsigned 32-bit integer and it must be at least the CLTV value. This
    28  	// establishes a maximum lock time of February 7, 2106. Any later requires
    29  	// using a block height instead of a unix epoch time stamp.
    30  	MaxCLTVScriptNum = 1<<32 - 1 // 0xffff_ffff a.k.a. 2^32-1
    31  
    32  	// SecretHashSize is the byte-length of the hash of the secret key used in an
    33  	// atomic swap.
    34  	SecretHashSize = 32
    35  
    36  	// SecretKeySize is the byte-length of the secret key used in an atomic swap.
    37  	SecretKeySize = 32
    38  
    39  	// ContractHashSize is the size of the script-hash for an atomic swap
    40  	// contract.
    41  	ContractHashSize = 20
    42  
    43  	// PubKeyLength is the length of a serialized compressed public key.
    44  	PubKeyLength = 33
    45  
    46  	// 4 bytes version + 4 bytes locktime + 2 bytes of varints for the number of
    47  	// transaction inputs and outputs
    48  	MinimumBlockOverHead = 10
    49  
    50  	// SwapContractSize is the worst case scenario size for a swap contract,
    51  	// which is the pk-script of the non-change output of an initialization
    52  	// transaction as used in execution of an atomic swap.
    53  	// See ExtractSwapDetails for a breakdown of the bytes.
    54  	SwapContractSize = 97
    55  
    56  	// DERSigLength is the maximum length of a DER encoded signature with a
    57  	// sighash type byte.
    58  	DERSigLength = 73
    59  
    60  	// RedeemSwapSigScriptSize is the worst case (largest) serialize size
    61  	// of a transaction signature script that redeems atomic swap output contract.
    62  	// It is calculated as:
    63  	//
    64  	//   - OP_DATA_73
    65  	//   - 72 bytes DER signature + 1 byte sighash
    66  	//   - OP_DATA_33
    67  	//   - 33 bytes serialized compressed pubkey
    68  	//   - OP_DATA_32
    69  	//   - 32 bytes secret key
    70  	//   - OP_1
    71  	//   - varint 97
    72  	//   - 97 bytes redeem script
    73  	RedeemSwapSigScriptSize = 1 + DERSigLength + 1 + 33 + 1 + 32 + 1 + 2 + 97
    74  
    75  	// RefundSigScriptSize is the worst case (largest) serialize size
    76  	// of a transaction input script that refunds a compressed P2PKH output.
    77  	// It is calculated as:
    78  	//
    79  	//   - OP_DATA_73
    80  	//   - 72 bytes DER signature + 1 byte sighash
    81  	//   - OP_DATA_33
    82  	//   - 33 bytes serialized compressed pubkey
    83  	//   - OP_0
    84  	//   - varint 97 => OP_PUSHDATA1(0x4c) + 0x61
    85  	//   - 97 bytes contract
    86  	RefundSigScriptSize = 1 + DERSigLength + 1 + 33 + 1 + 2 + 97
    87  
    88  	// Overhead for a wire.TxIn. See wire.TxIn.SerializeSize.
    89  	// hash 32 bytes + index 4 bytes + sequence 4 bytes.
    90  	TxInOverhead = 32 + 4 + 4 // 40
    91  
    92  	// TxOutOverhead is the overhead associated with a transaction output.
    93  	// 8 bytes value + at least 1 byte varint script size
    94  	TxOutOverhead = 8 + 1
    95  
    96  	RedeemP2PKSigScriptSize = 1 + DERSigLength
    97  
    98  	// RedeemP2PKHSigScriptSize is the worst case (largest) serialize size
    99  	// of a transaction input script that redeems a compressed P2PKH output.
   100  	// It is calculated as:
   101  	//
   102  	//   - OP_DATA_73
   103  	//   - 72 bytes DER signature + 1 byte sighash
   104  	//   - OP_DATA_33
   105  	//   - 33 bytes serialized compressed pubkey
   106  	RedeemP2PKHSigScriptSize = 1 + DERSigLength + 1 + 33 // 108
   107  
   108  	// RedeemP2SHSigScriptSize does not include the redeem script.
   109  	//RedeemP2SHSigScriptSize = 1 + DERSigLength + 1 + 1 + 33 + 1 // + redeem script!
   110  
   111  	// P2PKHPkScriptSize is the size of a transaction output script that
   112  	// pays to a compressed pubkey hash.  It is calculated as:
   113  	//
   114  	//   - OP_DUP
   115  	//   - OP_HASH160
   116  	//   - OP_DATA_20
   117  	//   - 20 bytes pubkey hash
   118  	//   - OP_EQUALVERIFY
   119  	//   - OP_CHECKSIG
   120  	P2PKHPkScriptSize = 1 + 1 + 1 + 20 + 1 + 1 // 25
   121  
   122  	// P2PKHOutputSize is the size of the serialized P2PKH output.
   123  	P2PKHOutputSize = TxOutOverhead + P2PKHPkScriptSize // 9 + 25 = 34
   124  
   125  	// P2SHPkScriptSize is the size of a transaction output script that
   126  	// pays to a redeem script.  It is calculated as:
   127  	//
   128  	//   - OP_HASH160
   129  	//   - OP_DATA_20
   130  	//   - 20 bytes redeem script hash
   131  	//   - OP_EQUAL
   132  	P2SHPkScriptSize = 1 + 1 + 20 + 1
   133  
   134  	// P2SHOutputSize is the size of the serialized P2SH output.
   135  	P2SHOutputSize = TxOutOverhead + P2SHPkScriptSize // 9 + 23 = 32
   136  
   137  	// P2WSHPkScriptSize is the size of a segwit transaction output script that
   138  	// pays to a redeem script.  It is calculated as:
   139  	//
   140  	//   - OP_0
   141  	//   - OP_DATA_32
   142  	//   - 32 bytes redeem script hash
   143  	P2WSHPkScriptSize = 1 + 1 + 32
   144  
   145  	// P2WSHOutputSize is the size of the serialized P2WSH output.
   146  	P2WSHOutputSize = TxOutOverhead + P2WSHPkScriptSize // 9 + 34 = 43
   147  
   148  	// RedeemP2PKHInputSize is the worst case (largest) serialize size of a
   149  	// transaction input redeeming a compressed P2PKH output.  It is
   150  	// calculated as:
   151  	//
   152  	//   - 32 bytes previous tx
   153  	//   - 4 bytes output index
   154  	//   - 4 bytes sequence
   155  	//   - 1 byte compact int encoding value 108
   156  	//   - 108 bytes signature script
   157  	RedeemP2PKHInputSize = TxInOverhead + 1 + RedeemP2PKHSigScriptSize // 40 + 1 + 108 = 149
   158  
   159  	// RedeemP2WPKHInputSize is the worst case size of a transaction
   160  	// input redeeming a P2WPKH output. This does not account for witness data,
   161  	// which is considered at a lower weight for fee calculations. It is
   162  	// calculated as
   163  	//
   164  	//   - 32 bytes previous tx
   165  	//   - 4 bytes output index
   166  	//   - 4 bytes sequence
   167  	//   - 1 byte encoding empty redeem script
   168  	//   - 0 bytes signature script
   169  	RedeemP2WPKHInputSize = TxInOverhead + 1
   170  
   171  	// RedeemP2WPKHInputWitnessWeight is the worst case weight of
   172  	// a witness for spending P2WPKH and nested P2WPKH outputs. It
   173  	// is calculated as:
   174  	//
   175  	//   - 1 wu compact int encoding value 2 (number of items)
   176  	//   - 1 wu compact int encoding value 73
   177  	//   - 72 wu DER signature + 1 wu sighash
   178  	//   - 1 wu compact int encoding value 33
   179  	//   - 33 wu serialized compressed pubkey
   180  	// NOTE: witness data is not script.
   181  	RedeemP2WPKHInputWitnessWeight = 1 + 1 + DERSigLength + 1 + 33 // 109
   182  
   183  	// RedeemP2WPKHInputTotalSize is the worst case size of a transaction
   184  	// input redeeming a P2WPKH output and the corresponding witness data.
   185  	// It is calculated as:
   186  	//
   187  	// 41 vbytes base tx input
   188  	// 109wu witness = 28 vbytes
   189  	// total = 69 vbytes
   190  	RedeemP2WPKHInputTotalSize = RedeemP2WPKHInputSize +
   191  		(RedeemP2WPKHInputWitnessWeight+(witnessWeight-1))/witnessWeight
   192  
   193  	// SigwitMarkerAndFlagWeight is the 2 bytes of overhead witness data
   194  	// added to every segwit transaction.
   195  	SegwitMarkerAndFlagWeight = 2
   196  
   197  	// RedeemP2WSHInputWitnessWeight depends on the number of redeem script and
   198  	// number of signatures.
   199  	//  version + signatures + length of redeem script + redeem script
   200  	// RedeemP2WSHInputWitnessWeight = 1 + N*DERSigLength + 1 + (redeem script bytes)
   201  
   202  	// P2WPKHPkScriptSize is the size of a transaction output script that
   203  	// pays to a witness pubkey hash. It is calculated as:
   204  	//
   205  	//   - OP_0
   206  	//   - OP_DATA_20
   207  	//   - 20 bytes pubkey hash
   208  	P2WPKHPkScriptSize = 1 + 1 + 20
   209  
   210  	// P2WPKHOutputSize is the serialize size of a transaction output with a
   211  	// P2WPKH output script. It is calculated as:
   212  	//
   213  	//   - 8 bytes output value
   214  	//   - 1 byte compact int encoding value 22
   215  	//   - 22 bytes P2PKH output script
   216  	P2WPKHOutputSize = TxOutOverhead + P2WPKHPkScriptSize // 31
   217  
   218  	// MinimumTxOverhead is the size of an empty transaction.
   219  	// 4 bytes version + 4 bytes locktime + 2 bytes of varints for the number of
   220  	// transaction inputs and outputs
   221  	MinimumTxOverhead = 4 + 4 + 1 + 1 // 10
   222  
   223  	// InitTxSizeBase is the size of a standard serialized atomic swap
   224  	// initialization transaction with one change output and no inputs. This is
   225  	// MsgTx overhead + 1 P2PKH change output + 1 P2SH contract output. However,
   226  	// the change output might be P2WPKH, in which case it would be smaller.
   227  	InitTxSizeBase = MinimumTxOverhead + P2PKHOutputSize + P2SHOutputSize // 10 + 34 + 32 = 76
   228  	// leaner with P2WPKH+P2SH outputs: 10 + 31 + 32 = 73
   229  
   230  	// InitTxSize is InitTxBaseSize + 1 P2PKH input
   231  	InitTxSize = InitTxSizeBase + RedeemP2PKHInputSize // 76 + 149 = 225
   232  	// Varies greatly with some other input types, e.g nested witness (p2sh with
   233  	// p2wpkh redeem script): 23 byte scriptSig + 108 byte (75 vbyte) witness = ~50
   234  
   235  	// InitTxSizeBaseSegwit is the size of a standard serialized atomic swap
   236  	// initialization transaction with one change output and no inputs. The
   237  	// change output is assumed to be segwit. 10 + 31 + 43 = 84
   238  	InitTxSizeBaseSegwit = MinimumTxOverhead + P2WPKHOutputSize + P2WSHOutputSize
   239  
   240  	// InitTxSizeSegwit is InitTxSizeSegwit + 1 P2WPKH input.
   241  	// 84 vbytes base tx
   242  	// 41 vbytes base tx input
   243  	// 109wu witness +  2wu segwit marker and flag = 28 vbytes
   244  	// total = 153 vbytes
   245  	InitTxSizeSegwit = InitTxSizeBaseSegwit + RedeemP2WPKHInputSize +
   246  		(SegwitMarkerAndFlagWeight+RedeemP2WPKHInputWitnessWeight+(witnessWeight-1))/witnessWeight
   247  
   248  	witnessWeight = 4 // github.com/btcsuite/btcd/blockchain.WitnessScaleFactor
   249  
   250  	// BondScriptSize is the maximum size of a DEX time-locked fidelity bond
   251  	// output script to which a bond P2SH pays:
   252  	//   OP_DATA_4/5 (4/5 bytes lockTime) OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 OP_DATA_20 (20-byte pubkey hash160) OP_EQUALVERIFY OP_CHECKSIG
   253  	BondScriptSize = 1 + 5 + 1 + 1 + 1 + 1 + 1 + 20 + 1 + 1 // 33
   254  
   255  	// RedeemBondSigScriptSize is the worst case size of a fidelity bond
   256  	// signature script that spends a bond output. It includes a signature, a
   257  	// compressed pubkey, and the bond script. Each of said data pushes use an
   258  	// OP_DATA_ code.
   259  	RedeemBondSigScriptSize = 1 + DERSigLength + 1 + 33 + 1 + BondScriptSize // 142
   260  
   261  	// BondPushDataSize is the size of the nulldata in a bond commitment output:
   262  	//  OP_RETURN <pushData: ver[2] | account_id[32] | lockTime[4] | pkh[20]>
   263  	BondPushDataSize = 2 + account.HashSize + 4 + 20
   264  )
   265  
   266  // redeemP2SHTxSize calculates the size of the redeeming transaction for a
   267  // P2SH transaction with the given sigScipt (or witness data) size.
   268  func redeemP2SHTxSize(segwit bool, redeemSigScriptSize uint64) uint64 {
   269  	if segwit {
   270  		witnessVBytes := (redeemSigScriptSize + 2 + 3) / 4
   271  		return MinimumTxOverhead + TxInOverhead + witnessVBytes + P2WPKHOutputSize
   272  	}
   273  	inputSize := TxInOverhead + redeemSigScriptSize
   274  	return MinimumTxOverhead + inputSize + P2PKHOutputSize
   275  }
   276  
   277  // RedeemSwapTxSize returns the size of a swap refund tx.
   278  func RedeemSwapTxSize(segwit bool) uint64 {
   279  	return redeemP2SHTxSize(segwit, RedeemSwapSigScriptSize)
   280  }
   281  
   282  // RefundBondTxSize returns the size of a bond refund tx.
   283  func RefundBondTxSize(segwit bool) uint64 {
   284  	return redeemP2SHTxSize(segwit, RedeemBondSigScriptSize)
   285  }
   286  
   287  // minHTLCValue calculates the minimum value for the output of a chained
   288  // P2SH -> P2WPKH transaction pair where the spending tx size is known.
   289  func minHTLCValue(maxFeeRate, redeemTxSize uint64, segwit bool) uint64 {
   290  	// Reversing IsDustVal.
   291  	// totalSize adds some buffer for the spending transaction.
   292  	var outputSize uint64 = P2PKHOutputSize // larger of p2sh output and p2pkh output.
   293  	if segwit {
   294  		outputSize = P2WSHOutputSize // larger of p2wsh output and p2wpkh output
   295  	}
   296  	totalSize := outputSize + 41
   297  	if segwit {
   298  		totalSize += (107 / witnessWeight) // + 26
   299  	} else {
   300  		totalSize += 107
   301  	}
   302  	minInitTxValue := maxFeeRate * totalSize * 3
   303  
   304  	// The minInitTxValue would get the pssh tx accepted, but when we go to
   305  	// redemption, we need that output to pass too, so we need to add the fees
   306  	// for the redemption tx itself.
   307  	redeemFees := redeemTxSize * maxFeeRate
   308  
   309  	return minInitTxValue + redeemFees
   310  }
   311  
   312  // MinBondSize is the minimum bond size that avoids dust for a given max network
   313  // fee rate.
   314  func MinBondSize(maxFeeRate uint64, segwit bool) uint64 {
   315  	refundTxSize := RefundBondTxSize(segwit)
   316  	return minHTLCValue(maxFeeRate, refundTxSize, segwit)
   317  }
   318  
   319  // MinLotSize is the minimum lot size that avoids dust for a given max network
   320  // fee rate.
   321  func MinLotSize(maxFeeRate uint64, segwit bool) uint64 {
   322  	redeemSize := RedeemSwapTxSize(segwit)
   323  	return minHTLCValue(maxFeeRate, redeemSize, segwit)
   324  }
   325  
   326  // BTCScriptType holds details about a pubkey script and possibly it's redeem
   327  // script.
   328  type BTCScriptType uint8
   329  
   330  const (
   331  	ScriptP2PKH = 1 << iota
   332  	ScriptP2PK
   333  	ScriptP2SH
   334  	ScriptTypeSegwit
   335  	ScriptMultiSig
   336  	ScriptUnsupported
   337  )
   338  
   339  // IsP2SH will return boolean true if the script is a P2SH script.
   340  func (s BTCScriptType) IsP2SH() bool {
   341  	return s&ScriptP2SH != 0 && s&ScriptTypeSegwit == 0
   342  }
   343  
   344  // IsP2WSH will return boolean true if the script is a P2WSH script.
   345  func (s BTCScriptType) IsP2WSH() bool {
   346  	return s&ScriptP2SH != 0 && s&ScriptTypeSegwit != 0
   347  }
   348  
   349  // IsP2PKH will return boolean true if the script is a P2PKH script.
   350  func (s BTCScriptType) IsP2PKH() bool {
   351  	return s&ScriptP2PKH != 0 && s&ScriptTypeSegwit == 0
   352  }
   353  
   354  // IsP2PK will return boolean true if the script is a P2PK script.
   355  func (s BTCScriptType) IsP2PK() bool {
   356  	return s&ScriptP2PK != 0 && s&ScriptTypeSegwit == 0
   357  }
   358  
   359  // IsP2WPKH will return boolean true if the script is a P2WPKH script.
   360  func (s BTCScriptType) IsP2WPKH() bool {
   361  	return s&ScriptP2PKH != 0 && s&ScriptTypeSegwit != 0
   362  }
   363  
   364  // IsSegwit will return boolean true if the script is a P2WPKH or P2WSH script.
   365  func (s BTCScriptType) IsSegwit() bool {
   366  	return s&ScriptTypeSegwit != 0
   367  }
   368  
   369  // IsMultiSig is whether the pkscript references a multi-sig redeem script.
   370  // Since the DEX will know the redeem script, we can say whether it's multi-sig.
   371  func (s BTCScriptType) IsMultiSig() bool {
   372  	return s&ScriptMultiSig != 0
   373  }
   374  
   375  // ParseScriptType creates a BTCScriptType bitmap for the script type. A script
   376  // type will be some combination of pay-to-pubkey-hash, pay-to-script-hash,
   377  // and stake. If a script type is P2SH, it may or may not be mutli-sig.
   378  func ParseScriptType(pkScript, redeemScript []byte) BTCScriptType {
   379  	var scriptType BTCScriptType
   380  	class := txscript.GetScriptClass(pkScript)
   381  
   382  	switch class {
   383  	case txscript.PubKeyTy:
   384  		scriptType |= ScriptP2PK
   385  	case txscript.PubKeyHashTy:
   386  		scriptType |= ScriptP2PKH
   387  	case txscript.WitnessV0PubKeyHashTy:
   388  		scriptType |= ScriptP2PKH | ScriptTypeSegwit
   389  	case txscript.ScriptHashTy:
   390  		scriptType |= ScriptP2SH
   391  	case txscript.WitnessV0ScriptHashTy:
   392  		scriptType |= ScriptP2SH | ScriptTypeSegwit
   393  	default:
   394  		return ScriptUnsupported
   395  	}
   396  	if scriptType.IsP2SH() || scriptType.IsP2WSH() {
   397  		scriptClass := txscript.GetScriptClass(redeemScript)
   398  		if scriptClass == txscript.MultiSigTy {
   399  			scriptType |= ScriptMultiSig
   400  		}
   401  		if scriptClass == txscript.ScriptHashTy || scriptClass == txscript.WitnessV0ScriptHashTy {
   402  			// nested p2sh-pswsh, p2sh-p2sh, etc are not supported.
   403  			return ScriptUnsupported
   404  		}
   405  	}
   406  	return scriptType
   407  }
   408  
   409  // MakeContract creates a segwit atomic swap contract. The secretHash MUST
   410  // be computed from a secret of length SecretKeySize bytes or the resulting
   411  // contract will be invalid.
   412  func MakeContract(rAddr, sAddr btcutil.Address, secretHash []byte, lockTime int64, segwit bool, chainParams *chaincfg.Params) ([]byte, error) {
   413  	if segwit {
   414  		_, ok := rAddr.(*btcutil.AddressWitnessPubKeyHash)
   415  		if !ok {
   416  			return nil, fmt.Errorf("recipient address %s is not a witness-pubkey-hash address", rAddr.String())
   417  		}
   418  		_, ok = sAddr.(*btcutil.AddressWitnessPubKeyHash)
   419  		if !ok {
   420  			return nil, fmt.Errorf("sender address %s is not a witness-pubkey-hash address", sAddr.String())
   421  		}
   422  	} else {
   423  		_, ok := rAddr.(*btcutil.AddressPubKeyHash)
   424  		if !ok {
   425  			return nil, fmt.Errorf("recipient address %s is not a pubkey-hash address", rAddr.String())
   426  		}
   427  		_, ok = sAddr.(*btcutil.AddressPubKeyHash)
   428  		if !ok {
   429  			return nil, fmt.Errorf("sender address %s is not a witness-pubkey-hash address", sAddr.String())
   430  		}
   431  	}
   432  	if len(secretHash) != SecretHashSize {
   433  		return nil, fmt.Errorf("secret hash of length %d not supported", len(secretHash))
   434  	}
   435  
   436  	return txscript.NewScriptBuilder().
   437  		AddOps([]byte{
   438  			txscript.OP_IF,
   439  			txscript.OP_SIZE,
   440  		}).AddInt64(SecretKeySize).
   441  		AddOps([]byte{
   442  			txscript.OP_EQUALVERIFY,
   443  			txscript.OP_SHA256,
   444  		}).AddData(secretHash).
   445  		AddOps([]byte{
   446  			txscript.OP_EQUALVERIFY,
   447  			txscript.OP_DUP,
   448  			txscript.OP_HASH160,
   449  		}).AddData(rAddr.ScriptAddress()).
   450  		AddOp(txscript.OP_ELSE).
   451  		AddInt64(lockTime).AddOps([]byte{
   452  		txscript.OP_CHECKLOCKTIMEVERIFY,
   453  		txscript.OP_DROP,
   454  		txscript.OP_DUP,
   455  		txscript.OP_HASH160,
   456  	}).AddData(sAddr.ScriptAddress()).
   457  		AddOps([]byte{
   458  			txscript.OP_ENDIF,
   459  			txscript.OP_EQUALVERIFY,
   460  			txscript.OP_CHECKSIG,
   461  		}).Script()
   462  }
   463  
   464  // IsDust returns whether or not the passed transaction output amount is
   465  // considered dust or not based on the passed minimum transaction relay fee.
   466  // Dust is defined in terms of the minimum transaction relay fee.
   467  // Based on btcd/policy isDust. See btcd/policy for further documentation.
   468  func IsDust(txOut *wire.TxOut, minRelayTxFee uint64) bool {
   469  	if txscript.IsUnspendable(txOut.PkScript) {
   470  		return true
   471  	}
   472  	return IsDustVal(uint64(txOut.SerializeSize()), uint64(txOut.Value), minRelayTxFee, txscript.IsWitnessProgram(txOut.PkScript))
   473  }
   474  
   475  // IsDustVal is like IsDust but only takes the txSize, amount and if segwit.
   476  func IsDustVal(txOutSize, value, minRelayTxFee uint64, segwit bool) bool {
   477  	totalSize := txOutSize + 41
   478  	if segwit {
   479  		// This function is taken from btcd, but noting here that we are not
   480  		// rounding up and probably should be.
   481  		totalSize += (107 / witnessWeight) // + 26
   482  	} else {
   483  		totalSize += 107
   484  	}
   485  	return int64(value)/(3*int64(totalSize)) < int64(minRelayTxFee)
   486  }
   487  
   488  // ExtractScriptData extracts script type, addresses, and required signature
   489  // count from a pkScript. Non-standard scripts are not necessarily an error;
   490  // non-nil errors are only returned if the script cannot be parsed. See also
   491  // InputInfo for additional signature script size data
   492  func ExtractScriptData(script []byte, chainParams *chaincfg.Params) (BTCScriptType, []string, int, error) {
   493  	class, addrs, numRequired, err := txscript.ExtractPkScriptAddrs(script, chainParams)
   494  	if err != nil {
   495  		return ScriptUnsupported, nil, 0, err
   496  	}
   497  	if class == txscript.NonStandardTy {
   498  		return ScriptUnsupported, nil, 0, nil
   499  	}
   500  
   501  	// Could switch on class from ExtractPkScriptAddrs, but use ParseScriptType
   502  	// for internal consistency.
   503  	scriptType := ParseScriptType(script, nil)
   504  
   505  	addresses := make([]string, len(addrs))
   506  	for i, addr := range addrs {
   507  		addresses[i] = addr.String()
   508  	}
   509  
   510  	return scriptType, addresses, numRequired, nil
   511  }
   512  
   513  // BtcScriptAddrs is information about the pubkeys or pubkey hashes present in
   514  // a scriptPubKey (and the redeem script, for p2sh). This information can be
   515  // used to estimate the spend script size, e.g. pubkeys in a redeem script don't
   516  // require pubkeys in the witness/scriptSig, but pubkey hashes do.
   517  type BtcScriptAddrs struct {
   518  	PubKeys   []btcutil.Address
   519  	NumPK     int
   520  	PkHashes  []btcutil.Address
   521  	NumPKH    int
   522  	NRequired int // num sigs needed
   523  }
   524  
   525  // ExtractScriptAddrs extracts the addresses from the pubkey script, or the
   526  // redeem script if the pubkey script is P2SH. The returned bool indicates if
   527  // the script is non-standard.
   528  func ExtractScriptAddrs(script []byte, chainParams *chaincfg.Params) (*BtcScriptAddrs, bool, error) {
   529  	pubkeys := make([]btcutil.Address, 0)
   530  	pkHashes := make([]btcutil.Address, 0)
   531  	// For P2SH and non-P2SH multi-sig, pull the addresses from the pubkey script.
   532  	class, addrs, numRequired, err := txscript.ExtractPkScriptAddrs(script, chainParams)
   533  	nonStandard := class == txscript.NonStandardTy
   534  	if err != nil { // txscript.ExtractPkScriptAddrs always returns a nil error now, so this should not happen
   535  		return nil, nonStandard, fmt.Errorf("ExtractScriptAddrs: %w", err)
   536  	}
   537  	if nonStandard {
   538  		return &BtcScriptAddrs{}, nonStandard, nil
   539  	}
   540  	for _, addr := range addrs {
   541  		// If the address is an unhashed public key, is won't need a pubkey as part
   542  		// of its sigScript, so count them separately.
   543  		_, isPubkey := addr.(*btcutil.AddressPubKey)
   544  		if isPubkey {
   545  			pubkeys = append(pubkeys, addr)
   546  		} else {
   547  			pkHashes = append(pkHashes, addr)
   548  		}
   549  	}
   550  	return &BtcScriptAddrs{
   551  		PubKeys:   pubkeys,
   552  		NumPK:     len(pubkeys),
   553  		PkHashes:  pkHashes,
   554  		NumPKH:    len(pkHashes),
   555  		NRequired: numRequired,
   556  	}, false, nil
   557  }
   558  
   559  // ExtractSwapDetails extacts the sender and receiver addresses from a swap
   560  // contract. If the provided script is not a swap contract, an error will be
   561  // returned.
   562  func ExtractSwapDetails(pkScript []byte, segwit bool, chainParams *chaincfg.Params) (
   563  	sender, receiver btcutil.Address, lockTime uint64, secretHash []byte, err error) {
   564  	// A swap redemption sigScript is <pubkey> <secret> and satisfies the
   565  	// following swap contract.
   566  	//
   567  	// OP_IF
   568  	//  OP_SIZE OP_DATA_1 secretSize OP_EQUALVERIFY OP_SHA256 OP_DATA_32 secretHash OP_EQUALVERIFY OP_DUP OP_HASH160 OP_DATA20 pkHashReceiver
   569  	//     1   +   1     +    1     +      1       +    1    +    1     +   32     +      1       +   1  +    1     +    1    +    20
   570  	// OP_ELSE
   571  	//  OP_DATA4 lockTime OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 OP_DATA_20 pkHashSender
   572  	//     1    +    4   +           1          +   1   +  1   +    1     +   1      +    20
   573  	// OP_ENDIF
   574  	// OP_EQUALVERIFY
   575  	// OP_CHECKSIG
   576  	//
   577  	// 5 bytes if-else-endif-equalverify-checksig
   578  	// 1 + 1 + 1 + 1 + 1 + 1 + 32 + 1 + 1 + 1 + 1 + 20 = 62 bytes for redeem block
   579  	// 1 + 4 + 1 + 1 + 1 + 1 + 1 + 20 = 30 bytes for refund block
   580  	// 5 + 62 + 30 = 97 bytes
   581  	//
   582  	// Note that this allows for a secret size of up to 75 bytes, but the secret
   583  	// must be 32 bytes to be considered valid.
   584  	if len(pkScript) != SwapContractSize {
   585  		err = fmt.Errorf("incorrect swap contract length. expected %d, got %d",
   586  			SwapContractSize, len(pkScript))
   587  		return
   588  	}
   589  
   590  	if pkScript[0] == txscript.OP_IF &&
   591  		pkScript[1] == txscript.OP_SIZE &&
   592  		pkScript[2] == txscript.OP_DATA_1 &&
   593  		// secretSize (1 bytes)
   594  		pkScript[4] == txscript.OP_EQUALVERIFY &&
   595  		pkScript[5] == txscript.OP_SHA256 &&
   596  		pkScript[6] == txscript.OP_DATA_32 &&
   597  		// secretHash (32 bytes)
   598  		pkScript[39] == txscript.OP_EQUALVERIFY &&
   599  		pkScript[40] == txscript.OP_DUP &&
   600  		pkScript[41] == txscript.OP_HASH160 &&
   601  		pkScript[42] == txscript.OP_DATA_20 &&
   602  		// receiver's pkh (20 bytes)
   603  		pkScript[63] == txscript.OP_ELSE &&
   604  		pkScript[64] == txscript.OP_DATA_4 &&
   605  		// lockTime (4 bytes)
   606  		pkScript[69] == txscript.OP_CHECKLOCKTIMEVERIFY &&
   607  		pkScript[70] == txscript.OP_DROP &&
   608  		pkScript[71] == txscript.OP_DUP &&
   609  		pkScript[72] == txscript.OP_HASH160 &&
   610  		pkScript[73] == txscript.OP_DATA_20 &&
   611  		// sender's pkh (20 bytes)
   612  		pkScript[94] == txscript.OP_ENDIF &&
   613  		pkScript[95] == txscript.OP_EQUALVERIFY &&
   614  		pkScript[96] == txscript.OP_CHECKSIG {
   615  
   616  		if ssz := pkScript[3]; ssz != SecretKeySize {
   617  			return nil, nil, 0, nil, fmt.Errorf("invalid secret size %d", ssz)
   618  		}
   619  
   620  		if segwit {
   621  			receiver, err = btcutil.NewAddressWitnessPubKeyHash(pkScript[43:63], chainParams)
   622  			if err != nil {
   623  				return nil, nil, 0, nil, fmt.Errorf("error decoding address from recipient's pubkey hash")
   624  			}
   625  
   626  			sender, err = btcutil.NewAddressWitnessPubKeyHash(pkScript[74:94], chainParams)
   627  			if err != nil {
   628  				return nil, nil, 0, nil, fmt.Errorf("error decoding address from sender's pubkey hash")
   629  			}
   630  		} else {
   631  			receiver, err = btcutil.NewAddressPubKeyHash(pkScript[43:63], chainParams)
   632  			if err != nil {
   633  				return nil, nil, 0, nil, fmt.Errorf("error decoding address from recipient's pubkey hash")
   634  			}
   635  
   636  			sender, err = btcutil.NewAddressPubKeyHash(pkScript[74:94], chainParams)
   637  			if err != nil {
   638  				return nil, nil, 0, nil, fmt.Errorf("error decoding address from sender's pubkey hash")
   639  			}
   640  		}
   641  
   642  		lockTime = uint64(binary.LittleEndian.Uint32(pkScript[65:69]))
   643  		secretHash = pkScript[7:39]
   644  
   645  		return
   646  	}
   647  
   648  	err = fmt.Errorf("invalid swap contract")
   649  	return
   650  }
   651  
   652  // RedeemP2SHContract returns the signature script to redeem a contract output
   653  // using the redeemer's signature and the initiator's secret.  This function
   654  // assumes P2SH and appends the contract as the final data push.
   655  func RedeemP2SHContract(contract, sig, pubkey, secret []byte) ([]byte, error) {
   656  	return txscript.NewScriptBuilder().
   657  		AddData(sig).
   658  		AddData(pubkey).
   659  		AddData(secret).
   660  		AddInt64(1).
   661  		AddData(contract).
   662  		Script()
   663  }
   664  
   665  // RedeemP2WSHContract returns the witness script to redeem a contract output
   666  // using the redeemer's signature and the initiator's secret.  This function
   667  // assumes P2WSH and appends the contract as the final data push.
   668  func RedeemP2WSHContract(contract, sig, pubkey, secret []byte) [][]byte {
   669  	return [][]byte{
   670  		sig,
   671  		pubkey,
   672  		secret,
   673  		{0x01},
   674  		contract,
   675  	}
   676  }
   677  
   678  // RefundP2SHContract returns the signature script to refund a contract output
   679  // using the contract author's signature after the locktime has been reached.
   680  // This function assumes P2SH and appends the contract as the final data push.
   681  func RefundP2SHContract(contract, sig, pubkey []byte) ([]byte, error) {
   682  	return txscript.NewScriptBuilder().
   683  		AddData(sig).
   684  		AddData(pubkey).
   685  		AddInt64(0).
   686  		AddData(contract).
   687  		Script()
   688  }
   689  
   690  // OP_RETURN <pushData: ver[2] | account_id[32] | lockTime[4] | pkh[20]>
   691  func extractBondCommitDataV0(pushData []byte) (acct account.AccountID, lockTime uint32, pubkeyHash [20]byte, err error) {
   692  	if len(pushData) < 2 {
   693  		err = errors.New("invalid data")
   694  		return
   695  	}
   696  	ver := binary.BigEndian.Uint16(pushData)
   697  	if ver != 0 {
   698  		err = fmt.Errorf("unexpected bond commitment version %d, expected 0", ver)
   699  		return
   700  	}
   701  
   702  	if len(pushData) != BondPushDataSize {
   703  		err = fmt.Errorf("invalid bond commitment output script length: %d", len(pushData))
   704  		return
   705  	}
   706  
   707  	pushData = pushData[2:] // pop off ver
   708  
   709  	copy(acct[:], pushData)
   710  	pushData = pushData[account.HashSize:]
   711  
   712  	lockTime = binary.BigEndian.Uint32(pushData)
   713  	pushData = pushData[4:]
   714  
   715  	copy(pubkeyHash[:], pushData)
   716  
   717  	return
   718  }
   719  
   720  // ExtractBondCommitDataV0 parses a v0 bond commitment output script. This is
   721  // the OP_RETURN output, not the P2SH bond output. Use ExtractBondDetailsV0 to
   722  // parse the P2SH bond output's redeem script.
   723  //
   724  // If the decoded commitment data indicates a version other than 0, an error is
   725  // returned.
   726  func ExtractBondCommitDataV0(scriptVer uint16, pkScript []byte) (acct account.AccountID, lockTime uint32, pubkeyHash [20]byte, err error) {
   727  	tokenizer := txscript.MakeScriptTokenizer(scriptVer, pkScript)
   728  	if !tokenizer.Next() {
   729  		err = tokenizer.Err()
   730  		return
   731  	}
   732  
   733  	if tokenizer.Opcode() != txscript.OP_RETURN {
   734  		err = errors.New("not a null data output")
   735  		return
   736  	}
   737  
   738  	if !tokenizer.Next() {
   739  		err = tokenizer.Err()
   740  		return
   741  	}
   742  
   743  	pushData := tokenizer.Data()
   744  	acct, lockTime, pubkeyHash, err = extractBondCommitDataV0(pushData)
   745  	if err != nil {
   746  		return
   747  	}
   748  
   749  	if !tokenizer.Done() {
   750  		err = errors.New("script has extra opcodes")
   751  		return
   752  	}
   753  
   754  	return
   755  }
   756  
   757  // MakeBondScript constructs a versioned bond output script for the provided
   758  // lock time and pubkey hash. Only version 0 is supported at present. The lock
   759  // time must be less than 2^32-1 so that it uses at most 5 bytes. The lockTime
   760  // is also required to use at least 4 bytes (time stamp, not block time).
   761  func MakeBondScript(ver uint16, lockTime uint32, pubkeyHash []byte) ([]byte, error) {
   762  	if ver != 0 {
   763  		return nil, errors.New("only version 0 bonds supported")
   764  	}
   765  	if lockTime >= MaxCLTVScriptNum { // == should be OK, but let's not
   766  		return nil, errors.New("invalid lock time")
   767  	}
   768  	lockTimeInt64 := int64(lockTime)
   769  	if len(pubkeyHash) != 20 {
   770  		return nil, errors.New("invalid pubkey hash")
   771  	}
   772  	return txscript.NewScriptBuilder().
   773  		AddInt64(lockTimeInt64).
   774  		AddOp(txscript.OP_CHECKLOCKTIMEVERIFY).
   775  		AddOp(txscript.OP_DROP).
   776  		AddOp(txscript.OP_DUP).
   777  		AddOp(txscript.OP_HASH160).
   778  		AddData(pubkeyHash).
   779  		AddOp(txscript.OP_EQUALVERIFY).
   780  		AddOp(txscript.OP_CHECKSIG).
   781  		Script()
   782  }
   783  
   784  // RefundBondScript builds the signature script to refund a time-locked fidelity
   785  // bond in a P2SH output paying to the provided P2PKH bondScript.
   786  func RefundBondScript(bondScript, sig, pubkey []byte) ([]byte, error) {
   787  	return txscript.NewScriptBuilder().
   788  		AddData(sig).
   789  		AddData(pubkey).
   790  		AddData(bondScript).
   791  		Script()
   792  }
   793  
   794  // RefundBondScript builds the signature script to refund a time-locked fidelity
   795  // bond in a P2WSH output paying to the provided P2PKH bondScript.
   796  func RefundBondScriptSegwit(bondScript, sig, pubkey []byte) [][]byte {
   797  	return [][]byte{
   798  		sig,
   799  		pubkey,
   800  		bondScript,
   801  	}
   802  }
   803  
   804  // ExtractBondDetailsV0 validates the provided bond redeem script, extracting
   805  // the lock time and pubkey. The V0 format of the script must be as follows:
   806  //
   807  //	<lockTime> OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 <pubkeyhash[20]> OP_EQUALVERIFY OP_CHECKSIG
   808  //
   809  // The script version refers to the pkScript version, not bond version, which
   810  // pertains to DEX's version of the bond script.
   811  func ExtractBondDetailsV0(scriptVersion uint16, bondScript []byte) (lockTime uint32, pkh []byte, err error) {
   812  	type templateMatch struct {
   813  		expectInt     bool
   814  		maxIntBytes   int
   815  		opcode        byte
   816  		extractedInt  int64
   817  		extractedData []byte
   818  	}
   819  	var template = [...]templateMatch{
   820  		{expectInt: true, maxIntBytes: 5}, // extractedInt
   821  		{opcode: txscript.OP_CHECKLOCKTIMEVERIFY},
   822  		{opcode: txscript.OP_DROP},
   823  		{opcode: txscript.OP_DUP},
   824  		{opcode: txscript.OP_HASH160},
   825  		{opcode: txscript.OP_DATA_20}, // extractedData
   826  		{opcode: txscript.OP_EQUALVERIFY},
   827  		{opcode: txscript.OP_CHECKSIG},
   828  	}
   829  
   830  	var templateOffset int
   831  	tokenizer := txscript.MakeScriptTokenizer(scriptVersion, bondScript)
   832  	for tokenizer.Next() {
   833  		if templateOffset >= len(template) {
   834  			return 0, nil, errors.New("too many script elements")
   835  		}
   836  
   837  		op, data := tokenizer.Opcode(), tokenizer.Data()
   838  		tplEntry := &template[templateOffset]
   839  		if tplEntry.expectInt {
   840  			switch {
   841  			case data != nil:
   842  				val, err := dcrtxscript.MakeScriptNum(data, tplEntry.maxIntBytes)
   843  				if err != nil {
   844  					return 0, nil, err
   845  				}
   846  				tplEntry.extractedInt = int64(val)
   847  			case dcrtxscript.IsSmallInt(op): // not expected for our lockTimes, but it is an integer
   848  				tplEntry.extractedInt = int64(dcrtxscript.AsSmallInt(op))
   849  			default:
   850  				return 0, nil, errors.New("expected integer")
   851  			}
   852  		} else {
   853  			if op != tplEntry.opcode {
   854  				return 0, nil, fmt.Errorf("expected opcode %v, got %v", tplEntry.opcode, op)
   855  			}
   856  
   857  			tplEntry.extractedData = data
   858  		}
   859  
   860  		templateOffset++
   861  	}
   862  	if err := tokenizer.Err(); err != nil {
   863  		return 0, nil, err
   864  	}
   865  	if !tokenizer.Done() || templateOffset != len(template) {
   866  		return 0, nil, errors.New("incorrect script length")
   867  	}
   868  
   869  	// The script matches in structure. Now validate the two pushes.
   870  
   871  	lockTime64 := template[0].extractedInt
   872  	if lockTime64 <= 0 { // || lockTime64 > MaxCLTVScriptNum {
   873  		return 0, nil, fmt.Errorf("invalid locktime %d", lockTime64)
   874  	}
   875  	lockTime = uint32(lockTime64)
   876  
   877  	const pubkeyHashLen = 20
   878  	bondPubKeyHash := template[5].extractedData
   879  	if len(bondPubKeyHash) != pubkeyHashLen {
   880  		err = errors.New("missing or invalid pubkeyhash data")
   881  		return
   882  	}
   883  	pkh = make([]byte, pubkeyHashLen)
   884  	copy(pkh, bondPubKeyHash)
   885  
   886  	return
   887  }
   888  
   889  // MsgTxVBytes returns the transaction's virtual size, which accounts for the
   890  // segwit input weighting.
   891  func MsgTxVBytes(msgTx *wire.MsgTx) uint64 {
   892  	baseSize := msgTx.SerializeSizeStripped()
   893  	totalSize := msgTx.SerializeSize()
   894  	txWeight := baseSize*(witnessWeight-1) + totalSize
   895  	// vbytes is ceil(tx_weight/4)
   896  	return uint64(txWeight+(witnessWeight-1)) / witnessWeight // +3 before / 4 to round up
   897  	// NOTE: This is the same as doing the following:
   898  	// tx := btcutil.NewTx(msgTx)
   899  	// return uint64(blockchain.GetTransactionWeight(tx)+(blockchain.WitnessScaleFactor-1)) /
   900  	// 	blockchain.WitnessScaleFactor // mempool.GetTxVirtualSize(tx)
   901  }
   902  
   903  // RefundP2WSHContract returns the witness to refund a contract output
   904  // using the contract author's signature after the locktime has been reached.
   905  // This function assumes P2WSH and appends the contract as the final data push.
   906  func RefundP2WSHContract(contract, sig, pubkey []byte) [][]byte {
   907  	return [][]byte{
   908  		sig,
   909  		pubkey,
   910  		{},
   911  		contract,
   912  	}
   913  }
   914  
   915  // SpendInfo is information about an input and it's previous outpoint.
   916  type SpendInfo struct {
   917  	SigScriptSize     uint32
   918  	WitnessSize       uint32
   919  	ScriptAddrs       *BtcScriptAddrs
   920  	ScriptType        BTCScriptType
   921  	NonStandardScript bool
   922  }
   923  
   924  // VBytes is the virtual bytes of the spending transaction input. Miners use
   925  // weight/4 = vbytes to calculate contribution to block size limit and therefore
   926  // transaction fees.
   927  func (nfo *SpendInfo) VBytes() uint32 {
   928  	return TxInOverhead + uint32(wire.VarIntSerializeSize(uint64(nfo.SigScriptSize))) +
   929  		nfo.SigScriptSize + (nfo.WitnessSize+(witnessWeight-1))/witnessWeight // Add 3 before dividing witness weight to force rounding up.
   930  }
   931  
   932  // InputInfo is some basic information about the input required to spend an
   933  // output. The pubkey script of the output is provided. If the pubkey script
   934  // parses as P2SH or P2WSH, the redeem script must be provided.
   935  func InputInfo(pkScript, redeemScript []byte, chainParams *chaincfg.Params) (*SpendInfo, error) {
   936  	// Get information about the signatures and pubkeys needed to spend the utxo.
   937  	scriptType := ParseScriptType(pkScript, redeemScript)
   938  	if scriptType == ScriptUnsupported {
   939  		return nil, dex.UnsupportedScriptError
   940  	}
   941  	evalScript := pkScript
   942  	if scriptType.IsP2SH() || scriptType.IsP2WSH() {
   943  		if len(redeemScript) == 0 {
   944  			return nil, fmt.Errorf("no redeem script provided for p2sh or p2wsh address")
   945  		}
   946  		evalScript = redeemScript
   947  	}
   948  	scriptAddrs, nonStandard, err := ExtractScriptAddrs(evalScript, chainParams)
   949  	if err != nil {
   950  		return nil, fmt.Errorf("error parsing script addresses: %w", err)
   951  	}
   952  	if nonStandard {
   953  		return &SpendInfo{
   954  			// SigScriptSize and WitnessSize cannot be determined, leave zero.
   955  			ScriptAddrs:       scriptAddrs,
   956  			ScriptType:        scriptType,
   957  			NonStandardScript: true,
   958  		}, nil
   959  	}
   960  
   961  	// Start with standard P2PKH.
   962  	var sigScriptSize, witnessWeight int
   963  	switch {
   964  	case scriptType.IsP2PK():
   965  		sigScriptSize = RedeemP2PKSigScriptSize
   966  		witnessWeight = 0
   967  	case scriptType.IsP2PKH():
   968  		sigScriptSize = RedeemP2PKHSigScriptSize
   969  		witnessWeight = 0
   970  	case scriptType.IsP2WPKH():
   971  		sigScriptSize = 0
   972  		witnessWeight = RedeemP2WPKHInputWitnessWeight
   973  	case scriptType.IsP2SH():
   974  		// If it's a P2SH, the size must be calculated based on other factors.
   975  
   976  		// If the redeem script is P2SM, there is a leading OP_0 in Bitcoin.
   977  		if scriptType.IsMultiSig() {
   978  			sigScriptSize++
   979  		}
   980  
   981  		// The signatures.
   982  		sigScriptSize += (DERSigLength + 1) * scriptAddrs.NRequired // 73 max for sig, 1 for push code
   983  
   984  		// If there are pubkey-hash addresses, they'll need pubkeys.
   985  		if scriptAddrs.NumPKH > 0 {
   986  			sigScriptSize += scriptAddrs.NRequired * (PubKeyLength + 1)
   987  		}
   988  
   989  		// Then add the script_length(1) + len(script).
   990  		sigScriptSize += len(redeemScript) + 1
   991  	case scriptType.IsP2WSH():
   992  		witnessWeight = (DERSigLength + 1) * scriptAddrs.NRequired
   993  		if scriptAddrs.NumPKH > 0 {
   994  			witnessWeight += scriptAddrs.NRequired * (PubKeyLength + 1)
   995  		}
   996  		witnessWeight += len(redeemScript) + 1
   997  	default:
   998  		return nil, fmt.Errorf("error calculating size. unknown script type %d?", scriptType)
   999  	}
  1000  	return &SpendInfo{
  1001  		SigScriptSize: uint32(sigScriptSize),
  1002  		WitnessSize:   uint32(witnessWeight),
  1003  		ScriptAddrs:   scriptAddrs,
  1004  		ScriptType:    scriptType,
  1005  	}, nil
  1006  }
  1007  
  1008  // FindKeyPush attempts to extract the secret key from the signature script. The
  1009  // contract must be provided for the search algorithm to verify the correct data
  1010  // push. Only contracts of length SwapContractSize that can be validated by
  1011  // ExtractSwapDetails are recognized.
  1012  func FindKeyPush(witness [][]byte, sigScript, contractHash []byte, segwit bool, chainParams *chaincfg.Params) ([]byte, error) {
  1013  	var redeemScript, secret []byte
  1014  	var hasher func([]byte) []byte
  1015  	if segwit {
  1016  		if len(witness) != 5 {
  1017  			return nil, fmt.Errorf("witness should contain 5 data pushes. Found %d", len(witness))
  1018  		}
  1019  		secret, redeemScript = witness[2], witness[4]
  1020  		hasher = func(b []byte) []byte {
  1021  			h := sha256.Sum256(b)
  1022  			return h[:]
  1023  		}
  1024  	} else {
  1025  		pushes, err := txscript.PushedData(sigScript)
  1026  		if err != nil {
  1027  			return nil, fmt.Errorf("sigScript PushedData(%x): %w", sigScript, err)
  1028  		}
  1029  		if len(pushes) != 4 {
  1030  			return nil, fmt.Errorf("sigScript should contain 4 data pushes. Found %d", len(pushes))
  1031  		}
  1032  		secret, redeemScript = pushes[2], pushes[3]
  1033  		hasher = btcutil.Hash160
  1034  	}
  1035  	return findKeyPush(redeemScript, secret, contractHash, chainParams, hasher)
  1036  }
  1037  
  1038  func findKeyPush(redeemScript, secret, contractHash []byte, chainParams *chaincfg.Params, hasher func([]byte) []byte) ([]byte, error) {
  1039  	// Doesn't matter what we pass for the bool segwit argument, since we're not
  1040  	// using the addresses, and the contract's 20-byte pubkey hashes are
  1041  	// compatible with both address types.
  1042  	_, _, _, keyHash, err := ExtractSwapDetails(redeemScript, true, chainParams)
  1043  	if err != nil {
  1044  		return nil, fmt.Errorf("error extracting atomic swap details: %w", err)
  1045  	}
  1046  	if !bytes.Equal(hasher(redeemScript), contractHash) {
  1047  		return nil, fmt.Errorf("redeemScript is not correct for provided contract hash")
  1048  	}
  1049  	h := sha256.Sum256(secret)
  1050  	if !bytes.Equal(h[:], keyHash) {
  1051  		return nil, fmt.Errorf("incorrect secret")
  1052  	}
  1053  	return secret, nil
  1054  }
  1055  
  1056  // ExtractPubKeyHash extracts the pubkey hash from the passed script if it is a
  1057  // standard pay-to-pubkey-hash script.  It will return nil otherwise.
  1058  func ExtractPubKeyHash(script []byte) []byte {
  1059  	// A pay-to-pubkey-hash script is of the form:
  1060  	//  OP_DUP OP_HASH160 <20-byte hash> OP_EQUALVERIFY OP_CHECKSIG
  1061  	if len(script) == 25 &&
  1062  		script[0] == txscript.OP_DUP &&
  1063  		script[1] == txscript.OP_HASH160 &&
  1064  		script[2] == txscript.OP_DATA_20 &&
  1065  		script[23] == txscript.OP_EQUALVERIFY &&
  1066  		script[24] == txscript.OP_CHECKSIG {
  1067  
  1068  		return script[3:23]
  1069  	}
  1070  
  1071  	return nil
  1072  }
  1073  
  1074  // ExtractContractHash extracts the contract P2SH or P2WSH address from a
  1075  // pkScript. A non-nil error is returned if the hexadecimal encoding of the
  1076  // pkScript is invalid, or if the pkScript is not a P2SH or P2WSH script.
  1077  func ExtractContractHash(scriptHex string) ([]byte, error) {
  1078  	pkScript, err := hex.DecodeString(scriptHex)
  1079  	if err != nil {
  1080  		return nil, fmt.Errorf("error decoding scriptPubKey '%s': %w",
  1081  			scriptHex, err)
  1082  	}
  1083  	scriptHash := ExtractScriptHash(pkScript)
  1084  	if scriptHash == nil {
  1085  		return nil, fmt.Errorf("error extracting script hash")
  1086  	}
  1087  	return scriptHash, nil
  1088  }
  1089  
  1090  // ExtractScriptHash attempts to extract the redeem script hash from a pkScript.
  1091  // If it is not a P2SH or P2WSH pkScript, a nil slice is returned.
  1092  func ExtractScriptHash(script []byte) []byte {
  1093  	// A pay-to-script-hash pkScript is of the form:
  1094  	//  OP_HASH160 <20-byte scripthash> OP_EQUAL
  1095  	if len(script) == 23 &&
  1096  		script[0] == txscript.OP_HASH160 &&
  1097  		script[1] == txscript.OP_DATA_20 &&
  1098  		script[22] == txscript.OP_EQUAL {
  1099  
  1100  		return script[2:22]
  1101  	}
  1102  	// A pay-to-witness-script-hash pkScript is of the form:
  1103  	//  OP_0 <32-byte scripthash>
  1104  	if len(script) == 34 &&
  1105  		script[0] == txscript.OP_0 &&
  1106  		script[1] == txscript.OP_DATA_32 {
  1107  		return script[2:34]
  1108  	}
  1109  	return nil
  1110  }