diff --git a/Cargo.toml b/Cargo.toml index 36cd096..9e58475 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,36 +1,56 @@ [package] name = "cryptoscript" +description = "cryptoscript is a small language for pre-signing" version = "0.1.0" edition = "2018" -[[bin]] -name = "cryptoscript" -path = "src/main.rs" - -[[bin]] -name = "rest-api" -path = "src/rest_api.rs" +[lib] +crate-type = ["lib", "cdylib"] +path = "src/lib.rs" [dependencies] -actix-web = { version = "4.0.1", default-features = false, features = ["macros"] } - -clap = { version = "3.1.6", features = ["derive"] } enumset = { version = "1.0.8", features = ["serde"] } -futures = { version = "0.3.21", features = ["executor", "thread-pool"] } generic-array = "0.14" hex = "0.4" -hex-literal = "0.3" indexmap = "1.5" -k256 = { version = "0.10.2", features = ["std", "ecdsa", "serde"] } nom = "7.1.1" -quickcheck = "1.0.3" -quickcheck_macros = "1.0.0" reqwest = { version = "0.11.10", features = ["json"] } serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0.79", features = ["arbitrary_precision", "preserve_order"] } sha2 = "0.9" -sha3 = "0.9" -tokio = { version = "1.17.0", features = ["macros", "rt-multi-thread"] } -tokio-stream = "0.1.8" thiserror = "1.0" typenum = "1.15.0" + +actix-web = { version = "4.0.1", default-features = false, features = ["macros"], optional = true } +clap = { version = "3.1.6", features = ["derive"], optional = true } +tokio = { version = "1.17.0", features = ["macros", "rt-multi-thread"], optional = true } +tokio-stream = { version = "0.1.8", optional = true } +wasm-bindgen = { version = "0.2", features = ["serde-serialize"], optional = true } + +[dev-dependencies] +hex-literal = "0.3" +quickcheck = "1.0.3" +sha3 = "0.9" + +[features] +build-bin = [ + "actix-web", + "clap", + "tokio", + "tokio-stream", + ] +build-wasm = [ + "wasm-bindgen", + ] +default = ["build-bin"] + +[[bin]] +name = "cryptoscript" +path = "src/main.rs" +required-features = ["build-bin"] + +[[bin]] +name = "rest-api" +path = "src/rest_api.rs" +required-features = ["build-bin"] + diff --git a/README.md b/README.md index 94e9f82..f03235d 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,26 @@ There are two demos: - Etherscan: this demo requires a free Etherscan API key, which you can get [here](https://docs.etherscan.io/getting-started/viewing-api-usage-statistics) +### Building + +To build the `rest-api`: + +```bash +cargo b --bin rest-api --features build-bin +``` + +To build the cryptoscript interpreter: + +```bash +cargo b --bin cryptoscript --features build-bin +``` + +Building for the WASM target: + +```bash +wasm-pack build --target web --no-default-features --features build-wasm +``` + ### Local Demo The local demo requires running a tiny test server, which can be started with the following command: diff --git a/src/arbitrary.rs b/src/arbitrary.rs index b29e20b..2ba4237 100644 --- a/src/arbitrary.rs +++ b/src/arbitrary.rs @@ -1,107 +1,112 @@ -use serde::{Deserialize, Serialize}; -use serde_json::{Map, Number, Value}; -use quickcheck::{empty_shrinker, Arbitrary, Gen}; -/// Wrapped Number for Arbitrary generation -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct ArbitraryNumber { - /// Wrapped Number - pub number: Number, -} +#[cfg(test)] +pub mod test_arbitrary_defs { + use serde::{Deserialize, Serialize}; + use serde_json::{Map, Number, Value}; + use quickcheck::{empty_shrinker, Arbitrary, Gen}; -impl Arbitrary for ArbitraryNumber { - fn arbitrary(g: &mut Gen) -> Self { - if Arbitrary::arbitrary(g) { - if Arbitrary::arbitrary(g) { - let x: u64 = Arbitrary::arbitrary(g); - ArbitraryNumber { number: - From::from(x) - } - } else { - let x: i64 = Arbitrary::arbitrary(g); - ArbitraryNumber { number: - From::from(x) - } - } - } else { - let x: f64 = Arbitrary::arbitrary(g); - ArbitraryNumber { number: - Number::from_f64(x) - .unwrap_or_else(|| From::from(0u8)) - } - } - } + /// Wrapped Number for Arbitrary generation + #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] + pub struct ArbitraryNumber { + /// Wrapped Number + pub number: Number, + } - fn shrink(&self) -> Box> { - match self.number.as_f64() { - None => match self.number.as_u64() { - None => match self.number.as_i64() { - None => empty_shrinker(), - Some(self_i64) => Box::new( - self_i64.shrink() - .map(|x| ArbitraryNumber { - number: From::from(x), - })), - }, - Some(self_u64) => Box::new( - self_u64.shrink() - .map(|x| ArbitraryNumber { - number: From::from(x), - })), - }, - Some(self_f64) => Box::new( - self_f64.shrink() - .map(|x| ArbitraryNumber { - number: Number::from_f64(x) - .unwrap_or_else(|| From::from(0u8)), - })), - } - } -} + impl Arbitrary for ArbitraryNumber { + fn arbitrary(g: &mut Gen) -> Self { + if Arbitrary::arbitrary(g) { + if Arbitrary::arbitrary(g) { + let x: u64 = Arbitrary::arbitrary(g); + ArbitraryNumber { number: + From::from(x) + } + } else { + let x: i64 = Arbitrary::arbitrary(g); + ArbitraryNumber { number: + From::from(x) + } + } + } else { + let x: f64 = Arbitrary::arbitrary(g); + ArbitraryNumber { number: + Number::from_f64(x) + .unwrap_or_else(|| From::from(0u8)) + } + } + } + fn shrink(&self) -> Box> { + match self.number.as_f64() { + None => match self.number.as_u64() { + None => match self.number.as_i64() { + None => empty_shrinker(), + Some(self_i64) => Box::new( + self_i64.shrink() + .map(|x| ArbitraryNumber { + number: From::from(x), + })), + }, + Some(self_u64) => Box::new( + self_u64.shrink() + .map(|x| ArbitraryNumber { + number: From::from(x), + })), + }, + Some(self_f64) => Box::new( + self_f64.shrink() + .map(|x| ArbitraryNumber { + number: Number::from_f64(x) + .unwrap_or_else(|| From::from(0u8)), + })), + } + } + } -/// Wrapped Map, encoded as a Vec of (key, value) pairs, for Arbitrary generation -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct ArbitraryMap { - /// Map encoded as a Vec of (key, value) pairs - pub map: Vec<(String, Value)>, -} -impl From for Map { - fn from(x: ArbitraryMap) -> Self { - x.map.into_iter().collect() - } -} + /// Wrapped Map, encoded as a Vec of (key, value) pairs, for Arbitrary generation + #[derive(Clone, Debug, PartialEq, Eq)] + pub struct ArbitraryMap { + /// Map encoded as a Vec of (key, value) pairs + pub map: Vec<(String, Value)>, + } -impl Arbitrary for ArbitraryMap { - fn arbitrary(g: &mut Gen) -> Self { - let map_vec: Vec<(String, ArbitraryValue)> = Arbitrary::arbitrary(g); - ArbitraryMap { - map: map_vec.into_iter().map(|x| (x.0, x.1.value)).collect(), - } - } + impl From for Map { + fn from(x: ArbitraryMap) -> Self { + x.map.into_iter().collect() + } + } - fn shrink(&self) -> Box> { - empty_shrinker() - } -} + impl Arbitrary for ArbitraryMap { + fn arbitrary(g: &mut Gen) -> Self { + let map_vec: Vec<(String, ArbitraryValue)> = Arbitrary::arbitrary(g); + ArbitraryMap { + map: map_vec.into_iter().map(|x| (x.0, x.1.value)).collect(), + } + } + fn shrink(&self) -> Box> { + empty_shrinker() + } + } -/// Wrapped Value for Arbitrary generation -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct ArbitraryValue { - /// Wrapped Value - pub value: Value, -} -impl Arbitrary for ArbitraryValue { - fn arbitrary(_g: &mut Gen) -> Self { - ArbitraryValue { - value: Value::Null, - } - } + /// Wrapped Value for Arbitrary generation + #[derive(Clone, Debug, PartialEq, Eq)] + pub struct ArbitraryValue { + /// Wrapped Value + pub value: Value, + } - fn shrink(&self) -> Box> { - empty_shrinker() - } + impl Arbitrary for ArbitraryValue { + fn arbitrary(_g: &mut Gen) -> Self { + ArbitraryValue { + value: Value::Null, + } + } + + fn shrink(&self) -> Box> { + empty_shrinker() + } + } } + diff --git a/src/elem.rs b/src/elem.rs index 07f1773..296d84d 100644 --- a/src/elem.rs +++ b/src/elem.rs @@ -1,12 +1,15 @@ -use crate::arbitrary::{ArbitraryNumber, ArbitraryMap, ArbitraryValue}; +#[cfg(test)] +use crate::arbitrary::test_arbitrary_defs::{ArbitraryNumber, ArbitraryMap, ArbitraryValue}; +#[cfg(test)] +use quickcheck::{empty_shrinker, Arbitrary, Gen}; +#[cfg(test)] +use enumset::EnumSet; use std::cmp; use std::fmt; use std::fmt::{Debug, Display, Formatter}; -use std::iter::IntoIterator; -use enumset::{EnumSet, EnumSetType}; -use quickcheck::{empty_shrinker, Arbitrary, Gen}; +use enumset::EnumSetType; use serde::{Deserialize, Serialize}; use serde_json::{Map, Number, Value}; @@ -109,6 +112,7 @@ pub enum ElemSymbol { Json, } +#[cfg(test)] impl Arbitrary for ElemSymbol { fn arbitrary(g: &mut Gen) -> Self { let choices: Vec = EnumSet::all().iter().collect(); @@ -121,6 +125,7 @@ impl Arbitrary for ElemSymbol { } } +#[cfg(test)] impl ElemSymbol { /// Given a Gen, use this ElemSymbol as a template of an Elem, and fill it /// with Arbitrary contents. @@ -152,6 +157,7 @@ impl ElemSymbol { } } +#[cfg(test)] impl Arbitrary for Elem { fn arbitrary(g: &mut Gen) -> Self { let symbol: ElemSymbol = Arbitrary::arbitrary(g); diff --git a/src/lib.rs b/src/lib.rs index e5822b6..1b7914c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,8 +12,12 @@ mod restack; pub use restack::{Restack, StackIx}; + mod arbitrary; -pub use arbitrary::{ArbitraryNumber, ArbitraryMap, ArbitraryValue}; +#[cfg(test)] +pub use arbitrary::test_arbitrary_defs; +#[cfg(test)] +pub use arbitrary::test_arbitrary_defs::{ArbitraryNumber, ArbitraryMap, ArbitraryValue}; mod elem; pub use elem::{Elem, ElemSymbol}; mod elem_type; @@ -86,9 +90,14 @@ pub use parse_utils::{parse_string, whitespace_delimited}; mod parse_nom; pub use parse_nom::{parse_nom, SourceCode, SourceBlock, Comment, Var, Assignment, App, Expr, TypeAnnotation, InstructionsWriter}; +#[cfg(feature = "build-bin")] mod rest_api; +#[cfg(feature = "build-bin")] pub use rest_api::Api; + +#[cfg(feature = "build-bin")] mod cli; +#[cfg(feature = "build-bin")] pub use cli::Cli; use sha2::{Digest, Sha256}; diff --git a/src/query.rs b/src/query.rs index c0fa33a..5201b62 100644 --- a/src/query.rs +++ b/src/query.rs @@ -8,7 +8,6 @@ use reqwest::Client; use serde::{Deserialize, Serialize}; use serde_json::{Map, Value}; use thiserror::Error; -use tokio_stream::{self as stream, StreamExt}; /// HTTP request type #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -106,9 +105,9 @@ impl QueryTemplate { } /// Convert to a Query with the given variables, cache_location, resp. - pub fn to_query(self, variables: Arc>, cache_location: Arc) -> Query { + pub fn to_query(&self, variables: Arc>, cache_location: Arc) -> Query { Query { - query_template: self, + query_template: self.clone(), variables, cache_location, } @@ -241,10 +240,13 @@ impl QueryTemplates { /// Run a list of QueryTemplate's, in series, and collect their results pub async fn run(self, variables: Arc>, cache_location: Arc) -> Result>, QueryError> { let mut result = Vec::with_capacity(self.queries.len()); - let mut stream = stream::iter(self.queries); - while let Some(query_template) = stream.next().await { + let mut stream = self.queries.iter(); + while let Some(query_template) = stream.next() { let query_json = query_template.to_json()?; - let query_result = query_template.to_query(variables.clone(), cache_location.clone()).run().await?; + let query_result = query_template + .to_query(variables.clone(), cache_location.clone()) + .run() + .await?; let mut query_result_json = Map::new(); query_result_json.insert("query".to_string(), query_json); query_result_json.insert("result".to_string(), query_result);