Skip to content

Commit b7bb224

Browse files
committed
Primitives Adapter errors & Ethereum Adapter errors
1 parent 73971a7 commit b7bb224

File tree

2 files changed

+120
-81
lines changed

2 files changed

+120
-81
lines changed

adapter/src/ethereum.rs

Lines changed: 119 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ lazy_static! {
3636
static ref ADEXCORE_ABI: &'static [u8] =
3737
include_bytes!("../../lib/protocol-eth/abi/AdExCore.json");
3838
static ref CHANNEL_STATE_ACTIVE: U256 = 1.into();
39-
static ref PRIVILEGE_LEVEL_NONE: u8 = 0;
4039
}
4140

4241
#[derive(Debug, Clone)]
@@ -57,19 +56,18 @@ impl ChannelValidator for EthereumAdapter {}
5756

5857
impl EthereumAdapter {
5958
pub fn init(opts: KeystoreOptions, config: &Config) -> AdapterResult<EthereumAdapter, Error> {
60-
let keystore_contents = fs::read_to_string(&opts.keystore_file)
61-
.map_err(|err| Error::Keystore(KeystoreError::ReadingFile(err)))?;
59+
let keystore_contents =
60+
fs::read_to_string(&opts.keystore_file).map_err(KeystoreError::ReadingFile)?;
6261

63-
let keystore_json: Value = serde_json::from_str(&keystore_contents)
64-
.map_err(|err| Error::Keystore(KeystoreError::Deserialization(err)))?;
62+
let keystore_json: Value =
63+
serde_json::from_str(&keystore_contents).map_err(KeystoreError::Deserialization)?;
6564

6665
let address = keystore_json["address"]
6766
.as_str()
6867
.map(eth_checksum::checksum)
69-
.ok_or_else(|| Error::Keystore(KeystoreError::AddressMissing))?;
68+
.ok_or_else(|| KeystoreError::AddressMissing)?;
7069

71-
let address = ValidatorId::try_from(&address)
72-
.map_err(|err| Error::Keystore(KeystoreError::AddressInvalid(err)))?;
70+
let address = ValidatorId::try_from(&address).map_err(KeystoreError::AddressInvalid)?;
7371

7472
let (eloop, transport) =
7573
web3::transports::Http::new(&config.ethereum_network).map_err(Error::Web3)?;
@@ -97,7 +95,7 @@ impl Adapter for EthereumAdapter {
9795
fn unlock(&mut self) -> AdapterResult<(), Self::AdapterError> {
9896
let account = SafeAccount::from_file(
9997
serde_json::from_value(self.keystore_json.clone())
100-
.map_err(|err| Error::Keystore(KeystoreError::Deserialization(err)))?,
98+
.map_err(KeystoreError::Deserialization)?,
10199
None,
102100
&Some(self.keystore_pwd.clone()),
103101
)
@@ -114,12 +112,12 @@ impl Adapter for EthereumAdapter {
114112

115113
fn sign(&self, state_root: &str) -> AdapterResult<String, Self::AdapterError> {
116114
if let Some(wallet) = &self.wallet {
117-
let state_root = hex::decode(state_root)
118-
.map_err(|_| AdapterError::Signature("invalid state_root".to_string()))?;
115+
let state_root =
116+
hex::decode(state_root).map_err(StateRootError::StateRootHexDecoding)?;
119117
let message = Message::from_slice(&hash_message(&state_root));
120118
let wallet_sign = wallet
121119
.sign(&self.keystore_pwd, &message)
122-
.map_err(|err| Error::SignMessage(EwtSigningError::SigningMessage(err)))?;
120+
.map_err(EwtSigningError::SigningMessage)?;
123121
let signature: Signature = wallet_sign.into_electrum().into();
124122

125123
Ok(format!("0x{}", signature))
@@ -135,17 +133,19 @@ impl Adapter for EthereumAdapter {
135133
sig: &str,
136134
) -> AdapterResult<bool, Self::AdapterError> {
137135
if !sig.starts_with("0x") {
138-
return Err(AdapterError::Signature("not 0x prefixed hex".to_string()));
136+
return Err(StateRootError::SignatureNotPrefixed.into());
139137
}
140-
let decoded_signature = hex::decode(&sig[2..])
141-
.map_err(|_| AdapterError::Signature("invalid signature".to_string()))?;
138+
let decoded_signature =
139+
hex::decode(&sig[2..]).map_err(StateRootError::SignatureHexDecoding)?;
142140
let address = Address::from_slice(signer.inner());
143141
let signature = Signature::from_electrum(&decoded_signature);
144-
let state_root = hex::decode(state_root)
145-
.map_err(|_| AdapterError::Signature("invalid state_root".to_string()))?;
142+
let state_root = hex::decode(state_root).map_err(StateRootError::StateRootHexDecoding)?;
146143
let message = Message::from_slice(&hash_message(&state_root));
147144

148-
verify_address(&address, &signature, &message).or_else(|_| Ok(false))
145+
let verify_address = verify_address(&address, &signature, &message)
146+
.map_err(StateRootError::PublicKeyRecovery)?;
147+
148+
Ok(verify_address)
149149
}
150150

151151
fn validate_channel<'a>(
@@ -173,19 +173,19 @@ impl Adapter for EthereumAdapter {
173173
let contract_address: Address = self.config.ethereum_core_address.into();
174174

175175
let contract = Contract::from_json(self.web3.eth(), contract_address, &ADEXCORE_ABI)
176-
.map_err(|_| map_error("failed to init core contract"))?;
176+
.map_err(Error::ContractInitialization)?;
177177

178178
let channel_status: U256 = contract
179179
.query(
180180
"states",
181-
(Token::FixedBytes(channel.id.as_ref().to_vec()),),
181+
Token::FixedBytes(channel.id.as_ref().to_vec()),
182182
None,
183183
Options::default(),
184184
None,
185185
)
186186
.compat()
187187
.await
188-
.map_err(|_| map_error("contract channel status query failed"))?;
188+
.map_err(Error::ContractQuerying)?;
189189

190190
if channel_status != *CHANNEL_STATE_ACTIVE {
191191
Err(AdapterError::Adapter(Error::ChannelInactive(channel.id)))
@@ -204,7 +204,9 @@ impl Adapter for EthereumAdapter {
204204
) -> BoxFuture<'a, AdapterResult<Session, Self::AdapterError>> {
205205
async move {
206206
if token.len() < 16 {
207-
return Err(AdapterError::Failed("invalid token id".to_string()));
207+
return Err(AdapterError::Authentication(
208+
"Invalid token id length".to_string(),
209+
));
208210
}
209211

210212
let parts: Vec<&str> = token.split('.').collect();
@@ -214,18 +216,18 @@ impl Adapter for EthereumAdapter {
214216
(header_encoded, payload_encoded, token_encoded)
215217
}
216218
_ => {
217-
return Err(AdapterError::Failed(format!(
219+
return Err(AdapterError::Authentication(format!(
218220
"{} token string is incorrect",
219221
token
220222
)))
221223
}
222224
};
223225

224226
let verified = ewt_verify(header_encoded, payload_encoded, token_encoded)
225-
.map_err(|err| AdapterError::Adapter(Error::VerifyMessage(err)))?;
227+
.map_err(Error::VerifyMessage)?;
226228

227229
if self.whoami().to_checksum() != verified.payload.id {
228-
return Err(AdapterError::Configuration(
230+
return Err(AdapterError::Authentication(
229231
"token payload.id !== whoami(): token was not intended for us".to_string(),
230232
));
231233
}
@@ -338,10 +340,6 @@ fn hash_message(message: &[u8]) -> [u8; 32] {
338340
res
339341
}
340342

341-
fn map_error(err: &str) -> AdapterError<Error> {
342-
AdapterError::Failed(err.to_string())
343-
}
344-
345343
// Ethereum Web Tokens
346344
#[derive(Clone, Debug, Serialize, Deserialize)]
347345
pub struct Payload {
@@ -434,49 +432,10 @@ pub fn ewt_verify(
434432
}
435433

436434
mod error {
437-
use primitives::adapter::AdapterErrorKind;
435+
use primitives::adapter::{AdapterErrorKind, Error as AdapterError};
438436
use primitives::ChannelId;
439437
use std::fmt;
440438

441-
#[derive(Debug)]
442-
pub enum KeystoreError {
443-
/// `address` key is missing from the keystore file
444-
AddressMissing,
445-
/// The `address` key in the keystore file is not a valid `ValidatorId`
446-
AddressInvalid(primitives::DomainError),
447-
/// reading the keystore file failed
448-
ReadingFile(std::io::Error),
449-
/// Deserializing the keystore file failed
450-
Deserialization(serde_json::Error),
451-
}
452-
453-
impl std::error::Error for KeystoreError {
454-
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
455-
use KeystoreError::*;
456-
match self {
457-
AddressMissing => None,
458-
AddressInvalid(err) => Some(err),
459-
ReadingFile(err) => Some(err),
460-
Deserialization(err) => Some(err),
461-
}
462-
}
463-
}
464-
465-
impl fmt::Display for KeystoreError {
466-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
467-
use KeystoreError::*;
468-
469-
match self {
470-
AddressMissing => write!(f, "\"address\" key missing in keystore file"),
471-
AddressInvalid(err) => write!(f, "\"address\" is invalid: {}", err),
472-
ReadingFile(err) => write!(f, "Reading the keystore file failed: {}", err),
473-
Deserialization(err) => {
474-
write!(f, "Deserializing the keystore file failed: {}", err)
475-
}
476-
}
477-
}
478-
}
479-
480439
#[derive(Debug)]
481440
pub enum Error {
482441
Keystore(KeystoreError),
@@ -493,6 +452,9 @@ mod error {
493452
/// Signing of the message failed
494453
SignMessage(EwtSigningError),
495454
VerifyMessage(EwtVerifyError),
455+
ContractInitialization(ethabi::Error),
456+
ContractQuerying(web3::contract::Error),
457+
StateRoot(StateRootError),
496458
}
497459

498460
impl std::error::Error for Error {}
@@ -512,10 +474,89 @@ mod error {
512474
ChannelInactive(channel_id) => write!(f, "Channel ({}) is not Active on the ethereum network", channel_id),
513475
SignMessage(err) => write!(f, "Signing message - {}", err),
514476
VerifyMessage(err) => write!(f, "Verifying message - {}", err),
477+
ContractInitialization(err) => write!(f, "Contract initialization - {}", err),
478+
ContractQuerying(err) => write!(f, "Contract querying - {}", err),
479+
StateRoot(err) => write!(f, "State root - {}", err)
480+
}
481+
}
482+
}
483+
484+
#[derive(Debug)]
485+
pub enum StateRootError {
486+
PublicKeyRecovery(parity_crypto::publickey::Error),
487+
StateRootHexDecoding(hex::FromHexError),
488+
SignatureHexDecoding(hex::FromHexError),
489+
SignatureNotPrefixed,
490+
}
491+
492+
impl fmt::Display for StateRootError {
493+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
494+
use StateRootError::*;
495+
496+
match self {
497+
PublicKeyRecovery(err) => {
498+
write!(f, "Recovering the public key from the signature - {}", err)
499+
}
500+
StateRootHexDecoding(err) => {
501+
write!(f, "Decoding the hex of the state root - {}", err)
502+
}
503+
SignatureHexDecoding(err) => {
504+
write!(f, "Decoding the hex of the signature - {}", err)
505+
}
506+
SignatureNotPrefixed => write!(f, "Signature is not prefixed with `0x`"),
515507
}
516508
}
517509
}
518510

511+
impl From<StateRootError> for AdapterError<Error> {
512+
fn from(err: StateRootError) -> Self {
513+
AdapterError::Adapter(Error::StateRoot(err))
514+
}
515+
}
516+
517+
#[derive(Debug)]
518+
pub enum KeystoreError {
519+
/// `address` key is missing from the keystore file
520+
AddressMissing,
521+
/// The `address` key in the keystore file is not a valid `ValidatorId`
522+
AddressInvalid(primitives::DomainError),
523+
/// reading the keystore file failed
524+
ReadingFile(std::io::Error),
525+
/// Deserializing the keystore file failed
526+
Deserialization(serde_json::Error),
527+
}
528+
529+
impl std::error::Error for KeystoreError {
530+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
531+
use KeystoreError::*;
532+
match self {
533+
AddressMissing => None,
534+
AddressInvalid(err) => Some(err),
535+
ReadingFile(err) => Some(err),
536+
Deserialization(err) => Some(err),
537+
}
538+
}
539+
}
540+
541+
impl fmt::Display for KeystoreError {
542+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
543+
use KeystoreError::*;
544+
545+
match self {
546+
AddressMissing => write!(f, "\"address\" key missing in keystore file"),
547+
AddressInvalid(err) => write!(f, "\"address\" is invalid - {}", err),
548+
ReadingFile(err) => write!(f, "Reading keystore file - {}", err),
549+
Deserialization(err) => write!(f, "Deserializing keystore file - {}", err),
550+
}
551+
}
552+
}
553+
554+
impl From<KeystoreError> for AdapterError<Error> {
555+
fn from(err: KeystoreError) -> Self {
556+
AdapterError::Adapter(Error::Keystore(err))
557+
}
558+
}
559+
519560
#[derive(Debug)]
520561
pub enum EwtSigningError {
521562
HeaderSerialization(serde_json::Error),
@@ -531,11 +572,16 @@ mod error {
531572
match self {
532573
HeaderSerialization(err) => write!(f, "Header serialization - {}", err),
533574
PayloadSerialization(err) => write!(f, "Payload serialization - {}", err),
534-
SigningMessage(err) => write!(f, "{}", err),
575+
SigningMessage(err) => write!(f, "Signing message - {}", err),
535576
DecodingHexSignature(err) => write!(f, "Decoding hex of Signature - {}", err),
536577
}
537578
}
538579
}
580+
impl From<EwtSigningError> for AdapterError<Error> {
581+
fn from(err: EwtSigningError) -> Self {
582+
AdapterError::Adapter(Error::SignMessage(err))
583+
}
584+
}
539585

540586
#[derive(Debug)]
541587
pub enum EwtVerifyError {
@@ -638,7 +684,8 @@ mod test {
638684
)
639685
.expect("Failed to verify signatures");
640686

641-
assert!(verify, "invalid signature verification");
687+
assert!(verify, "invalid signature 1 verification");
688+
assert!(verify2, "invalid signature 2 verification");
642689
}
643690

644691
#[test]
@@ -689,9 +736,7 @@ mod test {
689736
address: eth_adapter.whoami().to_checksum(),
690737
};
691738

692-
let token = ewt_sign(&wallet.unwrap(), &eth_adapter.keystore_pwd, &payload)
693-
.map_err(|_| map_error("Failed to sign token"))
694-
.unwrap();
739+
let token = ewt_sign(&wallet.unwrap(), &eth_adapter.keystore_pwd, &payload).unwrap();
695740

696741
let session: Session = eth_adapter.session_from_token(&token).await.unwrap();
697742

primitives/src/adapter.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,11 @@ pub trait AdapterErrorKind: fmt::Debug + fmt::Display {}
1515
pub enum Error<AE: AdapterErrorKind> {
1616
Authentication(String),
1717
Authorization(String),
18-
Configuration(String),
19-
Signature(String),
2018
InvalidChannel(ChannelError),
21-
Failed(String),
2219
/// Adapter specific errors
2320
Adapter(AE),
2421
Domain(DomainError),
25-
/// If
22+
/// You need to `.unlock()` the wallet first
2623
LockedWallet,
2724
}
2825

@@ -39,10 +36,7 @@ impl<AE: AdapterErrorKind> fmt::Display for Error<AE> {
3936
match self {
4037
Error::Authentication(error) => write!(f, "Authentication error: {}", error),
4138
Error::Authorization(error) => write!(f, "Authorization error: {}", error),
42-
Error::Configuration(error) => write!(f, "Configuration error: {}", error),
43-
Error::Signature(error) => write!(f, "Signature error: {}", error),
4439
Error::InvalidChannel(error) => write!(f, "{}", error),
45-
Error::Failed(error) => write!(f, "error: {}", error),
4640
Error::Adapter(error) => write!(f, "Adapter specific error: {}", error),
4741
Error::Domain(error) => write!(f, "Domain error: {}", error),
4842
Error::LockedWallet => write!(f, "You must `.unlock()` the wallet first"),

0 commit comments

Comments
 (0)