/ htlcswitch / resolution_store.go
resolution_store.go
  1  package htlcswitch
  2  
  3  import (
  4  	"bytes"
  5  	"errors"
  6  	"io"
  7  
  8  	"github.com/lightningnetwork/lnd/channeldb"
  9  	"github.com/lightningnetwork/lnd/contractcourt"
 10  	"github.com/lightningnetwork/lnd/kvdb"
 11  	"github.com/lightningnetwork/lnd/lnwire"
 12  )
 13  
 14  var (
 15  	// resBucketKey is used for the root level bucket that stores the
 16  	// CircuitKey -> ResolutionMsg mapping.
 17  	resBucketKey = []byte("resolution-store-bucket-key")
 18  
 19  	// errResMsgNotFound is used to let callers know that the resolution
 20  	// message was not found for the given CircuitKey. This is used in the
 21  	// checkResolutionMsg function.
 22  	errResMsgNotFound = errors.New("resolution message not found")
 23  )
 24  
 25  // resolutionStore contains ResolutionMsgs received from the contractcourt. The
 26  // Switch deletes these from the store when the underlying circuit has been
 27  // removed via DeleteCircuits. If the circuit hasn't been deleted, the Switch
 28  // will dispatch the ResolutionMsg to a link if this was a multi-hop HTLC or to
 29  // itself if the Switch initiated the payment.
 30  type resolutionStore struct {
 31  	backend kvdb.Backend
 32  }
 33  
 34  func newResolutionStore(db kvdb.Backend) *resolutionStore {
 35  	return &resolutionStore{
 36  		backend: db,
 37  	}
 38  }
 39  
 40  // addResolutionMsg persists a ResolutionMsg to the resolutionStore.
 41  func (r *resolutionStore) addResolutionMsg(
 42  	resMsg *contractcourt.ResolutionMsg) error {
 43  
 44  	// The outKey will be the database key.
 45  	outKey := &CircuitKey{
 46  		ChanID: resMsg.SourceChan,
 47  		HtlcID: resMsg.HtlcIndex,
 48  	}
 49  
 50  	var resBuf bytes.Buffer
 51  	if err := serializeResolutionMsg(&resBuf, resMsg); err != nil {
 52  		return err
 53  	}
 54  
 55  	err := kvdb.Update(r.backend, func(tx kvdb.RwTx) error {
 56  		resBucket, err := tx.CreateTopLevelBucket(resBucketKey)
 57  		if err != nil {
 58  			return err
 59  		}
 60  
 61  		return resBucket.Put(outKey.Bytes(), resBuf.Bytes())
 62  	}, func() {})
 63  	if err != nil {
 64  		return err
 65  	}
 66  
 67  	return nil
 68  }
 69  
 70  // checkResolutionMsg returns nil if the resolution message is found in the
 71  // store. It returns an error if no resolution message was found for the
 72  // passed outKey or if a database error occurred.
 73  func (r *resolutionStore) checkResolutionMsg(outKey *CircuitKey) error {
 74  	err := kvdb.View(r.backend, func(tx kvdb.RTx) error {
 75  		resBucket := tx.ReadBucket(resBucketKey)
 76  		if resBucket == nil {
 77  			// Return an error if the bucket doesn't exist.
 78  			return errResMsgNotFound
 79  		}
 80  
 81  		msg := resBucket.Get(outKey.Bytes())
 82  		if msg == nil {
 83  			// Return the not found error since no message exists
 84  			// for this CircuitKey.
 85  			return errResMsgNotFound
 86  		}
 87  
 88  		// Return nil to indicate that the message was found.
 89  		return nil
 90  	}, func() {})
 91  	if err != nil {
 92  		return err
 93  	}
 94  
 95  	return nil
 96  }
 97  
 98  // fetchAllResolutionMsg returns a slice of all stored ResolutionMsgs. This is
 99  // used by the Switch on start-up.
100  func (r *resolutionStore) fetchAllResolutionMsg() (
101  	[]*contractcourt.ResolutionMsg, error) {
102  
103  	var msgs []*contractcourt.ResolutionMsg
104  
105  	err := kvdb.View(r.backend, func(tx kvdb.RTx) error {
106  		resBucket := tx.ReadBucket(resBucketKey)
107  		if resBucket == nil {
108  			return nil
109  		}
110  
111  		return resBucket.ForEach(func(k, v []byte) error {
112  			kr := bytes.NewReader(k)
113  			outKey := &CircuitKey{}
114  			if err := outKey.Decode(kr); err != nil {
115  				return err
116  			}
117  
118  			vr := bytes.NewReader(v)
119  			resMsg, err := deserializeResolutionMsg(vr)
120  			if err != nil {
121  				return err
122  			}
123  
124  			// Set the CircuitKey values on the ResolutionMsg.
125  			resMsg.SourceChan = outKey.ChanID
126  			resMsg.HtlcIndex = outKey.HtlcID
127  
128  			msgs = append(msgs, resMsg)
129  			return nil
130  		})
131  	}, func() {
132  		msgs = nil
133  	})
134  	if err != nil {
135  		return nil, err
136  	}
137  
138  	return msgs, nil
139  }
140  
141  // deleteResolutionMsg removes a ResolutionMsg with the passed-in CircuitKey.
142  func (r *resolutionStore) deleteResolutionMsg(outKey *CircuitKey) error {
143  	err := kvdb.Update(r.backend, func(tx kvdb.RwTx) error {
144  		resBucket, err := tx.CreateTopLevelBucket(resBucketKey)
145  		if err != nil {
146  			return err
147  		}
148  
149  		return resBucket.Delete(outKey.Bytes())
150  	}, func() {})
151  	return err
152  }
153  
154  // serializeResolutionMsg writes part of a ResolutionMsg to the passed
155  // io.Writer.
156  func serializeResolutionMsg(w io.Writer,
157  	resMsg *contractcourt.ResolutionMsg) error {
158  
159  	isFail := resMsg.Failure != nil
160  
161  	if err := channeldb.WriteElement(w, isFail); err != nil {
162  		return err
163  	}
164  
165  	// If this is a failure message, then we're done serializing.
166  	if isFail {
167  		return nil
168  	}
169  
170  	// Else this is a settle message, and we need to write the preimage.
171  	return channeldb.WriteElement(w, *resMsg.PreImage)
172  }
173  
174  // deserializeResolutionMsg reads part of a ResolutionMsg from the passed
175  // io.Reader.
176  func deserializeResolutionMsg(r io.Reader) (*contractcourt.ResolutionMsg,
177  	error) {
178  
179  	resMsg := &contractcourt.ResolutionMsg{}
180  	var isFail bool
181  
182  	if err := channeldb.ReadElements(r, &isFail); err != nil {
183  		return nil, err
184  	}
185  
186  	// If a failure resolution msg was stored, set the Failure field.
187  	if isFail {
188  		failureMsg := &lnwire.FailPermanentChannelFailure{}
189  		resMsg.Failure = failureMsg
190  		return resMsg, nil
191  	}
192  
193  	var preimage [32]byte
194  	resMsg.PreImage = &preimage
195  
196  	// Else this is a settle resolution msg and we will read the preimage.
197  	if err := channeldb.ReadElement(r, resMsg.PreImage); err != nil {
198  		return nil, err
199  	}
200  
201  	return resMsg, nil
202  }