Ver Fonte

solana-install design proposal

Michael Vines há 6 anos atrás
pai
commit
a17843c8f6
8 ficheiros alterados com 368 adições e 0 exclusões
  1. 15 0
      Cargo.lock
  2. 1 0
      Cargo.toml
  3. 1 0
      book/src/SUMMARY.md
  4. 21 0
      install/Cargo.toml
  5. 15 0
      install/build.rs
  6. 101 0
      install/src/main.rs
  7. 1 0
      proposals/src/SUMMARY.md
  8. 213 0
      proposals/src/installer.md

+ 15 - 0
Cargo.lock

@@ -2171,6 +2171,21 @@ dependencies = [
  "solana-vote-api 0.13.0",
 ]
 
+[[package]]
+name = "solana-install"
+version = "0.13.0"
+dependencies = [
+ "bincode 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "solana-client 0.13.0",
+ "solana-logger 0.13.0",
+ "solana-sdk 0.13.0",
+]
+
 [[package]]
 name = "solana-keygen"
 version = "0.13.0"

+ 1 - 0
Cargo.toml

@@ -65,6 +65,7 @@ members = [
     "drone",
     "fullnode",
     "genesis",
+    "install",
     "keygen",
     "ledger-tool",
     "logger",

+ 1 - 0
book/src/SUMMARY.md

@@ -33,3 +33,4 @@
   - [JSON RPC API](jsonrpc-api.md)
   - [JavaScript API](javascript-api.md)
   - [solana-wallet CLI](wallet.md)
+

+ 21 - 0
install/Cargo.toml

@@ -0,0 +1,21 @@
+[package]
+authors = ["Solana Maintainers <maintainers@solana.com>"]
+edition = "2018"
+name = "solana-install"
+description = "The solana cluster software installer"
+version = "0.13.0"
+repository = "https://github.com/solana-labs/solana"
+license = "Apache-2.0"
+homepage = "https://solana.com/"
+
+[dependencies]
+bincode = "1.1.2"
+bs58 = "0.2.0"
+clap = { version = "2.32.0"}
+chrono = { version = "0.4.0", features = ["serde"] }
+log = "0.4.2"
+serde_json = "1.0.39"
+solana-client = { path = "../client", version = "0.13.0" }
+solana-logger = { path = "../logger", version = "0.13.0" }
+solana-sdk = { path = "../sdk", version = "0.13.0" }
+

+ 15 - 0
install/build.rs

@@ -0,0 +1,15 @@
+use std::time::SystemTime;
+
+fn main() {
+    println!(
+        "cargo:rustc-env=TARGET={}",
+        std::env::var("TARGET").unwrap()
+    );
+    println!(
+        "cargo:rustc-env=BUILD_SECONDS_SINCE_UNIX_EPOCH={}",
+        SystemTime::now()
+            .duration_since(SystemTime::UNIX_EPOCH)
+            .unwrap()
+            .as_secs(),
+    );
+}

+ 101 - 0
install/src/main.rs

@@ -0,0 +1,101 @@
+use clap::{crate_description, crate_name, crate_version, App, AppSettings, Arg, SubCommand};
+//use clap::{crate_description, crate_version, load_yaml, App, AppSettings};
+use std::error;
+use std::time::Duration;
+
+const TARGET: &str = env!("TARGET");
+const BUILD_SECONDS_SINCE_UNIX_EPOCH: &str = env!("BUILD_SECONDS_SINCE_UNIX_EPOCH");
+
+fn main() -> Result<(), Box<dyn error::Error>> {
+    solana_logger::setup();
+
+    let matches = App::new(crate_name!())
+        .about(crate_description!())
+        .version(crate_version!())
+        .setting(AppSettings::ArgRequiredElseHelp)
+        .subcommand(
+            SubCommand::with_name("init")
+                .about("initializes a new installation")
+                .setting(AppSettings::DisableVersion)
+                .arg(
+                    Arg::with_name("json_rpc_url")
+                        .short("u")
+                        .long("url")
+                        .value_name("URL")
+                        .takes_value(true)
+                        .default_value("https://api.testnet.solana.com/")
+                        .help("JSON RPC URL for the solana cluster"),
+                )
+                .arg(
+                    Arg::with_name("update_pubkey")
+                        .short("p")
+                        .long("pubkey")
+                        .value_name("PUBKEY")
+                        .takes_value(true)
+                        .default_value("Solana-managed update manifest")
+                        .help("Public key of the update manifest"),
+                ),
+        )
+        .subcommand(
+            SubCommand::with_name("info")
+                .about("displays information about the current installation")
+                .setting(AppSettings::DisableVersion)
+                .arg(
+                    Arg::with_name("local_info_only")
+                        .short("l")
+                        .long("local")
+                        .help(
+                        "only display local information, don't check the cluster for new updates",
+                    ),
+                ),
+        )
+        .subcommand(
+            SubCommand::with_name("deploy")
+                .about("deploys a new update")
+                .setting(AppSettings::DisableVersion)
+                .arg(
+                    Arg::with_name("download_url")
+                        .index(1)
+                        .required(true)
+                        .help("URL to the solana release archive"),
+                )
+                .arg(
+                    Arg::with_name("update_manifest_keypair")
+                        .index(2)
+                        .required(true)
+                        .help("Keypair file for the update manifest (/path/to/keypair.json)"),
+                ),
+        )
+        .subcommand(
+            SubCommand::with_name("update")
+                .about("checks for an update, and if available downloads and applies it")
+                .setting(AppSettings::DisableVersion),
+        )
+        .subcommand(
+            SubCommand::with_name("run")
+                .about("Runs a program while periodically checking and applying software updates")
+                .after_help("The program will be restarted upon a successful software update")
+                .setting(AppSettings::DisableVersion)
+                .arg(
+                    Arg::with_name("program_name")
+                        .index(1)
+                        .required(true)
+                        .help("program to run"),
+                )
+                .arg(
+                    Arg::with_name("program_arguments")
+                        .index(2)
+                        .multiple(true)
+                        .help("arguments to supply to the program"),
+                ),
+        )
+        .get_matches();
+
+    println!("TARGET={}", TARGET);
+    println!(
+        "BUILD_SECONDS_SINCE_UNIX_EPOCH={:?}",
+        Duration::from_secs(u64::from_str_radix(BUILD_SECONDS_SINCE_UNIX_EPOCH, 10).unwrap())
+    );
+    println!("{:?}", matches);
+    Ok(())
+}

+ 1 - 0
proposals/src/SUMMARY.md

@@ -23,6 +23,7 @@
     - [References](ed_references.md)
   - [Cluster Test Framework](cluster-test-framework.md)
   - [Testing Programs](testing-programs.md)
+  - [Cluster Software Installation and Updates](installer.md)
 
 - [Implemented Design Proposals](implemented-proposals.md)
   - [Leader-to-Leader Transition](leader-leader-transition.md)

+ 213 - 0
proposals/src/installer.md

@@ -0,0 +1,213 @@
+## Cluster Software Installation and Updates
+Currently users are required to build the solana cluster software themselves
+from the git repository and manually update it, which is error prone and
+inconvenient.
+
+This document proposes an easy to use software install and updater that can be
+used to deploy pre-built binaries for supported platforms.  Users may elect to
+use binaries supplied by Solana or any other party they trust.  Deployment of
+updates is managed using an on-chain update manifest program.
+
+### Motivating Examples
+#### Fetch and run a pre-built installer
+
+With a well-known release URL, a pre-built binary can be obtained for supported
+platforms:
+
+```bash
+$ curl -o solana-install https://github.com/solana-labs/solana/releases/download/v1.2.3/solana-install-x86_64-apple-darwin
+$ chmod +x ./solana-install
+$ ./solana-install --help
+```
+
+Note: future enhancements should include building wrapper in the style of
+https://rustup.rs/ to make bootstrapping an install even easier.
+
+#### Build and run the installer from source
+
+If a pre-built binary is not available for a given platform, building the
+installer from source is always an option:
+```bash
+$ git clone https://github.com/solana-labs/solana.git
+$ cd solana/install
+$ cargo run -- --help
+```
+
+#### Deploy a new update to a cluster
+Given a solana release tarball (as created by `ci/publish-tarball.sh`) that has already been uploaded to a publicly accessible URL,
+the following commands will deploy the update:
+```bash
+$ solana-keygen -o update-manifest.json  # <-- only generated once, the public key is shared with users
+$ solana-install deploy http://example.com/path/to/solana-release.tar.bz2 update-manifest.json
+```
+
+Note: Supporting IPFS download URLs in the future would be attractive.
+
+#### Run a validator node that auto updates itself
+
+```bash
+$ solana-install init --pubkey 92DMonmBYXwEMHJ99c9ceRSpAmk9v6i3RdvDdXaVcrfj  # <-- pubkey is obtained from whoever is deploying the updates
+$ export PATH=~/.local/share/solana-install/bin:$PATH
+$ solana-keygen ...  # <-- runs the latest solana-keygen
+$ solana-install run solana-fullnode ...  # <-- runs a fullnode, restarting it as necesary when an update is applied
+```
+
+### Update Manifest on-chain program
+The Update Manifest program is used to advertise the deployment of new release tarballs
+on a solana cluster.  Each instance of this program describes a logical update
+channel for a given target triple (eg, `x86_64-apple-darwin`).  The public key
+of each program instance is well-known between the entity deploying new updates
+and users consuming those updates.
+
+The update tarball itself is hosted elsewhere, off-chain and can be fetched from
+the specified `download_url`.
+
+```rust,ignore
+use solana_sdk::signature::Signature;
+
+/// Information required to download and apply a given update
+pub struct UpdateManifest {
+  pub target: String,                 // Target triple (TARGET)
+  pub commit: String,                 // git sha1 of this update, must match the commit sha1 in the release tar.bz2
+  pub timestamp_secs: u64,            // When the release was deployed (seconds since UNIX EPOC)
+  pub download_url: String,           // Download URL to the release tar.bz2
+  pub download_signature: Signature,  // Signature of the release tar.bz2 file, verify with the Account public key
+}
+
+/// Userdata of an Update Manifest program Account.
+pub struct SignedUpdateManifest {
+  pub manifest: UpdateManifest,
+  pub manifest_signature: Signature,  // Signature of UpdateInfo, verify with the Account public key
+}
+```
+
+Note that the `manifest` field itself contains a corresponding signature
+(`manifest_signature`) to guard against man-in-the-middle attacks between the
+`solana-install` tool and the solana cluster RPC API.
+
+To guard against rollback attacks, `solana-install` will refuse to install an
+update with an older `timestamp_secs` than what is currently installed.
+
+### solana-install Tool
+
+The `solana-install` tool is used by the user to install and update their cluster software.
+
+It manages the following files and directories in the user's home directory:
+* `~/.config/solana/updater.json` - user configuration and information about currently installed software version
+* `~/.local/share/solana-install/bin` - a symlink to the current release. eg, `~/.local/share/solana-update/<update-pubkey>-<manifest_signature>/bin`
+* `~/.local/share/solana-install/<update-pubkey>-<manifest_signature>/` - contents of the release
+* `~/.local/share/solana-install/<update-pubkey>-<manifest_signature>.tmp/` - temporary directory used while downloading a new release
+
+#### Command-line Interface
+```bash
+$ solana-install --help
+solana-install 0.13.0
+The solana cluster software installer
+
+USAGE:
+    solana-install [SUBCOMMAND]
+
+FLAGS:
+    -h, --help    Prints help information
+
+SUBCOMMANDS:
+    deploy    deploys a new update
+    help      Prints this message or the help of the given subcommand(s)
+    info      displays information about the current installation
+    init      initializes a new installation
+    run       Runs a program while periodically checking and applying software updates. The program will be
+              restarted upon a successful software update
+    update    checks for an update, and if available downloads and applies it
+```
+
+##### init
+```bash
+$ solana-install init --help
+solana-install-init
+initializes a new installation
+
+USAGE:
+    solana-install init [OPTIONS]
+
+FLAGS:
+    -h, --help    Prints help information
+
+OPTIONS:
+    -u, --url <URL>          JSON RPC URL for the solana cluster [default: https://api.testnet.solana.com/]
+    -p, --pubkey <PUBKEY>    Public key of the update manifest [default: Solana-managed update manifest]
+```
+
+##### info
+```bash
+$ solana-install info --help
+solana-install-info
+displays information about the current installation
+
+USAGE:
+    solana-install info [FLAGS]
+
+FLAGS:
+    -h, --help    Prints help information
+    -l            only display local information, don't check the cluster for new updates
+```
+
+##### deploy
+```bash
+$ solana-install deploy --help
+solana-install-deploy
+deploys a new update
+
+USAGE:
+    solana-install deploy <URL> <PATH>
+
+FLAGS:
+    -h, --help    Prints help information
+
+ARGS:
+    <URL>     URL to the solana release archive
+    <PATH>    Keypair file for the update manifest (/path/to/keypair.json)
+```
+
+##### update
+```bash
+$ solana-install update --help
+solana-install-update
+checks for an update, and if available downloads and applies it
+
+USAGE:
+    solana-install update
+
+FLAGS:
+    -h, --help    Prints help information
+```
+
+##### run
+```bash
+$ solana-install run --help
+solana-install-run
+Runs a program while periodically checking and applying software updates. The program will be restarted upon a
+successful software update
+
+USAGE:
+    solana-install run <program_name> [program_arguments]...
+
+FLAGS:
+    -h, --help    Prints help information
+
+ARGS:
+    <program_name>            program to run
+    <program_arguments>...    arguments to supply to the program
+```
+
+### Release Archive Contents
+A release archive is expected to be a tar file compressed with
+bzip2 with the following internal structure:
+
+* `/version.yml` - a simple YAML file containing the fields (1) `"commit"` - the git
+  sha1 for this release, and (2) `"target"` - the target tuple.  Any additional
+  fields are ignored.
+* `/bin/` -- directory containing available programs in the release.
+  `solana-install` will symlink this directory to
+  `~/.local/share/solana-install/bin` for use by the `PATH` environment
+  variable.
+* `...` -- any additional files and directories are permitted