diff --git a/client.go b/client.go index c765637..89abf7c 100644 --- a/client.go +++ b/client.go @@ -138,12 +138,12 @@ func (s *Client) FetchSwaps() ([]*SwapInfo, error) { } swaps = append(swaps, &SwapInfo{ - SwapType: TypeOut, - SwapContract: swp.Contract.SwapContract, - State: swp.State(), - SwapHash: swp.Hash, - LastUpdate: swp.LastUpdateTime(), - HtlcAddress: htlc.Address, + SwapType: TypeOut, + SwapContract: swp.Contract.SwapContract, + SwapStateData: swp.State(), + SwapHash: swp.Hash, + LastUpdate: swp.LastUpdateTime(), + HtlcAddress: htlc.Address, }) } @@ -158,12 +158,12 @@ func (s *Client) FetchSwaps() ([]*SwapInfo, error) { } swaps = append(swaps, &SwapInfo{ - SwapType: TypeIn, - SwapContract: swp.Contract.SwapContract, - State: swp.State(), - SwapHash: swp.Hash, - LastUpdate: swp.LastUpdateTime(), - HtlcAddress: htlc.Address, + SwapType: TypeIn, + SwapContract: swp.Contract.SwapContract, + SwapStateData: swp.State(), + SwapHash: swp.Hash, + LastUpdate: swp.LastUpdateTime(), + HtlcAddress: htlc.Address, }) } @@ -259,7 +259,7 @@ func (s *Client) resumeSwaps(ctx context.Context, } for _, pend := range loopOutSwaps { - if pend.State().Type() != loopdb.StateTypePending { + if pend.State().State.Type() != loopdb.StateTypePending { continue } swap, err := resumeLoopOutSwap(ctx, swapCfg, pend) @@ -272,7 +272,7 @@ func (s *Client) resumeSwaps(ctx context.Context, } for _, pend := range loopInSwaps { - if pend.State().Type() != loopdb.StateTypePending { + if pend.State().State.Type() != loopdb.StateTypePending { continue } swap, err := resumeLoopInSwap(ctx, swapCfg, pend) diff --git a/client_test.go b/client_test.go index 09b921a..9419521 100644 --- a/client_test.go +++ b/client_test.go @@ -202,7 +202,9 @@ func testResume(t *testing.T, expired, preimageRevealed, expectSuccess bool) { Loop: loopdb.Loop{ Events: []*loopdb.LoopEvent{ { - State: state, + SwapStateData: loopdb.SwapStateData{ + State: state, + }, }, }, Hash: hash, diff --git a/interface.go b/interface.go index 15d8245..bee3179 100644 --- a/interface.go +++ b/interface.go @@ -280,12 +280,12 @@ func (t Type) String() string { // SwapInfo exposes common info fields for loop in and loop out swaps. type SwapInfo struct { + loopdb.SwapStateData + LastUpdate time.Time SwapHash lntypes.Hash - State loopdb.SwapState - SwapType Type loopdb.SwapContract diff --git a/loopdb/interface.go b/loopdb/interface.go index 72b92d0..86dd853 100644 --- a/loopdb/interface.go +++ b/loopdb/interface.go @@ -18,7 +18,8 @@ type SwapStore interface { // UpdateLoopOut stores a new event for a target loop out swap. This // appends to the event log for a particular swap as it goes through // the various stages in its lifetime. - UpdateLoopOut(hash lntypes.Hash, time time.Time, state SwapState) error + UpdateLoopOut(hash lntypes.Hash, time time.Time, + state SwapStateData) error // FetchLoopInSwaps returns all swaps currently in the store. FetchLoopInSwaps() ([]*LoopIn, error) @@ -29,7 +30,8 @@ type SwapStore interface { // UpdateLoopIn stores a new event for a target loop in swap. This // appends to the event log for a particular swap as it goes through // the various stages in its lifetime. - UpdateLoopIn(hash lntypes.Hash, time time.Time, state SwapState) error + UpdateLoopIn(hash lntypes.Hash, time time.Time, + state SwapStateData) error // Close closes the underlying database. Close() error diff --git a/loopdb/loop.go b/loopdb/loop.go index 80298e8..df44ee7 100644 --- a/loopdb/loop.go +++ b/loopdb/loop.go @@ -53,21 +53,22 @@ type Loop struct { // LoopEvent contains the dynamic data of a swap. type LoopEvent struct { - // State is the new state for this swap as a result of this event. - State SwapState + SwapStateData // Time is the time that this swap had its state changed. Time time.Time } // State returns the most recent state of this swap. -func (s *Loop) State() SwapState { +func (s *Loop) State() SwapStateData { lastUpdate := s.LastUpdate() if lastUpdate == nil { - return StateInitiated + return SwapStateData{ + State: StateInitiated, + } } - return lastUpdate.State + return lastUpdate.SwapStateData } // LastUpdate returns the most recent update of this swap. @@ -84,7 +85,7 @@ func (s *Loop) LastUpdate() *LoopEvent { // serializeLoopEvent serializes a state update of a swap. This is used for both // in and out swaps. -func serializeLoopEvent(time time.Time, state SwapState) ( +func serializeLoopEvent(time time.Time, state SwapStateData) ( []byte, error) { var b bytes.Buffer diff --git a/loopdb/store.go b/loopdb/store.go index 463395f..2d731b5 100644 --- a/loopdb/store.go +++ b/loopdb/store.go @@ -346,7 +346,7 @@ func (s *boltSwapStore) CreateLoopIn(hash lntypes.Hash, // updateLoop saves a new swap state transition to the store. It takes in a // bucket key so that this function can be used for both in and out swaps. func (s *boltSwapStore) updateLoop(bucketKey []byte, hash lntypes.Hash, - time time.Time, state SwapState) error { + time time.Time, state SwapStateData) error { return s.db.Update(func(tx *bbolt.Tx) error { // Starting from the root bucket, we'll traverse the bucket @@ -386,7 +386,7 @@ func (s *boltSwapStore) updateLoop(bucketKey []byte, hash lntypes.Hash, // // NOTE: Part of the loopdb.SwapStore interface. func (s *boltSwapStore) UpdateLoopOut(hash lntypes.Hash, time time.Time, - state SwapState) error { + state SwapStateData) error { return s.updateLoop(loopOutBucketKey, hash, time, state) } @@ -396,7 +396,7 @@ func (s *boltSwapStore) UpdateLoopOut(hash lntypes.Hash, time time.Time, // // NOTE: Part of the loopdb.SwapStore interface. func (s *boltSwapStore) UpdateLoopIn(hash lntypes.Hash, time time.Time, - state SwapState) error { + state SwapStateData) error { return s.updateLoop(loopInBucketKey, hash, time, state) } diff --git a/loopdb/store_test.go b/loopdb/store_test.go index f2a0869..1e1a61f 100644 --- a/loopdb/store_test.go +++ b/loopdb/store_test.go @@ -107,7 +107,7 @@ func TestLoopOutStore(t *testing.T) { t.Fatal("invalid pending swap data") } - if swaps[0].State() != expectedState { + if swaps[0].State().State != expectedState { t.Fatalf("expected state %v, but got %v", expectedState, swaps[0].State(), ) @@ -130,7 +130,10 @@ func TestLoopOutStore(t *testing.T) { // Next, we'll update to the next state of the pre-image being // revealed. The state should be reflected here again. err = store.UpdateLoopOut( - hash, testTime, StatePreimageRevealed, + hash, testTime, + SwapStateData{ + State: StatePreimageRevealed, + }, ) if err != nil { t.Fatal(err) @@ -140,7 +143,10 @@ func TestLoopOutStore(t *testing.T) { // Next, we'll update to the final state to ensure that the state is // properly updated. err = store.UpdateLoopOut( - hash, testTime, StateFailInsufficientValue, + hash, testTime, + SwapStateData{ + State: StateFailInsufficientValue, + }, ) if err != nil { t.Fatal(err) @@ -229,7 +235,7 @@ func TestLoopInStore(t *testing.T) { t.Fatal("invalid pending swap data") } - if swaps[0].State() != expectedState { + if swaps[0].State().State != expectedState { t.Fatalf("expected state %v, but got %v", expectedState, swaps[0].State(), ) @@ -252,7 +258,10 @@ func TestLoopInStore(t *testing.T) { // Next, we'll update to the next state of the pre-image being // revealed. The state should be reflected here again. err = store.UpdateLoopIn( - hash, testTime, StatePreimageRevealed, + hash, testTime, + SwapStateData{ + State: StatePreimageRevealed, + }, ) if err != nil { t.Fatal(err) @@ -262,7 +271,10 @@ func TestLoopInStore(t *testing.T) { // Next, we'll update to the final state to ensure that the state is // properly updated. err = store.UpdateLoopIn( - hash, testTime, StateFailInsufficientValue, + hash, testTime, + SwapStateData{ + State: StateFailInsufficientValue, + }, ) if err != nil { t.Fatal(err) diff --git a/loopdb/swapstate.go b/loopdb/swapstate.go index db795a1..be3393d 100644 --- a/loopdb/swapstate.go +++ b/loopdb/swapstate.go @@ -125,3 +125,8 @@ func (s SwapState) String() string { return "Unknown" } } + +// SwapStateData is all persistent data to describe the current swap state. +type SwapStateData struct { + State SwapState +} diff --git a/loopin.go b/loopin.go index 050c180..f0a0376 100644 --- a/loopin.go +++ b/loopin.go @@ -616,7 +616,12 @@ func (s *loopInSwap) publishTimeoutTx(ctx context.Context, // persistState updates the swap state and sends out an update notification. func (s *loopInSwap) persistState(ctx context.Context) error { // Update state in store. - err := s.store.UpdateLoopIn(s.hash, s.lastUpdateTime, s.state) + err := s.store.UpdateLoopIn( + s.hash, s.lastUpdateTime, + loopdb.SwapStateData{ + State: s.state, + }, + ) if err != nil { return err } diff --git a/loopin_test.go b/loopin_test.go index 35cc717..a2ae55b 100644 --- a/loopin_test.go +++ b/loopin_test.go @@ -248,7 +248,9 @@ func testLoopInResume(t *testing.T, state loopdb.SwapState, expired bool) { Loop: loopdb.Loop{ Events: []*loopdb.LoopEvent{ { - State: state, + SwapStateData: loopdb.SwapStateData{ + State: state, + }, }, }, Hash: testPreimage.Hash(), diff --git a/loopout.go b/loopout.go index a7dcacf..ab9b9ee 100644 --- a/loopout.go +++ b/loopout.go @@ -342,7 +342,12 @@ func (s *loopOutSwap) persistState(ctx context.Context) error { s.lastUpdateTime = updateTime // Update state in store. - err := s.store.UpdateLoopOut(s.hash, updateTime, s.state) + err := s.store.UpdateLoopOut( + s.hash, updateTime, + loopdb.SwapStateData{ + State: s.state, + }, + ) if err != nil { return err } diff --git a/store_mock_test.go b/store_mock_test.go index 9b33014..70c53dd 100644 --- a/store_mock_test.go +++ b/store_mock_test.go @@ -13,14 +13,14 @@ import ( // storeMock implements a mock client swap store. type storeMock struct { loopOutSwaps map[lntypes.Hash]*loopdb.LoopOutContract - loopOutUpdates map[lntypes.Hash][]loopdb.SwapState + loopOutUpdates map[lntypes.Hash][]loopdb.SwapStateData loopOutStoreChan chan loopdb.LoopOutContract - loopOutUpdateChan chan loopdb.SwapState + loopOutUpdateChan chan loopdb.SwapStateData loopInSwaps map[lntypes.Hash]*loopdb.LoopInContract - loopInUpdates map[lntypes.Hash][]loopdb.SwapState + loopInUpdates map[lntypes.Hash][]loopdb.SwapStateData loopInStoreChan chan loopdb.LoopInContract - loopInUpdateChan chan loopdb.SwapState + loopInUpdateChan chan loopdb.SwapStateData t *testing.T } @@ -34,14 +34,14 @@ type finishData struct { func newStoreMock(t *testing.T) *storeMock { return &storeMock{ loopOutStoreChan: make(chan loopdb.LoopOutContract, 1), - loopOutUpdateChan: make(chan loopdb.SwapState, 1), + loopOutUpdateChan: make(chan loopdb.SwapStateData, 1), loopOutSwaps: make(map[lntypes.Hash]*loopdb.LoopOutContract), - loopOutUpdates: make(map[lntypes.Hash][]loopdb.SwapState), + loopOutUpdates: make(map[lntypes.Hash][]loopdb.SwapStateData), loopInStoreChan: make(chan loopdb.LoopInContract, 1), - loopInUpdateChan: make(chan loopdb.SwapState, 1), + loopInUpdateChan: make(chan loopdb.SwapStateData, 1), loopInSwaps: make(map[lntypes.Hash]*loopdb.LoopInContract), - loopInUpdates: make(map[lntypes.Hash][]loopdb.SwapState), + loopInUpdates: make(map[lntypes.Hash][]loopdb.SwapStateData), t: t, } } @@ -57,7 +57,7 @@ func (s *storeMock) FetchLoopOutSwaps() ([]*loopdb.LoopOut, error) { events := make([]*loopdb.LoopEvent, len(updates)) for i, u := range updates { events[i] = &loopdb.LoopEvent{ - State: u, + SwapStateData: u, } } @@ -86,7 +86,7 @@ func (s *storeMock) CreateLoopOut(hash lntypes.Hash, } s.loopOutSwaps[hash] = swap - s.loopOutUpdates[hash] = []loopdb.SwapState{} + s.loopOutUpdates[hash] = []loopdb.SwapStateData{} s.loopOutStoreChan <- *swap return nil @@ -101,7 +101,7 @@ func (s *storeMock) FetchLoopInSwaps() ([]*loopdb.LoopIn, error) { events := make([]*loopdb.LoopEvent, len(updates)) for i, u := range updates { events[i] = &loopdb.LoopEvent{ - State: u, + SwapStateData: u, } } @@ -130,7 +130,7 @@ func (s *storeMock) CreateLoopIn(hash lntypes.Hash, } s.loopInSwaps[hash] = swap - s.loopInUpdates[hash] = []loopdb.SwapState{} + s.loopInUpdates[hash] = []loopdb.SwapStateData{} s.loopInStoreChan <- *swap return nil @@ -142,7 +142,7 @@ func (s *storeMock) CreateLoopIn(hash lntypes.Hash, // // NOTE: Part of the loopdb.SwapStore interface. func (s *storeMock) UpdateLoopOut(hash lntypes.Hash, time time.Time, - state loopdb.SwapState) error { + state loopdb.SwapStateData) error { updates, ok := s.loopOutUpdates[hash] if !ok { @@ -162,7 +162,7 @@ func (s *storeMock) UpdateLoopOut(hash lntypes.Hash, time time.Time, // // NOTE: Part of the loopdb.SwapStore interface. func (s *storeMock) UpdateLoopIn(hash lntypes.Hash, time time.Time, - state loopdb.SwapState) error { + state loopdb.SwapStateData) error { updates, ok := s.loopInUpdates[hash] if !ok { @@ -215,7 +215,7 @@ func (s *storeMock) assertLoopInState(expectedState loopdb.SwapState) { s.t.Helper() state := <-s.loopOutUpdateChan - if state != expectedState { + if state.State != expectedState { s.t.Fatalf("unexpected state") } } @@ -226,7 +226,7 @@ func (s *storeMock) assertStorePreimageReveal() { select { case state := <-s.loopOutUpdateChan: - if state != loopdb.StatePreimageRevealed { + if state.State != loopdb.StatePreimageRevealed { s.t.Fatalf("unexpected state") } case <-time.After(test.Timeout): @@ -239,7 +239,7 @@ func (s *storeMock) assertStoreFinished(expectedResult loopdb.SwapState) { select { case state := <-s.loopOutUpdateChan: - if state != expectedResult { + if state.State != expectedResult { s.t.Fatalf("expected result %v, but got %v", expectedResult, state) } diff --git a/swap.go b/swap.go index 74a0276..ad4b02c 100644 --- a/swap.go +++ b/swap.go @@ -68,8 +68,10 @@ func (s *swapKit) sendUpdate(ctx context.Context) error { SwapHash: s.hash, SwapType: s.swapType, LastUpdate: s.lastUpdateTime, - State: s.state, - HtlcAddress: s.htlc.Address, + SwapStateData: loopdb.SwapStateData{ + State: s.state, + }, + HtlcAddress: s.htlc.Address, } s.log.Infof("state %v", info.State) diff --git a/testcontext_test.go b/testcontext_test.go index 9dca8ae..6e3ab7e 100644 --- a/testcontext_test.go +++ b/testcontext_test.go @@ -79,9 +79,9 @@ func createClientTestContext(t *testing.T, for _, s := range pendingSwaps { store.loopOutSwaps[s.Hash] = s.Contract - updates := []loopdb.SwapState{} + updates := []loopdb.SwapStateData{} for _, e := range s.Events { - updates = append(updates, e.State) + updates = append(updates, e.SwapStateData) } store.loopOutUpdates[s.Hash] = updates }