From 7c465c20270c46720c5d0c6372221a50894539b2 Mon Sep 17 00:00:00 2001 From: Georgios Konstantopoulos Date: Thu, 28 May 2020 00:48:48 +0300 Subject: [PATCH] add some block tests --- Cargo.lock | 11 ++++++ crates/ethers-types/Cargo.toml | 1 + crates/ethers-types/src/block.rs | 18 ++++++++++ crates/ethers-types/src/ens.rs | 62 ++++++++++++++++++++++++++++++++ crates/ethers-types/src/keys.rs | 23 +++++++----- 5 files changed, 106 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d32f960d..83deaed8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,6 +52,15 @@ name = "base64" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bincode" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitflags" version = "1.2.1" @@ -320,6 +329,7 @@ dependencies = [ name = "ethers-types" version = "0.1.0" dependencies = [ + "bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethers-utils 0.1.0", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1523,6 +1533,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +"checksum bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum bitvec 0.17.4 (registry+https://github.com/rust-lang/crates.io-index)" = "41262f11d771fd4a61aa3ce019fca363b4b6c282fca9da2a31186d3965a47a5c" "checksum bumpalo 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5356f1d23ee24a1f785a56d1d1a5f0fd5b0f6a0c0fb2412ce11da71649ab78f6" diff --git a/crates/ethers-types/Cargo.toml b/crates/ethers-types/Cargo.toml index 6df57ba6..6edfdd4d 100644 --- a/crates/ethers-types/Cargo.toml +++ b/crates/ethers-types/Cargo.toml @@ -21,3 +21,4 @@ zeroize = { version = "1.1.0", default-features = false } [dev-dependencies] serde_json = { version = "1.0.53", default-features = false } rand = { version = "0.5.1" } +bincode = "1.2.1" diff --git a/crates/ethers-types/src/block.rs b/crates/ethers-types/src/block.rs index 49884231..40dd2750 100644 --- a/crates/ethers-types/src/block.rs +++ b/crates/ethers-types/src/block.rs @@ -134,3 +134,21 @@ impl Serialize for BlockNumber { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{Transaction, TxHash}; + + #[test] + fn deserialize_blk_no_txs() { + let block = r#"{"number":"0x3","hash":"0xda53da08ef6a3cbde84c33e51c04f68c3853b6a3731f10baa2324968eee63972","parentHash":"0x689c70c080ca22bc0e681694fa803c1aba16a69c8b6368fed5311d279eb9de90","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x7270c1c4440180f2bd5215809ee3d545df042b67329499e1ab97eb759d31610d","stateRoot":"0x29f32984517a7d25607da485b23cefabfd443751422ca7e603395e1de9bc8a4b","receiptsRoot":"0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2","miner":"0x0000000000000000000000000000000000000000","difficulty":"0x0","totalDifficulty":"0x0","extraData":"0x","size":"0x3e8","gasLimit":"0x6691b7","gasUsed":"0x5208","timestamp":"0x5ecedbb9","transactions":["0xc3c5f700243de37ae986082fd2af88d2a7c2752a0c0f7b9d6ac47c729d45e067"],"uncles":[]}"#; + let _block: Block = serde_json::from_str(&block).unwrap(); + } + + #[test] + fn deserialize_blk_with_txs() { + let block = r#"{"number":"0x3","hash":"0xda53da08ef6a3cbde84c33e51c04f68c3853b6a3731f10baa2324968eee63972","parentHash":"0x689c70c080ca22bc0e681694fa803c1aba16a69c8b6368fed5311d279eb9de90","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x7270c1c4440180f2bd5215809ee3d545df042b67329499e1ab97eb759d31610d","stateRoot":"0x29f32984517a7d25607da485b23cefabfd443751422ca7e603395e1de9bc8a4b","receiptsRoot":"0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2","miner":"0x0000000000000000000000000000000000000000","difficulty":"0x0","totalDifficulty":"0x0","extraData":"0x","size":"0x3e8","gasLimit":"0x6691b7","gasUsed":"0x5208","timestamp":"0x5ecedbb9","transactions":[{"hash":"0xc3c5f700243de37ae986082fd2af88d2a7c2752a0c0f7b9d6ac47c729d45e067","nonce":"0x2","blockHash":"0xda53da08ef6a3cbde84c33e51c04f68c3853b6a3731f10baa2324968eee63972","blockNumber":"0x3","transactionIndex":"0x0","from":"0xfdcedc3bfca10ecb0890337fbdd1977aba84807a","to":"0xdca8ce283150ab773bcbeb8d38289bdb5661de1e","value":"0x0","gas":"0x15f90","gasPrice":"0x4a817c800","input":"0x","v":"0x25","r":"0x19f2694eb9113656dbea0b925e2e7ceb43df83e601c4116aee9c0dd99130be88","s":"0x73e5764b324a4f7679d890a198ba658ba1c8cd36983ff9797e10b1b89dbb448e"}],"uncles":[]}"#; + let _block: Block = serde_json::from_str(&block).unwrap(); + } +} diff --git a/crates/ethers-types/src/ens.rs b/crates/ethers-types/src/ens.rs index 1a337582..3acec927 100644 --- a/crates/ethers-types/src/ens.rs +++ b/crates/ethers-types/src/ens.rs @@ -5,7 +5,9 @@ use serde::{ser::Error as SerializationError, Deserialize, Deserializer, Seriali /// ENS name or Ethereum Address. Not RLP encoded/serialized if it's a name #[derive(Clone, Debug, PartialEq, Eq)] pub enum NameOrAddress { + /// An ENS Name (format does not get checked) Name(String), + /// An Ethereum Address Address(Address), } @@ -19,6 +21,14 @@ impl Encodable for &NameOrAddress { } } +impl Encodable for NameOrAddress { + fn rlp_append(&self, s: &mut RlpStream) { + if let NameOrAddress::Address(inner) = self { + inner.rlp_append(s); + } + } +} + impl From<&str> for NameOrAddress { fn from(s: &str) -> Self { NameOrAddress::Name(s.to_owned()) @@ -58,3 +68,55 @@ impl<'de> Deserialize<'de> for NameOrAddress { Ok(NameOrAddress::Address(inner)) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn rlp_name_not_serialized() { + let name = NameOrAddress::Name("ens.eth".to_string()); + + let mut rlp = RlpStream::new(); + name.rlp_append(&mut rlp); + assert!(rlp.is_empty()); + + let mut rlp = RlpStream::new(); + (&name).rlp_append(&mut rlp); + assert!(rlp.is_empty()); + } + + #[test] + fn rlp_address_serialized() { + let addr = "f02c1c8e6114b1dbe8937a39260b5b0a374432bb".parse().unwrap(); + let union = NameOrAddress::Address(addr); + + let mut expected = RlpStream::new(); + addr.rlp_append(&mut expected); + + let mut rlp = RlpStream::new(); + union.rlp_append(&mut rlp); + assert_eq!(rlp.as_raw(), expected.as_raw()); + + let mut rlp = RlpStream::new(); + (&union).rlp_append(&mut rlp); + assert_eq!(rlp.as_raw(), expected.as_raw()); + } + + #[test] + fn serde_name_not_serialized() { + let name = NameOrAddress::Name("ens.eth".to_string()); + bincode::serialize(&name).unwrap_err(); + } + + #[test] + fn serde_address_serialized() { + let addr = "f02c1c8e6114b1dbe8937a39260b5b0a374432bb".parse().unwrap(); + let union = NameOrAddress::Address(addr); + + assert_eq!( + bincode::serialize(&addr).unwrap(), + bincode::serialize(&union).unwrap(), + ); + } +} diff --git a/crates/ethers-types/src/keys.rs b/crates/ethers-types/src/keys.rs index f80e1989..053d0fd0 100644 --- a/crates/ethers-types/src/keys.rs +++ b/crates/ethers-types/src/keys.rs @@ -3,7 +3,8 @@ use ethers_utils::{hash_message, keccak256}; use rand::Rng; use secp256k1::{ - key::ONE_KEY, Error as SecpError, Message, PublicKey as PubKey, Secp256k1, SecretKey, + key::ONE_KEY, Error as SecpError, Message, PublicKey as PubKey, recovery::RecoveryId, Secp256k1, + SecretKey, }; use std::ops::Deref; use std::str::FromStr; @@ -119,14 +120,7 @@ impl PrivateKey { .sign_recoverable(message, &self.0) .serialize_compact(); - let standard_v = recovery_id.to_i32() as u64; - let v = if let Some(chain_id) = chain_id { - // When signing with a chain ID, add chain replay protection. - standard_v + 35 + chain_id.as_u64() * 2 - } else { - // Otherwise, convert to 'Electrum' notation. - standard_v + 27 - }; + let v = to_eip155_v(recovery_id, chain_id); let r = H256::from_slice(&signature[..32]); let s = H256::from_slice(&signature[32..]); @@ -135,6 +129,17 @@ impl PrivateKey { } } +fn to_eip155_v(recovery_id: RecoveryId, chain_id: Option) -> u64 { + let standard_v = recovery_id.to_i32() as u64; + if let Some(chain_id) = chain_id { + // When signing with a chain ID, add chain replay protection. + standard_v + 35 + chain_id.as_u64() * 2 + } else { + // Otherwise, convert to 'Electrum' notation. + standard_v + 27 + } +} + impl Default for PrivateKey { fn default() -> Self { PrivateKey(ONE_KEY)