/ 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 }