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  }