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: extend forest-cli chain head #4952

Merged
merged 2 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@

### Breaking

- [#4952](https://github.com/ChainSafe/forest/pull/4952) Extended the
`forest-cli chain head` command to allow for specifying number of last tipsets
to display. This change is breaking as the output now contains the epoch of
tipsets.

### Added

- [#4937](https://github.com/ChainSafe/forest/pull/4937) Added
Expand Down
4 changes: 4 additions & 0 deletions scripts/tests/calibnet_other_check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ echo "Test dev commands (which could brick the node/cause subsequent snapshots t
echo "Test subcommand: chain set-head"
$FOREST_CLI_PATH chain set-head --epoch -10 --force

echo "Test subcommand: chain head"
$FOREST_CLI_PATH chain head
$FOREST_CLI_PATH chain head --tipsets 10

echo "Test subcommand: info show"
$FOREST_CLI_PATH info show

Expand Down
2 changes: 1 addition & 1 deletion scripts/tests/calibnet_stateless_mode_check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ source "$(dirname "$0")/harness.sh"
forest_init_stateless

echo "Verifying the heaviest tipset to be the genesis"
HEAD_CID=$($FOREST_CLI_PATH chain head)
HEAD_CID=$($FOREST_CLI_PATH chain head | tail -n +2)
assert_eq "$HEAD_CID" "bafy2bzacecyaggy24wol5ruvs6qm73gjibs2l2iyhcqmvi7r7a4ph7zx3yqd4"

# Example format: /ip4/127.0.0.1/tcp/41937/p2p/12D3KooWAB9z7vZ1x1v9t4BViVkX1Hy1ScoRnWV2GgGy5ec6pfUZ
Expand Down
32 changes: 29 additions & 3 deletions src/cli/subcommands/chain_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::blocks::{Tipset, TipsetKey};
use crate::lotus_json::HasLotusJson;
use crate::message::ChainMessage;
use crate::rpc::{self, prelude::*};
use anyhow::bail;
use anyhow::{bail, ensure};
use cid::Cid;
use clap::Subcommand;
use nunny::Vec as NonEmpty;
Expand All @@ -24,7 +24,12 @@ pub enum ChainCommands {
Genesis,

/// Prints out the canonical head of the chain
Head,
Head {
/// Print the first `n` tipsets from the head (inclusive).
/// Tipsets are categorized by epoch in descending order.
#[arg(short = 'n', long, default_value = "1")]
tipsets: u64,
},

/// Reads and prints out a message referenced by the specified CID from the
/// chain block store
Expand Down Expand Up @@ -63,7 +68,7 @@ impl ChainCommands {
print_pretty_lotus_json(ChainGetBlock::call(&client, (cid,)).await?)
}
Self::Genesis => print_pretty_lotus_json(ChainGetGenesis::call(&client, ()).await?),
Self::Head => print_rpc_res_cids(ChainHead::call(&client, ()).await?),
Self::Head { tipsets } => print_chain_head(&client, tipsets).await,
Self::Message { cid } => {
let bytes = ChainReadObj::call(&client, (cid,)).await?;
match fvm_ipld_encoding::from_slice::<ChainMessage>(&bytes)? {
Expand Down Expand Up @@ -145,3 +150,24 @@ fn maybe_confirm(no_confirm: bool, prompt: impl Into<String>) -> anyhow::Result<
false => bail!("Operation cancelled by user"),
}
}

/// Print the first `n` tipsets from the head (inclusive).
async fn print_chain_head(client: &rpc::Client, n: u64) -> anyhow::Result<()> {
ensure!(n > 0, "number of tipsets must be positive");
let head = ChainHead::call(client, ()).await?;
let current_epoch = head.epoch() as u64;

// edge case for, e.g., stateless nodes.
if current_epoch == 0 {
println!("[0]");
print_rpc_res_cids(head)?;
return Ok(());
}

for epoch in (current_epoch.saturating_sub(n - 1)..=current_epoch).rev() {
let tipset = tipset_by_epoch_or_offset(client, epoch.try_into()?).await?;
println!("[{}]", epoch);
print_rpc_res_cids(tipset)?;
}
Ok(())
}
Loading