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(unionvisor): add set-binary command #2880

Merged
Show file tree
Hide file tree
Changes from all commits
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
18 changes: 18 additions & 0 deletions docs/src/content/docs/joining-testnet/unionvisor.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,24 @@ We use `sudo` here because Docker created the files we are copying with elevated

:::

### Using Snapshots or State Sync

For networks that have been producing blocks for more than a few weeks, syncing from genesis is often not recommended. Most validators and node operators prefer to use node snapshots or state sync to jump start their nodes.

To use state sync or node snapshots with Unionvisor, you will need to use the `set-uniond-version` sub-command of Unionvisor. You should set Unionvisor to use the version of `uniond` that was used to generate the node snapshot or state sync snapshot.

You can use the `set-uniond-version` command as follows:

```sh frame="none"
docker run \
--volume ~/.unionvisor:/.unionvisor \
--volume /tmp:/tmp \
-it ghcr.io/unionlabs/bundle-testnet-8:$UNIONVISOR_VERSION \
set-uniond-version $UNIOND_VERSION
```
*Where `UNIOND_VERSION` is the version of `uniond` used when the snapshot was generated*


### Issuing Sub-Commands to uniond via Unionvisor

To run `uniond` sub-commands, it will be useful to alias the Docker command in your shell `.*rc` file.
Expand Down
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,7 @@

SQLX_OFFLINE = true;
LIBCLANG_PATH = "${pkgs.llvmPackages_14.libclang.lib}/lib";
PROTOC = "${pkgs.protobuf}/bin/protoc";
};

treefmt = {
Expand Down
55 changes: 54 additions & 1 deletion unionvisor/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{
init::{self, SetSeedsError},
logging::LogFormat,
supervisor::{self, RuntimeError},
symlinker::{MakeFallbackLinkError, Symlinker},
symlinker::{MakeFallbackLinkError, Symlinker, SymlinkerError},
};

#[derive(Parser, Clone)]
Expand Down Expand Up @@ -55,6 +55,10 @@ pub struct Cli {

#[derive(Clone, Parser)]
pub enum Command {
/// Set the current binary to a specific version in the bundle.
/// Use this when using unionvisor in combination with a node snapshot or state sync.
SetUniondVersion(SetUniondVersionCmd),

/// Call the current binary, forwarding all arguments passed.
/// `unionvisor call ..arg` is equivalent to `uniond ..args`.
Call(CallCmd),
Expand All @@ -66,6 +70,15 @@ pub enum Command {
Init(InitCmd),
}

#[derive(Clone, Parser)]
pub struct SetUniondVersionCmd {
/// Path to where the binary bundle is stored.
#[arg(short, long, env = "UNIONVISOR_BUNDLE")]
bundle: PathBuf,

version: String,
}

#[derive(Clone, Parser)]
pub struct CallCmd {
/// Path to where the binary bundle is stored.
Expand Down Expand Up @@ -116,6 +129,10 @@ pub struct RunCmd {
impl Cli {
pub fn run(self) -> Result<(), RunCliError> {
match &self.command {
Command::SetUniondVersion(cmd) => {
cmd.set_uniond_version(self.root)?;
Ok(())
}
Command::Call(cmd) => {
cmd.call(self.root)?;
Ok(())
Expand All @@ -134,6 +151,8 @@ impl Cli {

#[derive(Debug, Error)]
pub enum RunCliError {
#[error("set binary error")]
SetUniondVersion(#[from] SetUniondVersionError),
#[error("call command error")]
Call(#[from] CallError),
#[error("run command error")]
Expand Down Expand Up @@ -229,6 +248,40 @@ pub enum RunError {
Runtime(#[from] RuntimeError),
}

#[derive(Debug, Error)]
pub enum SetUniondVersionError {
#[error("runtime error")]
Runtime(#[from] RuntimeError),
#[error("new bundle error")]
NewBundle(#[from] NewBundleError),
#[error("symlink error")]
Symlink(#[from] SymlinkerError),
}

impl SetUniondVersionCmd {
fn set_uniond_version(&self, root: impl Into<PathBuf>) -> Result<(), SetUniondVersionError> {
let root = root.into();
let bundle = Bundle::new(self.bundle.clone())?;
log_bundle(&bundle);
let symlinker = Symlinker::new(root.clone(), bundle);

// Ensure version exists in bundle
symlinker
.bundle
.path_to(&self.version)
.validate()
.map_err(|source| RuntimeError::BinaryUnavailable {
name: self.version.clone(),
source,
})?;

// Swap version symlink
symlinker.swap(&self.version)?;

Ok(())
}
}

impl CallCmd {
/// Executes the logic for the Call variant. Will panic if the enum is not [`Command::Call`].
fn call(&self, root: impl Into<PathBuf>) -> Result<(), CallError> {
Expand Down
2 changes: 1 addition & 1 deletion versions/versions.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
},
"union-testnet-8": {
"versions": ["v0.21.0", "v0.22.0", "v0.23.0", "v0.24.0"],
"current": "v0.22.0",
"current": "v0.24.0",
"seeds": "c2bf0d5b2ad3a1df0f4e9cc32debffa239c0af90@testnet.seed.poisonphang.com:26656"
}
}