github.com/decred/dcrlnd@v0.7.6/channeldb/waitingproof.go (about) 1 package channeldb 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "sync" 7 8 "io" 9 10 "bytes" 11 12 "github.com/decred/dcrlnd/kvdb" 13 "github.com/decred/dcrlnd/lnwire" 14 "github.com/go-errors/errors" 15 ) 16 17 var ( 18 // waitingProofsBucketKey byte string name of the waiting proofs store. 19 waitingProofsBucketKey = []byte("waitingproofs") 20 21 // ErrWaitingProofNotFound is returned if waiting proofs haven't been 22 // found by db. 23 ErrWaitingProofNotFound = errors.New("waiting proofs haven't been " + 24 "found") 25 26 // ErrWaitingProofAlreadyExist is returned if waiting proofs haven't been 27 // found by db. 28 ErrWaitingProofAlreadyExist = errors.New("waiting proof with such " + 29 "key already exist") 30 ) 31 32 // WaitingProofStore is the bold db map-like storage for half announcement 33 // signatures. The one responsibility of this storage is to be able to 34 // retrieve waiting proofs after client restart. 35 type WaitingProofStore struct { 36 // cache is used in order to reduce the number of redundant get 37 // calls, when object isn't stored in it. 38 cache map[WaitingProofKey]struct{} 39 db kvdb.Backend 40 mu sync.RWMutex 41 } 42 43 // NewWaitingProofStore creates new instance of proofs storage. 44 func NewWaitingProofStore(db kvdb.Backend) (*WaitingProofStore, error) { 45 s := &WaitingProofStore{ 46 db: db, 47 } 48 49 if err := s.ForAll(func(proof *WaitingProof) error { 50 s.cache[proof.Key()] = struct{}{} 51 return nil 52 }, func() { 53 s.cache = make(map[WaitingProofKey]struct{}) 54 }); err != nil && err != ErrWaitingProofNotFound { 55 return nil, err 56 } 57 58 return s, nil 59 } 60 61 // Add adds new waiting proof in the storage. 62 func (s *WaitingProofStore) Add(proof *WaitingProof) error { 63 s.mu.Lock() 64 defer s.mu.Unlock() 65 66 err := kvdb.Update(s.db, func(tx kvdb.RwTx) error { 67 var err error 68 var b bytes.Buffer 69 70 // Get or create the bucket. 71 bucket, err := tx.CreateTopLevelBucket(waitingProofsBucketKey) 72 if err != nil { 73 return err 74 } 75 76 // Encode the objects and place it in the bucket. 77 if err := proof.Encode(&b); err != nil { 78 return err 79 } 80 81 key := proof.Key() 82 83 return bucket.Put(key[:], b.Bytes()) 84 }, func() {}) 85 if err != nil { 86 return err 87 } 88 89 // Knowing that the write succeeded, we can now update the in-memory 90 // cache with the proof's key. 91 s.cache[proof.Key()] = struct{}{} 92 93 return nil 94 } 95 96 // Remove removes the proof from storage by its key. 97 func (s *WaitingProofStore) Remove(key WaitingProofKey) error { 98 s.mu.Lock() 99 defer s.mu.Unlock() 100 101 if _, ok := s.cache[key]; !ok { 102 return ErrWaitingProofNotFound 103 } 104 105 err := kvdb.Update(s.db, func(tx kvdb.RwTx) error { 106 // Get or create the top bucket. 107 bucket := tx.ReadWriteBucket(waitingProofsBucketKey) 108 if bucket == nil { 109 return ErrWaitingProofNotFound 110 } 111 112 return bucket.Delete(key[:]) 113 }, func() {}) 114 if err != nil { 115 return err 116 } 117 118 // Since the proof was successfully deleted from the store, we can now 119 // remove it from the in-memory cache. 120 delete(s.cache, key) 121 122 return nil 123 } 124 125 // ForAll iterates thought all waiting proofs and passing the waiting proof 126 // in the given callback. 127 func (s *WaitingProofStore) ForAll(cb func(*WaitingProof) error, 128 reset func()) error { 129 130 return kvdb.View(s.db, func(tx kvdb.RTx) error { 131 bucket := tx.ReadBucket(waitingProofsBucketKey) 132 if bucket == nil { 133 return ErrWaitingProofNotFound 134 } 135 136 // Iterate over objects buckets. 137 return bucket.ForEach(func(k, v []byte) error { 138 // Skip buckets fields. 139 if v == nil { 140 return nil 141 } 142 143 r := bytes.NewReader(v) 144 proof := &WaitingProof{} 145 if err := proof.Decode(r); err != nil { 146 return err 147 } 148 149 return cb(proof) 150 }) 151 }, reset) 152 } 153 154 // Get returns the object which corresponds to the given index. 155 func (s *WaitingProofStore) Get(key WaitingProofKey) (*WaitingProof, error) { 156 var proof *WaitingProof 157 158 s.mu.RLock() 159 defer s.mu.RUnlock() 160 161 if _, ok := s.cache[key]; !ok { 162 return nil, ErrWaitingProofNotFound 163 } 164 165 err := kvdb.View(s.db, func(tx kvdb.RTx) error { 166 bucket := tx.ReadBucket(waitingProofsBucketKey) 167 if bucket == nil { 168 return ErrWaitingProofNotFound 169 } 170 171 // Iterate over objects buckets. 172 v := bucket.Get(key[:]) 173 if v == nil { 174 return ErrWaitingProofNotFound 175 } 176 177 r := bytes.NewReader(v) 178 return proof.Decode(r) 179 }, func() { 180 proof = &WaitingProof{} 181 }) 182 183 return proof, err 184 } 185 186 // WaitingProofKey is the proof key which uniquely identifies the waiting 187 // proof object. The goal of this key is distinguish the local and remote 188 // proof for the same channel id. 189 type WaitingProofKey [9]byte 190 191 // WaitingProof is the storable object, which encapsulate the half proof and 192 // the information about from which side this proof came. This structure is 193 // needed to make channel proof exchange persistent, so that after client 194 // restart we may receive remote/local half proof and process it. 195 type WaitingProof struct { 196 *lnwire.AnnounceSignatures 197 isRemote bool 198 } 199 200 // NewWaitingProof constructs a new waiting prof instance. 201 func NewWaitingProof(isRemote bool, proof *lnwire.AnnounceSignatures) *WaitingProof { 202 return &WaitingProof{ 203 AnnounceSignatures: proof, 204 isRemote: isRemote, 205 } 206 } 207 208 // OppositeKey returns the key which uniquely identifies opposite waiting proof. 209 func (p *WaitingProof) OppositeKey() WaitingProofKey { 210 var key [9]byte 211 binary.BigEndian.PutUint64(key[:8], p.ShortChannelID.ToUint64()) 212 213 if !p.isRemote { 214 key[8] = 1 215 } 216 return key 217 } 218 219 // Key returns the key which uniquely identifies waiting proof. 220 func (p *WaitingProof) Key() WaitingProofKey { 221 var key [9]byte 222 binary.BigEndian.PutUint64(key[:8], p.ShortChannelID.ToUint64()) 223 224 if p.isRemote { 225 key[8] = 1 226 } 227 return key 228 } 229 230 // Encode writes the internal representation of waiting proof in byte stream. 231 func (p *WaitingProof) Encode(w io.Writer) error { 232 if err := binary.Write(w, byteOrder, p.isRemote); err != nil { 233 return err 234 } 235 236 // TODO(yy): remove the type assertion when we finished refactoring db 237 // into using write buffer. 238 buf, ok := w.(*bytes.Buffer) 239 if !ok { 240 return fmt.Errorf("expect io.Writer to be *bytes.Buffer") 241 } 242 243 if err := p.AnnounceSignatures.Encode(buf, 0); err != nil { 244 return err 245 } 246 247 return nil 248 } 249 250 // Decode reads the data from the byte stream and initializes the 251 // waiting proof object with it. 252 func (p *WaitingProof) Decode(r io.Reader) error { 253 if err := binary.Read(r, byteOrder, &p.isRemote); err != nil { 254 return err 255 } 256 257 msg := &lnwire.AnnounceSignatures{} 258 if err := msg.Decode(r, 0); err != nil { 259 return err 260 } 261 262 p.AnnounceSignatures = msg 263 return nil 264 }