Skip to content
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!: add chainbuilder tool #3886

Merged
merged 15 commits into from
Sep 24, 2024
Merged

feat!: add chainbuilder tool #3886

merged 15 commits into from
Sep 24, 2024

Conversation

cmwaters
Copy link
Contributor

Adds a tool for quickly generating an entire chain (based on a single validator)

@cmwaters cmwaters changed the title tool: chainbuilder fead: add chainbuilder tool Sep 18, 2024
@cmwaters cmwaters marked this pull request as ready for review September 18, 2024 16:01
@cmwaters cmwaters requested a review from a team as a code owner September 18, 2024 16:01
@cmwaters cmwaters requested review from rootulp and evan-forbes and removed request for a team September 18, 2024 16:01
Copy link
Contributor

coderabbitai bot commented Sep 18, 2024

Walkthrough

Walkthrough

The pull request introduces changes primarily focused on updating the go.mod file with new and modified dependencies. It also adds a new main.go file that implements a command-line tool for building a Celestia blockchain, allowing users to configure various parameters for chain management. The modifications include new functions and types to facilitate blockchain operations, along with updates to existing dependencies, reflecting improvements in dependency management and functionality within the project.

Changes

File Change Summary
go.mod Added new dependencies, updated existing ones, and removed some from indirect requirements.
tools/chainbuilder/main.go Implemented command-line tool for building a Celestia blockchain with various configuration options.

Possibly related PRs

Suggested reviewers

  • staheri14
  • evan-forbes

Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between c02da35 and 1ad3a7d.

Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
Files selected for processing (2)
  • go.mod (5 hunks)
  • tools/chainbuilder/main.go (1 hunks)
Files skipped from review as they are similar to previous changes (2)
  • go.mod
  • tools/chainbuilder/main.go

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    -- @coderabbitai generate unit testing code for this file.
    -- @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    -- @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    -- @coderabbitai read src/utils.ts and generate unit testing code.
    -- @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    -- @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@cmwaters cmwaters changed the title fead: add chainbuilder tool feat: add chainbuilder tool Sep 18, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Outside diff range and nitpick comments (3)
tools/chainbuilder/README.md (3)

13-13: Consider using "afterward" instead of "afterwards".

In American English, "afterward" is the preferred variant. "Afterwards" is more commonly used in British English and other dialects.

-This will create a directory with the name `testnode-{chainID}`. All files will be populated and blocks generated based on specified input. You can run a validator on the file system afterwards by calling:
+This will create a directory with the name `testnode-{chainID}`. All files will be populated and blocks generated based on specified input. You can run a validator on the file system afterward by calling:
Tools
LanguageTool

[locale-violation] ~13-~13: In American English, ‘afterward’ is the preferred variant. ‘Afterwards’ is more commonly used in British English and other dialects.
Context: ... can run a validator on the file system afterwards by calling: ``` celestia-appd start --...

(AFTERWARDS_US)


25-25: Add a comma after "By default".

Adding a comma after "By default" improves readability and adheres to common punctuation practices.

-`namespace` allows you to pick a custom v0 namespace. By default "test" will be chosen.
+`namespace` allows you to pick a custom v0 namespace. By default, "test" will be chosen.
Tools
LanguageTool

[uncategorized] ~25-~25: Did you mean: “By default,”?
Context: ...lows you to pick a custom v0 namespace. By default "test" will be chosen. This tool takes...

(BY_DEFAULT_COMMA)


29-29: Remove the extra blank line at the end of the file.

Multiple consecutive blank lines are unnecessary and do not adhere to common Markdown formatting practices. Remove the extra blank line to improve the file's formatting.

-
-
Tools
Markdownlint

29-29: Expected: 1; Actual: 2
Multiple consecutive blank lines

(MD012, no-multiple-blanks)

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 306c587 and e9ff46c.

Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
Files selected for processing (10)
  • go.mod (5 hunks)
  • pkg/user/account.go (1 hunks)
  • test/util/genesis/document.go (2 hunks)
  • test/util/genesis/files.go (2 hunks)
  • test/util/genesis/genesis.go (3 hunks)
  • test/util/testnode/network.go (2 hunks)
  • tools/chainbuilder/README.md (1 hunks)
  • tools/chainbuilder/benchmark_test.go (1 hunks)
  • tools/chainbuilder/integration_test.go (1 hunks)
  • tools/chainbuilder/main.go (1 hunks)
Additional context used
LanguageTool
tools/chainbuilder/README.md

[locale-violation] ~13-~13: In American English, ‘afterward’ is the preferred variant. ‘Afterwards’ is more commonly used in British English and other dialects.
Context: ... can run a validator on the file system afterwards by calling: ``` celestia-appd start --...

(AFTERWARDS_US)


[uncategorized] ~25-~25: Did you mean: “By default,”?
Context: ...lows you to pick a custom v0 namespace. By default "test" will be chosen. This tool takes...

(BY_DEFAULT_COMMA)

Markdownlint
tools/chainbuilder/README.md

29-29: Expected: 1; Actual: 2
Multiple consecutive blank lines

(MD012, no-multiple-blanks)


9-9: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


15-15: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

Additional comments not posted (27)
tools/chainbuilder/benchmark_test.go (1)

11-26: LGTM!

The benchmark test for the Run function is well-structured and follows the standard Go benchmarking conventions. It sets up a reasonable configuration for the builder, executes the Run function in a loop, and checks for errors. The use of a temporary directory for each benchmark run ensures isolation and prevents interference between runs.

This benchmark will be useful for measuring the performance of the Run function under different configurations and can help identify performance bottlenecks if needed.

tools/chainbuilder/README.md (1)

1-12: LGTM!

The introduction and usage example are clear and well-written. The go run command is the correct way to execute the tool.

Tools
Markdownlint

9-9: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

test/util/genesis/files.go (5)

8-8: LGTM!

The import statement for the srvconfig package is valid and follows the standard naming convention.


21-74: Excellent work on refactoring the InitFiles function!

The changes made to the function signature, return type, and internal logic significantly improve the function's interface and functionality. Here are the key improvements:

  1. The addition of the appCfg parameter allows the function to handle application configuration alongside the existing parameters, enhancing its role in the initialization process.

  2. Changing the return type to a single error simplifies the error handling mechanism and makes the code more readable.

  3. Setting the root directory for tmConfig using the provided rootDir streamlines the logic and eliminates the need for constructing a separate basePath.

  4. Creating the configuration directory using rootDir is consistent with the changes made to the function signature and improves code clarity.

  5. Writing configuration files for both the application (app.toml) and Tendermint (config.toml) enhances the function's responsibility in setting up the necessary configuration files.

  6. Directly returning errors improves error handling and code readability.

Overall, these changes make the InitFiles function more efficient, maintainable, and easier to use. Great job!


27-27: Good use of fmt.Errorf for formatting the error message.

Using fmt.Errorf is a better practice compared to string concatenation when formatting error messages. The error message is clear and includes the relevant information about the missing validator index.


40-40: Excellent error wrapping using fmt.Errorf and the %w verb.

Wrapping the original error with fmt.Errorf and the %w verb is a best practice in Go error handling. It allows the error to be propagated up the call stack while providing additional context about the operation that failed. The error message clearly indicates that the error occurred during the exporting of genesis and includes the original error.


69-72: Great addition of writing application and Tendermint configuration files.

Writing the application configuration to a separate file (app.toml) in the config directory is a good practice for maintaining a clear configuration structure and separating concerns. Using the srvconfig.WriteConfigFile function ensures that the application configuration is written in the correct format and location.

Similarly, writing the Tendermint configuration to config.toml using the config.WriteConfigFile function is consistent with the Tendermint configuration management practices and ensures proper configuration setup.

These additions enhance the InitFiles function's responsibility in setting up the necessary configuration files for the application and Tendermint.

pkg/user/account.go (1)

43-45: LGTM!

The AccountNumber method is a simple and straightforward addition to the Account struct. It provides a convenient way to access the accountNumber field without introducing any breaking changes or compatibility issues.

The method is correctly defined as a value receiver and is exported, which aligns with the PR objectives of enhancing the functionality of the Account type.

No further changes are required.

test/util/testnode/network.go (2)

5-5: LGTM!

The import statement for the filepath package is valid and correctly formatted. This package is a standard Go library used for file path manipulation and is likely needed for the changes made in the NewNetwork function.


23-24: Looks good!

The changes made in this code segment improve the organization and clarity of the test setup process:

  1. The baseDir path is constructed by joining the temporary directory created for the test with a subdirectory named "testnode". This enhances the structure of generated files by specifying a dedicated location for the test node.

  2. The update to the genesis.InitFiles function call, which now includes config.AppConfig as an argument, aligns with the updated requirements for initializing the genesis and validator files. This change suggests that the application configuration is now being handled during the initialization process.

Overall, these modifications contribute to a cleaner and more organized test setup.

tools/chainbuilder/integration_test.go (1)

28-103: Excellent integration test for the chainbuilder tool!

The TestRun function provides comprehensive coverage for the chainbuilder tool's functionality and integration with the Celestia application. Here are some strengths of the test:

  • Skips execution in short mode, which is a good practice for resource-intensive tests.
  • Uses a reasonable number of blocks (10) for the chainbuilder configuration.
  • Handles both first run and second run (with existing directory) scenarios.
  • Properly sets up the Tendermint configuration, application database, and application instance.
  • Loads the node key and creates a new Tendermint node, ensuring that it starts without errors.
  • Creates a local client and verifies that the node's status is not nil.
  • Asserts that the new node makes progress in the blockchain by checking the latest block height.
  • Stops the node gracefully using defer, ensuring proper cleanup.
  • Uses require for assertions, which is a good practice for tests.
  • Uses require.Eventually for retrying the block height assertion, handling asynchronous behavior.
  • Uses reasonable timeouts and retry intervals for the require.Eventually call.

Overall, this test helps ensure that the chainbuilder tool can successfully create and manage a blockchain node, and it helps catch potential regressions or issues in the tool's behavior.

test/util/genesis/document.go (2)

77-77: LGTM!

The change in the GenesisTime field assignment is correct and consistent with the new function signature.


27-27: Verify the function signature change in the codebase.

The addition of the genesisTime parameter is a good change that enhances the flexibility of the function by allowing for the specification of a custom genesis time.

Run the following script to verify the function usage:

Verification successful

Function signature change verified successfully

The Document function call in test/util/genesis/genesis.go has been correctly updated to include the new genesisTime parameter. The g.GenesisTime argument is passed as the sixth parameter, aligning with the updated function signature. This confirms that the change has been consistently applied across the codebase.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all function calls to `Document` match the new signature.

# Test: Search for the function usage. Expect: Only occurrences of the new signature.
rg --type go -A 5 $'Document\('

Length of output: 612


Script:

#!/bin/bash
# Description: View the complete function call to Document in genesis.go

# Search for the Document function call with more context
rg --type go -C 10 'return Document\(' test/util/genesis/genesis.go

Length of output: 343

test/util/genesis/genesis.go (3)

123-126: LGTM!

The new WithKeyring method provides a convenient way to set the keyring of the Genesis struct directly, enhancing the flexibility of the Genesis configuration. The implementation looks good.


230-232: LGTM!

The new EncodingConfig method provides a convenient way to access the encoding configuration associated with the Genesis instance. This addition may facilitate better handling of encoding-related tasks within the genesis context. The implementation looks good.


216-216: Verify the impact of the change in the exported state.

The Export method now includes g.GenesisTime in its return values, which suggests a change in the exported state of the Genesis object. This may affect how the genesis data is serialized or utilized downstream.

Please review and ensure that this change is intended and handled correctly by the consumers of this method.

Run the following script to verify the usage of the Export method in the codebase and analyze the impact:

Verification successful

Verification successful: GenesisTime inclusion is correctly implemented

The Export method now correctly includes g.GenesisTime in its return values by passing it to the Document function. This change appears to be intentional and properly implemented.

The impact on other parts of the codebase seems minimal based on the usage patterns of the Export method. However, to ensure full compatibility, it's recommended to:

  • Thoroughly test the components that use the Export method, particularly in:
    • tools/chainbuilder/main.go
    • test/util/test_app.go
    • test/util/genesis/files.go
    • test/e2e/testnet/testnet.go
    • app/test/upgrade_test.go

Ensure that these components correctly handle the updated genesis document that now includes the genesis time.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of the `Export` method and analyze the impact of the change in the exported state.

# Test: Search for the method usage. Expect: Occurrences of the method with the correct handling of the returned genesis time.
rg --type go -A 10 $'\\(g \\*Genesis\\) Export\\('

Length of output: 697


Script:

#!/bin/bash
# Description: View the complete implementation of the Export method and search for its usages

# View the complete Export method implementation
echo "Complete Export method implementation:"
rg --type go -A 30 '^\s*func \(g \*Genesis\) Export\(' test/util/genesis/genesis.go

echo "\nUsages of the Export method:"
# Search for usages of the Export method in the entire codebase
rg --type go '\.Export\(\)'

Length of output: 1324

go.mod (5)

14-14: Verify the usage and compatibility of the new cometbft-db dependency.

Please ensure that:

  1. The github.com/cometbft/cometbft-db package is actually used in the codebase to justify its addition.
  2. This new dependency doesn't introduce any conflicts or compatibility issues with existing dependencies.

63-63: Verify the impact of updating backoff to v4.2.1.

Please ensure that:

  1. The update to github.com/cenkalti/backoff/v4 v4.2.1 doesn't introduce any breaking changes in the codebase.
  2. All usages of the backoff package are compatible with the new version.

73-73: Clarify the purpose and necessity of the new Docker related dependencies.

Several Docker related dependencies have been added:

  • github.com/containerd/continuity
  • github.com/distribution/reference
  • github.com/docker/docker
  • github.com/docker/go-connections
  • github.com/docker/go-units

Please provide clarification on:

  1. Why were these dependencies introduced? What functionality do they provide?
  2. Are all of these dependencies necessary? Can any of them be removed?
  3. The +incompatible suffix on docker/docker version suggests potential compatibility issues. Has this been checked and resolved?

Also applies to: 89-92


178-179: Clarify the purpose and necessity of the new opencontainers related dependencies.

Two opencontainers related dependencies have been added:

  • github.com/opencontainers/go-digest
  • github.com/opencontainers/image-spec

Please provide clarification on:

  1. Why were these dependencies introduced? What functionality do they provide?
  2. Are both of these dependencies necessary? Can any of them be removed?

211-211: Verify the impact of updating bbolt to v1.3.10.

Please ensure that:

  1. The update to go.etcd.io/bbolt v1.3.10 doesn't introduce any breaking changes in the codebase.
  2. All usages of the bbolt package are compatible with the new version.
tools/chainbuilder/main.go (6)

47-98: LGTM!

The main function sets up the CLI interface correctly using Cobra. The flags are defined with appropriate default values and descriptions. The Run function is invoked with the correct arguments.


110-413: The core logic of the Run function is implemented correctly.

The function correctly distinguishes between creating a new chain and extending an existing one. It sets up the necessary configurations, databases, and stores based on the provided arguments. The block generation logic is implemented correctly, with appropriate error handling. The usage of goroutines for concurrent processing is a good practice.


415-475: LGTM!

The generateSquareRoutine function correctly generates a blob, creates a transaction, builds a data square, and sends it to the dataCh channel. The logic is implemented correctly with appropriate error handling.


483-508: LGTM!

The persistDataRoutine function correctly saves the state and blocks to the database. It receives data from the dataCh channel, persists it using the stateStore and blockStore, and logs progress messages appropriately.


100-108: LGTM!

The BuilderConfig struct includes all the necessary fields to configure the chain builder. The field names are descriptive and follow the Go naming conventions. The field types are appropriate for their respective values.


477-481: LGTM!

The persistData struct includes all the necessary fields to persist the chain data. The field names are descriptive and follow the Go naming conventions. The field types are appropriate for their respective values.

Comment on lines 110 to 413
ValidatorAddress: validatorAddr,
Timestamp: currentTime,
Signature: precommitVote.Signature,
}
commit = types.NewCommit(height, 0, blockID, []types.CommitSig{commitSig})

var lastCommitInfo abci.LastCommitInfo
if height > 1 {
lastCommitInfo = abci.LastCommitInfo{
Round: 0,
Votes: []abci.VoteInfo{
{
Validator: abci.Validator{
Address: validatorAddr,
Power: validatorPower,
},
SignedLastBlock: true,
},
},
}
}

beginBlockResp := simApp.BeginBlock(abci.RequestBeginBlock{
Hash: block.Hash(),
Header: *block.Header.ToProto(),
LastCommitInfo: lastCommitInfo,
})

deliverTxResponses := make([]*abci.ResponseDeliverTx, len(block.Data.Txs))

for idx, tx := range block.Data.Txs {
blobTx, isBlobTx := types.UnmarshalBlobTx(tx)
if isBlobTx {
tx = blobTx.Tx
}
deliverTxResponse := simApp.DeliverTx(abci.RequestDeliverTx{
Tx: tx,
})
if deliverTxResponse.Code != abci.CodeTypeOK {
return fmt.Errorf("failed to deliver tx: %s", deliverTxResponse.Log)
}
deliverTxResponses[idx] = &deliverTxResponse
}

endBlockResp := simApp.EndBlock(abci.RequestEndBlock{
Height: block.Height,
})

commitResp := simApp.Commit()
state.LastBlockHeight = height
state.LastBlockID = blockID
state.LastBlockTime = block.Time
state.LastValidators = state.Validators
state.Validators = state.NextValidators
state.NextValidators = state.NextValidators.CopyIncrementProposerPriority(1)
state.AppHash = commitResp.Data
state.LastResultsHash = sm.ABCIResponsesResultsHash(&smproto.ABCIResponses{
DeliverTxs: deliverTxResponses,
BeginBlock: &beginBlockResp,
EndBlock: &endBlockResp,
})
currentTime = currentTime.Add(cfg.BlockInterval)
persistCh <- persistData{
state: state.Copy(),
block: block,
seenCommit: &types.Commit{
Height: commit.Height,
Round: commit.Round,
BlockID: commit.BlockID,
Signatures: []types.CommitSig{commitSig},
},
}
}
}

close(dataCh)
close(persistCh)

var firstErr error
for i := 0; i < cap(errCh); i++ {
err := <-errCh
if err != nil && firstErr == nil {
firstErr = err
}
}

if err := blockDB.Close(); err != nil {
return fmt.Errorf("failed to close block database: %w", err)
}
if err := stateDB.Close(); err != nil {
return fmt.Errorf("failed to close state database: %w", err)
}
if err := appDB.Close(); err != nil {
return fmt.Errorf("failed to close application database: %w", err)
}

fmt.Println("Chain built successfully", state.LastBlockHeight)

return firstErr
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider refactoring the Run function into smaller, more focused functions.

The Run function is quite large and handles multiple responsibilities. Consider breaking it down into smaller functions that each handle a specific task, such as setting up the configuration, initializing the genesis state, generating blocks, and persisting data. This will improve the readability and maintainability of the code.

evan-forbes
evan-forbes previously approved these changes Sep 18, 2024
test/util/genesis/document.go Show resolved Hide resolved
rootulp
rootulp previously approved these changes Sep 18, 2024
tools/chainbuilder/README.md Outdated Show resolved Hide resolved
@cmwaters cmwaters changed the title feat: add chainbuilder tool feat!: add chainbuilder tool Sep 19, 2024
@cmwaters cmwaters dismissed stale reviews from rootulp and evan-forbes via 5465877 September 19, 2024 12:39
@celestia-bot celestia-bot requested review from a team, staheri14 and ninabarbakadze and removed request for a team September 19, 2024 12:39
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Outside diff range and nitpick comments (2)
tools/chainbuilder/README.md (2)

9-11: Specify the language for fenced code blocks.

For better syntax highlighting and clarity, please specify the language for the fenced code blocks.

Apply this diff to specify the language:

-```
+```bash
 go run ./tools/chainbuilder

```diff
-```
+```bash
 celestia-appd start --home /path/to/testnode-{chainID}


Also applies to: 15-17

<details>
<summary>Tools</summary>

<details>
<summary>Markdownlint</summary><blockquote>

9-9: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</blockquote></details>

</details>

---

`13-13`: **Fix minor grammar issues.**

A couple of minor grammar improvements:
- In American English, "afterward" is the preferred variant instead of "afterwards".
- Add a comma after "By default".

Apply this diff to fix the grammar issues:

```diff
-This will create a directory with the name `testnode-{chainID}`. All files will be populated and blocks generated based on specified input. You can run a validator on the file system afterwards by calling:
+This will create a directory with the name `testnode-{chainID}`. All files will be populated and blocks generated based on specified input. You can run a validator on the file system afterward by calling:
-- `namespace` allows you to pick a custom v0 namespace. By default "test" will be chosen.
+- `namespace` allows you to pick a custom v0 namespace. By default, "test" will be chosen.

Also applies to: 25-25

Tools
LanguageTool

[locale-violation] ~13-~13: In American English, ‘afterward’ is the preferred variant. ‘Afterwards’ is more commonly used in British English and other dialects.
Context: ... can run a validator on the file system afterwards by calling: ``` celestia-appd start --...

(AFTERWARDS_US)

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between e9ff46c and 5465877.

Files selected for processing (2)
  • tools/chainbuilder/README.md (1 hunks)
  • tools/chainbuilder/integration_test.go (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • tools/chainbuilder/integration_test.go
Additional context used
LanguageTool
tools/chainbuilder/README.md

[locale-violation] ~13-~13: In American English, ‘afterward’ is the preferred variant. ‘Afterwards’ is more commonly used in British English and other dialects.
Context: ... can run a validator on the file system afterwards by calling: ``` celestia-appd start --...

(AFTERWARDS_US)


[uncategorized] ~25-~25: Did you mean: “By default,”?
Context: ...lows you to pick a custom v0 namespace. By default "test" will be chosen. This tool takes...

(BY_DEFAULT_COMMA)

Markdownlint
tools/chainbuilder/README.md

9-9: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


15-15: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

Additional comments not posted (1)
tools/chainbuilder/README.md (1)

1-27: LGTM!

Overall, the README.md file provides a clear and informative documentation for the chainbuilder tool. It covers the usage, options, and performance aspects of the tool. With the minor improvements suggested above, the documentation will be even better.

Tools
LanguageTool

[locale-violation] ~13-~13: In American English, ‘afterward’ is the preferred variant. ‘Afterwards’ is more commonly used in British English and other dialects.
Context: ... can run a validator on the file system afterwards by calling: ``` celestia-appd start --...

(AFTERWARDS_US)


[uncategorized] ~25-~25: Did you mean: “By default,”?
Context: ...lows you to pick a custom v0 namespace. By default "test" will be chosen. This tool takes...

(BY_DEFAULT_COMMA)

Markdownlint

9-9: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


15-15: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

@celestia-bot celestia-bot requested a review from a team September 19, 2024 14:07
rootulp
rootulp previously approved these changes Sep 20, 2024
staheri14
staheri14 previously approved these changes Sep 20, 2024
Copy link
Contributor

@staheri14 staheri14 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

This will create a directory with the name `testnode-{chainID}`. All files will be populated and blocks generated based on specified input. You can run a validator on the file system afterwards by calling:

```
celestia-appd start --home /path/to/testnode-{chainID}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] It might be helpful to mention how the pruning option may need adjustment. When I ran this and pointed it to the generated directory by chainbuilder, I encountered this error:

celestia-appd start --home ./testnode-1YgtBH --force-no-bbr
Error: cannot enable state sync snapshots with 'everything' pruning setting: error in app.toml

I had to modify the pruning setting in app.toml to resolve the error. Up to you, but it might be worth mentioning in the documentation.

evan-forbes
evan-forbes previously approved these changes Sep 20, 2024
@celestia-bot celestia-bot requested review from a team and rach-id and removed request for a team September 23, 2024 09:12
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 5465877 and 8bfa934.

Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
Files selected for processing (1)
  • tools/chainbuilder/main.go (1 hunks)
Additional context used
GitHub Check: lint / golangci-lint
tools/chainbuilder/main.go

[failure] 291-291:
S1038: should use fmt.Printf instead of fmt.Println(fmt.Sprintf(...)) (but don't forget the newline) (gosimple)

Comment on lines +253 to +254
validatorPower := state.Validators.Validators[0].VotingPower

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure Validators slice is not empty before accessing

The code assumes that state.Validators.Validators has at least one validator. Accessing index [0] without checking could cause a panic if the slice is empty. Consider adding a check to ensure the slice is not empty before accessing.

Add a check for empty validators:

+	if len(state.Validators.Validators) == 0 {
+		return fmt.Errorf("no validators found in state")
+	}
	validatorPower := state.Validators.Validators[0].VotingPower
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
validatorPower := state.Validators.Validators[0].VotingPower
if len(state.Validators.Validators) == 0 {
return fmt.Errorf("no validators found in state")
}
validatorPower := state.Validators.Validators[0].VotingPower

Comment on lines 291 to 292
fmt.Println(fmt.Sprintf("blocks cannot be generated into the future, stopping at height %d",
lastBlock.Height))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplify the print statement by using fmt.Printf directly

Instead of nesting fmt.Sprintf within fmt.Println, you can use fmt.Printf to format and print the string in a single call.

Apply this diff to simplify the code:

-    			fmt.Println(fmt.Sprintf("blocks cannot be generated into the future, stopping at height %d",
-    				lastBlock.Height))
+    			fmt.Printf("blocks cannot be generated into the future, stopping at height %d\n",
+    				lastBlock.Height)
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fmt.Println(fmt.Sprintf("blocks cannot be generated into the future, stopping at height %d",
lastBlock.Height))
fmt.Printf("blocks cannot be generated into the future, stopping at height %d\n",
lastBlock.Height)
Tools
GitHub Check: lint / golangci-lint

[failure] 291-291:
S1038: should use fmt.Printf instead of fmt.Println(fmt.Sprintf(...)) (but don't forget the newline) (gosimple)

Comment on lines +448 to +449
fee := float64(blobGas) * appconsts.DefaultMinGasPrice * 2
tx, _, err := signer.CreatePayForBlobs(account.Name(), []*share.Blob{blob}, user.SetGasLimit(blobGas), user.SetFee(uint64(fee)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid loss of precision in fee calculation

The fee is calculated using floating-point arithmetic and then cast to uint64, which may result in loss of precision. It's better to perform fee calculations using integer arithmetic to prevent rounding errors.

Modify the fee calculation to use integer arithmetic:

-		fee := float64(blobGas) * appconsts.DefaultMinGasPrice * 2
+		fee := uint64(float64(blobGas) * appconsts.DefaultMinGasPrice * 2)

Ensure that the fee remains accurate after the conversion.

Committable suggestion was skipped due to low confidence.

@celestia-bot celestia-bot requested a review from a team September 23, 2024 09:30
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Outside diff range and nitpick comments (2)
tools/chainbuilder/main.go (2)

433-438: Pass context.Context as the first parameter

In Go conventions, the context.Context parameter should be the first parameter in function signatures. This enhances readability and consistency across the codebase.

Apply this diff to reorder the parameters:

-func generateSquareRoutine(
-	ctx context.Context,
-	signer *user.Signer,
-	cfg BuilderConfig,
-	dataCh chan<- *tmproto.Data,
-) error {
+func generateSquareRoutine(
+	signer *user.Signer,
+	cfg BuilderConfig,
+	dataCh chan<- *tmproto.Data,
+	ctx context.Context,
+) error {

Update the function calls accordingly.


495-499: Consider adding a comment to explain the persistData struct

Adding a comment above the persistData struct can improve code readability by explaining its purpose.

Apply this diff to add a comment:

+// persistData holds the state, block, and seenCommit needed for persistence.
 type persistData struct {
 	state      sm.State
 	block      *types.Block
 	seenCommit *types.Commit
 }
Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 8bfa934 and c02da35.

Files selected for processing (3)
  • tools/chainbuilder/benchmark_test.go (1 hunks)
  • tools/chainbuilder/integration_test.go (1 hunks)
  • tools/chainbuilder/main.go (1 hunks)
Files skipped from review as they are similar to previous changes (2)
  • tools/chainbuilder/benchmark_test.go
  • tools/chainbuilder/integration_test.go
Additional comments not posted (3)
tools/chainbuilder/main.go (3)

260-261: Ensure Validators slice is not empty before accessing


454-455: Avoid loss of precision in fee calculation


119-120: Ensure time calculations account for block intervals accurately

The calculation of startTime subtracts the total expected time span of blocks from the current time. However, if cfg.BlockInterval or cfg.NumBlocks are large, this could result in startTime being in the distant past or even negative. Consider validating the resulting startTime or setting a reasonable minimum to prevent potential issues.

Run the following script to check if startTime is in a valid range:

Verification successful

Time calculations properly account for block intervals

Based on the executed scripts, startTime remains within a valid range even with large cfg.BlockInterval and cfg.NumBlocks values. No issues detected.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that startTime is not before Unix epoch time.

# Test: Check if startTime is after January 1, 1970.
# Expect: Start time should be a valid recent timestamp.

# Replace with actual values if available
NUM_BLOCKS=100
BLOCK_INTERVAL_SECONDS=1

START_TIME=$(date -d "@$(($(date +%s) - $NUM_BLOCKS * $BLOCK_INTERVAL_SECONDS))" +%s)

if [ $START_TIME -lt 0 ]; then
  echo "startTime is before Unix epoch time. Please validate the calculation."
else
  echo "startTime is valid."
fi

Length of output: 183


Script:

#!/bin/bash
# Description: Verify that startTime remains valid with large NUM_BLOCKS and BLOCK_INTERVAL_SECONDS.

# Test: Check if startTime is after January 1, 1970, with large parameters.
# Expect: startTime should still be a valid recent timestamp or within a reasonable range.

# Set large values
NUM_BLOCKS=1000000
BLOCK_INTERVAL_SECONDS=60

# Get current timestamp
CURRENT_TIMESTAMP=$(date +%s)

# Calculate start time
START_TIME=$((CURRENT_TIMESTAMP - NUM_BLOCKS * BLOCK_INTERVAL_SECONDS))

# Check if start time is before Unix epoch
if [ $START_TIME -lt 0 ]; then
  echo "startTime is before Unix epoch time. Please validate the calculation."
else
  # Optionally, check if startTime is too far in the past
  # For example, not older than a certain threshold, say 10 years
  TEN_YEARS_SECONDS=$((10 * 365 * 24 * 60 * 60))
  if [ $((CURRENT_TIMESTAMP - START_TIME)) -gt $TEN_YEARS_SECONDS ]; then
    echo "startTime is more than 10 years in the past. Please validate the calculation."
  else
    echo "startTime is valid."
  fi
fi

Length of output: 254

Comment on lines +327 to +328
return fmt.Errorf("failed to sign precommit vote (%s): %w", precommitVote.String(), err)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid exposing sensitive information in error messages

The error message includes the string representation of precommitVote, which may contain sensitive information. It's safer to omit or sanitize such details in error logs to prevent potential information leaks.

Apply this diff to remove sensitive information from the error message:

-    				return fmt.Errorf("failed to sign precommit vote (%s): %w", precommitVote.String(), err)
+    				return fmt.Errorf("failed to sign precommit vote: %w", err)
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return fmt.Errorf("failed to sign precommit vote (%s): %w", precommitVote.String(), err)
}
return fmt.Errorf("failed to sign precommit vote: %w", err)

Comment on lines +151 to +158
fmt.Println("Creating chain from scratch with Chain ID:", gen.ChainID)
} else {
cfgPath := filepath.Join(cfg.ExistingDir, "config/config.toml")
if _, err := os.Stat(cfgPath); os.IsNotExist(err) {
return fmt.Errorf("config file for existing chain not found at %s", cfgPath)
}
fmt.Println("Loading chain from existing directory:", cfg.ExistingDir)
tmCfg.SetRoot(cfg.ExistingDir)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using a structured logging library instead of fmt.Println

The code uses fmt.Println for logging informational messages. For better logging practices, consider using a structured logging library like Go's standard log package or third-party libraries such as logrus or zap. This allows for log levels, formatted output, and easier maintenance.

Example using the standard log package:

-    		fmt.Println("Creating chain from scratch with Chain ID:", gen.ChainID)
+    		log.Printf("Creating chain from scratch with Chain ID: %s\n", gen.ChainID)

Repeat this change for other fmt.Println calls to ensure consistent logging throughout the application.

Committable suggestion was skipped due to low confidence.

Comment on lines +56 to +62
numBlocks, _ := cmd.Flags().GetInt("num-blocks")
blockSize, _ := cmd.Flags().GetInt("block-size")
blockInterval, _ := cmd.Flags().GetDuration("block-interval")
existingDir, _ := cmd.Flags().GetString("existing-dir")
namespaceStr, _ := cmd.Flags().GetString("namespace")
upToTime, _ := cmd.Flags().GetBool("up-to-now")
appVersion, _ := cmd.Flags().GetUint64("app-version")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle errors when parsing command-line flags

The current implementation ignores errors returned by cmd.Flags().Get* methods. This could lead to unexpected behavior if a flag cannot be parsed correctly. It's important to check and handle these errors to ensure robustness.

Apply this diff to handle the errors:

-    			numBlocks, _ := cmd.Flags().GetInt("num-blocks")
-    			blockSize, _ := cmd.Flags().GetInt("block-size")
-    			blockInterval, _ := cmd.Flags().GetDuration("block-interval")
-    			existingDir, _ := cmd.Flags().GetString("existing-dir")
-    			namespaceStr, _ := cmd.Flags().GetString("namespace")
-    			upToTime, _ := cmd.Flags().GetBool("up-to-now")
-    			appVersion, _ := cmd.Flags().GetUint64("app-version")
+    			numBlocks, err := cmd.Flags().GetInt("num-blocks")
+    			if err != nil {
+    				return fmt.Errorf("failed to get 'num-blocks' flag: %w", err)
+    			}
+    			blockSize, err := cmd.Flags().GetInt("block-size")
+    			if err != nil {
+    				return fmt.Errorf("failed to get 'block-size' flag: %w", err)
+    			}
+    			blockInterval, err := cmd.Flags().GetDuration("block-interval")
+    			if err != nil {
+    				return fmt.Errorf("failed to get 'block-interval' flag: %w", err)
+    			}
+    			existingDir, err := cmd.Flags().GetString("existing-dir")
+    			if err != nil {
+    				return fmt.Errorf("failed to get 'existing-dir' flag: %w", err)
+    			}
+    			namespaceStr, err := cmd.Flags().GetString("namespace")
+    			if err != nil {
+    				return fmt.Errorf("failed to get 'namespace' flag: %w", err)
+    			}
+    			upToTime, err := cmd.Flags().GetBool("up-to-now")
+    			if err != nil {
+    				return fmt.Errorf("failed to get 'up-to-now' flag: %w", err)
+    			}
+    			appVersion, err := cmd.Flags().GetUint64("app-version")
+    			if err != nil {
+    				return fmt.Errorf("failed to get 'app-version' flag: %w", err)
+    			}
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
numBlocks, _ := cmd.Flags().GetInt("num-blocks")
blockSize, _ := cmd.Flags().GetInt("block-size")
blockInterval, _ := cmd.Flags().GetDuration("block-interval")
existingDir, _ := cmd.Flags().GetString("existing-dir")
namespaceStr, _ := cmd.Flags().GetString("namespace")
upToTime, _ := cmd.Flags().GetBool("up-to-now")
appVersion, _ := cmd.Flags().GetUint64("app-version")
numBlocks, err := cmd.Flags().GetInt("num-blocks")
if err != nil {
return fmt.Errorf("failed to get 'num-blocks' flag: %w", err)
}
blockSize, err := cmd.Flags().GetInt("block-size")
if err != nil {
return fmt.Errorf("failed to get 'block-size' flag: %w", err)
}
blockInterval, err := cmd.Flags().GetDuration("block-interval")
if err != nil {
return fmt.Errorf("failed to get 'block-interval' flag: %w", err)
}
existingDir, err := cmd.Flags().GetString("existing-dir")
if err != nil {
return fmt.Errorf("failed to get 'existing-dir' flag: %w", err)
}
namespaceStr, err := cmd.Flags().GetString("namespace")
if err != nil {
return fmt.Errorf("failed to get 'namespace' flag: %w", err)
}
upToTime, err := cmd.Flags().GetBool("up-to-now")
if err != nil {
return fmt.Errorf("failed to get 'up-to-now' flag: %w", err)
}
appVersion, err := cmd.Flags().GetUint64("app-version")
if err != nil {
return fmt.Errorf("failed to get 'app-version' flag: %w", err)
}

tools/chainbuilder/main.go Show resolved Hide resolved
@cmwaters cmwaters merged commit 27dc26f into main Sep 24, 2024
32 checks passed
@cmwaters cmwaters deleted the cal/chain-builder branch September 24, 2024 09:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants