Skip to content

Commit edb2cf0

Browse files
authored
Merge pull request #389 from AdExNetwork/aip-61-all-around-generic-changes
AIP #61 v5: All around generic changes
2 parents f345f6a + a752604 commit edb2cf0

32 files changed

+935
-784
lines changed

Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

adapter/src/lib.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ use std::error::Error;
66

77
use chrono::{DateTime, Utc};
88
use hex::FromHex;
9-
use primitives::{channel::ChannelError, BigNum, Channel, ValidatorId};
9+
use primitives::{channel::ChannelError, Address, BigNum, Channel, ValidatorId};
1010
use sha2::{Digest, Sha256};
1111
use std::convert::TryFrom;
1212
use tiny_keccak::Keccak;
1313
use web3::{
1414
ethabi::{encode, token::Token},
15-
types::{Address, U256},
15+
types::{Address as EthAddress, U256},
1616
};
1717

1818
pub use self::dummy::DummyAdapter;
@@ -46,9 +46,9 @@ pub fn get_signable_state_root(
4646
Ok(res)
4747
}
4848

49-
pub fn get_balance_leaf(acc: &ValidatorId, amnt: &BigNum) -> Result<[u8; 32], Box<dyn Error>> {
49+
pub fn get_balance_leaf(acc: &Address, amnt: &BigNum) -> Result<[u8; 32], Box<dyn Error>> {
5050
let tokens = [
51-
Token::Address(Address::from_slice(acc.inner())),
51+
Token::Address(EthAddress::from_slice(acc.as_bytes())),
5252
Token::Uint(
5353
U256::from_dec_str(&amnt.to_str_radix(10))
5454
.map_err(|_| ChannelError::InvalidArgument("failed to parse amt".into()))?,
@@ -67,11 +67,11 @@ pub fn get_balance_leaf(acc: &ValidatorId, amnt: &BigNum) -> Result<[u8; 32], Bo
6767

6868
// OnChain channel Representation
6969
pub struct EthereumChannel {
70-
pub creator: Address,
71-
pub token_addr: Address,
70+
pub creator: EthAddress,
71+
pub token_addr: EthAddress,
7272
pub token_amount: U256,
7373
pub valid_until: U256,
74-
pub validators: Vec<Address>,
74+
pub validators: Vec<EthAddress>,
7575
pub spec: [u8; 32],
7676
}
7777

@@ -121,16 +121,16 @@ impl EthereumChannel {
121121
return Err(ChannelError::InvalidArgument("invalid token amount".into()));
122122
}
123123

124-
let creator = Address::from_slice(creator);
125-
let token_addr = Address::from_slice(token_addr);
124+
let creator = EthAddress::from_slice(creator);
125+
let token_addr = EthAddress::from_slice(token_addr);
126126
let token_amount = U256::from_dec_str(&token_amount)
127127
.map_err(|_| ChannelError::InvalidArgument("failed to parse token amount".into()))?;
128128
let valid_until = U256::from_dec_str(&valid_until.timestamp().to_string())
129129
.map_err(|_| ChannelError::InvalidArgument("failed to parse valid until".into()))?;
130130

131131
let validators = validators
132132
.iter()
133-
.map(|v| Address::from_slice(v.inner()))
133+
.map(|v| EthAddress::from_slice(v.as_bytes()))
134134
.collect();
135135

136136
Ok(Self {
@@ -145,7 +145,7 @@ impl EthereumChannel {
145145

146146
pub fn hash(&self, contract_addr: &[u8; 20]) -> [u8; 32] {
147147
let tokens = [
148-
Token::Address(Address::from_slice(contract_addr)),
148+
Token::Address(EthAddress::from_slice(contract_addr)),
149149
Token::Address(self.creator.to_owned()),
150150
Token::Address(self.token_addr.to_owned()),
151151
Token::Uint(self.token_amount.to_owned()),

primitives/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ slog-async = "^2.3.0"
2525
thiserror = "^1.0"
2626
chrono = { version = "0.4", features = ["serde"] }
2727
time = "0.1.42"
28+
uuid = { version = "0.8", features = ["v4"] }
2829
# For encoding the Channel to a ChannelId
2930
ethabi = "13.0.0"
3031
# For the nonce U256

primitives/src/address.rs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use hex::{FromHex, FromHexError};
22
use serde::{Deserialize, Serialize, Serializer};
3-
use std::{convert::TryFrom, fmt};
3+
use std::{convert::TryFrom, fmt, str::FromStr};
44
use thiserror::Error;
55

66
use crate::{targeting::Value, DomainError, ToETHChecksum, ToHex};
@@ -29,6 +29,10 @@ impl Address {
2929
pub fn as_bytes(&self) -> &[u8; 20] {
3030
&self.0
3131
}
32+
33+
pub fn from_bytes(bytes: &[u8; 20]) -> Self {
34+
Self(*bytes)
35+
}
3236
}
3337

3438
impl Serialize for Address {
@@ -67,6 +71,14 @@ impl AsRef<[u8]> for Address {
6771
}
6872
}
6973

74+
impl FromStr for Address {
75+
type Err = Error;
76+
77+
fn from_str(s: &str) -> Result<Self, Self::Err> {
78+
Ok(Self(from_bytes(s, Prefix::Insensitive)?))
79+
}
80+
}
81+
7082
impl TryFrom<&str> for Address {
7183
type Error = Error;
7284

@@ -83,6 +95,14 @@ impl TryFrom<&String> for Address {
8395
}
8496
}
8597

98+
impl TryFrom<&[u8]> for Address {
99+
type Error = Error;
100+
101+
fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
102+
Ok(Self(from_bytes(slice, Prefix::Insensitive)?))
103+
}
104+
}
105+
86106
impl TryFrom<Value> for Address {
87107
type Error = DomainError;
88108

@@ -135,3 +155,46 @@ pub fn from_bytes<T: AsRef<[u8]>>(from: T, prefix: Prefix) -> Result<[u8; 20], E
135155
_ => Err(Error::Length),
136156
}
137157
}
158+
159+
#[cfg(feature = "postgres")]
160+
pub mod postgres {
161+
use super::Address;
162+
use crate::ToETHChecksum;
163+
use bytes::BytesMut;
164+
use postgres_types::{FromSql, IsNull, ToSql, Type};
165+
use std::error::Error;
166+
167+
impl<'a> FromSql<'a> for Address {
168+
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
169+
let str_slice = <&str as FromSql>::from_sql(ty, raw)?;
170+
171+
Ok(str_slice.parse()?)
172+
}
173+
174+
fn accepts(ty: &Type) -> bool {
175+
matches!(*ty, Type::TEXT | Type::VARCHAR)
176+
}
177+
}
178+
179+
impl ToSql for Address {
180+
fn to_sql(
181+
&self,
182+
ty: &Type,
183+
w: &mut BytesMut,
184+
) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
185+
self.to_checksum().to_sql(ty, w)
186+
}
187+
188+
fn accepts(ty: &Type) -> bool {
189+
<String as ToSql>::accepts(ty)
190+
}
191+
192+
fn to_sql_checked(
193+
&self,
194+
ty: &Type,
195+
out: &mut BytesMut,
196+
) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
197+
self.to_checksum().to_sql_checked(ty, out)
198+
}
199+
}
200+
}

primitives/src/balances_map.rs

Lines changed: 83 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,58 @@
1-
use std::collections::BTreeMap;
1+
use serde::{Deserialize, Serialize};
2+
use std::{
3+
collections::{
4+
btree_map::{Entry, IntoIter, Iter, Values},
5+
BTreeMap,
6+
},
7+
iter::FromIterator,
8+
ops::Index,
9+
};
210

3-
use crate::{BigNum, ValidatorId};
4-
use std::collections::btree_map::{Entry, IntoIter, Iter, Values};
11+
use crate::{Address, BigNum, UnifiedNum};
512

6-
use serde::{Deserialize, Serialize};
7-
use std::iter::FromIterator;
8-
use std::ops::Index;
13+
pub type UnifiedMap = Map<Address, UnifiedNum>;
14+
pub type BalancesMap = Map<Address, BigNum>;
915

10-
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
16+
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
1117
#[serde(transparent)]
12-
pub struct BalancesMap(BTreeMap<ValidatorId, BigNum>);
18+
pub struct Map<K: Ord, V>(BTreeMap<K, V>);
19+
20+
impl<K: Ord, V> Default for Map<K, V> {
21+
fn default() -> Self {
22+
Map(BTreeMap::default())
23+
}
24+
}
1325

14-
impl Index<&'_ ValidatorId> for BalancesMap {
15-
type Output = BigNum;
26+
impl<K: Ord, V> Index<&'_ K> for Map<K, V> {
27+
type Output = V;
1628

17-
fn index(&self, index: &ValidatorId) -> &Self::Output {
29+
fn index(&self, index: &K) -> &Self::Output {
1830
self.0.index(index)
1931
}
2032
}
2133

22-
impl BalancesMap {
23-
pub fn iter(&self) -> Iter<'_, ValidatorId, BigNum> {
34+
impl<K: Ord, V> Map<K, V> {
35+
pub fn iter(&self) -> Iter<'_, K, V> {
2436
self.0.iter()
2537
}
2638

27-
pub fn values(&self) -> Values<'_, ValidatorId, BigNum> {
39+
pub fn values(&self) -> Values<'_, K, V> {
2840
self.0.values()
2941
}
3042

31-
pub fn get(&self, key: &ValidatorId) -> Option<&BigNum> {
43+
pub fn get(&self, key: &K) -> Option<&V> {
3244
self.0.get(key)
3345
}
3446

35-
pub fn contains_key(&self, key: &ValidatorId) -> bool {
47+
pub fn contains_key(&self, key: &K) -> bool {
3648
self.0.contains_key(key)
3749
}
3850

39-
pub fn entry(&mut self, key: ValidatorId) -> Entry<'_, ValidatorId, BigNum> {
51+
pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
4052
self.0.entry(key)
4153
}
4254

43-
pub fn insert(&mut self, key: ValidatorId, value: BigNum) -> Option<BigNum> {
55+
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
4456
self.0.insert(key, value)
4557
}
4658

@@ -53,18 +65,18 @@ impl BalancesMap {
5365
}
5466
}
5567

56-
impl FromIterator<(ValidatorId, BigNum)> for BalancesMap {
57-
fn from_iter<I: IntoIterator<Item = (ValidatorId, BigNum)>>(iter: I) -> Self {
68+
impl<K: Ord, V> FromIterator<(K, V)> for Map<K, V> {
69+
fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
5870
// @TODO: Is there better way to do this?
59-
let btree_map: BTreeMap<ValidatorId, BigNum> = iter.into_iter().collect();
71+
let btree_map: BTreeMap<K, V> = iter.into_iter().collect();
6072

61-
BalancesMap(btree_map)
73+
Map(btree_map)
6274
}
6375
}
6476

65-
impl IntoIterator for BalancesMap {
66-
type Item = (ValidatorId, BigNum);
67-
type IntoIter = IntoIter<ValidatorId, BigNum>;
77+
impl<K: Ord, V> IntoIterator for Map<K, V> {
78+
type Item = (K, V);
79+
type IntoIter = IntoIter<K, V>;
6880

6981
fn into_iter(self) -> Self::IntoIter {
7082
self.0.into_iter()
@@ -73,42 +85,73 @@ impl IntoIterator for BalancesMap {
7385

7486
#[cfg(test)]
7587
mod test {
88+
use serde_json::json;
89+
7690
use super::*;
77-
use crate::util::tests::prep_db::IDS;
78-
use crate::BigNum;
91+
use crate::util::tests::prep_db::ADDRESSES;
7992

8093
#[test]
81-
fn test_balances_map_serialization() {
82-
let data = vec![
83-
(IDS["leader"].clone(), BigNum::from(50_u64)),
84-
(IDS["follower"].clone(), BigNum::from(100_u64)),
85-
];
94+
fn test_unified_map_de_serialization() {
95+
let unified_map: UnifiedMap = vec![
96+
(ADDRESSES["leader"].clone(), UnifiedNum::from(50_u64)),
97+
(ADDRESSES["follower"].clone(), UnifiedNum::from(100_u64)),
98+
]
99+
.into_iter()
100+
.collect();
101+
102+
let actual_json = serde_json::to_value(&unified_map).expect("Should serialize it");
103+
let expected_json = json!({
104+
"0xC91763D7F14ac5c5dDfBCD012e0D2A61ab9bDED3":100,
105+
"0xce07CbB7e054514D590a0262C93070D838bFBA2e":50
106+
});
86107

87-
let balances_map: BalancesMap = data.into_iter().collect();
108+
assert_eq!(expected_json, actual_json);
109+
110+
let balances_map_from_json: UnifiedMap =
111+
serde_json::from_value(actual_json).expect("Should deserialize it");
112+
113+
assert_eq!(unified_map, balances_map_from_json);
114+
}
115+
116+
#[test]
117+
fn test_balances_map_de_serialization() {
118+
let balances_map: BalancesMap = vec![
119+
(ADDRESSES["leader"].clone(), BigNum::from(50_u64)),
120+
(ADDRESSES["follower"].clone(), BigNum::from(100_u64)),
121+
]
122+
.into_iter()
123+
.collect();
88124

89-
let actual_json = serde_json::to_string(&balances_map).expect("Should serialize it");
90-
let expected_json = r#"{"0xC91763D7F14ac5c5dDfBCD012e0D2A61ab9bDED3":"100","0xce07CbB7e054514D590a0262C93070D838bFBA2e":"50"}"#;
125+
let actual_json = serde_json::to_value(&balances_map).expect("Should serialize it");
126+
let expected_json = json!({
127+
"0xC91763D7F14ac5c5dDfBCD012e0D2A61ab9bDED3":"100",
128+
"0xce07CbB7e054514D590a0262C93070D838bFBA2e":"50"
129+
});
91130

92131
assert_eq!(expected_json, actual_json);
93132

94133
let balances_map_from_json: BalancesMap =
95-
serde_json::from_str(&actual_json).expect("Should deserialize it");
134+
serde_json::from_value(actual_json).expect("Should deserialize it");
96135

97136
assert_eq!(balances_map, balances_map_from_json);
98137
}
99138

100139
#[test]
101140
fn test_balances_map_deserialization_with_same_keys() {
102141
// the first is ETH Checksummed, the second is lowercase!
103-
let json = r#"{"0xC91763D7F14ac5c5dDfBCD012e0D2A61ab9bDED3":"100","0xc91763d7f14ac5c5ddfbcd012e0d2a61ab9bded3":"20","0xce07CbB7e054514D590a0262C93070D838bFBA2e":"50"}"#;
142+
let json = json!({
143+
"0xC91763D7F14ac5c5dDfBCD012e0D2A61ab9bDED3":"100",
144+
"0xc91763d7f14ac5c5ddfbcd012e0d2a61ab9bded3":"20",
145+
"0xce07CbB7e054514D590a0262C93070D838bFBA2e":"50"
146+
});
104147

105148
let actual_deserialized: BalancesMap =
106-
serde_json::from_str(&json).expect("Should deserialize it");
149+
serde_json::from_value(json).expect("Should deserialize it");
107150

108151
let expected_deserialized: BalancesMap = vec![
109-
(IDS["leader"].clone(), BigNum::from(50_u64)),
152+
(ADDRESSES["leader"].clone(), BigNum::from(50_u64)),
110153
// only the second should be accepted, as it appears second in the string and it's the latest one
111-
(IDS["follower"].clone(), BigNum::from(20_u64)),
154+
(ADDRESSES["follower"].clone(), BigNum::from(20_u64)),
112155
]
113156
.into_iter()
114157
.collect();

0 commit comments

Comments
 (0)