Skip to content

Commit b647999

Browse files
committed
Merge branch 'aip-61-adex-v5' into analytics-routes
2 parents 7e8d449 + f0f08d4 commit b647999

File tree

81 files changed

+3490
-2319
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+3490
-2319
lines changed

Cargo.lock

+663-537
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ members = [
1010
]
1111

1212
[patch.crates-io]
13-
postgres-types = { git = "https://github.com/elpiel/rust-postgres", branch = "from-T-for-boxed-dyn-ToSql"}
13+
postgres-types = { git = "https://github.com/elpiel/rust-postgres", branch = "boxed-dyn-ToSql"}

adapter/Cargo.toml

+20-23
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,45 @@
11
[package]
22
name = "adapter"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
authors = [
55
"Ambire <[email protected]>",
66
"Lachezar Lechev <[email protected]>",
7-
"Omidiora Samuel <[email protected]>",
7+
"Samparsky <[email protected]>",
88
]
99
edition = "2021"
10+
license = "AGPL-3.0"
11+
1012

1113
[features]
1214

15+
# Enables testing untilites for working with Ganache.
1316
test-util = ["primitives/test-util"]
1417

1518
[dependencies]
1619
primitives = { path = "../primitives" }
17-
# Time handling
18-
chrono = "0.4"
19-
# To/From Hex
20-
hex = "0.4"
21-
serde = { version = "^1.0", features = ['derive'] }
22-
serde_json = "1.0"
23-
serde-hex = "0.1.0"
24-
# Ethereum
20+
21+
# For Ethereum client
2522
web3 = { version = "0.17", features = ["http-tls", "signing"] }
26-
eth_checksum = "0.1"
27-
tiny-keccak = "1.5"
2823
ethstore = { git = "https://github.com/openethereum/openethereum", tag = "v3.1.1-rc.1" }
2924
create2 = "0.0.2"
3025

31-
# API client
32-
reqwest = { version = "0.11", features = ["json"] }
26+
# For Dummy client
27+
dashmap = "4.0"
3328

34-
sha2 = "0.9"
35-
base64 = "0.13"
36-
once_cell = "^1.8"
37-
thiserror = "^1"
38-
# Futures
39-
futures = "0.3"
4029
async-trait = "0.1"
30+
thiserror = "1"
4131

42-
# Dummy adapter
43-
dashmap = "4.0"
32+
# Time handling
33+
chrono = "0.4"
34+
serde = { version = "^1.0", features = ["derive"] }
35+
serde_json = "1.0"
36+
hex = "0.4"
37+
base64 = "0.13"
38+
once_cell = "^1.8"
39+
# Macro for easier derive of Display & FromStr
40+
parse-display = "^0.5.0"
4441

4542
[dev-dependencies]
4643
byteorder = "^1.4"
4744
tokio = { version = "^1", features = ["macros", "rt-multi-thread"] }
48-
wiremock = "0.5"
45+
pretty_assertions = "1"

adapter/Makefile.toml

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ dependencies = [
1212
"ganache-down",
1313
]
1414

15+
[tasks.test]
16+
# run tests in release because of slow unlock time of Ethereum adapter (i.e. keystore decryption)
17+
args = ["test", "--release", "--all-features"]
18+
1519
[tasks.ganache-up]
1620
script = '''
1721
docker-compose -f ../docker-compose.harness.yml up --renew-anon-volumes -d ganache \

adapter/src/adapter.rs

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
use crate::primitives::*;
2+
use async_trait::async_trait;
3+
use std::{marker::PhantomData, sync::Arc};
4+
5+
use crate::{
6+
client::{Locked, Unlockable, Unlocked},
7+
Error,
8+
};
9+
10+
pub(crate) mod state {
11+
#[derive(Debug, Clone, Copy)]
12+
/// The `Locked` state of the [`crate::Adapter`].
13+
/// See [`crate::client::Locked`]
14+
pub struct LockedState;
15+
16+
/// The `Unlocked` state of the [`crate::Adapter`].
17+
/// See [`crate::client::Unlocked`]
18+
#[derive(Debug, Clone, Copy)]
19+
pub struct UnlockedState;
20+
}
21+
22+
#[derive(Debug)]
23+
/// The [`Adapter`] struct and it's states.
24+
///
25+
/// Used for communication with the underlying client implementation.
26+
///
27+
/// # Available adapters
28+
///
29+
/// 2 Adapters are available in this crate:
30+
/// - Ethereum
31+
/// - [`crate::ethereum::LockedAdapter`] and [`crate::ethereum::UnlockedAdapter`]
32+
/// - Client implementation [`crate::Ethereum`] for chains compatible with EVM.
33+
/// - Dummy
34+
/// - [`crate::dummy::Adapter`] and it's client implementation [`crate::Dummy`] for testing.
35+
pub struct Adapter<C, S = state::LockedState> {
36+
/// client in a specific state - Locked or Unlocked
37+
pub client: Arc<C>,
38+
_state: PhantomData<S>,
39+
}
40+
41+
impl<C, S: Clone> Clone for Adapter<C, S> {
42+
fn clone(&self) -> Self {
43+
Self {
44+
client: self.client.clone(),
45+
_state: self._state,
46+
}
47+
}
48+
}
49+
50+
impl<C: Locked> Adapter<C> {
51+
/// Create a new [`Adapter`] in [`Locked`] state using a [`Locked`].
52+
pub fn new(client: C) -> Adapter<C, state::LockedState> {
53+
Adapter {
54+
client: Arc::new(client),
55+
_state: PhantomData::default(),
56+
}
57+
}
58+
}
59+
60+
impl<C: Unlocked> Adapter<C, state::LockedState> {
61+
/// Create a new [`Adapter`] in [`state::UnlockedState`] state using an [`Unlocked`] client.
62+
pub fn with_unlocked(client: C) -> Adapter<C, state::UnlockedState> {
63+
Adapter {
64+
client: Arc::new(client),
65+
_state: PhantomData::default(),
66+
}
67+
}
68+
}
69+
70+
impl<C> Adapter<C, state::LockedState>
71+
where
72+
C: Locked + Unlockable,
73+
<C::Unlocked as Locked>::Error: Into<Error>,
74+
C::Error: Into<Error>,
75+
{
76+
pub fn unlock(self) -> Result<Adapter<C::Unlocked, state::UnlockedState>, Error> {
77+
let unlocked = self.client.unlock().map_err(Into::into)?;
78+
79+
Ok(Adapter {
80+
client: Arc::new(unlocked),
81+
_state: PhantomData::default(),
82+
})
83+
}
84+
}
85+
86+
#[async_trait]
87+
impl<C> Unlocked for Adapter<C, state::UnlockedState>
88+
where
89+
C: Unlocked + Sync + Send,
90+
C::Error: Into<Error>,
91+
{
92+
fn sign(&self, state_root: &str) -> Result<String, Error> {
93+
self.client.sign(state_root).map_err(Into::into)
94+
}
95+
96+
fn get_auth(&self, intended_for: ValidatorId) -> Result<String, Error> {
97+
self.client.get_auth(intended_for).map_err(Into::into)
98+
}
99+
}
100+
101+
#[async_trait]
102+
impl<C, S> Locked for Adapter<C, S>
103+
where
104+
C: Locked + Sync + Send,
105+
C::Error: Into<Error>,
106+
S: Sync + Send,
107+
{
108+
type Error = Error;
109+
/// Get Adapter whoami
110+
fn whoami(&self) -> ValidatorId {
111+
self.client.whoami()
112+
}
113+
114+
/// Verify, based on the signature & state_root, that the signer is the same
115+
fn verify(
116+
&self,
117+
signer: ValidatorId,
118+
state_root: &str,
119+
signature: &str,
120+
) -> Result<bool, Error> {
121+
self.client
122+
.verify(signer, state_root, signature)
123+
.map_err(Into::into)
124+
}
125+
126+
/// Creates a `Session` from a provided Token by calling the Contract.
127+
/// Does **not** cache the (`Token`, [`Session`]) pair.
128+
async fn session_from_token(&self, token: &str) -> Result<Session, Error> {
129+
self.client
130+
.session_from_token(token)
131+
.await
132+
.map_err(Into::into)
133+
}
134+
135+
async fn get_deposit(
136+
&self,
137+
channel: &Channel,
138+
depositor_address: Address,
139+
) -> Result<Deposit, Error> {
140+
self.client
141+
.get_deposit(channel, depositor_address)
142+
.await
143+
.map_err(Into::into)
144+
}
145+
}

adapter/src/client.rs

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//! The Client traits that define the actions for each state.
2+
//!
3+
//! - [`Locked`]
4+
//! - [`Unlocked`]
5+
//! - [`Unlockable`]
6+
7+
use crate::primitives::{Deposit, Session};
8+
use async_trait::async_trait;
9+
use primitives::{Address, Channel, ValidatorId};
10+
11+
#[async_trait]
12+
/// Available methods for Locked clients.
13+
pub trait Locked: Sync + Send {
14+
type Error: std::error::Error + Into<crate::Error> + 'static;
15+
16+
/// Get Adapter whoami
17+
fn whoami(&self) -> ValidatorId;
18+
19+
/// Verify, based on the signature & state_root, that the signer is the same
20+
fn verify(
21+
&self,
22+
signer: ValidatorId,
23+
state_root: &str,
24+
signature: &str,
25+
) -> Result<bool, Self::Error>;
26+
27+
/// Creates a `Session` from a provided Token by calling the Contract.
28+
/// Does **not** cache the (`Token`, `Session`) pair.
29+
async fn session_from_token(&self, token: &str) -> Result<Session, Self::Error>;
30+
31+
async fn get_deposit(
32+
&self,
33+
channel: &Channel,
34+
depositor_address: Address,
35+
) -> Result<Deposit, Self::Error>;
36+
37+
// fn unlock(
38+
// &self,
39+
// ) -> Result<
40+
// <Self as Unlockable>::Unlocked,
41+
// <<Self as Unlockable>::Unlocked as Locked>::Error,
42+
// >
43+
// where
44+
// Self: Unlockable,
45+
// {
46+
// <Self as Unlockable>::unlock(self)
47+
// }
48+
}
49+
50+
/// Available methods for Unlocked clients.
51+
/// Unlocked clients should also implement [`Locked`].
52+
#[async_trait]
53+
pub trait Unlocked: Locked {
54+
// requires Unlocked
55+
fn sign(&self, state_root: &str) -> Result<String, Self::Error>;
56+
57+
// requires Unlocked
58+
fn get_auth(&self, intended_for: ValidatorId) -> Result<String, Self::Error>;
59+
}
60+
61+
/// A client that can be `unlock()`ed
62+
/// and implements both [`Locked`] & [`Unlocked`].
63+
///
64+
/// **Note:** A possibly expensive operation as it might result in cloning
65+
pub trait Unlockable {
66+
type Unlocked: Unlocked;
67+
68+
fn unlock(&self) -> Result<Self::Unlocked, <Self::Unlocked as Locked>::Error>;
69+
}

0 commit comments

Comments
 (0)