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 }