Skip to content
This repository has been archived by the owner on Mar 23, 2021. It is now read-only.

Commit

Permalink
Replace H256 and H160 with own Hash and Address
Browse files Browse the repository at this point in the history
  • Loading branch information
da-kami committed Apr 7, 2020
1 parent 96e35f3 commit f9126c7
Show file tree
Hide file tree
Showing 17 changed files with 269 additions and 89 deletions.
12 changes: 6 additions & 6 deletions cnd/src/btsieve/ethereum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ use crate::{
btsieve::{
find_relevant_blocks, BlockByHash, BlockHash, LatestBlock, Predates, PreviousBlockHash,
},
ethereum::{Address, Bytes, Input, Log, Transaction, TransactionReceipt, H256, U256},
ethereum::{Address, Bytes, Input, Log, Transaction, TransactionReceipt, U256},
};
use anyhow;
use async_trait::async_trait;
use chrono::NaiveDateTime;
use genawaiter::{sync::Gen, GeneratorState};

type Hash = H256;
type Hash = crate::ethereum::Hash;
type Block = crate::ethereum::Block;

#[async_trait]
Expand All @@ -24,7 +24,7 @@ pub trait ReceiptByHash: Send + Sync + 'static {
impl BlockHash for Block {
type BlockHash = Hash;

fn block_hash(&self) -> H256 {
fn block_hash(&self) -> Hash {
self.hash
.expect("Connector returned latest block with null hash")
}
Expand All @@ -33,7 +33,7 @@ impl BlockHash for Block {
impl PreviousBlockHash for Block {
type BlockHash = Hash;

fn previous_block_hash(&self) -> H256 {
fn previous_block_hash(&self) -> Hash {
self.parent_hash
}
}
Expand Down Expand Up @@ -174,7 +174,7 @@ where
topic.as_ref().map_or(true, |topic| {
block
.logs_bloom
.contains_input(Input::Raw(topic.0.as_ref()))
.contains_input(Input::Raw(&topic.0.as_bytes()))
})
});
if !maybe_contains_transaction {
Expand Down Expand Up @@ -227,7 +227,7 @@ impl Predates for Block {

#[derive(Clone, Copy, Default, Eq, PartialEq, serde::Serialize, serdebug::SerDebug)]
#[serde(transparent)]
pub struct Topic(pub H256);
pub struct Topic(pub Hash);

/// Event works similar to web3 filters:
/// https://web3js.readthedocs.io/en/1.0/web3-eth-subscribe.html?highlight=filter#subscribe-logs
Expand Down
6 changes: 3 additions & 3 deletions cnd/src/btsieve/ethereum/web3_connector.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
btsieve::{ethereum::ReceiptByHash, BlockByHash, LatestBlock},
config::validation::FetchNetworkId,
ethereum::{TransactionReceipt, H256},
ethereum::{Hash, TransactionReceipt},
jsonrpc,
swap_protocols::ledger::ethereum::ChainId,
};
Expand Down Expand Up @@ -45,7 +45,7 @@ impl LatestBlock for Web3Connector {
#[async_trait]
impl BlockByHash for Web3Connector {
type Block = crate::ethereum::Block;
type BlockHash = crate::ethereum::H256;
type BlockHash = crate::ethereum::Hash;

async fn block_by_hash(&self, block_hash: Self::BlockHash) -> anyhow::Result<Self::Block> {
let block = self
Expand All @@ -64,7 +64,7 @@ impl BlockByHash for Web3Connector {

#[async_trait]
impl ReceiptByHash for Web3Connector {
async fn receipt_by_hash(&self, transaction_hash: H256) -> anyhow::Result<TransactionReceipt> {
async fn receipt_by_hash(&self, transaction_hash: Hash) -> anyhow::Result<TransactionReceipt> {
let receipt = self
.client
.send(jsonrpc::Request::new("eth_getTransactionReceipt", vec![
Expand Down
2 changes: 1 addition & 1 deletion cnd/src/comit_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ mod tests {
#[test]
fn erc20_quantity_to_header() -> Result<(), serde_json::Error> {
let quantity = asset::Erc20::new(
Address::zero(),
Address::from([0u8; 20]),
asset::Erc20Quantity::from_wei(U256::from(100_000_000_000_000u64)),
);
let header = AssetKind::from(quantity).to_header()?;
Expand Down
204 changes: 192 additions & 12 deletions cnd/src/ethereum.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,140 @@
#![warn(unused_extern_crates, missing_debug_implementations, rust_2018_idioms)]
#![forbid(unsafe_code)]

use bitcoin::hashes::core::{fmt::Formatter, str::FromStr};
use core::fmt;
pub use ethbloom::{Bloom as H2048, Input};
pub use primitive_types::{H160, H256, U128, U256};
use hex::FromHexError;
pub use primitive_types::U256;
use serde::{Deserialize, Serialize};
use serde_hex::{CompactPfx, SerHex, SerHexSeq, StrictPfx};

pub type Address = H160;
use std::fmt::Display;

#[derive(Debug, Default, Copy, Clone, PartialEq, Deserialize)]
pub struct H64(#[serde(with = "SerHex::<StrictPfx>")] [u8; 8]);

#[derive(
Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
)]
pub struct Address(#[serde(with = "SerHex::<StrictPfx>")] [u8; 20]);

impl Address {
pub fn from_slice(src: &[u8]) -> Self {
let mut address = Address([0u8; 20]);
address.0.copy_from_slice(src);
address
}
}

impl From<[u8; 20]> for Address {
fn from(bytes: [u8; 20]) -> Self {
Address(bytes)
}
}

impl From<Address> for [u8; 20] {
fn from(s: Address) -> Self {
s.0
}
}

impl FromStr for Address {
type Err = FromHexError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
hex::decode(s).map(|v| Address::from_slice(v.as_slice()))
}
}

impl From<Address> for Hash {
fn from(address: Address) -> Self {
let mut h256 = Hash([0u8; 32]);
h256.0[(32 - 20)..32].copy_from_slice(&address.0);
h256
}
}

impl fmt::LowerHex for Address {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if f.alternate() {
write!(f, "0x")?;
}
for i in &self.0[..] {
write!(f, "{:02x}", i)?;
}
Ok(())
}
}

#[derive(
Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
)]
pub struct Hash(#[serde(with = "SerHex::<StrictPfx>")] [u8; 32]);

impl From<[u8; 32]> for Hash {
fn from(bytes: [u8; 32]) -> Self {
Hash(bytes)
}
}

impl From<Hash> for [u8; 32] {
fn from(s: Hash) -> Self {
s.0
}
}

impl Hash {
pub fn from_slice(src: &[u8]) -> Self {
let mut h256 = Hash([0u8; 32]);
h256.0.copy_from_slice(src);
h256
}

pub fn as_bytes(&self) -> &[u8] {
&self.0
}
}

impl FromStr for Hash {
type Err = FromHexError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
hex::decode(s).map(|v| Hash::from_slice(v.as_slice()))
}
}

impl fmt::LowerHex for Hash {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if f.alternate() {
write!(f, "0x")?;
}
for i in &self.0[..] {
write!(f, "{:02x}", i)?;
}
Ok(())
}
}

impl Display for Hash {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "0x")?;
for i in &self.0[0..2] {
write!(f, "{:02x}", i)?;
}
write!(f, "…")?;
for i in &self.0[32 - 2..32] {
write!(f, "{:02x}", i)?;
}
Ok(())
}
}

/// "Receipt" of an executed transaction: details of its execution.
#[derive(Debug, Default, Clone, PartialEq, Deserialize)]
pub struct TransactionReceipt {
/// Contract address created, or `None` if not a deployment.
#[serde(rename = "contractAddress")]
pub contract_address: Option<H160>,
pub contract_address: Option<Address>,
/// Logs generated within this transaction.
pub logs: Vec<Log>,
/// Status: either 1 (success) or 0 (failure).
Expand All @@ -34,9 +152,9 @@ impl TransactionReceipt {
#[derive(Debug, Default, Clone, PartialEq, Deserialize)]
pub struct Transaction {
/// Hash
pub hash: H256,
pub hash: Hash,
/// Recipient (None when contract creation)
pub to: Option<H160>,
pub to: Option<Address>,
/// Transfered value
pub value: U256,
/// Input data
Expand All @@ -47,9 +165,9 @@ pub struct Transaction {
#[derive(Debug, Clone, PartialEq, Deserialize)]
pub struct Log {
/// H160
pub address: H160,
pub address: Address,
/// Topics
pub topics: Vec<H256>,
pub topics: Vec<Hash>,
/// Data
pub data: Bytes,
}
Expand All @@ -60,10 +178,10 @@ pub struct Log {
#[derive(Debug, Default, Clone, PartialEq, Deserialize)]
pub struct Block {
/// Hash of the block
pub hash: Option<H256>,
pub hash: Option<Hash>,
/// Hash of the parent
#[serde(rename = "parentHash")]
pub parent_hash: H256,
pub parent_hash: Hash,
/// Logs bloom
#[serde(rename = "logsBloom")]
pub logs_bloom: H2048,
Expand All @@ -85,8 +203,70 @@ impl<T: Into<Vec<u8>>> From<T> for Bytes {

#[cfg(test)]
mod tests {
use super::Log;
use crate::ethereum::TransactionReceipt;
use super::*;

#[test]
fn deserialise_address() {
let json =
serde_json::Value::String("0xc5549e335b2786520f4c5d706c76c9ee69d0a028".to_owned());
let _: Address = Address::deserialize(&json).unwrap();
}

#[test]
fn deserialise_address_when_not_using_reference_to_deserialize_fails() {
// This is due to a bug in serde-jex, keep this test until https://github.com/fspmarshall/serde-hex/pull/8
// is fixed.
let json =
serde_json::Value::String("0xc5549e335b2786520f4c5d706c76c9ee69d0a028".to_owned());

let deserialized = serde_json::from_value::<Address>(json);
matches!(deserialized, Err(_));
}

#[test]
fn from_string_address() {
let json =
serde_json::Value::String("0xc5549e335b2786520f4c5d706c76c9ee69d0a028".to_owned());
let deserialized: Address = Address::deserialize(&json).unwrap();

let from_string = Address::from_str("c5549e335b2786520f4c5d706c76c9ee69d0a028").unwrap();

assert_eq!(from_string, deserialized);
}

#[test]
fn deserialise_hash() {
let json = serde_json::Value::String(
"0x3ae3b6ffb04204f52dee42000e8b971c0f7c2b4aa8dd9455e41a30ee4b31e8a9".to_owned(),
);
let _: Hash = Hash::deserialize(&json).unwrap();
}

#[test]
fn deserialise_hash_when_not_using_reference_to_deserialize_fails() {
// This is due to a bug in serde-jex, keep this test until https://github.com/fspmarshall/serde-hex/pull/8
// is fixed.
let json = serde_json::Value::String(
"0x3ae3b6ffb04204f52dee42000e8b971c0f7c2b4aa8dd9455e41a30ee4b31e8a9".to_owned(),
);

let deserialized = serde_json::from_value::<Hash>(json);
matches!(deserialized, Err(_));
}

#[test]
fn from_string_hash() {
let json = serde_json::Value::String(
"0x3ae3b6ffb04204f52dee42000e8b971c0f7c2b4aa8dd9455e41a30ee4b31e8a9".to_owned(),
);
let deserialized: Hash = Hash::deserialize(&json).unwrap();

let from_string =
Hash::from_str("3ae3b6ffb04204f52dee42000e8b971c0f7c2b4aa8dd9455e41a30ee4b31e8a9")
.unwrap();

assert_eq!(from_string, deserialized);
}

#[test]
fn deserialise_log() {
Expand Down
8 changes: 4 additions & 4 deletions cnd/src/http_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ impl Serialize for Http<identity::Bitcoin> {
}

impl_serialize_type_with_fields!(htlc_location::Bitcoin { "txid" => txid, "vout" => vout });
impl_serialize_http!(crate::ethereum::H160);
impl_serialize_http!(crate::ethereum::Address);
impl_serialize_http!(SwapId);

impl Serialize for Http<SwapProtocol> {
Expand Down Expand Up @@ -489,7 +489,7 @@ mod tests {
asset,
asset::ethereum::FromWei,
bitcoin::PublicKey,
ethereum::{H160, H256, U256},
ethereum::{Address, Hash, U256},
http_api::{Http, HttpAsset, HttpLedger},
swap_protocols::{
ledger::{bitcoin, ethereum, Ethereum},
Expand Down Expand Up @@ -591,7 +591,7 @@ mod tests {
output: vec![],
};
let ethereum_tx = transaction::Ethereum {
hash: H256::repeat_byte(1),
hash: Hash::from([1u8; 32]),
..transaction::Ethereum::default()
};

Expand All @@ -618,7 +618,7 @@ mod tests {
.parse()
.unwrap();

let ethereum_identity = H160::repeat_byte(7);
let ethereum_identity = Address::from([7u8; 20]);

let bitcoin_identity = Http(bitcoin_identity);
let ethereum_identity = Http(ethereum_identity);
Expand Down
Loading

0 comments on commit f9126c7

Please sign in to comment.