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 }