Skip to content
This repository has been archived by the owner on Jun 3, 2020. It is now read-only.

Upgrade to Abscissa 0.1.0-pre.1 #259

Merged
merged 1 commit into from
Jun 9, 2019
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
619 changes: 382 additions & 237 deletions Cargo.lock

Large diffs are not rendered by default.

27 changes: 15 additions & 12 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,40 @@ members = [".", "tendermint-rs"]
[badges]
circle-ci = { repository = "tendermint/kms" }

[dependencies.abscissa]
version = "0.1.0-pre.1"
default-features = false
features = ["application", "signals", "secrets", "time"]

[dependencies]
abscissa = "0.0.6"
abscissa_derive = "0.0.2"
atomicwrites = "0.2"
byteorder = "1.2"
bytes = "0.4"
chrono = "0.4"
failure = "0.1"
failure_derive = "0.1"
gumdrop = "0.5"
Copy link
Contributor

Choose a reason for hiding this comment

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

This is only used indirectly (via [derive(Options)], right? (I could not find any sign of #[macro_use] extern crate gumdrop;)

Copy link
Contributor

Choose a reason for hiding this comment

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

I've largely switched to using Rust 2018 conventions for importing macros, where instead of #[macro_use] spooky-action-at-a-distance, macros can be imported by name just like anything else.

This allows a crate like gumdrop to re-export the proc macros from gumdrop_derive so that consumers don't need both. After the 2018 edition was released, pretty much everything with a proc macro crate switched to this convention (including abscissa).

hkdf = "0.7"
hmac = "0.7"
lazy_static = "1"
ledger-tendermint = { version = "0.4.0", optional = true }
log = "0.4"
prost-amino = "0.4.0"
prost-amino-derive = "0.4.0"
rand_os = "0.1"
serde = "1"
serde_derive = "1"
serde = { version = "1", features = ["serde_derive"] }
serde_json = "1"
sha2 = "0.8"
signal-hook = "0.1.7"
signatory = { version = "0.11.1", features = ["ed25519", "ecdsa"] }
signatory-dalek = "0.11"
signatory-secp256k1 = "0.11"
signatory = { version = "0.12", features = ["ed25519", "ecdsa"] }
signatory-dalek = "0.12"
signatory-secp256k1 = "0.12"
signatory-ledger-tm = { version = "0.12", optional = true }
subtle = "2"
subtle-encoding = { version = "0.3", features = ["bech32-preview"] }
tendermint = { version = "0.7", path = "tendermint-rs", features = ["amino-types", "secret-connection"] }
tiny-bip39 = "0.6"
wait-timeout = "0.2"
yubihsm = { version = "0.22", features = ["setup", "usb"], optional = true }
zeroize = "0.5"
yubihsm = { version = "0.25", features = ["setup", "usb"], optional = true }
zeroize = "0.9"

[dev-dependencies]
tempfile = "3"
Expand All @@ -55,7 +58,7 @@ rand = "0.6" # TODO: switch to the getrandom crate
[features]
default = []
softsign = []
ledgertm = ["ledger-tendermint"]
ledgertm = ["signatory-ledger-tm"]
yubihsm-mock = ["yubihsm/mockhsm"]

# Enable integer overflow checks in release builds for security reasons
Expand Down
96 changes: 87 additions & 9 deletions src/application.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,103 @@
//! Abscissa `Application` for the KMS

use abscissa::{self, Application, LoggingConfig};

use crate::{commands::KmsCommand, config::KmsConfig};
use abscissa::{application, Application, FrameworkError, LoggingConfig, StandardPaths};
use lazy_static::lazy_static;

lazy_static! {
/// Application state
pub static ref APPLICATION: application::Lock<KmsApplication> = application::Lock::default();
}

/// Obtain a read-only (multi-reader) lock on the application state.
///
/// Panics if the application state has not been initialized.
pub fn app_reader() -> application::lock::Reader<KmsApplication> {
APPLICATION.read()
}

/// Obtain an exclusive mutable lock on the application state.
pub fn app_writer() -> application::lock::Writer<KmsApplication> {
APPLICATION.write()
}

/// Obtain a read-only (multi-reader) lock on the application configuration.
///
/// Panics if the application configuration has not been loaded.
pub fn app_config() -> abscissa::config::Reader<KmsApplication> {
abscissa::config::Reader::new(&APPLICATION)
}

/// The `tmkms` application
#[derive(Debug)]
pub struct KmsApplication;
pub struct KmsApplication {
/// Application configuration.
config: Option<KmsConfig>,

/// Application state.
state: application::State<Self>,
}

impl KmsApplication {
/// Boot the application
// TODO: use the upstream implementation of this method
pub fn boot() {
abscissa::boot(KmsApplication)
impl Default for KmsApplication {
fn default() -> Self {
Self {
config: None,
state: application::State::default(),
}
}
}

impl Application for KmsApplication {
/// Entrypoint command for this application.
type Cmd = KmsCommand;
type Config = KmsConfig;

/// Application configuration.
type Cfg = KmsConfig;

/// Paths to resources within the application.
type Paths = StandardPaths;

/// Accessor for application configuration.
fn config(&self) -> Option<&KmsConfig> {
self.config.as_ref()
}

/// Borrow the application state immutably.
fn state(&self) -> &application::State<Self> {
&self.state
}

/// Borrow the application state mutably.
fn state_mut(&mut self) -> &mut application::State<Self> {
&mut self.state
}

/// Register all components used by this application.
///
/// If you would like to add additional components to your application
/// beyond the default ones provided by the framework, this is the place
/// to do so.
fn register_components(&mut self, command: &Self::Cmd) -> Result<(), FrameworkError> {
let components = self.framework_components(command)?;
self.state.components.register(components)
}

/// Post-configuration lifecycle callback.
///
/// Called regardless of whether config is loaded to indicate this is the
/// time in app lifecycle when configuration would be loaded if
/// possible.
fn after_config(&mut self, config: Option<Self::Cfg>) -> Result<(), FrameworkError> {
// Provide configuration to all component `after_config()` handlers
for component in self.state.components.iter_mut() {
component.after_config(config.as_ref())?;
}

self.config = config;
Ok(())
}

/// Get logging configuration from command-line options
fn logging_config(&self, command: &KmsCommand) -> LoggingConfig {
if command.verbose() {
LoggingConfig::verbose()
Expand Down
5 changes: 2 additions & 3 deletions src/bin/tmkms/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
//! Main entry point for the `tmkms` executable

extern crate tmkms;
use tmkms::KmsApplication;
use tmkms::application::APPLICATION;

/// Boot the `tmkms` application
fn main() {
KmsApplication::boot();
abscissa::boot(&APPLICATION);
}
6 changes: 3 additions & 3 deletions src/chain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub use self::{
};
use crate::{
config::{chain::ChainConfig, KmsConfig},
error::KmsError,
error::Error,
keyring::{self, KeyRing},
};
use std::{path::PathBuf, sync::Mutex};
Expand All @@ -31,7 +31,7 @@ pub struct Chain {

impl Chain {
/// Attempt to create a `Chain` state from the given configuration
pub fn from_config(config: &ChainConfig) -> Result<Chain, KmsError> {
pub fn from_config(config: &ChainConfig) -> Result<Chain, Error> {
let state_file = match config.state_file {
Some(ref path) => path.to_owned(),
None => PathBuf::from(&format!("{}_priv_validator_state.json", config.id)),
Expand Down Expand Up @@ -62,7 +62,7 @@ impl Chain {
}

/// Initialize the chain registry from the configuration file
pub fn load_config(config: &KmsConfig) -> Result<(), KmsError> {
pub fn load_config(config: &KmsConfig) -> Result<(), Error> {
for config in &config.chain {
REGISTRY.register(Chain::from_config(config)?)?;
}
Expand Down
10 changes: 6 additions & 4 deletions src/chain/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

use super::{Chain, Guard, Id};
use crate::{
error::{KmsError, KmsErrorKind::*},
error::{Error, ErrorKind::*},
keyring,
};
use lazy_static::lazy_static;
use std::{collections::BTreeMap, sync::RwLock};

lazy_static! {
/// State of Tendermint blockchain networks
pub static ref REGISTRY: GlobalRegistry = GlobalRegistry::default();
}

Expand All @@ -21,7 +23,7 @@ impl Registry {
&mut self,
chain_id: &Id,
signer: keyring::ed25519::Signer,
) -> Result<(), KmsError> {
) -> Result<(), Error> {
// TODO(tarcieri):
let chain = self.0.get_mut(chain_id).ok_or_else(|| {
err!(
Expand All @@ -36,7 +38,7 @@ impl Registry {
}

/// Register a `Chain` with the registry
pub fn register_chain(&mut self, chain: Chain) -> Result<(), KmsError> {
pub fn register_chain(&mut self, chain: Chain) -> Result<(), Error> {
let chain_id = chain.id;

if self.0.insert(chain_id, chain).is_none() {
Expand Down Expand Up @@ -72,7 +74,7 @@ impl GlobalRegistry {
}

/// Register a chain with the registry
pub fn register(&self, chain: Chain) -> Result<(), KmsError> {
pub fn register(&self, chain: Chain) -> Result<(), Error> {
// TODO(tarcieri): better handle `PoisonError` here?
let mut registry = self.0.write().unwrap();
registry.register_chain(chain)
Expand Down
5 changes: 3 additions & 2 deletions src/chain/state/hook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

use crate::{
config::chain::HookConfig,
error::{KmsError, KmsErrorKind::HookError},
error::{Error, ErrorKind::HookError},
};
use serde::Deserialize;
use std::{process::Command, time::Duration};
use tendermint::block;
use wait_timeout::ChildExt;
Expand All @@ -16,7 +17,7 @@ const DEFAULT_TIMEOUT_SECS: u64 = 1;
pub const BLOCK_HEIGHT_SANITY_LIMIT: u64 = 9000;

/// Run the given hook command to obtain the last signing state
pub fn run(config: &HookConfig) -> Result<Output, KmsError> {
pub fn run(config: &HookConfig) -> Result<Output, Error> {
let mut child = Command::new(&config.cmd[0])
.args(&config.cmd[1..])
.spawn()?;
Expand Down
4 changes: 2 additions & 2 deletions src/chain/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ mod error;
pub mod hook;

pub use self::error::{StateError, StateErrorKind};
use crate::error::{KmsError, KmsErrorKind::*};
use crate::error::{Error, ErrorKind::*};
use atomicwrites::{AtomicFile, OverwriteBehavior};
use serde_json;
use std::{
Expand All @@ -25,7 +25,7 @@ pub struct State {

impl State {
/// Load the state from the given path
pub fn load_state<P>(path: P) -> Result<State, KmsError>
pub fn load_state<P>(path: P) -> Result<State, Error>
where
P: AsRef<Path>,
{
Expand Down
17 changes: 9 additions & 8 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

use crate::{
config::ValidatorConfig,
error::{KmsError, KmsErrorKind},
error::{Error, ErrorKind},
keyring::SecretKeyEncoding,
session::Session,
};
Expand Down Expand Up @@ -120,7 +120,7 @@ fn tcp_session(
port: u16,
secret_key_path: &Path,
should_term: &Arc<AtomicBool>,
) -> Result<(), KmsError> {
) -> Result<(), Error> {
let secret_key = load_secret_connection_key(secret_key_path)?;

let node_public_key =
Expand All @@ -145,7 +145,7 @@ fn tcp_session(

session.request_loop(should_term)
})
.unwrap_or_else(|ref e| Err(KmsError::from_panic(e)))
.unwrap_or_else(|ref e| Err(Error::from_panic(e)))
}

/// Create a validator session over a Unix domain socket
Expand All @@ -154,7 +154,7 @@ fn unix_session(
max_height: Option<tendermint::block::Height>,
socket_path: &Path,
should_term: &Arc<AtomicBool>,
) -> Result<(), KmsError> {
) -> Result<(), Error> {
panic::catch_unwind(move || {
let mut session = Session::connect_unix(chain_id, max_height, socket_path)?;

Expand All @@ -166,16 +166,16 @@ fn unix_session(

session.request_loop(should_term)
})
.unwrap_or_else(|ref e| Err(KmsError::from_panic(e)))
.unwrap_or_else(|ref e| Err(Error::from_panic(e)))
}

/// Initialize KMS secret connection private key
fn load_secret_connection_key(path: &Path) -> Result<ed25519::Seed, KmsError> {
fn load_secret_connection_key(path: &Path) -> Result<ed25519::Seed, Error> {
if path.exists() {
Ok(
ed25519::Seed::decode_from_file(path, &SecretKeyEncoding::default()).map_err(|e| {
err!(
KmsErrorKind::ConfigError,
ErrorKind::ConfigError,
"error loading SecretConnection key from {}: {}",
path.display(),
e
Expand All @@ -184,7 +184,8 @@ fn load_secret_connection_key(path: &Path) -> Result<ed25519::Seed, KmsError> {
)
} else {
let seed = ed25519::Seed::generate();
seed.encode_to_file(path, &SecretKeyEncoding::default())?;
seed.encode_to_file(path, &SecretKeyEncoding::default())
.map_err(|_| Error::from(ErrorKind::IoError))?;
Ok(seed)
}
}
16 changes: 12 additions & 4 deletions src/commands/help.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
//! The `help` subcommand

use abscissa::{Callable, Command};
use abscissa::{Command, Runnable};

use super::KmsCommand;

/// The `help` subcommand
#[derive(Debug, Default, Options)]
pub struct HelpCommand {
/// Arguments to the `help` command
#[options(free)]
pub args: Vec<String>,
}

impl Callable for HelpCommand {
impl Runnable for HelpCommand {
/// Print help message
fn call(&self) {
KmsCommand::print_usage(self.args.as_slice());
fn run(&self) {
KmsCommand::print_usage(
&self
.args
.as_slice()
.iter()
.map(|arg| arg.as_ref())
.collect::<Vec<_>>(),
);
}
}
Loading