-
Notifications
You must be signed in to change notification settings - Fork 33
Expand file tree
/
Copy pathdebug.go
More file actions
222 lines (191 loc) · 6.44 KB
/
debug.go
File metadata and controls
222 lines (191 loc) · 6.44 KB
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
//go:build debug
// +build debug
package cli
import (
"log"
"os"
"sync"
"github.com/manifoldco/promptui"
"github.com/pokt-network/pocket/consensus"
"github.com/pokt-network/pocket/logger"
"github.com/pokt-network/pocket/p2p"
"github.com/pokt-network/pocket/rpc"
"github.com/pokt-network/pocket/runtime"
"github.com/pokt-network/pocket/shared"
pocketCrypto "github.com/pokt-network/pocket/shared/crypto"
"github.com/pokt-network/pocket/shared/messaging"
"github.com/pokt-network/pocket/shared/modules"
"github.com/pokt-network/pocket/telemetry"
"github.com/spf13/cobra"
"google.golang.org/protobuf/types/known/anypb"
)
// TECHDEBT: Lowercase variables / constants that do not need to be exported.
const (
PromptResetToGenesis string = "ResetToGenesis"
PromptPrintNodeState string = "PrintNodeState"
PromptTriggerNextView string = "TriggerNextView"
PromptTogglePacemakerMode string = "TogglePacemakerMode"
PromptShowLatestBlockInStore string = "ShowLatestBlockInStore"
defaultConfigPath = "build/config/config1.json"
defaultGenesisPath = "build/config/genesis.json"
)
var (
// A P2P module is initialized in order to broadcast a message to the local network
p2pMod modules.P2PModule
// A consensus module is initialized in order to get a list of the validator network
consensusMod modules.ConsensusModule
modInitOnce sync.Once
items = []string{
PromptResetToGenesis,
PromptPrintNodeState,
PromptTriggerNextView,
PromptTogglePacemakerMode,
PromptShowLatestBlockInStore,
}
)
func init() {
rootCmd.AddCommand(NewDebugCommand())
}
func NewDebugCommand() *cobra.Command {
return &cobra.Command{
Use: "debug",
Short: "Debug utility for rapid development",
Args: cobra.ExactArgs(0),
PersistentPreRun: func(cmd *cobra.Command, args []string) {
initDebug(remoteCLIURL)
},
RunE: runDebug,
}
}
func runDebug(cmd *cobra.Command, args []string) (err error) {
for {
if selection, err := promptGetInput(); err == nil {
handleSelect(selection)
} else {
return err
}
}
}
func promptGetInput() (string, error) {
prompt := promptui.Select{
Label: "Select an action",
Items: items,
Size: len(items),
}
_, result, err := prompt.Run()
if err == promptui.ErrInterrupt {
os.Exit(0)
}
if err != nil {
log.Printf("Prompt failed %v\n", err)
return "", err
}
return result, nil
}
func handleSelect(selection string) {
switch selection {
case PromptResetToGenesis:
m := &messaging.DebugMessage{
Action: messaging.DebugMessageAction_DEBUG_CONSENSUS_RESET_TO_GENESIS,
Message: nil,
}
broadcastDebugMessage(m)
case PromptPrintNodeState:
m := &messaging.DebugMessage{
Action: messaging.DebugMessageAction_DEBUG_CONSENSUS_PRINT_NODE_STATE,
Message: nil,
}
broadcastDebugMessage(m)
case PromptTriggerNextView:
m := &messaging.DebugMessage{
Action: messaging.DebugMessageAction_DEBUG_CONSENSUS_TRIGGER_NEXT_VIEW,
Message: nil,
}
broadcastDebugMessage(m)
case PromptTogglePacemakerMode:
m := &messaging.DebugMessage{
Action: messaging.DebugMessageAction_DEBUG_CONSENSUS_TOGGLE_PACE_MAKER_MODE,
Message: nil,
}
broadcastDebugMessage(m)
case PromptShowLatestBlockInStore:
m := &messaging.DebugMessage{
Action: messaging.DebugMessageAction_DEBUG_SHOW_LATEST_BLOCK_IN_STORE,
Message: nil,
}
sendDebugMessage(m)
default:
log.Println("Selection not yet implemented...", selection)
}
}
// Broadcast to the entire validator set
func broadcastDebugMessage(debugMsg *messaging.DebugMessage) {
anyProto, err := anypb.New(debugMsg)
if err != nil {
log.Fatalf("[ERROR] Failed to create Any proto: %v", err)
}
// TODO(olshansky): Once we implement the cleanup layer in RainTree, we'll be able to use
// broadcast. The reason it cannot be done right now is because this client is not in the
// address book of the actual validator nodes, so `node1.consensus` never receives the message.
// p2pMod.Broadcast(anyProto, messaging.PocketTopic_DEBUG_TOPIC)
for _, val := range consensusMod.ValidatorMap() {
addr, err := pocketCrypto.NewAddress(val.GetAddress())
if err != nil {
log.Fatalf("[ERROR] Failed to convert validator address into pocketCrypto.Address: %v", err)
}
p2pMod.Send(addr, anyProto)
}
}
// Send to just a single (i.e. first) validator in the set
func sendDebugMessage(debugMsg *messaging.DebugMessage) {
anyProto, err := anypb.New(debugMsg)
if err != nil {
log.Fatalf("[ERROR] Failed to create Any proto: %v", err)
}
var validatorAddress []byte
for _, val := range consensusMod.ValidatorMap() {
validatorAddress, err = pocketCrypto.NewAddress(val.GetAddress())
if err != nil {
log.Fatalf("[ERROR] Failed to convert validator address into pocketCrypto.Address: %v", err)
}
break
}
p2pMod.Send(validatorAddress, anyProto)
}
func initDebug(remoteCLIURL string) {
modInitOnce.Do(func() {
var err error
runtimeMgr := runtime.NewManagerFromFiles(defaultConfigPath, defaultGenesisPath, runtime.WithRandomPK())
consM, err := consensus.Create(runtimeMgr)
if err != nil {
logger.Global.Fatal().Err(err).Msg("Failed to create consensus module")
}
consensusMod = consM.(modules.ConsensusModule)
p2pM, err := p2p.Create(runtimeMgr)
if err != nil {
log.Fatalf("[ERROR] Failed to create p2p module: %v", err.Error())
}
p2pMod = p2pM.(modules.P2PModule)
// This telemetry module instance is a NOOP because the 'enable_telemetry' flag in the `cfg` above is set to false.
// Since this client mimics partial - networking only - functionality of a full node, some of the telemetry-related
// code paths are executed. To avoid those messages interfering with the telemetry data collected, a non-nil telemetry
// module that NOOPs (per the configs above) is injected.
telemetryM, err := telemetry.Create(runtimeMgr)
if err != nil {
logger.Global.Fatal().Err(err).Msg("Failed to create telemetry module")
}
telemetryMod := telemetryM.(modules.TelemetryModule)
loggerM, err := logger.Create(runtimeMgr)
if err != nil {
logger.Global.Fatal().Err(err).Msg("Failed to create logger module")
}
loggerMod := loggerM.(modules.LoggerModule)
rpcM, err := rpc.Create(runtimeMgr)
if err != nil {
logger.Global.Fatal().Err(err).Msg("Failed to create rpc module")
}
rpcMod := rpcM.(modules.RPCModule)
_ = shared.CreateBusWithOptionalModules(runtimeMgr, nil, p2pMod, nil, consensusMod, telemetryMod, loggerMod, rpcMod) // REFACTOR: use the `WithXXXModule()` pattern accepting a slice of IntegratableModule
p2pMod.Start()
})
}