Skip to content

Commit 6d55e48

Browse files
committed
fix: make adapter options enum and tryfrom channel to ethchannel
1 parent 8be6f50 commit 6d55e48

File tree

6 files changed

+109
-70
lines changed

6 files changed

+109
-70
lines changed

adapter/src/dummy.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use primitives::adapter::{Adapter, AdapterError, AdapterOptions, AdapterResult, Session};
22
use primitives::channel_validator::ChannelValidator;
33
use primitives::config::Config;
4-
use primitives::{Channel, ValidatorDesc};
4+
use primitives::Channel;
55
use std::collections::HashMap;
66

77
#[derive(Debug, Clone)]
@@ -22,17 +22,18 @@ impl Adapter for DummyAdapter {
2222
type Output = DummyAdapter;
2323

2424
fn init(opts: AdapterOptions, config: &Config) -> AdapterResult<DummyAdapter> {
25-
let (identity, authorization_tokens, session_tokens) =
26-
match (opts.dummy_identity, opts.dummy_auth, opts.dummy_auth_tokens) {
27-
(Some(identity), Some(authorization_tokens), Some(session_tokens)) => {
28-
(identity, authorization_tokens, session_tokens)
29-
}
30-
(_, _, _) => {
31-
return Err(AdapterError::Configuration(
32-
"dummy_identity, dummy_auth, dummy_auth_tokens required".to_string(),
33-
))
34-
}
35-
};
25+
let (identity, authorization_tokens, session_tokens) = match opts {
26+
AdapterOptions::DummAdapter {
27+
dummy_identity,
28+
dummy_auth,
29+
dummy_auth_tokens,
30+
} => (dummy_identity, dummy_auth, dummy_auth_tokens),
31+
_ => {
32+
return Err(AdapterError::Configuration(
33+
"dummy_identity, dummy_auth, dummy_auth_tokens required".to_string(),
34+
))
35+
}
36+
};
3637

3738
Ok(Self {
3839
identity,

adapter/src/ethereum.rs

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ use primitives::{
77
adapter::{Adapter, AdapterError, AdapterOptions, AdapterResult, Session},
88
channel_validator::ChannelValidator,
99
config::Config,
10-
Channel, ValidatorDesc,
10+
Channel,
1111
};
1212
use serde::{Deserialize, Serialize};
1313
use serde_json::Value;
1414
use std::collections::HashMap;
15+
use std::convert::TryFrom;
1516
use std::error::Error;
1617
use std::fs;
1718
use tiny_keccak::Keccak;
@@ -52,9 +53,11 @@ impl Adapter for EthereumAdapter {
5253
type Output = EthereumAdapter;
5354

5455
fn init(opts: AdapterOptions, config: &Config) -> AdapterResult<EthereumAdapter> {
55-
let (keystore_file, keystore_pwd) = match (opts.keystore_file, opts.keystore_pwd) {
56-
(Some(file), Some(pwd)) => (file, pwd),
57-
(_, _) => {
56+
let (keystore_file, keystore_pwd) = match opts {
57+
AdapterOptions::EthereumAdapter(keystore_opts) => {
58+
(keystore_opts.keystore_file, keystore_opts.keystore_pwd)
59+
}
60+
_ => {
5861
return Err(AdapterError::Configuration(
5962
"Missing keystore json file or password".to_string(),
6063
))
@@ -139,7 +142,19 @@ impl Adapter for EthereumAdapter {
139142
}
140143

141144
fn validate_channel(&self, channel: &Channel) -> AdapterResult<bool> {
142-
let eth_channel: EthereumChannel = channel.into();
145+
if check_validator_id_checksum(channel) {
146+
return Err(AdapterError::Configuration(
147+
"channel.validators: all addresses are checksummed".to_string(),
148+
));
149+
}
150+
// check if channel is valid
151+
if let Err(e) = EthereumAdapter::is_channel_valid(&self.config, channel) {
152+
return Err(AdapterError::InvalidChannel(e.to_string()));
153+
}
154+
155+
let eth_channel = EthereumChannel::try_from(channel)
156+
.map_err(|e| AdapterError::InvalidChannel(e.to_string()))?;
157+
143158
let channel_id = eth_channel
144159
.hash_hex(&self.config.ethereum_core_address)
145160
.map_err(|_| map_error("Failed to hash the channel id"))?;
@@ -150,15 +165,6 @@ impl Adapter for EthereumAdapter {
150165
));
151166
}
152167

153-
if check_validator_id_checksum(channel) {
154-
return Err(AdapterError::Configuration(
155-
"channel.validators: all addresses are checksummed".to_string(),
156-
));
157-
}
158-
// check if channel is valid
159-
if let Err(error) = EthereumAdapter::is_channel_valid(&self.config, channel) {
160-
return Err(AdapterError::InvalidChannel(error.to_string()));
161-
}
162168
// query the blockchain for the channel status
163169
let contract_address = Address::from_slice(self.config.ethereum_core_address.as_bytes());
164170
let contract = get_contract(&self.config, contract_address, &ADEXCORE_ABI)
@@ -399,17 +405,16 @@ pub fn ewt_verify(
399405
#[cfg(test)]
400406
mod test {
401407
use super::*;
408+
use primitives::adapter::KeystoreOptions;
402409
use primitives::config::configuration;
403410

404411
fn setup_eth_adapter() -> EthereumAdapter {
405412
let config = configuration("development", None).expect("failed parse config");
406-
let adapter_options = AdapterOptions {
407-
keystore_file: Some("./test/resources/keystore.json".to_string()),
408-
keystore_pwd: Some("adexvalidator".to_string()),
409-
dummy_identity: None,
410-
dummy_auth: None,
411-
dummy_auth_tokens: None,
413+
let keystore_options = KeystoreOptions {
414+
keystore_file: "./test/resources/keystore.json".to_string(),
415+
keystore_pwd: "adexvalidator".to_string(),
412416
};
417+
let adapter_options = AdapterOptions::EthereumAdapter(keystore_options);
413418

414419
EthereumAdapter::init(adapter_options, &config).expect("should init ethereum adapter")
415420
}

adapter/src/lib.rs

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ use chrono::{DateTime, Utc};
44
use ethabi::encode;
55
use ethabi::param_type::ParamType;
66
use ethabi::token::{LenientTokenizer, StrictTokenizer, Tokenizer};
7+
use primitives::channel::ChannelError;
78
use primitives::BigNum;
89
use primitives::Channel;
910
use sha2::{Digest, Sha256};
10-
use std::convert::From;
11+
use std::convert::TryFrom;
1112
use tiny_keccak::Keccak;
1213

1314
pub use self::dummy::DummyAdapter;
@@ -66,9 +67,12 @@ pub struct EthereumChannel {
6667
pub spec: String,
6768
}
6869

69-
impl From<&Channel> for EthereumChannel {
70-
fn from(channel: &Channel) -> Self {
71-
let spec = serde_json::to_string(&channel.spec).expect("Failed to serialize channel spec");
70+
impl TryFrom<&Channel> for EthereumChannel {
71+
type Error = ChannelError;
72+
73+
fn try_from(channel: &Channel) -> Result<Self, Self::Error> {
74+
let spec = serde_json::to_string(&channel.spec)
75+
.map_err(|e| ChannelError::InvalidArgument(e.to_string()))?;
7276

7377
let mut hash = Sha256::new();
7478
hash.input(spec);
@@ -101,16 +105,44 @@ impl EthereumChannel {
101105
valid_until: DateTime<Utc>,
102106
validators: Vec<String>,
103107
spec: &str,
104-
) -> Self {
105-
// @TODO some validation
106-
Self {
108+
) -> Result<Self, ChannelError> {
109+
// check creator addres
110+
if creator != eth_checksum::checksum(creator) {
111+
return Err(ChannelError::InvalidArgument(
112+
"Invalid creator address".into(),
113+
));
114+
}
115+
116+
if token_addr != eth_checksum::checksum(token_addr) {
117+
return Err(ChannelError::InvalidArgument(
118+
"invalid token addresss".into(),
119+
));
120+
}
121+
122+
if let Err(_) = BigNum::try_from(token_amount) {
123+
return Err(ChannelError::InvalidArgument("invalid token amount".into()));
124+
}
125+
126+
if spec.len() != 32 {
127+
return Err(ChannelError::InvalidArgument(
128+
"32 len string expected".into(),
129+
));
130+
}
131+
132+
if validators.iter().any(|v| *v != eth_checksum::checksum(v)) {
133+
return Err(ChannelError::InvalidArgument(
134+
"invalid validator address: must start with a 0x and be 42 characters long".into(),
135+
));
136+
}
137+
138+
Ok(Self {
107139
creator: creator.to_owned(),
108140
token_addr: token_addr.to_owned(),
109141
token_amount: token_amount.to_owned(),
110142
valid_until: valid_until.timestamp(),
111143
validators: format!("[{}]", validators.join(",")),
112144
spec: spec.to_owned(),
113-
}
145+
})
114146
}
115147

116148
pub fn hash(&self, contract_addr: &str) -> Result<[u8; 32], Box<dyn Error>> {

primitives/src/adapter.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,19 @@ impl fmt::Display for AdapterError {
3434
}
3535

3636
#[derive(Debug, Clone)]
37-
pub struct AdapterOptions {
38-
pub dummy_identity: Option<String>,
39-
pub dummy_auth: Option<HashMap<String, String>>,
40-
pub dummy_auth_tokens: Option<HashMap<String, String>>,
41-
pub keystore_file: Option<String>,
42-
pub keystore_pwd: Option<String>,
37+
pub enum AdapterOptions {
38+
DummAdapter {
39+
dummy_identity: String,
40+
dummy_auth: HashMap<String, String>,
41+
dummy_auth_tokens: HashMap<String, String>,
42+
},
43+
EthereumAdapter(KeystoreOptions),
44+
}
45+
46+
#[derive(Debug, Clone)]
47+
pub struct KeystoreOptions {
48+
pub keystore_file: String,
49+
pub keystore_pwd: String,
4350
}
4451

4552
#[derive(Debug, Clone)]

validator_worker/src/lib.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,10 @@ mod test {
5656
use std::sync::{Arc, RwLock};
5757

5858
fn setup_iface(channel: &Channel) -> SentryApi<DummyAdapter> {
59-
let adapter_options = AdapterOptions {
60-
dummy_identity: Some(IDS["leader"].clone()),
61-
dummy_auth: Some(IDS.clone()),
62-
dummy_auth_tokens: Some(AUTH.clone()),
63-
keystore_file: None,
64-
keystore_pwd: None,
59+
let adapter_options = AdapterOptions::DummAdapter {
60+
dummy_identity: IDS["leader"].clone(),
61+
dummy_auth: IDS.clone(),
62+
dummy_auth_tokens: AUTH.clone(),
6563
};
6664
let config = configuration("development", None).expect("Dev config should be available");
6765
let dummy_adapter = DummyAdapter::init(adapter_options, &config).expect("init adadpter");

validator_worker/src/main.rs

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
use clap::{App, Arg};
66

77
use adapter::{AdapterTypes, DummyAdapter, EthereumAdapter};
8-
use primitives::adapter::{Adapter, AdapterOptions};
8+
use primitives::adapter::{Adapter, AdapterOptions, KeystoreOptions};
99
use primitives::config::{configuration, Config};
10+
use primitives::util::tests::prep_db::{AUTH, IDS};
1011

1112
fn main() {
1213
let cli = App::new("Validator worker")
@@ -60,30 +61,25 @@ fn main() {
6061

6162
let adapter = match cli.value_of("adapter").unwrap() {
6263
"ethereum" => {
63-
let keystore_file = cli.value_of("keystoreFile").unwrap();
64-
let keystore_pwd = std::env::var("KEYSTORE_PWD").unwrap();
65-
66-
let options = AdapterOptions {
67-
keystore_file: Some(keystore_file.to_string()),
68-
keystore_pwd: Some(keystore_pwd),
69-
dummy_identity: None,
70-
dummy_auth: None,
71-
dummy_auth_tokens: None,
64+
let keystore_file = cli
65+
.value_of("keystoreFile")
66+
.expect("unable to get keystore file");
67+
let keystore_pwd = std::env::var("KEYSTORE_PWD").expect("unable to get keystore pwd");
68+
let keystore_options = KeystoreOptions {
69+
keystore_file: keystore_file.to_string(),
70+
keystore_pwd,
7271
};
72+
let options = AdapterOptions::EthereumAdapter(keystore_options);
7373
AdapterTypes::EthereumAdapter(Box::new(
7474
EthereumAdapter::init(options, &config).expect("failed to init adapter"),
7575
))
7676
}
7777
"dummy" => {
7878
let dummy_identity = cli.value_of("dummyIdentity").unwrap();
79-
let options = AdapterOptions {
80-
dummy_identity: Some(dummy_identity.to_string()),
81-
// this should be prefilled using fixtures
82-
//
83-
dummy_auth: None,
84-
dummy_auth_tokens: None,
85-
keystore_file: None,
86-
keystore_pwd: None,
79+
let options = AdapterOptions::DummAdapter {
80+
dummy_identity: dummy_identity.to_string(),
81+
dummy_auth: IDS.clone(),
82+
dummy_auth_tokens: AUTH.clone(),
8783
};
8884
AdapterTypes::DummyAdapter(Box::new(
8985
DummyAdapter::init(options, &config).expect("failed to init adapter"),

0 commit comments

Comments
 (0)