-
Notifications
You must be signed in to change notification settings - Fork 382
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: unsafe reset all #1196
feat: unsafe reset all #1196
Conversation
Codecov ReportAttention: Patch coverage is 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think is the advantage of unsafe-reset-all
over make fclean
? (See Makefile in gno.land), aside from the fact that it dynamically gets the db directory (which IIRC is not configurable at this time, anyway?).
I don't think we necessarily want/need to have this within the gno.land
node code itself, but this is just an opinion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm against modifying global variables like os.Stdin for testing purposes. I think commands.IO works well, allows us for mock tests, and doesn't change anything in terms of security, on top of everything because this code is in a main package which cannot be imported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Retaining os.Stdin wrapped in commands.IO within the gno.land runtime presents a security vulnerability. Here are the concerns.
-
Future Misuse: If future developers, unaware of the security implications, start utilizing commands.IO's os.Stdin to pass tests or for any other reasons. This could lead to vulnerabilities. Code that was originally not designed to interact with os.Stdin might be altered to do so, creating an attack vector.
-
Malicious IPC: A malicious entity could exploit this implementation to inject data into the gno.land node runtime through IPC ( Interprocess Communication)
-
Trust Concerns: Node operators could have trust concerns in the system's integrity, fearing potential injection attacks through IPC due to the presence of os.Stdin in the codebase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I agree with your argument, I believe it reinforces the original usage rather than the recent change. I see this change as a regression in terms of flexibility and security. Could you provide an example where your change enhances security?
Edit: my review covers this pull request: #1333, where the security and flexibility issues are clearer IMO. Please look at my latest comment here: https://github.com/gnolang/gno/pull/1196/files#r1385496885, where I suggest going back to the io.Commands approach but with a new read-only interface (without os.Stdin). This would help ensure readonly commands remain so by preventing accidental os.Stdin inputs.
blockdb := filepath.Join(dbDir, "blockstore.db") | ||
state := filepath.Join(dbDir, "state.db") | ||
wal := filepath.Join(dbDir, "cs.wal") | ||
gnolang := filepath.Join(dbDir, "gnolang.db") | ||
|
||
if osm.FileExists(blockdb) { | ||
if err := os.RemoveAll(blockdb); err == nil { | ||
logger.Info("Removed all blockstore.db", "dir", blockdb) | ||
} else { | ||
logger.Error("error removing all blockstore.db", "dir", blockdb, "err", err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could be a for loop over an array/slice of strings instead of duplicating the same code 4 times...
also I think we can just do RemoveAll and log any error while returned by that function. 🤷
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good suggestion.
unsafe-reset-all not only deletes the data store, it also resets the validator state to genesis state at zero height. In addition, we will need a reset state right after this, which will need to keep the validator state instead of reset to genesis state. What are other places we might want to put the code in? It is in gno.land node code right now, because it for gno.land node operation, it does not server other purposes. I thought about Tm2. but it involves deleting the App DB, gnolang.db, which is for gnoland only. |
io.SetOut(commands.WriteNopCloser(mockOut)) | ||
io.SetErr(commands.WriteNopCloser(mockErr)) | ||
cmd := newRootCmd(io) | ||
in, err := NewMockStdin(name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a bad name, since we’re just trying to bufferize the stdout and not the stdin; we actually don’t care about stdin.
Name should be MockStdoutErr; or should just be MockIOs in general.
@@ -158,10 +139,10 @@ func execStart(c *startCfg, args []string, io *commands.IO) error { | |||
return fmt.Errorf("error in creating node: %w", err) | |||
} | |||
|
|||
fmt.Fprintln(io.Err, "Node created.") | |||
fmt.Println("Node created.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was better before.
) | ||
|
||
func main() { | ||
io := commands.NewDefaultIO() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To retain the benefits of commands.IO while aligning with your approach, I propose introducing a commands.OutErr that disallows stdin setting and enables compiler verification.
If you're on board, we can proceed with my initial work to transition IO from a struct to an interface, detailed in this pull request: #1270.
Additionally, we can create a variant that functions as a "read-only IO," (commands.OutErr or better name) analogous to Golang's IO Writer, Reader, and ReadWriter, for commands that distinguish between 'out' and 'err.'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you intend commands.OutErr
is an interface, subset of what would be commands.IO
, which does not have Stdin
?
@@ -11,3 +11,16 @@ | |||
$> gnoland start | |||
|
|||
Afterward, you can interact with [`gnokey`](../gnokey) or launch a [`gnoweb`](../gnoweb) interface. | |||
|
|||
|
|||
## Reset `gnoland` node back to genesis state. It's only suitable for testnets. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Referring to #1201, to focus on a production-ready gnoland binary and maintain separate helper tools, we could simply add a contribs/gnoland-resetall, or a contribs/gnolandtools with an 'unsafe-reset-all' subcommand.
Timed out; I think |
Contributors' checklist...
For #1195
The
unsafe-reset-all
is a method to hard reset the network to its genesis state. It's deemed unsafe and should only be used in a testing environment for several reasons:priv_validator_state.json
, which could result in network disruptions and chain forks if not coordinated properly.Additionally, in the PR, we made the following refactorings:
Removed the passing of
os.Stdin
wrapped incommands.IO
togno.land
. Directly includingos.Stdin
in the command presents a vulnerability, as it isn't necessary for the program's main function. It's only required for testing purposes.Introduced
MockIO
. This allows us to test with customized input strings, eliminating the need to passos.Stdin
directly to the node.Stopped passing the config file via
ff
commands. The configuration required byff
demands that we expose all properties, not just a subset, for them to be defined inconfig.toml
as flags in a CLI. This could result in more than 30 flags being listed. We now load thetm2
config separately. The current limitation is that we cannot overwrite it through flag options, but we plan to address this in a future update.I understood we plan to have a gno sdk package. That is a bigger topic and many more aspects need to be considered. We can address it in a separate PR