github.com/decred/dcrlnd@v0.7.6/internal/psbt/psbt_utils.go (about)

     1  package psbt
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  
     7  	"github.com/decred/dcrd/wire"
     8  )
     9  
    10  // SumUtxoInputValues tries to extract the sum of all inputs specified in the
    11  // UTXO fields of the PSBT. An error is returned if an input is specified that
    12  // does not contain any UTXO information.
    13  func SumUtxoInputValues(packet *Packet) (int64, error) {
    14  	// We take the TX ins of the unsigned TX as the truth for how many
    15  	// inputs there should be, as the fields in the extra data part of the
    16  	// PSBT can be empty.
    17  	if len(packet.UnsignedTx.TxIn) != len(packet.Inputs) {
    18  		return 0, fmt.Errorf("TX input length doesn't match PSBT " +
    19  			"input length")
    20  
    21  	}
    22  	inputSum := int64(0)
    23  	for idx, in := range packet.Inputs {
    24  		switch {
    25  		case in.WitnessUtxo != nil:
    26  			// Witness UTXOs only need to reference the TxOut.
    27  			inputSum += in.WitnessUtxo.Value
    28  
    29  		case in.NonWitnessUtxo != nil:
    30  			// Non-witness UTXOs reference to the whole transaction
    31  			// the UTXO resides in.
    32  			utxOuts := in.NonWitnessUtxo.TxOut
    33  			txIn := packet.UnsignedTx.TxIn[idx]
    34  			inputSum += utxOuts[txIn.PreviousOutPoint.Index].Value
    35  
    36  		default:
    37  			return 0, fmt.Errorf("input %d has no UTXO information",
    38  				idx)
    39  		}
    40  	}
    41  	return inputSum, nil
    42  }
    43  
    44  // TxOutsEqual returns true if two transaction outputs are equal.
    45  func TxOutsEqual(out1, out2 *wire.TxOut) bool {
    46  	if out1 == nil || out2 == nil {
    47  		return out1 == out2
    48  
    49  	}
    50  	return out1.Value == out2.Value &&
    51  		bytes.Equal(out1.PkScript, out2.PkScript)
    52  
    53  }
    54  
    55  // VerifyOutputsEqual verifies that the two slices of transaction outputs are
    56  // deep equal to each other. We do the length check and manual loop to provide
    57  // better error messages to the user than just returning "not equal".
    58  func VerifyOutputsEqual(outs1, outs2 []*wire.TxOut) error {
    59  	if len(outs1) != len(outs2) {
    60  		return fmt.Errorf("number of outputs are different")
    61  
    62  	}
    63  	for idx, out := range outs1 {
    64  		// There is a byte slice in the output so we can't use the
    65  		// equality operator.
    66  		if !TxOutsEqual(out, outs2[idx]) {
    67  			return fmt.Errorf("output %d is different", idx)
    68  		}
    69  	}
    70  	return nil
    71  }
    72  
    73  // VerifyInputPrevOutpointsEqual verifies that the previous outpoints of the
    74  // two slices of transaction inputs are deep equal to each other. We do the
    75  // length check and manual loop to provide better error messages to the user
    76  // than just returning "not equal".
    77  func VerifyInputPrevOutpointsEqual(ins1, ins2 []*wire.TxIn) error {
    78  	if len(ins1) != len(ins2) {
    79  		return fmt.Errorf("number of inputs are different")
    80  	}
    81  	for idx, in := range ins1 {
    82  		if in.PreviousOutPoint != ins2[idx].PreviousOutPoint {
    83  			return fmt.Errorf("previous outpoint of input %d is "+
    84  				"different", idx)
    85  		}
    86  	}
    87  	return nil
    88  }