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

     1  package watchtower
     2  
     3  import (
     4  	"fmt"
     5  	"path/filepath"
     6  
     7  	"github.com/boltdb/bolt"
     8  	"github.com/mit-dci/lit/coinparam"
     9  	"github.com/mit-dci/lit/lnutil"
    10  	"github.com/mit-dci/lit/uspv"
    11  )
    12  
    13  type Watcher interface {
    14  	// Links to the blockchain.
    15  	// Uses the same chainhook interface as the wallit does.  But only uses
    16  	// 2 of the functions: PushTx() and RawBlocks()
    17  	// Blocks come in from the chainhook, and justice transactions come out.
    18  	// The uint32 is the cointype, the string is the folder to put all db files.
    19  	HookLink(string, *coinparam.Params, uspv.ChainHook) error
    20  
    21  	// New Channel to watch
    22  	NewChannel(lnutil.WatchDescMsg) error
    23  
    24  	// Update a channel being watched
    25  	UpdateChannel(lnutil.WatchStateMsg) error
    26  
    27  	// Delete a channel being watched
    28  	DeleteChannel(lnutil.WatchDelMsg) error
    29  
    30  	// Later on, allow users to recover channel state from
    31  	// the data in a watcher.  Like if they wipe their ln.db files but
    32  	// still have their keys.
    33  }
    34  
    35  // The main watchtower struct
    36  type WatchTower struct {
    37  	Path string // where the DB goes?  needed?
    38  
    39  	WatchDB *bolt.DB // single DB with everything in it
    40  	// much more efficient to have a separate DB for each cointype
    41  	// ... but that's less anonymous.  To get that efficiency; make a bunch of
    42  	// towers, I guess.
    43  
    44  	Accepting bool // true if new channels and sigs are allowed in
    45  	Watching  bool // true if there are txids to watch for
    46  
    47  	SyncHeight int32 // last block we've sync'd to.  Not needed?
    48  
    49  	// map of cointypes to chainhooks
    50  	Hooks map[uint32]uspv.ChainHook
    51  }
    52  
    53  // Hooklink is the connection between the watchtower and the blockchain
    54  // Takes in a channel of blocks, and the cointype.  Immediately returns
    55  // a channel which it will send justice transactions to.
    56  func (w *WatchTower) HookLink(dbPath string, param *coinparam.Params,
    57  	hook uspv.ChainHook) error {
    58  
    59  	cointype := param.HDCoinType
    60  
    61  	// if the hooks map hasn't been initialized, make it. also open DB
    62  	if len(w.Hooks) == 0 {
    63  		w.Hooks = make(map[uint32]uspv.ChainHook)
    64  
    65  		towerDBName := filepath.Join(dbPath, "watch.db")
    66  		err := w.OpenDB(towerDBName)
    67  		if err != nil {
    68  			return err
    69  		}
    70  
    71  	}
    72  
    73  	// see if this cointype is already registered
    74  	_, ok := w.Hooks[cointype]
    75  	if ok {
    76  		return fmt.Errorf("Coin type %d already linked", cointype)
    77  	}
    78  
    79  	// only need this for the pushTx() method
    80  	w.Hooks[cointype] = hook
    81  
    82  	go w.BlockHandler(cointype, hook.RawBlocks())
    83  
    84  	return nil
    85  }
    86  
    87  // 2 structs used in the DB: IdxSigs and ChanStatic
    88  
    89  // IdxSig is what we save in the DB for each txid
    90  type IdxSig struct {
    91  	PKHIdx   uint32   // Who
    92  	StateIdx uint64   // When
    93  	Sig      [64]byte // What
    94  }
    95  
    96  /*
    97  func (w *WatchTower) HandleMessage(msg lnutil.LitMsg) error {
    98  	logging.Infof("got message from %x\n", msg.Peer())
    99  
   100  	switch msg.MsgType() {
   101  	case lnutil.MSGID_WATCH_DESC:
   102  		logging.Infof("new channel to watch\n")
   103  		message, ok := msg.(lnutil.WatchDescMsg)
   104  		if !ok {
   105  			return fmt.Errorf("didn't work")
   106  		} else {
   107  			return w.AddNewChannel(message)
   108  		}
   109  
   110  	case lnutil.MSGID_WATCH_STATEMSG:
   111  		logging.Infof("new commsg\n")
   112  		message, ok := msg.(lnutil.WatchStateMsg)
   113  		if !ok {
   114  			return fmt.Errorf("didn't work")
   115  		} else {
   116  			return w.AddState(message)
   117  		}
   118  
   119  	case lnutil.MSGID_WATCH_DELETE:
   120  		logging.Infof("delete message\n")
   121  		// delete not yet implemented
   122  	default:
   123  		logging.Infof("unknown message type %x\n", msg.MsgType())
   124  	}
   125  	return nil
   126  }
   127  */