github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/dlc/dlcdb.go (about)

     1  package dlc
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  
     8  	"github.com/boltdb/bolt"
     9  	"github.com/mit-dci/lit/lnutil"
    10  )
    11  
    12  // const strings for db usage
    13  var (
    14  	BKTOracles   = []byte("Oracles")
    15  	BKTContracts = []byte("Contracts")
    16  )
    17  
    18  // InitDB initializes the database for Discreet Log Contract storage
    19  func (mgr *DlcManager) InitDB(dbPath string) error {
    20  	var err error
    21  
    22  	mgr.DLCDB, err = bolt.Open(dbPath, 0600, nil)
    23  	if err != nil {
    24  		return err
    25  	}
    26  
    27  	// Ensure buckets exist that we need
    28  	err = mgr.DLCDB.Update(func(tx *bolt.Tx) error {
    29  		_, err = tx.CreateBucketIfNotExists(BKTOracles)
    30  		if err != nil {
    31  			return err
    32  		}
    33  		_, err = tx.CreateBucketIfNotExists(BKTContracts)
    34  		return err
    35  	})
    36  
    37  	return nil
    38  }
    39  
    40  // SaveOracle saves an oracle into the database. Generates a new index if the
    41  // passed oracle doesn't have one
    42  func (mgr *DlcManager) SaveOracle(o *DlcOracle) error {
    43  	err := mgr.DLCDB.Update(func(tx *bolt.Tx) error {
    44  		b := tx.Bucket(BKTOracles)
    45  
    46  		if o.Idx == 0 {
    47  			o.Idx, _ = b.NextSequence()
    48  		}
    49  		var wb bytes.Buffer
    50  		binary.Write(&wb, binary.BigEndian, o.Idx)
    51  		err := b.Put(wb.Bytes(), o.Bytes())
    52  
    53  		if err != nil {
    54  			return err
    55  		}
    56  
    57  		return nil
    58  	})
    59  
    60  	if err != nil {
    61  		return err
    62  	}
    63  	return nil
    64  }
    65  
    66  // LoadOracle loads an oracle from the database by index.
    67  func (mgr *DlcManager) LoadOracle(idx uint64) (*DlcOracle, error) {
    68  	o := new(DlcOracle)
    69  
    70  	err := mgr.DLCDB.View(func(tx *bolt.Tx) error {
    71  		b := tx.Bucket(BKTOracles)
    72  
    73  		var wb bytes.Buffer
    74  		binary.Write(&wb, binary.BigEndian, idx)
    75  
    76  		v := b.Get(wb.Bytes())
    77  
    78  		if v == nil {
    79  			return fmt.Errorf("Oracle %d does not exist", idx)
    80  		}
    81  		var err error
    82  		o, err = DlcOracleFromBytes(v)
    83  		if err != nil {
    84  			return err
    85  		}
    86  		o.Idx = idx
    87  		return nil
    88  	})
    89  
    90  	if err != nil {
    91  		return nil, err
    92  	}
    93  
    94  	return o, nil
    95  
    96  }
    97  
    98  // ListOracles loads all oracles from the database and returns them as an array
    99  func (mgr *DlcManager) ListOracles() ([]*DlcOracle, error) {
   100  	oracles := make([]*DlcOracle, 0)
   101  	err := mgr.DLCDB.View(func(tx *bolt.Tx) error {
   102  		b := tx.Bucket(BKTOracles)
   103  		c := b.Cursor()
   104  
   105  		for k, v := c.First(); k != nil; k, v = c.Next() {
   106  			buf := bytes.NewBuffer(k)
   107  			o, err := DlcOracleFromBytes(v)
   108  			if err != nil {
   109  				return err
   110  			}
   111  			binary.Read(buf, binary.BigEndian, &o.Idx)
   112  			oracles = append(oracles, o)
   113  		}
   114  		return nil
   115  	})
   116  
   117  	if err != nil {
   118  		return nil, err
   119  	}
   120  
   121  	return oracles, nil
   122  }
   123  
   124  // SaveContract saves a contract into the database. Will generate a new index
   125  // if the passed object doesn't have one.
   126  func (mgr *DlcManager) SaveContract(c *lnutil.DlcContract) error {
   127  	err := mgr.DLCDB.Update(func(tx *bolt.Tx) error {
   128  		b := tx.Bucket(BKTContracts)
   129  
   130  		if c.Idx == 0 {
   131  			c.Idx, _ = b.NextSequence()
   132  		}
   133  		var wb bytes.Buffer
   134  		binary.Write(&wb, binary.BigEndian, c.Idx)
   135  		err := b.Put(wb.Bytes(), c.Bytes())
   136  
   137  		if err != nil {
   138  			return err
   139  		}
   140  
   141  		return nil
   142  	})
   143  
   144  	if err != nil {
   145  		return err
   146  	}
   147  	return nil
   148  }
   149  
   150  // LoadContract loads a contract from the database by index.
   151  func (mgr *DlcManager) LoadContract(idx uint64) (*lnutil.DlcContract, error) {
   152  	c := new(lnutil.DlcContract)
   153  
   154  	err := mgr.DLCDB.View(func(tx *bolt.Tx) error {
   155  		b := tx.Bucket(BKTContracts)
   156  
   157  		var wb bytes.Buffer
   158  		binary.Write(&wb, binary.BigEndian, idx)
   159  
   160  		v := b.Get(wb.Bytes())
   161  
   162  		if v == nil {
   163  			return fmt.Errorf("Contract %d does not exist", idx)
   164  		}
   165  		var err error
   166  		c, err = lnutil.DlcContractFromBytes(v)
   167  		if err != nil {
   168  			return err
   169  		}
   170  		c.Idx = idx
   171  		return nil
   172  	})
   173  
   174  	if err != nil {
   175  		return nil, err
   176  	}
   177  
   178  	return c, nil
   179  
   180  }
   181  
   182  // ListContracts loads all contracts from the database
   183  func (mgr *DlcManager) ListContracts() ([]*lnutil.DlcContract, error) {
   184  	contracts := make([]*lnutil.DlcContract, 0)
   185  	err := mgr.DLCDB.View(func(tx *bolt.Tx) error {
   186  		b := tx.Bucket(BKTContracts)
   187  		c := b.Cursor()
   188  
   189  		for k, v := c.First(); k != nil; k, v = c.Next() {
   190  			buf := bytes.NewBuffer(k)
   191  			c, err := lnutil.DlcContractFromBytes(v)
   192  			if err != nil {
   193  				return err
   194  			}
   195  			binary.Read(buf, binary.BigEndian, &c.Idx)
   196  			contracts = append(contracts, c)
   197  		}
   198  		return nil
   199  	})
   200  
   201  	if err != nil {
   202  		return nil, err
   203  	}
   204  
   205  	return contracts, nil
   206  }