diff --git a/watchtower/wtdb/breach_hint.go b/watchtower/blob/derivation.go similarity index 98% rename from watchtower/wtdb/breach_hint.go rename to watchtower/blob/derivation.go index 8332745b..a052157a 100644 --- a/watchtower/wtdb/breach_hint.go +++ b/watchtower/blob/derivation.go @@ -1,4 +1,4 @@ -package wtdb +package blob import ( "encoding/hex" diff --git a/watchtower/lookout/interface.go b/watchtower/lookout/interface.go index 6a750c9f..a84f22b0 100644 --- a/watchtower/lookout/interface.go +++ b/watchtower/lookout/interface.go @@ -4,6 +4,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/chainntnfs" + "github.com/lightningnetwork/lnd/watchtower/blob" "github.com/lightningnetwork/lnd/watchtower/wtdb" ) @@ -37,7 +38,7 @@ type DB interface { // QueryMatches searches its database for any state updates matching the // provided breach hints. If any matches are found, they will be // returned along with encrypted blobs so that justice can be exacted. - QueryMatches([]wtdb.BreachHint) ([]wtdb.Match, error) + QueryMatches([]blob.BreachHint) ([]wtdb.Match, error) // SetLookoutTip writes the best epoch for which the watchtower has // queried for breach hints. diff --git a/watchtower/lookout/lookout.go b/watchtower/lookout/lookout.go index 556db2e8..6ab41b28 100644 --- a/watchtower/lookout/lookout.go +++ b/watchtower/lookout/lookout.go @@ -7,7 +7,6 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/watchtower/blob" - "github.com/lightningnetwork/lnd/watchtower/wtdb" ) // Config houses the Lookout's required resources to properly fulfill it's duty, @@ -159,11 +158,11 @@ func (l *Lookout) processEpoch(epoch *chainntnfs.BlockEpoch, // Iterate over the transactions contained in the block, deriving a // breach hint for each transaction and constructing an index mapping // the hint back to it's original transaction. - hintToTx := make(map[wtdb.BreachHint]*wire.MsgTx, numTxnsInBlock) - txHints := make([]wtdb.BreachHint, 0, numTxnsInBlock) + hintToTx := make(map[blob.BreachHint]*wire.MsgTx, numTxnsInBlock) + txHints := make([]blob.BreachHint, 0, numTxnsInBlock) for _, tx := range block.Transactions { hash := tx.TxHash() - hint := wtdb.NewBreachHintFromHash(&hash) + hint := blob.NewBreachHintFromHash(&hash) txHints = append(txHints, hint) hintToTx[hint] = tx diff --git a/watchtower/lookout/lookout_test.go b/watchtower/lookout/lookout_test.go index fb70a961..66a485ca 100644 --- a/watchtower/lookout/lookout_test.go +++ b/watchtower/lookout/lookout_test.go @@ -163,13 +163,13 @@ func TestLookoutBreachMatching(t *testing.T) { // Add both state updates to the tower's database. txBlob1 := &wtdb.SessionStateUpdate{ ID: makeArray33(1), - Hint: wtdb.NewBreachHintFromHash(&hash1), + Hint: blob.NewBreachHintFromHash(&hash1), EncryptedBlob: encBlob1, SeqNum: 1, } txBlob2 := &wtdb.SessionStateUpdate{ ID: makeArray33(2), - Hint: wtdb.NewBreachHintFromHash(&hash2), + Hint: blob.NewBreachHintFromHash(&hash2), EncryptedBlob: encBlob2, SeqNum: 1, } diff --git a/watchtower/wtclient/backup_task.go b/watchtower/wtclient/backup_task.go index 72e14934..b166428a 100644 --- a/watchtower/wtclient/backup_task.go +++ b/watchtower/wtclient/backup_task.go @@ -173,9 +173,9 @@ func (t *backupTask) bindSession(session *wtdb.ClientSessionBody) error { // required pieces from signatures, witness scripts, etc are then packaged into // a JusticeKit and encrypted using the breach transaction's key. func (t *backupTask) craftSessionPayload( - signer input.Signer) (wtdb.BreachHint, []byte, error) { + signer input.Signer) (blob.BreachHint, []byte, error) { - var hint wtdb.BreachHint + var hint blob.BreachHint // First, copy over the sweep pkscript, the pubkeys used to derive the // to-local script, and the remote CSV delay. @@ -290,7 +290,7 @@ func (t *backupTask) craftSessionPayload( // Finally, compute the breach hint, taken as the first half of the // breach transactions txid. Once the tower sees the breach transaction // on the network, it can use the full txid to decyrpt the blob. - hint = wtdb.NewBreachHintFromHash(&breachKey) + hint = blob.NewBreachHintFromHash(&breachKey) return hint, encBlob, nil } diff --git a/watchtower/wtclient/backup_task_internal_test.go b/watchtower/wtclient/backup_task_internal_test.go index 869c4042..807a7260 100644 --- a/watchtower/wtclient/backup_task_internal_test.go +++ b/watchtower/wtclient/backup_task_internal_test.go @@ -516,7 +516,7 @@ func testBackupTask(t *testing.T, test backupTaskTest) { // Verify that the breach hint matches the breach txid's prefix. breachTxID := test.breachInfo.BreachTransaction.TxHash() - expHint := wtdb.NewBreachHintFromHash(&breachTxID) + expHint := blob.NewBreachHintFromHash(&breachTxID) if hint != expHint { t.Fatalf("breach hint mismatch, want: %x, got: %v", expHint, hint) diff --git a/watchtower/wtclient/client_test.go b/watchtower/wtclient/client_test.go index b5a9bbbd..00abc19d 100644 --- a/watchtower/wtclient/client_test.go +++ b/watchtower/wtclient/client_test.go @@ -576,17 +576,17 @@ func (h *testHarness) registerChannel(id uint64) { // advanceChannelN calls advanceState on the channel identified by id the number // of provided times and returns the breach hints corresponding to the new // states. -func (h *testHarness) advanceChannelN(id uint64, n int) []wtdb.BreachHint { +func (h *testHarness) advanceChannelN(id uint64, n int) []blob.BreachHint { h.t.Helper() channel := h.channel(id) - var hints []wtdb.BreachHint + var hints []blob.BreachHint for i := uint64(0); i < uint64(n); i++ { channel.advanceState(h.t) commitTx, _ := h.channel(id).getState(i) breachTxID := commitTx.TxHash() - hints = append(hints, wtdb.NewBreachHintFromHash(&breachTxID)) + hints = append(hints, blob.NewBreachHintFromHash(&breachTxID)) } return hints @@ -621,18 +621,18 @@ func (h *testHarness) backupState(id, i uint64, expErr error) { // party for each state in from-to times and returns the breach hints for states // [from, to). func (h *testHarness) sendPayments(id, from, to uint64, - amt lnwire.MilliSatoshi) []wtdb.BreachHint { + amt lnwire.MilliSatoshi) []blob.BreachHint { h.t.Helper() channel := h.channel(id) - var hints []wtdb.BreachHint + var hints []blob.BreachHint for i := from; i < to; i++ { h.channel(id).sendPayment(h.t, amt) commitTx, _ := channel.getState(i) breachTxID := commitTx.TxHash() - hints = append(hints, wtdb.NewBreachHintFromHash(&breachTxID)) + hints = append(hints, blob.NewBreachHintFromHash(&breachTxID)) } return hints @@ -642,18 +642,18 @@ func (h *testHarness) sendPayments(id, from, to uint64, // remote party for each state in from-to times and returns the breach hints for // states [from, to). func (h *testHarness) recvPayments(id, from, to uint64, - amt lnwire.MilliSatoshi) []wtdb.BreachHint { + amt lnwire.MilliSatoshi) []blob.BreachHint { h.t.Helper() channel := h.channel(id) - var hints []wtdb.BreachHint + var hints []blob.BreachHint for i := from; i < to; i++ { channel.receivePayment(h.t, amt) commitTx, _ := channel.getState(i) breachTxID := commitTx.TxHash() - hints = append(hints, wtdb.NewBreachHintFromHash(&breachTxID)) + hints = append(hints, blob.NewBreachHintFromHash(&breachTxID)) } return hints @@ -662,7 +662,7 @@ func (h *testHarness) recvPayments(id, from, to uint64, // waitServerUpdates blocks until the breach hints provided all appear in the // watchtower's database or the timeout expires. This is used to test that the // client in fact sends the updates to the server, even if it is offline. -func (h *testHarness) waitServerUpdates(hints []wtdb.BreachHint, +func (h *testHarness) waitServerUpdates(hints []blob.BreachHint, timeout time.Duration) { h.t.Helper() @@ -671,7 +671,7 @@ func (h *testHarness) waitServerUpdates(hints []wtdb.BreachHint, // assert that no updates appear. wantUpdates := len(hints) > 0 - hintSet := make(map[wtdb.BreachHint]struct{}) + hintSet := make(map[blob.BreachHint]struct{}) for _, hint := range hints { hintSet[hint] = struct{}{} } @@ -737,7 +737,7 @@ func (h *testHarness) waitServerUpdates(hints []wtdb.BreachHint, // assertUpdatesForPolicy queries the server db for matches using the provided // breach hints, then asserts that each match has a session with the expected // policy. -func (h *testHarness) assertUpdatesForPolicy(hints []wtdb.BreachHint, +func (h *testHarness) assertUpdatesForPolicy(hints []blob.BreachHint, expPolicy wtpolicy.Policy) { // Query for matches on the provided hints. @@ -1113,7 +1113,7 @@ var clientTests = []clientTest{ // Generate the retributions for all 10 channels and // collect the breach hints. - var hints []wtdb.BreachHint + var hints []blob.BreachHint for id := uint64(0); id < 10; id++ { chanHints := h.advanceChannelN(id, numUpdates) hints = append(hints, chanHints...) diff --git a/watchtower/wtdb/client_db_test.go b/watchtower/wtdb/client_db_test.go index 66fd8a4e..92ebc95b 100644 --- a/watchtower/wtdb/client_db_test.go +++ b/watchtower/wtdb/client_db_test.go @@ -664,7 +664,7 @@ func randCommittedUpdate(t *testing.T, seqNum uint16) *wtdb.CommittedUpdate { t.Fatalf("unable to generate chan id: %v", err) } - var hint wtdb.BreachHint + var hint blob.BreachHint if _, err := io.ReadFull(crand.Reader, hint[:]); err != nil { t.Fatalf("unable to generate breach hint: %v", err) } diff --git a/watchtower/wtdb/client_session.go b/watchtower/wtdb/client_session.go index cb59ca57..768fe109 100644 --- a/watchtower/wtdb/client_session.go +++ b/watchtower/wtdb/client_session.go @@ -5,6 +5,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/watchtower/blob" "github.com/lightningnetwork/lnd/watchtower/wtpolicy" ) @@ -178,7 +179,7 @@ type CommittedUpdateBody struct { BackupID BackupID // Hint is the 16-byte prefix of the revoked commitment transaction ID. - Hint BreachHint + Hint blob.BreachHint // EncryptedBlob is a ciphertext containing the sweep information for // exacting justice if the commitment transaction matching the breach diff --git a/watchtower/wtdb/codec.go b/watchtower/wtdb/codec.go index 2fd30196..8c88f814 100644 --- a/watchtower/wtdb/codec.go +++ b/watchtower/wtdb/codec.go @@ -36,7 +36,7 @@ func ReadElement(r io.Reader, element interface{}) error { return err } - case *BreachHint: + case *blob.BreachHint: if _, err := io.ReadFull(r, e[:]); err != nil { return err } @@ -94,7 +94,7 @@ func WriteElement(w io.Writer, element interface{}) error { return err } - case BreachHint: + case blob.BreachHint: if _, err := w.Write(e[:]); err != nil { return err } diff --git a/watchtower/wtdb/session_info.go b/watchtower/wtdb/session_info.go index f4acf764..2c8809a9 100644 --- a/watchtower/wtdb/session_info.go +++ b/watchtower/wtdb/session_info.go @@ -4,6 +4,7 @@ import ( "errors" "io" + "github.com/lightningnetwork/lnd/watchtower/blob" "github.com/lightningnetwork/lnd/watchtower/wtpolicy" ) @@ -134,7 +135,7 @@ type Match struct { SeqNum uint16 // Hint is the breach hint that triggered the match. - Hint BreachHint + Hint blob.BreachHint // EncryptedBlob is the encrypted payload containing the justice kit // uploaded by the client. diff --git a/watchtower/wtdb/session_state_update.go b/watchtower/wtdb/session_state_update.go index 9b178220..c5e3131e 100644 --- a/watchtower/wtdb/session_state_update.go +++ b/watchtower/wtdb/session_state_update.go @@ -1,6 +1,10 @@ package wtdb -import "io" +import ( + "io" + + "github.com/lightningnetwork/lnd/watchtower/blob" +) // SessionStateUpdate holds a state update sent by a client along with its // SessionID. @@ -16,7 +20,7 @@ type SessionStateUpdate struct { LastApplied uint16 // Hint is the 16-byte prefix of the revoked commitment transaction. - Hint BreachHint + Hint blob.BreachHint // EncryptedBlob is a ciphertext containing the sweep information for // exacting justice if the commitment transaction matching the breach diff --git a/watchtower/wtdb/tower_db.go b/watchtower/wtdb/tower_db.go index 96edafca..2defce21 100644 --- a/watchtower/wtdb/tower_db.go +++ b/watchtower/wtdb/tower_db.go @@ -7,6 +7,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/chainntnfs" + "github.com/lightningnetwork/lnd/watchtower/blob" ) const ( @@ -369,7 +370,7 @@ func (t *TowerDB) DeleteSession(target SessionID) error { // QueryMatches searches against all known state updates for any that match the // passed breachHints. More than one Match will be returned for a given hint if // they exist in the database. -func (t *TowerDB) QueryMatches(breachHints []BreachHint) ([]Match, error) { +func (t *TowerDB) QueryMatches(breachHints []blob.BreachHint) ([]Match, error) { var matches []Match err := t.db.View(func(tx *bbolt.Tx) error { sessions := tx.Bucket(sessionsBkt) @@ -534,20 +535,20 @@ func removeSessionHintBkt(updateIndex *bbolt.Bucket, id *SessionID) error { // If the index for the session has not been initialized, this method returns // ErrNoSessionHintIndex. func getHintsForSession(updateIndex *bbolt.Bucket, - id *SessionID) ([]BreachHint, error) { + id *SessionID) ([]blob.BreachHint, error) { sessionHints := updateIndex.Bucket(id[:]) if sessionHints == nil { return nil, ErrNoSessionHintIndex } - var hints []BreachHint + var hints []blob.BreachHint err := sessionHints.ForEach(func(k, _ []byte) error { - if len(k) != BreachHintSize { + if len(k) != blob.BreachHintSize { return nil } - var hint BreachHint + var hint blob.BreachHint copy(hint[:], k) hints = append(hints, hint) return nil @@ -565,7 +566,7 @@ func getHintsForSession(updateIndex *bbolt.Bucket, // for the session has not been initialized, this method returns // ErrNoSessionHintIndex. func putHintForSession(updateIndex *bbolt.Bucket, id *SessionID, - hint BreachHint) error { + hint blob.BreachHint) error { sessionHints := updateIndex.Bucket(id[:]) if sessionHints == nil { diff --git a/watchtower/wtdb/tower_db_test.go b/watchtower/wtdb/tower_db_test.go index c9920bcb..57a95c4f 100644 --- a/watchtower/wtdb/tower_db_test.go +++ b/watchtower/wtdb/tower_db_test.go @@ -10,6 +10,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/watchtower" + "github.com/lightningnetwork/lnd/watchtower/blob" "github.com/lightningnetwork/lnd/watchtower/wtdb" "github.com/lightningnetwork/lnd/watchtower/wtmock" "github.com/lightningnetwork/lnd/watchtower/wtpolicy" @@ -97,10 +98,10 @@ func (h *towerDBHarness) deleteSession(id wtdb.SessionID, expErr error) { // queryMatches queries that database for the passed breach hint, returning all // matches found. -func (h *towerDBHarness) queryMatches(hint wtdb.BreachHint) []wtdb.Match { +func (h *towerDBHarness) queryMatches(hint blob.BreachHint) []wtdb.Match { h.t.Helper() - matches, err := h.db.QueryMatches([]wtdb.BreachHint{hint}) + matches, err := h.db.QueryMatches([]blob.BreachHint{hint}) if err != nil { h.t.Fatalf("unable to query matches: %v", err) } @@ -111,7 +112,7 @@ func (h *towerDBHarness) queryMatches(hint wtdb.BreachHint) []wtdb.Match { // hasUpdate queries the database for the passed breach hint, asserting that // only one match is present and that the hints indeed match. If successful, the // match is returned. -func (h *towerDBHarness) hasUpdate(hint wtdb.BreachHint) wtdb.Match { +func (h *towerDBHarness) hasUpdate(hint blob.BreachHint) wtdb.Match { h.t.Helper() matches := h.queryMatches(hint) @@ -169,7 +170,7 @@ func testMultipleMatches(h *towerDBHarness) { const numUpdates = 3 // Create a new session and send updates with all the same hint. - var hint wtdb.BreachHint + var hint blob.BreachHint for i := 0; i < numUpdates; i++ { id := *id(i) session := &wtdb.SessionInfo{ @@ -291,7 +292,7 @@ func testDeleteSession(h *towerDBHarness) { h.insertSession(session1, nil) // Create and insert updates for both sessions that have the same hint. - var hint wtdb.BreachHint + var hint blob.BreachHint update0 := &wtdb.SessionStateUpdate{ ID: *id0, Hint: hint, @@ -705,7 +706,7 @@ func updateFromInt(id *wtdb.SessionID, i int, lastApplied uint16) *wtdb.SessionStateUpdate { // Ensure the hint is unique. - var hint wtdb.BreachHint + var hint blob.BreachHint copy(hint[:4], id[:4]) binary.BigEndian.PutUint16(hint[4:6], uint16(i)) diff --git a/watchtower/wtmock/tower_db.go b/watchtower/wtmock/tower_db.go index 403d61e3..27cc25f9 100644 --- a/watchtower/wtmock/tower_db.go +++ b/watchtower/wtmock/tower_db.go @@ -4,6 +4,7 @@ import ( "sync" "github.com/lightningnetwork/lnd/chainntnfs" + "github.com/lightningnetwork/lnd/watchtower/blob" "github.com/lightningnetwork/lnd/watchtower/wtdb" ) @@ -12,14 +13,14 @@ type TowerDB struct { mu sync.Mutex lastEpoch *chainntnfs.BlockEpoch sessions map[wtdb.SessionID]*wtdb.SessionInfo - blobs map[wtdb.BreachHint]map[wtdb.SessionID]*wtdb.SessionStateUpdate + blobs map[blob.BreachHint]map[wtdb.SessionID]*wtdb.SessionStateUpdate } // NewTowerDB initializes a fresh mock TowerDB. func NewTowerDB() *TowerDB { return &TowerDB{ sessions: make(map[wtdb.SessionID]*wtdb.SessionInfo), - blobs: make(map[wtdb.BreachHint]map[wtdb.SessionID]*wtdb.SessionStateUpdate), + blobs: make(map[blob.BreachHint]map[wtdb.SessionID]*wtdb.SessionStateUpdate), } } @@ -113,7 +114,7 @@ func (db *TowerDB) DeleteSession(target wtdb.SessionID) error { // passed breachHints. More than one Match will be returned for a given hint if // they exist in the database. func (db *TowerDB) QueryMatches( - breachHints []wtdb.BreachHint) ([]wtdb.Match, error) { + breachHints []blob.BreachHint) ([]wtdb.Match, error) { db.mu.Lock() defer db.mu.Unlock()