-
Notifications
You must be signed in to change notification settings - Fork 151
/
coordinator_fix_state.go
125 lines (99 loc) · 4.19 KB
/
coordinator_fix_state.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package toolset
import (
"fmt"
"os"
"path/filepath"
flag "github.com/spf13/pflag"
coreDatabase "github.com/iotaledger/hornet/core/database"
"github.com/iotaledger/hornet/pkg/database"
"github.com/iotaledger/hornet/pkg/model/coordinator"
"github.com/iotaledger/hornet/pkg/model/storage"
"github.com/iotaledger/hornet/pkg/utils"
)
func coordinatorFixStateFile(args []string) error {
fs := flag.NewFlagSet("", flag.ContinueOnError)
databasePathFlag := fs.String(FlagToolDatabasePath, DefaultValueMainnetDatabasePath, "the path to the database")
cooStateFilePathFlag := fs.String(FlagToolCoordinatorFixStateCooStateFilePath, DefaultValueCoordinatorStateFilePath, "the path to the coordinator state file")
fs.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", ToolCoordinatorFixStateFile)
fs.PrintDefaults()
println(fmt.Sprintf("\nexample: %s --%s %s --%s %s",
ToolCoordinatorFixStateFile,
FlagToolDatabasePath,
DefaultValueMainnetDatabasePath,
FlagToolCoordinatorFixStateCooStateFilePath,
DefaultValueCoordinatorStateFilePath))
}
if err := parseFlagSet(fs, args); err != nil {
return err
}
if len(*databasePathFlag) == 0 {
return fmt.Errorf("'%s' not specified", FlagToolDatabasePath)
}
databasePath := *databasePathFlag
if _, err := os.Stat(databasePath); err != nil || os.IsNotExist(err) {
return fmt.Errorf("'%s' (%s) does not exist", FlagToolDatabasePath, databasePath)
}
coordinatorStateFilePath := *cooStateFilePathFlag
if coordinatorStateFilePath == "" {
return fmt.Errorf("'%s' is missing", FlagToolCoordinatorFixStateCooStateFilePath)
}
tangleStore, err := database.StoreWithDefaultSettings(filepath.Join(databasePath, coreDatabase.TangleDatabaseDirectoryName), false)
if err != nil {
return fmt.Errorf("%s database initialization failed: %w", coreDatabase.TangleDatabaseDirectoryName, err)
}
utxoStore, err := database.StoreWithDefaultSettings(filepath.Join(databasePath, coreDatabase.UTXODatabaseDirectoryName), false)
if err != nil {
return fmt.Errorf("%s database initialization failed: %w", coreDatabase.UTXODatabaseDirectoryName, err)
}
// clean up store
defer func() {
_ = tangleStore.Close()
_ = utxoStore.Close()
}()
dbStorage, err := storage.New(tangleStore, utxoStore)
if err != nil {
return err
}
ledgerIndex, err := dbStorage.UTXOManager().ReadLedgerIndex()
if err != nil {
return err
}
latestMilestoneFromDatabase := dbStorage.SearchLatestMilestoneIndexInStore()
if ledgerIndex != latestMilestoneFromDatabase {
return fmt.Errorf("node is not synchronized (solid milestone index: %d, latest milestone index: %d)", ledgerIndex, latestMilestoneFromDatabase)
}
cachedMilestone := dbStorage.CachedMilestoneOrNil(ledgerIndex) // milestone +1
if cachedMilestone == nil {
return fmt.Errorf("milestone %d not found", ledgerIndex)
}
defer cachedMilestone.Release(true) // milestone -1
_, err = os.Stat(coordinatorStateFilePath)
if err != nil && !os.IsNotExist(err) {
return fmt.Errorf("unable to check '%s' (%s), error: %w", FlagToolCoordinatorFixStateCooStateFilePath, coordinatorStateFilePath, err)
}
if err == nil {
// coordinator state file exists => rename it to not overwrite the original
backupFilePath := fmt.Sprintf("%s_backup", coordinatorStateFilePath)
_, err = os.Stat(backupFilePath)
if err != nil && !os.IsNotExist(err) {
return fmt.Errorf("unable to check backup file path (%s), error: %w", backupFilePath, err)
}
if err == nil {
return fmt.Errorf("backup file path already exists (%s), will not proceed to overwrite old backup file", backupFilePath)
}
if err := os.Rename(coordinatorStateFilePath, backupFilePath); err != nil {
return fmt.Errorf("unable to rename coordinator state file, error: %w", err)
}
}
// state of the coordinator holds information about the last issued milestones.
state := &coordinator.State{
LatestMilestoneIndex: ledgerIndex,
LatestMilestoneMessageID: cachedMilestone.Milestone().MessageID,
LatestMilestoneTime: cachedMilestone.Milestone().Timestamp,
}
if err := utils.WriteJSONToFile(coordinatorStateFilePath, state, 0660); err != nil {
return fmt.Errorf("failed to write coordinator state file (%s), error: %w", coordinatorStateFilePath, err)
}
return nil
}