Skip to content

Commit

Permalink
index, sqlite: reset consensus on sync error
Browse files Browse the repository at this point in the history
  • Loading branch information
n8maninger committed Aug 14, 2024
1 parent 4117b6a commit 83f360a
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 3 deletions.
9 changes: 7 additions & 2 deletions index/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package index

import (
"context"
"errors"
"fmt"
"sync"

Expand All @@ -17,6 +18,10 @@ import (
type (
// A Store is a persistent store for the index manager.
Store interface {
// ResetChainState resets the consensus state of the store. This
// should only occur if the user has reset their consensus database to
// sync from scratch.
ResetChainState() error
UpdateChainState(func(UpdateTx) error) error
Tip() (types.ChainIndex, error)
}
Expand Down Expand Up @@ -122,7 +127,7 @@ func NewManager(store Store, chain *chain.Manager, contracts ContractManager, wa
}

reorgCh := make(chan struct{}, 1)
reorgCh <- struct{}{} // trigger initial check
reorgCh <- struct{}{} // trigger initial sync
stop := m.chain.OnReorg(func(index types.ChainIndex) {
select {
case reorgCh <- struct{}{}:
Expand All @@ -145,7 +150,7 @@ func NewManager(store Store, chain *chain.Manager, contracts ContractManager, wa
case <-ctx.Done():
return
case <-reorgCh:
if err := m.syncDB(ctx); err != nil {
if err := m.syncDB(ctx); err != nil && !errors.Is(err, context.Canceled) {
m.log.Error("failed to sync database", zap.Error(err))
}
}
Expand Down
15 changes: 14 additions & 1 deletion index/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package index
import (
"context"
"fmt"
"strings"

"go.sia.tech/core/types"
"go.sia.tech/coreutils/wallet"
Expand Down Expand Up @@ -32,7 +33,19 @@ func (m *Manager) syncDB(ctx context.Context) error {
}

reverted, applied, err := m.chain.UpdatesSince(index, m.updateBatchSize)
if err != nil {
if err != nil && strings.Contains(err.Error(), "missing block at index") {
log.Warn("missing block at index, resetting chain state")
// reset the consensus state. Should delete all chain related
// state from the store
if err := m.store.ResetChainState(); err != nil {
return fmt.Errorf("failed to reset consensus state: %w", err)
}
// zero out the index to force a full resync
m.mu.Lock()
m.index = types.ChainIndex{}
m.mu.Unlock()
return nil
} else if err != nil {
return fmt.Errorf("failed to get updates since %v: %w", index, err)
} else if len(reverted) == 0 && len(applied) == 0 {
return nil
Expand Down
19 changes: 19 additions & 0 deletions persist/sqlite/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,25 @@ type (

var _ index.UpdateTx = (*updateTx)(nil)

// ResetChainState resets the consensus state of the store. This
// should only occur if the user has reset their consensus database to
// sync from scratch.
func (s *Store) ResetChainState() error {
return s.transaction(func(tx *txn) error {
_, err := tx.Exec(`
-- v2 contracts
DELETE FROM contracts_v2_chain_index_elements;
DELETE FROM contract_v2_state_elements;
-- wallet
DELETE FROM wallet_siacoin_elements;
DELETE FROM wallet_events;
DELETE FROM host_stats WHERE stat=?; -- reset wallet stats since they are derived from the chain
-- settings
UPDATE global_settings SET last_scanned_index=NULL, last_announce_index=NULL, last_announce_address=NULL`, metricWalletBalance)
return err
})
}

// WalletStateElements returns all state elements related to the wallet. It is used
// to update the proofs of all state elements affected by the update.
func (ux *updateTx) WalletStateElements() (elements []types.StateElement, err error) {
Expand Down

0 comments on commit 83f360a

Please sign in to comment.