github.com/decred/dcrlnd@v0.7.6/lnrpc/walletrpc/psbt.go (about)

     1  //go:build !no_walletrpc
     2  // +build !no_walletrpc
     3  
     4  package walletrpc
     5  
     6  import (
     7  	"fmt"
     8  	"math"
     9  	"time"
    10  
    11  	"github.com/decred/dcrd/wire"
    12  	"github.com/decred/dcrlnd/internal/psbt"
    13  	"github.com/decred/dcrlnd/lnwallet"
    14  )
    15  
    16  const (
    17  	defaultMaxConf = math.MaxInt32
    18  )
    19  
    20  var (
    21  	// DefaultLockDuration is the default duration used to lock outputs.
    22  	DefaultLockDuration = 10 * time.Minute
    23  )
    24  
    25  // verifyInputsUnspent checks that all inputs are contained in the list of
    26  // known, non-locked UTXOs given.
    27  func verifyInputsUnspent(inputs []*wire.TxIn, utxos []*lnwallet.Utxo) error {
    28  	// TODO(guggero): Pass in UTXOs as a map to make lookup more efficient.
    29  	for idx, txIn := range inputs {
    30  		found := false
    31  		for _, u := range utxos {
    32  			if u.OutPoint == txIn.PreviousOutPoint {
    33  				found = true
    34  				break
    35  			}
    36  		}
    37  
    38  		if !found {
    39  			return fmt.Errorf("input %d not found in list of non-"+
    40  				"locked UTXO", idx)
    41  		}
    42  	}
    43  
    44  	return nil
    45  }
    46  
    47  // lockInputs requests a lock lease for all inputs specified in a PSBT packet
    48  // by using the internal, static lock ID of lnd's wallet.
    49  func lockInputs(w lnwallet.WalletController, packet *psbt.Packet) ([]*lnwallet.LockedOutput,
    50  	error) {
    51  
    52  	locks := make([]*lnwallet.LockedOutput, len(packet.UnsignedTx.TxIn))
    53  	for idx, rawInput := range packet.UnsignedTx.TxIn {
    54  		lock := &lnwallet.LockedOutput{
    55  			LockID:   LndInternalLockID,
    56  			Outpoint: rawInput.PreviousOutPoint,
    57  		}
    58  
    59  		expiration, err := w.LeaseOutput(
    60  			lock.LockID, lock.Outpoint, DefaultLockDuration,
    61  		)
    62  		if err != nil {
    63  			// If we run into a problem with locking one output, we
    64  			// should try to unlock those that we successfully
    65  			// locked so far. If that fails as well, there's not
    66  			// much we can do.
    67  			for i := 0; i < idx; i++ {
    68  				op := locks[i].Outpoint
    69  				if err := w.ReleaseOutput(
    70  					LndInternalLockID, op,
    71  				); err != nil {
    72  
    73  					log.Errorf("could not release the "+
    74  						"lock on %v: %v", op, err)
    75  				}
    76  			}
    77  
    78  			return nil, fmt.Errorf("could not lease a lock on "+
    79  				"UTXO: %v", err)
    80  		}
    81  
    82  		lock.Expiration = expiration
    83  		locks[idx] = lock
    84  	}
    85  
    86  	return locks, nil
    87  }