From 000d2446b5850a1f7cee8de2749bd0757c29cd0c Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 22 Feb 2016 23:05:27 +0100 Subject: [PATCH 01/11] EIP8 --- util/src/crypto.rs | 22 +- util/src/network/connection.rs | 2 +- util/src/network/discovery.rs | 100 +++++++-- util/src/network/handshake.rs | 366 +++++++++++++++++++++++++++++---- 4 files changed, 429 insertions(+), 61 deletions(-) diff --git a/util/src/crypto.rs b/util/src/crypto.rs index 596265cd0..2d5516b6f 100644 --- a/util/src/crypto.rs +++ b/util/src/crypto.rs @@ -254,7 +254,7 @@ pub mod ecies { use crypto::*; /// Encrypt a message with a public key - pub fn encrypt(public: &Public, plain: &[u8]) -> Result { + pub fn encrypt(public: &Public, shared_mac: &[u8], plain: &[u8]) -> Result { use ::rcrypto::digest::Digest; use ::rcrypto::sha2::Sha256; use ::rcrypto::hmac::Hmac; @@ -284,13 +284,14 @@ pub mod ecies { let cipher_iv = &msgd[64..(64 + 16 + plain.len())]; hmac.input(cipher_iv); } + hmac.input(shared_mac); hmac.raw_result(&mut msgd[(64 + 16 + plain.len())..]); } Ok(msg) } /// Decrypt a message with a secret key - pub fn decrypt(secret: &Secret, encrypted: &[u8]) -> Result { + pub fn decrypt(secret: &Secret, shared_mac: &[u8], encrypted: &[u8]) -> Result { use ::rcrypto::digest::Digest; use ::rcrypto::sha2::Sha256; use ::rcrypto::hmac::Hmac; @@ -322,6 +323,7 @@ pub mod ecies { // Verify tag let mut hmac = Hmac::new(Sha256::new(), &mkey); hmac.input(cipher_with_iv); + hmac.input(shared_mac); let mut mac = H256::new(); hmac.raw_result(&mut mac); if &mac[..] != msg_mac { @@ -405,4 +407,20 @@ mod tests { let pair = KeyPair::from_secret(h256_from_hex("6f7b0d801bc7b5ce7bbd930b84fd0369b3eb25d09be58d64ba811091046f3aa2")).unwrap(); assert_eq!(pair.public().hex(), "101b3ef5a4ea7a1c7928e24c4c75fd053c235d7b80c22ae5c03d145d0ac7396e2a4ffff9adee3133a7b05044a5cee08115fd65145e5165d646bde371010d803c"); } + + #[test] + fn ecies_shared() { + let kp = KeyPair::create().unwrap(); + let message = b"So many books, so little time"; + + let shared = b"shared"; + let wrong_shared = b"incorrect"; + let encrypted = ecies::encrypt(kp.public(), shared, message).unwrap(); + assert!(encrypted[..] != message[..]); + assert_eq!(encrypted[0], 0x04); + + assert!(ecies::decrypt(kp.secret(), wrong_shared, &encrypted).is_err()); + let decrypted = ecies::decrypt(kp.secret(), shared, &encrypted).unwrap(); + assert_eq!(decrypted[..message.len()], message[..]); + } } diff --git a/util/src/network/connection.rs b/util/src/network/connection.rs index a7396ff33..55e688c91 100644 --- a/util/src/network/connection.rs +++ b/util/src/network/connection.rs @@ -279,7 +279,7 @@ impl EncryptedConnection { /// Create an encrypted connection out of the handshake. Consumes a handshake object. pub fn new(handshake: &mut Handshake) -> Result { - let shared = try!(crypto::ecdh::agree(handshake.ecdhe.secret(), &handshake.remote_public)); + let shared = try!(crypto::ecdh::agree(handshake.ecdhe.secret(), &handshake.remote_ephemeral)); let mut nonce_material = H512::new(); if handshake.originated { handshake.remote_nonce.copy_to(&mut nonce_material[0..32]); diff --git a/util/src/network/discovery.rs b/util/src/network/discovery.rs index 01d2da52c..e00837f8c 100644 --- a/util/src/network/discovery.rs +++ b/util/src/network/discovery.rs @@ -85,7 +85,8 @@ pub struct Discovery { discovery_id: NodeId, discovery_nodes: HashSet, node_buckets: Vec, - send_queue: VecDeque + send_queue: VecDeque, + check_timestamps: bool, } pub struct TableUpdates { @@ -107,6 +108,7 @@ impl Discovery { node_buckets: (0..NODE_BINS).map(|_| NodeBucket::new()).collect(), udp_socket: socket, send_queue: VecDeque::new(), + check_timestamps: true, } } @@ -347,20 +349,20 @@ impl Discovery { } } + fn check_timestamp(&self, timestamp: u64) -> Result<(), NetworkError>{ + if self.check_timestamps && timestamp < time::get_time().sec as u64{ + debug!(target: "discovery", "Expired packet"); + return Err(NetworkError::Expired); + } + Ok(()) + } + fn on_ping(&mut self, rlp: &UntrustedRlp, node: &NodeId, from: &SocketAddr) -> Result, NetworkError> { trace!(target: "discovery", "Got Ping from {:?}", &from); - let version: u32 = try!(rlp.val_at(0)); - if version != PROTOCOL_VERSION { - debug!(target: "discovery", "Unexpected protocol version: {}", version); - return Err(NetworkError::BadProtocol); - } let source = try!(NodeEndpoint::from_rlp(&try!(rlp.at(1)))); let dest = try!(NodeEndpoint::from_rlp(&try!(rlp.at(2)))); let timestamp: u64 = try!(rlp.val_at(3)); - if timestamp < time::get_time().sec as u64{ - debug!(target: "discovery", "Expired ping"); - return Err(NetworkError::Expired); - } + try!(self.check_timestamp(timestamp)); let mut added_map = HashMap::new(); let entry = NodeEntry { id: node.clone(), endpoint: source.clone() }; if !entry.endpoint.is_valid() || !entry.endpoint.is_global() { @@ -384,9 +386,7 @@ impl Discovery { // TODO: validate pong packet let dest = try!(NodeEndpoint::from_rlp(&try!(rlp.at(0)))); let timestamp: u64 = try!(rlp.val_at(2)); - if timestamp < time::get_time().sec as u64 { - return Err(NetworkError::Expired); - } + try!(self.check_timestamp(timestamp)); let mut entry = NodeEntry { id: node.clone(), endpoint: dest }; if !entry.endpoint.is_valid() { debug!(target: "discovery", "Bad address: {:?}", entry); @@ -402,10 +402,7 @@ impl Discovery { trace!(target: "discovery", "Got FindNode from {:?}", &from); let target: NodeId = try!(rlp.val_at(0)); let timestamp: u64 = try!(rlp.val_at(1)); - if timestamp < time::get_time().sec as u64 { - return Err(NetworkError::Expired); - } - + try!(self.check_timestamp(timestamp)); let limit = (MAX_DATAGRAM_SIZE - 109) / 90; let nearest = Discovery::nearest_node_entries(&target, &self.node_buckets); if nearest.is_empty() { @@ -504,6 +501,7 @@ mod tests { use network::node_table::*; use crypto::KeyPair; use std::str::FromStr; + use rustc_serialize::hex::FromHex; #[test] fn discovery() { @@ -543,7 +541,7 @@ mod tests { #[test] fn removes_expired() { let key = KeyPair::create().unwrap(); - let ep = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40446").unwrap(), udp_port: 40444 }; + let ep = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40446").unwrap(), udp_port: 40447 }; let mut discovery = Discovery::new(&key, ep.address.clone(), ep.clone(), 0); for _ in 0..1200 { discovery.add_node(NodeEntry { id: NodeId::random(), endpoint: ep.clone() }); @@ -552,4 +550,70 @@ mod tests { let removed = discovery.check_expired(true).len(); assert!(removed > 0); } + + #[test] + fn packets() { + let key = KeyPair::create().unwrap(); + let ep = NodeEndpoint { address: SocketAddr::from_str("127.0.0.1:40447").unwrap(), udp_port: 40447 }; + let mut discovery = Discovery::new(&key, ep.address.clone(), ep.clone(), 0); + discovery.check_timestamps = false; + let from = SocketAddr::from_str("99.99.99.99:40445").unwrap(); + + let packet = "\ + e9614ccfd9fc3e74360018522d30e1419a143407ffcce748de3e22116b7e8dc92ff74788c0b6663a\ + aa3d67d641936511c8f8d6ad8698b820a7cf9e1be7155e9a241f556658c55428ec0563514365799a\ + 4be2be5a685a80971ddcfa80cb422cdd0101ec04cb847f000001820cfa8215a8d790000000000000\ + 000000000000000000018208ae820d058443b9a3550102\ + ".from_hex().unwrap(); + assert!(discovery.on_packet(&packet, from.clone()).is_ok()); + + let packet = "\ + 577be4349c4dd26768081f58de4c6f375a7a22f3f7adda654d1428637412c3d7fe917cadc56d4e5e\ + 7ffae1dbe3efffb9849feb71b262de37977e7c7a44e677295680e9e38ab26bee2fcbae207fba3ff3\ + d74069a50b902a82c9903ed37cc993c50001f83e82022bd79020010db83c4d001500000000abcdef\ + 12820cfa8215a8d79020010db885a308d313198a2e037073488208ae82823a8443b9a355c5010203\ + 040531b9019afde696e582a78fa8d95ea13ce3297d4afb8ba6433e4154caa5ac6431af1b80ba7602\ + 3fa4090c408f6b4bc3701562c031041d4702971d102c9ab7fa5eed4cd6bab8f7af956f7d565ee191\ + 7084a95398b6a21eac920fe3dd1345ec0a7ef39367ee69ddf092cbfe5b93e5e568ebc491983c09c7\ + 6d922dc3\ + ".from_hex().unwrap(); + assert!(discovery.on_packet(&packet, from.clone()).is_ok()); + + let packet = "\ + 09b2428d83348d27cdf7064ad9024f526cebc19e4958f0fdad87c15eb598dd61d08423e0bf66b206\ + 9869e1724125f820d851c136684082774f870e614d95a2855d000f05d1648b2d5945470bc187c2d2\ + 216fbe870f43ed0909009882e176a46b0102f846d79020010db885a308d313198a2e037073488208\ + ae82823aa0fbc914b16819237dcd8801d7e53f69e9719adecb3cc0e790c57e91ca4461c9548443b9\ + a355c6010203c2040506a0c969a58f6f9095004c0177a6b47f451530cab38966a25cca5cb58f0555 + 42124e\ + ".from_hex().unwrap(); + assert!(discovery.on_packet(&packet, from.clone()).is_ok()); + + let packet = "\ + c7c44041b9f7c7e41934417ebac9a8e1a4c6298f74553f2fcfdcae6ed6fe53163eb3d2b52e39fe91\ + 831b8a927bf4fc222c3902202027e5e9eb812195f95d20061ef5cd31d502e47ecb61183f74a504fe\ + 04c51e73df81f25c4d506b26db4517490103f84eb840ca634cae0d49acb401d8a4c6b6fe8c55b70d\ + 115bf400769cc1400f3258cd31387574077f301b421bc84df7266c44e9e6d569fc56be0081290476\ + 7bf5ccd1fc7f8443b9a35582999983999999280dc62cc8255c73471e0a61da0c89acdc0e035e260a\ + dd7fc0c04ad9ebf3919644c91cb247affc82b69bd2ca235c71eab8e49737c937a2c396\ + ".from_hex().unwrap(); + assert!(discovery.on_packet(&packet, from.clone()).is_ok()); + + let packet = "\ + c679fc8fe0b8b12f06577f2e802d34f6fa257e6137a995f6f4cbfc9ee50ed3710faf6e66f932c4c8\ + d81d64343f429651328758b47d3dbc02c4042f0fff6946a50f4a49037a72bb550f3a7872363a83e1\ + b9ee6469856c24eb4ef80b7535bcf99c0004f9015bf90150f84d846321163782115c82115db84031\ + 55e1427f85f10a5c9a7755877748041af1bcd8d474ec065eb33df57a97babf54bfd2103575fa8291\ + 15d224c523596b401065a97f74010610fce76382c0bf32f84984010203040101b840312c55512422\ + cf9b8a4097e9a6ad79402e87a15ae909a4bfefa22398f03d20951933beea1e4dfa6f968212385e82\ + 9f04c2d314fc2d4e255e0d3bc08792b069dbf8599020010db83c4d001500000000abcdef12820d05\ + 820d05b84038643200b172dcfef857492156971f0e6aa2c538d8b74010f8e140811d53b98c765dd2\ + d96126051913f44582e8c199ad7c6d6819e9a56483f637feaac9448aacf8599020010db885a308d3\ + 13198a2e037073488203e78203e8b8408dcab8618c3253b558d459da53bd8fa68935a719aff8b811\ + 197101a4b2b47dd2d47295286fc00cc081bb542d760717d1bdd6bec2c37cd72eca367d6dd3b9df73\ + 8443b9a355010203b525a138aa34383fec3d2719a0\ + ".from_hex().unwrap(); + assert!(discovery.on_packet(&packet, from.clone()).is_ok()); + } + } diff --git a/util/src/network/handshake.rs b/util/src/network/handshake.rs index 087de63b3..30dd70c79 100644 --- a/util/src/network/handshake.rs +++ b/util/src/network/handshake.rs @@ -15,9 +15,11 @@ // along with Parity. If not, see . use std::sync::Arc; +use rand::random; use mio::*; use mio::tcp::*; use hash::*; +use rlp::*; use sha3::Hashable; use bytes::Bytes; use crypto::*; @@ -36,8 +38,12 @@ enum HandshakeState { New, /// Waiting for auth packet ReadingAuth, + /// Waiting for extended auth packet + ReadingAuthEip8, /// Waiting for ack packet ReadingAck, + /// Waiting for extended ack packet + ReadingAckEip8, /// Ready to start a session StartSession, } @@ -57,9 +63,11 @@ pub struct Handshake { /// Connection nonce pub nonce: H256, /// Handshake public key - pub remote_public: Public, + pub remote_ephemeral: Public, /// Remote connection nonce. pub remote_nonce: H256, + /// Remote RLPx protocol version. + pub remote_version: u64, /// A copy of received encryped auth packet pub auth_cipher: Bytes, /// A copy of received encryped ack packet @@ -68,9 +76,12 @@ pub struct Handshake { pub expired: bool, } -const AUTH_PACKET_SIZE: usize = 307; -const ACK_PACKET_SIZE: usize = 210; +const V4_AUTH_PACKET_SIZE: usize = 307; +const V4_ACK_PACKET_SIZE: usize = 210; const HANDSHAKE_TIMEOUT: u64 = 5000; +const PROTOCOL_VERSION: u64 = 4; +// Amount of bytes added when encrypting with encryptECIES. +const ECIES_OVERHEAD: usize = 113; impl Handshake { /// Create a new handshake object @@ -82,8 +93,9 @@ impl Handshake { state: HandshakeState::New, ecdhe: try!(KeyPair::create()), nonce: nonce.clone(), - remote_public: Public::new(), + remote_ephemeral: Public::new(), remote_nonce: H256::new(), + remote_version: PROTOCOL_VERSION, auth_cipher: Bytes::new(), ack_cipher: Bytes::new(), expired: false, @@ -115,11 +127,11 @@ impl Handshake { self.originated = originated; io.register_timer(self.connection.token, HANDSHAKE_TIMEOUT).ok(); if originated { - try!(self.write_auth(host)); + try!(self.write_auth(host.secret(), host.id())); } else { self.state = HandshakeState::ReadingAuth; - self.connection.expect(AUTH_PACKET_SIZE); + self.connection.expect(V4_AUTH_PACKET_SIZE); }; Ok(()) } @@ -134,20 +146,28 @@ impl Handshake { if !self.expired() { io.clear_timer(self.connection.token).unwrap(); match self.state { + HandshakeState::New => {} HandshakeState::ReadingAuth => { if let Some(data) = try!(self.connection.readable()) { - try!(self.read_auth(host, &data)); - try!(self.write_ack()); + try!(self.read_auth(host.secret(), &data)); + }; + }, + HandshakeState::ReadingAuthEip8 => { + if let Some(data) = try!(self.connection.readable()) { + try!(self.read_auth_eip8(host.secret(), &data)); }; }, HandshakeState::ReadingAck => { if let Some(data) = try!(self.connection.readable()) { - try!(self.read_ack(host, &data)); - self.state = HandshakeState::StartSession; + try!(self.read_ack(host.secret(), &data)); + }; + }, + HandshakeState::ReadingAckEip8 => { + if let Some(data) = try!(self.connection.readable()) { + try!(self.read_ack_eip8(host.secret(), &data)); }; }, HandshakeState::StartSession => {}, - _ => { panic!("Unexpected state"); } } if self.state != HandshakeState::StartSession { try!(io.update_registration(self.connection.token)); @@ -190,48 +210,105 @@ impl Handshake { Ok(()) } + fn set_auth(&mut self, host_secret: &Secret, sig: &[u8], remote_public: &[u8], remote_nonce: &[u8], remote_version: u64) -> Result<(), UtilError> { + self.id.clone_from_slice(remote_public); + self.remote_nonce.clone_from_slice(remote_nonce); + self.remote_version = remote_version; + let shared = try!(ecdh::agree(host_secret, &self.id)); + let signature = Signature::from_slice(sig); + self.remote_ephemeral = try!(ec::recover(&signature, &(&shared ^ &self.remote_nonce))); + Ok(()) + } + /// Parse, validate and confirm auth message - fn read_auth(&mut self, host: &HostInfo, data: &[u8]) -> Result<(), UtilError> { - trace!(target:"net", "Received handshake auth to {:?}", self.connection.socket.peer_addr()); - if data.len() != AUTH_PACKET_SIZE { + fn read_auth(&mut self, secret: &Secret, data: &[u8]) -> Result<(), UtilError> { + trace!(target:"net", "Received handshake auth from {:?}", self.connection.socket.peer_addr()); + if data.len() != V4_AUTH_PACKET_SIZE { debug!(target:"net", "Wrong auth packet size"); return Err(From::from(NetworkError::BadProtocol)); } self.auth_cipher = data.to_vec(); - let auth = try!(ecies::decrypt(host.secret(), data)); - let (sig, rest) = auth.split_at(65); - let (hepubk, rest) = rest.split_at(32); - let (pubk, rest) = rest.split_at(64); - let (nonce, _) = rest.split_at(32); - self.id.clone_from_slice(pubk); - self.remote_nonce.clone_from_slice(nonce); - let shared = try!(ecdh::agree(host.secret(), &self.id)); - let signature = Signature::from_slice(sig); - let spub = try!(ec::recover(&signature, &(&shared ^ &self.remote_nonce))); - self.remote_public = spub.clone(); - if &spub.sha3()[..] != hepubk { - trace!(target:"net", "Handshake hash mismath with {:?}", self.connection.socket.peer_addr()); - return Err(From::from(NetworkError::Auth)); - }; + match ecies::decrypt(secret, &[], data) { + Ok(auth) => { + let (sig, rest) = auth.split_at(65); + let (_, rest) = rest.split_at(32); + let (pubk, rest) = rest.split_at(64); + let (nonce, _) = rest.split_at(32); + try!(self.set_auth(secret, sig, pubk, nonce, PROTOCOL_VERSION)); + try!(self.write_ack()); + } + Err(_) => { + // Try to interpret as EIP-8 packet + let size = ((data[0] as u16) << 8 | (data[1] as u16)) as usize; + if size < V4_AUTH_PACKET_SIZE - 2 { + debug!(target:"net", "Wrong EIP8 auth packet size"); + return Err(From::from(NetworkError::BadProtocol)); + } + let rest = size - data.len() + 2; + self.state = HandshakeState::ReadingAuthEip8; + self.connection.expect(rest); + } + } + Ok(()) + } + + fn read_auth_eip8(&mut self, secret: &Secret, data: &[u8]) -> Result<(), UtilError> { + trace!(target:"net", "Received EIP8 handshake auth from {:?}", self.connection.socket.peer_addr()); + self.auth_cipher.extend_from_slice(data); + let auth = try!(ecies::decrypt(secret, &self.auth_cipher[0..2], &self.auth_cipher[2..])); + let rlp = UntrustedRlp::new(&auth); + let signature: Signature = try!(rlp.val_at(0)); + let remote_public: Public = try!(rlp.val_at(1)); + let remote_nonce: H256 = try!(rlp.val_at(2)); + let remote_version: u64 = try!(rlp.val_at(3)); + try!(self.set_auth(secret, &signature, &remote_public, &remote_nonce, remote_version)); + try!(self.write_ack_eip8()); Ok(()) } /// Parse and validate ack message - fn read_ack(&mut self, host: &HostInfo, data: &[u8]) -> Result<(), UtilError> { + fn read_ack(&mut self, secret: &Secret, data: &[u8]) -> Result<(), UtilError> { trace!(target:"net", "Received handshake auth to {:?}", self.connection.socket.peer_addr()); - if data.len() != ACK_PACKET_SIZE { + if data.len() != V4_ACK_PACKET_SIZE { debug!(target:"net", "Wrong ack packet size"); return Err(From::from(NetworkError::BadProtocol)); } self.ack_cipher = data.to_vec(); - let ack = try!(ecies::decrypt(host.secret(), data)); - self.remote_public.clone_from_slice(&ack[0..64]); - self.remote_nonce.clone_from_slice(&ack[64..(64+32)]); + match ecies::decrypt(secret, &[], data) { + Ok(ack) => { + self.remote_ephemeral.clone_from_slice(&ack[0..64]); + self.remote_nonce.clone_from_slice(&ack[64..(64+32)]); + self.state = HandshakeState::StartSession; + } + Err(_) => { + // Try to interpret as EIP-8 packet + let size = ((data[0] as u16) << 8 | (data[1] as u16)) as usize; + if size < (V4_ACK_PACKET_SIZE - 2) { + debug!(target:"net", "Wrong EIP8 ack packet size"); + return Err(From::from(NetworkError::BadProtocol)); + } + let rest = size - data.len() + 2; + self.state = HandshakeState::ReadingAckEip8; + self.connection.expect(rest); + } + } + Ok(()) + } + + fn read_ack_eip8(&mut self, secret: &Secret, data: &[u8]) -> Result<(), UtilError> { + trace!(target:"net", "Received EIP8 handshake auth from {:?}", self.connection.socket.peer_addr()); + self.ack_cipher.extend_from_slice(data); + let ack = try!(ecies::decrypt(secret, &self.ack_cipher[0..2], &self.ack_cipher[2..])); + let rlp = UntrustedRlp::new(&ack); + self.remote_ephemeral = try!(rlp.val_at(0)); + self.remote_nonce = try!(rlp.val_at(1)); + self.remote_version = try!(rlp.val_at(2)); + self.state = HandshakeState::StartSession; Ok(()) } /// Sends auth message - fn write_auth(&mut self, host: &HostInfo) -> Result<(), UtilError> { + fn write_auth(&mut self, secret: &Secret, public: &Public) -> Result<(), UtilError> { trace!(target:"net", "Sending handshake auth to {:?}", self.connection.socket.peer_addr()); let mut data = [0u8; /*Signature::SIZE*/ 65 + /*H256::SIZE*/ 32 + /*Public::SIZE*/ 64 + /*H256::SIZE*/ 32 + 1]; //TODO: use associated constants let len = data.len(); @@ -243,16 +320,16 @@ impl Handshake { let (nonce, _) = rest.split_at_mut(32); // E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0) - let shared = try!(crypto::ecdh::agree(host.secret(), &self.id)); + let shared = try!(crypto::ecdh::agree(secret, &self.id)); try!(crypto::ec::sign(self.ecdhe.secret(), &(&shared ^ &self.nonce))).copy_to(sig); self.ecdhe.public().sha3_into(hepubk); - host.id().copy_to(pubk); + public.copy_to(pubk); self.nonce.copy_to(nonce); } - let message = try!(crypto::ecies::encrypt(&self.id, &data)); + let message = try!(crypto::ecies::encrypt(&self.id, &[], &data)); self.auth_cipher = message.clone(); self.connection.send(message); - self.connection.expect(ACK_PACKET_SIZE); + self.connection.expect(V4_ACK_PACKET_SIZE); self.state = HandshakeState::ReadingAck; Ok(()) } @@ -269,10 +346,219 @@ impl Handshake { self.ecdhe.public().copy_to(epubk); self.nonce.copy_to(nonce); } - let message = try!(crypto::ecies::encrypt(&self.id, &data)); + let message = try!(crypto::ecies::encrypt(&self.id, &[], &data)); self.ack_cipher = message.clone(); self.connection.send(message); self.state = HandshakeState::StartSession; Ok(()) } + + /// Sends EIP8 ack message + fn write_ack_eip8(&mut self) -> Result<(), UtilError> { + trace!(target:"net", "Sending EIP8 handshake ack to {:?}", self.connection.socket.peer_addr()); + let mut rlp = RlpStream::new_list(3); + rlp.append(self.ecdhe.public()); + rlp.append(&self.nonce); + rlp.append(&PROTOCOL_VERSION); + + let pad_array = [0u8; 200]; + let pad = &pad_array[0 .. 100 + random::() % 100]; + rlp.append_raw(pad, 0); + + let encoded = rlp.drain(); + let len = (encoded.len() + ECIES_OVERHEAD) as u16; + let prefix = [ (len & 0xff) as u8, (len >> 8) as u8 ]; + let message = try!(crypto::ecies::encrypt(&self.id, &prefix, &encoded)); + self.ack_cipher.extend_from_slice(&prefix); + self.ack_cipher.extend_from_slice(&message); + self.connection.send(self.ack_cipher.clone()); + self.state = HandshakeState::StartSession; + Ok(()) + } } + +#[cfg(test)] +mod test { + use std::sync::Arc; + use std::str::FromStr; + use rustc_serialize::hex::FromHex; + use super::*; + use crypto::*; + use hash::*; + use std::net::SocketAddr; + use mio::tcp::TcpStream; + use network::stats::NetworkStats; + + fn check_auth(h: &Handshake, version: u64) { + assert_eq!(h.id, Public::from_str("fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877").unwrap()); + assert_eq!(h.remote_nonce, H256::from_str("7e968bba13b6c50e2c4cd7f241cc0d64d1ac25c7f5952df231ac6a2bda8ee5d6").unwrap()); + assert_eq!(h.remote_ephemeral, Public::from_str("654d1044b69c577a44e5f01a1209523adb4026e70c62d1c13a067acabc09d2667a49821a0ad4b634554d330a15a58fe61f8a8e0544b310c6de7b0c8da7528a8d").unwrap()); + assert_eq!(h.remote_version, version); + } + + fn check_ack(h: &Handshake, version: u64) { + assert_eq!(h.remote_nonce, H256::from_str("559aead08264d5795d3909718cdd05abd49572e84fe55590eef31a88a08fdffd").unwrap()); + assert_eq!(h.remote_ephemeral, Public::from_str("b6d82fa3409da933dbf9cb0140c5dde89f4e64aec88d476af648880f4a10e1e49fe35ef3e69e93dd300b4797765a747c6384a6ecf5db9c2690398607a86181e4").unwrap()); + assert_eq!(h.remote_version, version); + } + + fn create_handshake(to: Option<&Public>) -> Handshake { + let addr = SocketAddr::from_str("127.0.0.1:50556").unwrap(); + let socket = TcpStream::connect(&addr).unwrap(); + let nonce = H256::new(); + Handshake::new(0, to, socket, &nonce, Arc::new(NetworkStats::new())).unwrap() + } + + #[test] + fn test_handshake_auth_plain() { + let mut h = create_handshake(None); + let secret = Secret::from_str("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291").unwrap(); + let auth = + "\ + 048ca79ad18e4b0659fab4853fe5bc58eb83992980f4c9cc147d2aa31532efd29a3d3dc6a3d89eaf\ + 913150cfc777ce0ce4af2758bf4810235f6e6ceccfee1acc6b22c005e9e3a49d6448610a58e98744\ + ba3ac0399e82692d67c1f58849050b3024e21a52c9d3b01d871ff5f210817912773e610443a9ef14\ + 2e91cdba0bd77b5fdf0769b05671fc35f83d83e4d3b0b000c6b2a1b1bba89e0fc51bf4e460df3105\ + c444f14be226458940d6061c296350937ffd5e3acaceeaaefd3c6f74be8e23e0f45163cc7ebd7622\ + 0f0128410fd05250273156d548a414444ae2f7dea4dfca2d43c057adb701a715bf59f6fb66b2d1d2\ + 0f2c703f851cbf5ac47396d9ca65b6260bd141ac4d53e2de585a73d1750780db4c9ee4cd4d225173\ + a4592ee77e2bd94d0be3691f3b406f9bba9b591fc63facc016bfa8\ + ".from_hex().unwrap(); + + h.read_auth(&secret, &auth).unwrap(); + assert_eq!(h.state, super::HandshakeState::StartSession); + check_auth(&h, 4); + } + + #[test] + fn test_handshake_auth_eip8() { + let mut h = create_handshake(None); + let secret = Secret::from_str("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291").unwrap(); + let auth = + "\ + 01b304ab7578555167be8154d5cc456f567d5ba302662433674222360f08d5f1534499d3678b513b\ + 0fca474f3a514b18e75683032eb63fccb16c156dc6eb2c0b1593f0d84ac74f6e475f1b8d56116b84\ + 9634a8c458705bf83a626ea0384d4d7341aae591fae42ce6bd5c850bfe0b999a694a49bbbaf3ef6c\ + da61110601d3b4c02ab6c30437257a6e0117792631a4b47c1d52fc0f8f89caadeb7d02770bf999cc\ + 147d2df3b62e1ffb2c9d8c125a3984865356266bca11ce7d3a688663a51d82defaa8aad69da39ab6\ + d5470e81ec5f2a7a47fb865ff7cca21516f9299a07b1bc63ba56c7a1a892112841ca44b6e0034dee\ + 70c9adabc15d76a54f443593fafdc3b27af8059703f88928e199cb122362a4b35f62386da7caad09\ + c001edaeb5f8a06d2b26fb6cb93c52a9fca51853b68193916982358fe1e5369e249875bb8d0d0ec3\ + 6f917bc5e1eafd5896d46bd61ff23f1a863a8a8dcd54c7b109b771c8e61ec9c8908c733c0263440e\ + 2aa067241aaa433f0bb053c7b31a838504b148f570c0ad62837129e547678c5190341e4f1693956c\ + 3bf7678318e2d5b5340c9e488eefea198576344afbdf66db5f51204a6961a63ce072c8926c\ + ".from_hex().unwrap(); + + h.read_auth(&secret, &auth[0..super::V4_AUTH_PACKET_SIZE]).unwrap(); + assert_eq!(h.state, super::HandshakeState::ReadingAuthEip8); + h.read_auth_eip8(&secret, &auth[super::V4_AUTH_PACKET_SIZE..]).unwrap(); + assert_eq!(h.state, super::HandshakeState::StartSession); + check_auth(&h, 4); + } + + #[test] + fn test_handshake_auth_eip8_2() { + let mut h = create_handshake(None); + let secret = Secret::from_str("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291").unwrap(); + let auth = + "\ + 01b8044c6c312173685d1edd268aa95e1d495474c6959bcdd10067ba4c9013df9e40ff45f5bfd6f7\ + 2471f93a91b493f8e00abc4b80f682973de715d77ba3a005a242eb859f9a211d93a347fa64b597bf\ + 280a6b88e26299cf263b01b8dfdb712278464fd1c25840b995e84d367d743f66c0e54a586725b7bb\ + f12acca27170ae3283c1073adda4b6d79f27656993aefccf16e0d0409fe07db2dc398a1b7e8ee93b\ + cd181485fd332f381d6a050fba4c7641a5112ac1b0b61168d20f01b479e19adf7fdbfa0905f63352\ + bfc7e23cf3357657455119d879c78d3cf8c8c06375f3f7d4861aa02a122467e069acaf513025ff19\ + 6641f6d2810ce493f51bee9c966b15c5043505350392b57645385a18c78f14669cc4d960446c1757\ + 1b7c5d725021babbcd786957f3d17089c084907bda22c2b2675b4378b114c601d858802a55345a15\ + 116bc61da4193996187ed70d16730e9ae6b3bb8787ebcaea1871d850997ddc08b4f4ea668fbf3740\ + 7ac044b55be0908ecb94d4ed172ece66fd31bfdadf2b97a8bc690163ee11f5b575a4b44e36e2bfb2\ + f0fce91676fd64c7773bac6a003f481fddd0bae0a1f31aa27504e2a533af4cef3b623f4791b2cca6\ + d490\ + ".from_hex().unwrap(); + + h.read_auth(&secret, &auth[0..super::V4_AUTH_PACKET_SIZE]).unwrap(); + assert_eq!(h.state, super::HandshakeState::ReadingAuthEip8); + h.read_auth_eip8(&secret, &auth[super::V4_AUTH_PACKET_SIZE..]).unwrap(); + assert_eq!(h.state, super::HandshakeState::StartSession); + check_auth(&h, 56); + } + + #[test] + fn test_handshake_ack_plain() { + let remote = Public::from_str("fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877").unwrap(); + let mut h = create_handshake(Some(&remote)); + let secret = Secret::from_str("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee").unwrap(); + let ack = + "\ + 049f8abcfa9c0dc65b982e98af921bc0ba6e4243169348a236abe9df5f93aa69d99cadddaa387662\ + b0ff2c08e9006d5a11a278b1b3331e5aaabf0a32f01281b6f4ede0e09a2d5f585b26513cb794d963\ + 5a57563921c04a9090b4f14ee42be1a5461049af4ea7a7f49bf4c97a352d39c8d02ee4acc416388c\ + 1c66cec761d2bc1c72da6ba143477f049c9d2dde846c252c111b904f630ac98e51609b3b1f58168d\ + dca6505b7196532e5f85b259a20c45e1979491683fee108e9660edbf38f3add489ae73e3dda2c71b\ + d1497113d5c755e942d1\ + ".from_hex().unwrap(); + + h.read_ack(&secret, &ack).unwrap(); + assert_eq!(h.state, super::HandshakeState::StartSession); + check_ack(&h, 4); + } + + #[test] + fn test_handshake_ack_eip8() { + let remote = Public::from_str("fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877").unwrap(); + let mut h = create_handshake(Some(&remote)); + let secret = Secret::from_str("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee").unwrap(); + let ack = + "\ + 01ea0451958701280a56482929d3b0757da8f7fbe5286784beead59d95089c217c9b917788989470\ + b0e330cc6e4fb383c0340ed85fab836ec9fb8a49672712aeabbdfd1e837c1ff4cace34311cd7f4de\ + 05d59279e3524ab26ef753a0095637ac88f2b499b9914b5f64e143eae548a1066e14cd2f4bd7f814\ + c4652f11b254f8a2d0191e2f5546fae6055694aed14d906df79ad3b407d94692694e259191cde171\ + ad542fc588fa2b7333313d82a9f887332f1dfc36cea03f831cb9a23fea05b33deb999e85489e645f\ + 6aab1872475d488d7bd6c7c120caf28dbfc5d6833888155ed69d34dbdc39c1f299be1057810f34fb\ + e754d021bfca14dc989753d61c413d261934e1a9c67ee060a25eefb54e81a4d14baff922180c395d\ + 3f998d70f46f6b58306f969627ae364497e73fc27f6d17ae45a413d322cb8814276be6ddd13b885b\ + 201b943213656cde498fa0e9ddc8e0b8f8a53824fbd82254f3e2c17e8eaea009c38b4aa0a3f306e8\ + 797db43c25d68e86f262e564086f59a2fc60511c42abfb3057c247a8a8fe4fb3ccbadde17514b7ac\ + 8000cdb6a912778426260c47f38919a91f25f4b5ffb455d6aaaf150f7e5529c100ce62d6d92826a7\ + 1778d809bdf60232ae21ce8a437eca8223f45ac37f6487452ce626f549b3b5fdee26afd2072e4bc7\ + 5833c2464c805246155289f4\ + ".from_hex().unwrap(); + + h.read_ack(&secret, &ack[0..super::V4_ACK_PACKET_SIZE]).unwrap(); + assert_eq!(h.state, super::HandshakeState::ReadingAckEip8); + h.read_ack_eip8(&secret, &ack[super::V4_ACK_PACKET_SIZE..]).unwrap(); + assert_eq!(h.state, super::HandshakeState::StartSession); + check_ack(&h, 4); + } + + #[test] + fn test_handshake_ack_eip8_2() { + let remote = Public::from_str("fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877").unwrap(); + let mut h = create_handshake(Some(&remote)); + let secret = Secret::from_str("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee").unwrap(); + let ack = + "\ + 01f004076e58aae772bb101ab1a8e64e01ee96e64857ce82b1113817c6cdd52c09d26f7b90981cd7\ + ae835aeac72e1573b8a0225dd56d157a010846d888dac7464baf53f2ad4e3d584531fa203658fab0\ + 3a06c9fd5e35737e417bc28c1cbf5e5dfc666de7090f69c3b29754725f84f75382891c561040ea1d\ + dc0d8f381ed1b9d0d4ad2a0ec021421d847820d6fa0ba66eaf58175f1b235e851c7e2124069fbc20\ + 2888ddb3ac4d56bcbd1b9b7eab59e78f2e2d400905050f4a92dec1c4bdf797b3fc9b2f8e84a482f3\ + d800386186712dae00d5c386ec9387a5e9c9a1aca5a573ca91082c7d68421f388e79127a5177d4f8\ + 590237364fd348c9611fa39f78dcdceee3f390f07991b7b47e1daa3ebcb6ccc9607811cb17ce51f1\ + c8c2c5098dbdd28fca547b3f58c01a424ac05f869f49c6a34672ea2cbbc558428aa1fe48bbfd6115\ + 8b1b735a65d99f21e70dbc020bfdface9f724a0d1fb5895db971cc81aa7608baa0920abb0a565c9c\ + 436e2fd13323428296c86385f2384e408a31e104670df0791d93e743a3a5194ee6b076fb6323ca59\ + 3011b7348c16cf58f66b9633906ba54a2ee803187344b394f75dd2e663a57b956cb830dd7a908d4f\ + 39a2336a61ef9fda549180d4ccde21514d117b6c6fd07a9102b5efe710a32af4eeacae2cb3b1dec0\ + 35b9593b48b9d3ca4c13d245d5f04169b0b1\ + ".from_hex().unwrap(); + + h.read_ack(&secret, &ack[0..super::V4_ACK_PACKET_SIZE]).unwrap(); + assert_eq!(h.state, super::HandshakeState::ReadingAckEip8); + h.read_ack_eip8(&secret, &ack[super::V4_ACK_PACKET_SIZE..]).unwrap(); + assert_eq!(h.state, super::HandshakeState::StartSession); + check_ack(&h, 57); + } +} + From e3c8c99583e96466b00fa51514763eb3b84add6a Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Sat, 27 Feb 2016 15:02:02 +0300 Subject: [PATCH 02/11] finally caught mul bug --- util/src/uint.rs | 104 +++++++++++++++++++++++++++++------------------ 1 file changed, 65 insertions(+), 39 deletions(-) diff --git a/util/src/uint.rs b/util/src/uint.rs index b4940cfb8..97e7eecb3 100644 --- a/util/src/uint.rs +++ b/util/src/uint.rs @@ -173,53 +173,60 @@ macro_rules! uint_overflowing_mul { mov %rax, $0 mov %rdx, $1 - mov $6, %rax - mulq $9 + mov $5, %rax + mulq $10 add %rax, $1 + adc $$0, %rdx mov %rdx, $2 mov $5, %rax - mulq $10 - add %rax, $1 - adc %rdx, $2 - - mov $6, %rax - mulq $10 + mulq $11 add %rax, $2 + adc $$0, %rdx mov %rdx, $3 - mov $7, %rax - mulq $9 - add %rax, $2 - adc %rdx, $3 - - mov $5, %rax - mulq $11 - add %rax, $2 - adc %rdx, $3 - - mov $8, %rax - mulq $9 - adc %rax, $3 - adc $$0, %rdx - mov %rdx, %rcx - - mov $7, %rax - mulq $10 - add %rax, $3 - adc $$0, %rdx - or %rdx, %rcx - - mov $6, %rax - mulq $11 - add %rax, $3 - adc $$0, %rdx - or %rdx, %rcx - mov $5, %rax mulq $12 add %rax, $3 adc $$0, %rdx + mov %rdx, %rcx + + mov $6, %rax + mulq $9 + add %rax, $1 + adc %rdx, $2 + adc $$0, $3 + adc $$0, %rcx + + mov $6, %rax + mulq $10 + add %rax, $2 + adc %rdx, $3 + adc $$0, %rcx + adc $$0, $3 + adc $$0, %rcx + + mov $6, %rax + mulq $11 + add %rax, $3 + adc $$0, %rdx + or %rdx, %rcx + + mov $7, %rax + mulq $9 + add %rax, $2 + adc %rdx, $3 + adc $$0, %rcx + + mov $7, %rax + mulq $10 + add %rax, $3 + adc $$0, %rdx + or %rdx, %rcx + + mov $8, %rax + mulq $9 + add %rax, $3 or %rdx, %rcx cmpq $$0, %rcx @@ -251,15 +258,15 @@ macro_rules! uint_overflowing_mul { jrcxz 2f popcnt $7, %rcx - 2: - " + 2: + " : /* $0 */ "={r8}"(result[0]), /* $1 */ "={r9}"(result[1]), /* $2 */ "={r10}"(result[2]), /* $3 */ "={r11}"(result[3]), /* $4 */ "={rcx}"(overflow) : /* $5 */ "m"(self_t[0]), /* $6 */ "m"(self_t[1]), /* $7 */ "m"(self_t[2]), /* $8 */ "m"(self_t[3]), /* $9 */ "m"(other_t[0]), /* $10 */ "m"(other_t[1]), /* $11 */ "m"(other_t[2]), /* $12 */ "m"(other_t[3]) - : "rax", "rdx", "rbx" + : "rax", "rdx" : ); @@ -1533,6 +1540,8 @@ mod tests { #[test] fn u256_multi_muls() { + use hash::*; + let (result, _) = U256([0, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0])); assert_eq!(U256([0, 0, 0, 0]), result); @@ -1572,6 +1581,23 @@ mod tests { let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); assert_eq!(U256([1, 0, 0, 0]), result); + + let x1 = U256::from_str("0000000000000000000000000000000000000000000000000000012365124623").unwrap(); + let x2sqr_right = U256::from_str("000000000000000000000000000000000000000000014baeef72e0378e2328c9").unwrap(); + let x1sqr = x1 * x1; + assert_eq!(H256::from(x2sqr_right), H256::from(x1sqr)); + let x1cube = x1sqr * x1; + let x1cube_right = U256::from_str("0000000000000000000000000000000001798acde139361466f712813717897b").unwrap(); + assert_eq!(H256::from(x1cube_right), H256::from(x1cube)); + let x1quad = x1cube * x1; + let x1quad_right = U256::from_str("000000000000000000000001adbdd6bd6ff027485484b97f8a6a4c7129756dd1").unwrap(); + assert_eq!(H256::from(x1quad_right), H256::from(x1quad)); + let x1penta = x1quad * x1; + let x1penta_right = U256::from_str("00000000000001e92875ac24be246e1c57e0507e8c46cc8d233b77f6f4c72993").unwrap(); + assert_eq!(H256::from(x1penta_right), H256::from(x1penta)); + let x1septima = x1penta * x1; + let x1septima_right = U256::from_str("00022cca1da3f6e5722b7d3cc5bbfb486465ebc5a708dd293042f932d7eee119").unwrap(); + assert_eq!(H256::from(x1septima_right), H256::from(x1septima)); } #[test] From b2dd6ded1dbfc207ffc5275e1f17b04229bb9e1f Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 27 Feb 2016 15:02:05 +0100 Subject: [PATCH 03/11] Update discovery.rs --- util/src/network/discovery.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/src/network/discovery.rs b/util/src/network/discovery.rs index e00837f8c..f072b0a66 100644 --- a/util/src/network/discovery.rs +++ b/util/src/network/discovery.rs @@ -349,7 +349,7 @@ impl Discovery { } } - fn check_timestamp(&self, timestamp: u64) -> Result<(), NetworkError>{ + fn check_timestamp(&self, timestamp: u64) -> Result<(), NetworkError> { if self.check_timestamps && timestamp < time::get_time().sec as u64{ debug!(target: "discovery", "Expired packet"); return Err(NetworkError::Expired); From 213bfc4417b819d88c6c6eb0d7159115d4000f81 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 27 Feb 2016 15:05:13 +0100 Subject: [PATCH 04/11] Update handshake.rs --- util/src/network/handshake.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/util/src/network/handshake.rs b/util/src/network/handshake.rs index 30dd70c79..c3a898900 100644 --- a/util/src/network/handshake.rs +++ b/util/src/network/handshake.rs @@ -282,12 +282,12 @@ impl Handshake { } Err(_) => { // Try to interpret as EIP-8 packet - let size = ((data[0] as u16) << 8 | (data[1] as u16)) as usize; - if size < (V4_ACK_PACKET_SIZE - 2) { - debug!(target:"net", "Wrong EIP8 ack packet size"); + let total = (((data[0] as u16) << 8 | (data[1] as u16)) as usize) + 2; + if total < V4_ACK_PACKET_SIZE { + debug!(target: "net", "Wrong EIP8 ack packet size"); return Err(From::from(NetworkError::BadProtocol)); } - let rest = size - data.len() + 2; + let rest = total - data.len(); self.state = HandshakeState::ReadingAckEip8; self.connection.expect(rest); } From faa634789604e2a57c6aa223d1d0070b19bedc31 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 27 Feb 2016 15:07:21 +0100 Subject: [PATCH 05/11] Update handshake.rs --- util/src/network/handshake.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/util/src/network/handshake.rs b/util/src/network/handshake.rs index c3a898900..e6f14c6fc 100644 --- a/util/src/network/handshake.rs +++ b/util/src/network/handshake.rs @@ -239,12 +239,12 @@ impl Handshake { } Err(_) => { // Try to interpret as EIP-8 packet - let size = ((data[0] as u16) << 8 | (data[1] as u16)) as usize; - if size < V4_AUTH_PACKET_SIZE - 2 { + let total = (((data[0] as u16) << 8 | (data[1] as u16)) as usize) + 2; + if total < V4_AUTH_PACKET_SIZE { debug!(target:"net", "Wrong EIP8 auth packet size"); return Err(From::from(NetworkError::BadProtocol)); } - let rest = size - data.len() + 2; + let rest = total - data.len(); self.state = HandshakeState::ReadingAuthEip8; self.connection.expect(rest); } @@ -284,7 +284,7 @@ impl Handshake { // Try to interpret as EIP-8 packet let total = (((data[0] as u16) << 8 | (data[1] as u16)) as usize) + 2; if total < V4_ACK_PACKET_SIZE { - debug!(target: "net", "Wrong EIP8 ack packet size"); + debug!(target:"net", "Wrong EIP8 ack packet size"); return Err(From::from(NetworkError::BadProtocol)); } let rest = total - data.len(); From ec8c1cb5f9e0bb435770df9a56d25d6a3a2b05a4 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 27 Feb 2016 15:49:44 +0100 Subject: [PATCH 06/11] Make "random" trie tests fully determinate. --- util/src/trie/standardmap.rs | 25 +++++++++++----- util/src/trie/triedbmut.rs | 58 ++++++++++++------------------------ 2 files changed, 37 insertions(+), 46 deletions(-) diff --git a/util/src/trie/standardmap.rs b/util/src/trie/standardmap.rs index 98a5ae0f0..b7f3a9500 100644 --- a/util/src/trie/standardmap.rs +++ b/util/src/trie/standardmap.rs @@ -20,6 +20,7 @@ extern crate rand; use bytes::*; use sha3::*; use hash::*; +use rlp::encode; /// Alphabet to use when creating words for insertion into tries. pub enum Alphabet { @@ -39,6 +40,8 @@ pub enum ValueMode { Mirror, /// Randomly (50:50) 1 or 32 byte randomly string. Random, + /// RLP-encoded index. + Index, } /// Standard test map for profiling tries. @@ -89,19 +92,27 @@ impl StandardMap { /// Create the standard map (set of keys and values) for the object's fields. pub fn make(&self) -> Vec<(Bytes, Bytes)> { + self.make_with(&mut H256::new()) + } + + /// Create the standard map (set of keys and values) for the object's fields, using the given seed. + pub fn make_with(&self, seed: &mut H256) -> Vec<(Bytes, Bytes)> { let low = b"abcdef"; let mid = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_"; let mut d: Vec<(Bytes, Bytes)> = Vec::new(); - let mut seed = H256::new(); - for _ in 0..self.count { + for index in 0..self.count { let k = match self.alphabet { - Alphabet::All => Self::random_bytes(self.min_key, self.journal_key, &mut seed), - Alphabet::Low => Self::random_word(low, self.min_key, self.journal_key, &mut seed), - Alphabet::Mid => Self::random_word(mid, self.min_key, self.journal_key, &mut seed), - Alphabet::Custom(ref a) => Self::random_word(&a, self.min_key, self.journal_key, &mut seed), + Alphabet::All => Self::random_bytes(self.min_key, self.journal_key, seed), + Alphabet::Low => Self::random_word(low, self.min_key, self.journal_key, seed), + Alphabet::Mid => Self::random_word(mid, self.min_key, self.journal_key, seed), + Alphabet::Custom(ref a) => Self::random_word(&a, self.min_key, self.journal_key, seed), + }; + let v = match self.value_mode { + ValueMode::Mirror => k.clone(), + ValueMode::Random => Self::random_value(seed), + ValueMode::Index => encode(&index).to_vec(), }; - let v = match self.value_mode { ValueMode::Mirror => k.clone(), ValueMode::Random => Self::random_value(&mut seed) }; d.push((k, v)) } d diff --git a/util/src/trie/triedbmut.rs b/util/src/trie/triedbmut.rs index 2b4567264..829c1e518 100644 --- a/util/src/trie/triedbmut.rs +++ b/util/src/trie/triedbmut.rs @@ -687,31 +687,10 @@ mod tests { use super::*; use nibbleslice::*; use rlp::*; - use rand::random; - use std::collections::HashSet; - use bytes::{ToPretty,Bytes,Populatable}; + use bytes::ToPretty; use super::super::node::*; use super::super::trietraits::*; - - fn random_key(alphabet: &[u8], min_count: usize, journal_count: usize) -> Vec { - let mut ret: Vec = Vec::new(); - let r = min_count + if journal_count > 0 {random::() % journal_count} else {0}; - for _ in 0..r { - ret.push(alphabet[random::() % alphabet.len()]); - } - ret - } - - fn random_value_indexed(j: usize) -> Bytes { - match random::() % 2 { - 0 => encode(&j).to_vec(), - _ => { - let mut h = H256::new(); - h.as_slice_mut()[31] = j as u8; - encode(&h).to_vec() - }, - } - } + use super::super::standardmap::*; fn populate_trie<'db>(db: &'db mut HashDB, root: &'db mut H256, v: &[(Vec, Vec)]) -> TrieDBMut<'db> { let mut t = TrieDBMut::new(db, root); @@ -756,20 +735,18 @@ mod tests { };*/ // panic!(); + let mut seed = H256::new(); for test_i in 0..1 { if test_i % 50 == 0 { debug!("{:?} of 10000 stress tests done", test_i); } - let mut x: Vec<(Vec, Vec)> = Vec::new(); - let mut got: HashSet> = HashSet::new(); - let alphabet = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_"; - for j in 0..100usize { - let key = random_key(alphabet, 5, 0); - if !got.contains(&key) { - x.push((key.clone(), random_value_indexed(j))); - got.insert(key); - } - } + let x = StandardMap { + alphabet: Alphabet::Custom(b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_".to_vec()), + min_key: 5, + journal_key: 0, + value_mode: ValueMode::Index, + count: 100, + }.make_with(&mut seed); let real = trie_root(x.clone()); let mut memdb = MemoryDB::new(); @@ -1049,13 +1026,16 @@ mod tests { #[test] fn stress() { + let mut seed = H256::new(); for _ in 0..50 { - let mut x: Vec<(Vec, Vec)> = Vec::new(); - let alphabet = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_"; - for j in 0..4u32 { - let key = random_key(alphabet, 5, 1); - x.push((key, encode(&j).to_vec())); - } + let x = StandardMap { + alphabet: Alphabet::Custom(b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_".to_vec()), + min_key: 5, + journal_key: 0, + value_mode: ValueMode::Index, + count: 4, + }.make_with(&mut seed); + let real = trie_root(x.clone()); let mut memdb = MemoryDB::new(); let mut root = H256::new(); From e6bab014d1ca0e40726b29c7b88c7036f2c8fc2e Mon Sep 17 00:00:00 2001 From: arkpar Date: Sat, 27 Feb 2016 16:40:22 +0100 Subject: [PATCH 07/11] Fixed outgoing ack size --- util/src/network/handshake.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/src/network/handshake.rs b/util/src/network/handshake.rs index e6f14c6fc..0cfcbac3a 100644 --- a/util/src/network/handshake.rs +++ b/util/src/network/handshake.rs @@ -367,7 +367,7 @@ impl Handshake { let encoded = rlp.drain(); let len = (encoded.len() + ECIES_OVERHEAD) as u16; - let prefix = [ (len & 0xff) as u8, (len >> 8) as u8 ]; + let prefix = [ (len >> 8) as u8, (len & 0xff) as u8 ]; let message = try!(crypto::ecies::encrypt(&self.id, &prefix, &encoded)); self.ack_cipher.extend_from_slice(&prefix); self.ack_cipher.extend_from_slice(&message); From dc604c21b5bdc4dff5e39f8abd4bbb74be50b1d1 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Sat, 27 Feb 2016 18:43:38 +0300 Subject: [PATCH 08/11] most complete carry test ever --- util/src/uint.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/util/src/uint.rs b/util/src/uint.rs index 97e7eecb3..af0e4add0 100644 --- a/util/src/uint.rs +++ b/util/src/uint.rs @@ -1537,6 +1537,76 @@ mod tests { assert_eq!(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]), result); } + #[test] + fn u256_multi_carry_all() { + let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); + assert_eq!(U256([1, ::std::u64::MAX-1, 0, 0]), result); + + let (result, _) = U256([0, ::std::u64::MAX, 0, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); + assert_eq!(U256([0, 1, ::std::u64::MAX-1, 0]), result); + + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); + assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX-1, 0]), result); + + let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); + assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX-1, 0]), result); + + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]) + .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); + assert_eq!(U256([1, 0, ::std::u64::MAX-1, ::std::u64::MAX]), result); + + let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); + assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1]), result); + + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); + assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1]), result); + + let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul( + U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); + assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]), result); + + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) + .overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); + assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]), result); + + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]) + .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); + assert_eq!(U256([1, 0, ::std::u64::MAX, ::std::u64::MAX-1]), result); + + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]) + .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); + assert_eq!(U256([1, 0, ::std::u64::MAX, ::std::u64::MAX-1]), result); + + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) + .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); + assert_eq!(U256([1, 0, ::std::u64::MAX, ::std::u64::MAX]), result); + + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]) + .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); + assert_eq!(U256([1, 0, ::std::u64::MAX, ::std::u64::MAX]), result); + + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]) + .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); + assert_eq!(U256([1, 0, 0, ::std::u64::MAX-1]), result); + + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]) + .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); + assert_eq!(U256([1, 0, 0, ::std::u64::MAX]), result); + + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) + .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); + assert_eq!(U256([1, 0, 0, ::std::u64::MAX]), result); + + let (result, _) = U256([0, 0, 0, ::std::u64::MAX]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX])); + assert_eq!(U256([0, 0, 0, 0]), result); + + let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX])); + assert_eq!(U256([0, 0, 0, ::std::u64::MAX]), result); + + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) + .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); + assert_eq!(U256([1, 0, 0, 0]), result); + } #[test] fn u256_multi_muls() { From 4bdd5267b025822b0ec16bd89b3d61432b4f8eaf Mon Sep 17 00:00:00 2001 From: arkpar Date: Sat, 27 Feb 2016 16:44:47 +0100 Subject: [PATCH 09/11] Ack size test --- util/src/network/handshake.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/util/src/network/handshake.rs b/util/src/network/handshake.rs index 0cfcbac3a..cca133ba9 100644 --- a/util/src/network/handshake.rs +++ b/util/src/network/handshake.rs @@ -481,6 +481,9 @@ mod test { h.read_auth_eip8(&secret, &auth[super::V4_AUTH_PACKET_SIZE..]).unwrap(); assert_eq!(h.state, super::HandshakeState::StartSession); check_auth(&h, 56); + let ack = h.ack_cipher.clone(); + let total = (((ack[0] as u16) << 8 | (ack[1] as u16)) as usize) + 2; + assert_eq!(ack.len(), total); } #[test] From 019638628c68ea6020cd90938bab85e998c7de6f Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Sat, 27 Feb 2016 18:45:19 +0300 Subject: [PATCH 10/11] removed duplicates --- util/src/uint.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/util/src/uint.rs b/util/src/uint.rs index af0e4add0..ca8e2f4fd 100644 --- a/util/src/uint.rs +++ b/util/src/uint.rs @@ -1639,19 +1639,9 @@ mod tests { let (result, _) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 5, 0, 0])); assert_eq!(U256([0, 10, 0, 0]), result); - let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); - assert_eq!(U256([1, ::std::u64::MAX-1, 0, 0]), result); - - let (result, _) = U256([0, 0, 0, ::std::u64::MAX]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX])); - assert_eq!(U256([0, 0, 0, 0]), result); - let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX])); assert_eq!(U256([0, 0, 0, ::std::u64::MAX]), result); - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) - .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); - assert_eq!(U256([1, 0, 0, 0]), result); - let x1 = U256::from_str("0000000000000000000000000000000000000000000000000000012365124623").unwrap(); let x2sqr_right = U256::from_str("000000000000000000000000000000000000000000014baeef72e0378e2328c9").unwrap(); let x1sqr = x1 * x1; From 6a0e9c5ed0d88a83198f0abc8c86564a155d4893 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Sat, 27 Feb 2016 18:55:07 +0300 Subject: [PATCH 11/11] tabified --- util/src/uint.rs | 190 +++++++++++++++++++++++------------------------ 1 file changed, 95 insertions(+), 95 deletions(-) diff --git a/util/src/uint.rs b/util/src/uint.rs index ca8e2f4fd..b998784aa 100644 --- a/util/src/uint.rs +++ b/util/src/uint.rs @@ -1512,135 +1512,135 @@ mod tests { } - #[test] - fn u256_multi_subs() { - let (result, _) = U256([0, 0, 0, 0]).overflowing_sub(U256([0, 0, 0, 0])); - assert_eq!(result, U256([0, 0, 0, 0])); + #[test] + fn u256_multi_subs() { + let (result, _) = U256([0, 0, 0, 0]).overflowing_sub(U256([0, 0, 0, 0])); + assert_eq!(result, U256([0, 0, 0, 0])); - let (result, _) = U256([0, 0, 0, 1]).overflowing_sub(U256([0, 0, 0, 1])); - assert_eq!(result, U256([0, 0, 0, 0])); + let (result, _) = U256([0, 0, 0, 1]).overflowing_sub(U256([0, 0, 0, 1])); + assert_eq!(result, U256([0, 0, 0, 0])); - let (_, overflow) = U256([0, 0, 2, 1]).overflowing_sub(U256([0, 0, 3, 1])); - assert!(overflow); + let (_, overflow) = U256([0, 0, 2, 1]).overflowing_sub(U256([0, 0, 3, 1])); + assert!(overflow); - let (result, overflow) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) - .overflowing_sub(U256([::std::u64::MAX/2, ::std::u64::MAX/2, ::std::u64::MAX/2, ::std::u64::MAX/2])); - assert!(!overflow); - assert_eq!(U256([::std::u64::MAX/2+1, ::std::u64::MAX/2+1, ::std::u64::MAX/2+1, ::std::u64::MAX/2+1]), result); + let (result, overflow) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) + .overflowing_sub(U256([::std::u64::MAX/2, ::std::u64::MAX/2, ::std::u64::MAX/2, ::std::u64::MAX/2])); + assert!(!overflow); + assert_eq!(U256([::std::u64::MAX/2+1, ::std::u64::MAX/2+1, ::std::u64::MAX/2+1, ::std::u64::MAX/2+1]), result); - let (result, overflow) = U256([0, 0, 0, 1]).overflowing_sub(U256([0, 0, 1, 0])); - assert!(!overflow); - assert_eq!(U256([0, 0, ::std::u64::MAX, 0]), result); + let (result, overflow) = U256([0, 0, 0, 1]).overflowing_sub(U256([0, 0, 1, 0])); + assert!(!overflow); + assert_eq!(U256([0, 0, ::std::u64::MAX, 0]), result); - let (result, overflow) = U256([0, 0, 0, 1]).overflowing_sub(U256([1, 0, 0, 0])); - assert!(!overflow); - assert_eq!(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]), result); - } + let (result, overflow) = U256([0, 0, 0, 1]).overflowing_sub(U256([1, 0, 0, 0])); + assert!(!overflow); + assert_eq!(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]), result); + } #[test] fn u256_multi_carry_all() { - let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); - assert_eq!(U256([1, ::std::u64::MAX-1, 0, 0]), result); + let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); + assert_eq!(U256([1, ::std::u64::MAX-1, 0, 0]), result); - let (result, _) = U256([0, ::std::u64::MAX, 0, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); - assert_eq!(U256([0, 1, ::std::u64::MAX-1, 0]), result); + let (result, _) = U256([0, ::std::u64::MAX, 0, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); + assert_eq!(U256([0, 1, ::std::u64::MAX-1, 0]), result); - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); - assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX-1, 0]), result); + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); + assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX-1, 0]), result); - let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); - assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX-1, 0]), result); + let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); + assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX-1, 0]), result); - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]) + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]) .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); - assert_eq!(U256([1, 0, ::std::u64::MAX-1, ::std::u64::MAX]), result); + assert_eq!(U256([1, 0, ::std::u64::MAX-1, ::std::u64::MAX]), result); - let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); - assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1]), result); + let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); + assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1]), result); - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); - assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1]), result); + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); + assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1]), result); - let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul( + let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul( U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); - assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]), result); + assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]), result); - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) .overflowing_mul(U256([::std::u64::MAX, 0, 0, 0])); - assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]), result); + assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]), result); - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]) + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]) .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); - assert_eq!(U256([1, 0, ::std::u64::MAX, ::std::u64::MAX-1]), result); + assert_eq!(U256([1, 0, ::std::u64::MAX, ::std::u64::MAX-1]), result); - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]) + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]) .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); - assert_eq!(U256([1, 0, ::std::u64::MAX, ::std::u64::MAX-1]), result); + assert_eq!(U256([1, 0, ::std::u64::MAX, ::std::u64::MAX-1]), result); - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])); - assert_eq!(U256([1, 0, ::std::u64::MAX, ::std::u64::MAX]), result); + assert_eq!(U256([1, 0, ::std::u64::MAX, ::std::u64::MAX]), result); - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]) + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]) .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); - assert_eq!(U256([1, 0, ::std::u64::MAX, ::std::u64::MAX]), result); + assert_eq!(U256([1, 0, ::std::u64::MAX, ::std::u64::MAX]), result); - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]) + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]) .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); - assert_eq!(U256([1, 0, 0, ::std::u64::MAX-1]), result); + assert_eq!(U256([1, 0, 0, ::std::u64::MAX-1]), result); - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]) + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]) .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); - assert_eq!(U256([1, 0, 0, ::std::u64::MAX]), result); + assert_eq!(U256([1, 0, 0, ::std::u64::MAX]), result); - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])); - assert_eq!(U256([1, 0, 0, ::std::u64::MAX]), result); + assert_eq!(U256([1, 0, 0, ::std::u64::MAX]), result); - let (result, _) = U256([0, 0, 0, ::std::u64::MAX]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX])); - assert_eq!(U256([0, 0, 0, 0]), result); + let (result, _) = U256([0, 0, 0, ::std::u64::MAX]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX])); + assert_eq!(U256([0, 0, 0, 0]), result); - let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX])); - assert_eq!(U256([0, 0, 0, ::std::u64::MAX]), result); + let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX])); + assert_eq!(U256([0, 0, 0, ::std::u64::MAX]), result); - let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) + let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]) .overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])); - assert_eq!(U256([1, 0, 0, 0]), result); + assert_eq!(U256([1, 0, 0, 0]), result); } #[test] fn u256_multi_muls() { use hash::*; - let (result, _) = U256([0, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0])); - assert_eq!(U256([0, 0, 0, 0]), result); + let (result, _) = U256([0, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0])); + assert_eq!(U256([0, 0, 0, 0]), result); - let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([1, 0, 0, 0])); - assert_eq!(U256([1, 0, 0, 0]), result); + let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([1, 0, 0, 0])); + assert_eq!(U256([1, 0, 0, 0]), result); - let (result, _) = U256([5, 0, 0, 0]).overflowing_mul(U256([5, 0, 0, 0])); - assert_eq!(U256([25, 0, 0, 0]), result); + let (result, _) = U256([5, 0, 0, 0]).overflowing_mul(U256([5, 0, 0, 0])); + assert_eq!(U256([25, 0, 0, 0]), result); - let (result, _) = U256([0, 5, 0, 0]).overflowing_mul(U256([0, 5, 0, 0])); - assert_eq!(U256([0, 0, 25, 0]), result); + let (result, _) = U256([0, 5, 0, 0]).overflowing_mul(U256([0, 5, 0, 0])); + assert_eq!(U256([0, 0, 25, 0]), result); - let (result, _) = U256([0, 0, 0, 1]).overflowing_mul(U256([1, 0, 0, 0])); - assert_eq!(U256([0, 0, 0, 1]), result); + let (result, _) = U256([0, 0, 0, 1]).overflowing_mul(U256([1, 0, 0, 0])); + assert_eq!(U256([0, 0, 0, 1]), result); - let (result, _) = U256([0, 0, 0, 5]).overflowing_mul(U256([2, 0, 0, 0])); - assert_eq!(U256([0, 0, 0, 10]), result); + let (result, _) = U256([0, 0, 0, 5]).overflowing_mul(U256([2, 0, 0, 0])); + assert_eq!(U256([0, 0, 0, 10]), result); - let (result, _) = U256([0, 0, 1, 0]).overflowing_mul(U256([0, 5, 0, 0])); - assert_eq!(U256([0, 0, 0, 5]), result); + let (result, _) = U256([0, 0, 1, 0]).overflowing_mul(U256([0, 5, 0, 0])); + assert_eq!(U256([0, 0, 0, 5]), result); - let (result, _) = U256([0, 0, 8, 0]).overflowing_mul(U256([0, 0, 7, 0])); - assert_eq!(U256([0, 0, 0, 0]), result); + let (result, _) = U256([0, 0, 8, 0]).overflowing_mul(U256([0, 0, 7, 0])); + assert_eq!(U256([0, 0, 0, 0]), result); - let (result, _) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 5, 0, 0])); - assert_eq!(U256([0, 10, 0, 0]), result); + let (result, _) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 5, 0, 0])); + assert_eq!(U256([0, 10, 0, 0]), result); - let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX])); - assert_eq!(U256([0, 0, 0, ::std::u64::MAX]), result); + let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX])); + assert_eq!(U256([0, 0, 0, ::std::u64::MAX]), result); let x1 = U256::from_str("0000000000000000000000000000000000000000000000000000012365124623").unwrap(); let x2sqr_right = U256::from_str("000000000000000000000000000000000000000000014baeef72e0378e2328c9").unwrap(); @@ -1662,32 +1662,32 @@ mod tests { #[test] fn u256_multi_muls_overflow() { - let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0])); - assert!(!overflow); + let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0])); + assert!(!overflow); - let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX])); - assert!(!overflow); + let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX])); + assert!(!overflow); - let (_, overflow) = U256([0, 1, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX])); - assert!(overflow); + let (_, overflow) = U256([0, 1, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX])); + assert!(overflow); - let (_, overflow) = U256([0, 1, 0, 0]).overflowing_mul(U256([0, 1, 0, 0])); - assert!(!overflow); + let (_, overflow) = U256([0, 1, 0, 0]).overflowing_mul(U256([0, 1, 0, 0])); + assert!(!overflow); - let (_, overflow) = U256([0, 1, 0, ::std::u64::MAX]).overflowing_mul(U256([0, 1, 0, ::std::u64::MAX])); - assert!(overflow); + let (_, overflow) = U256([0, 1, 0, ::std::u64::MAX]).overflowing_mul(U256([0, 1, 0, ::std::u64::MAX])); + assert!(overflow); - let (_, overflow) = U256([0, ::std::u64::MAX, 0, 0]).overflowing_mul(U256([0, ::std::u64::MAX, 0, 0])); - assert!(!overflow); + let (_, overflow) = U256([0, ::std::u64::MAX, 0, 0]).overflowing_mul(U256([0, ::std::u64::MAX, 0, 0])); + assert!(!overflow); - let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([10, 0, 0, 0])); - assert!(!overflow); + let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([10, 0, 0, 0])); + assert!(!overflow); - let (_, overflow) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX / 2])); - assert!(!overflow); + let (_, overflow) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX / 2])); + assert!(!overflow); - let (_, overflow) = U256([0, 0, 8, 0]).overflowing_mul(U256([0, 0, 7, 0])); - assert!(overflow); + let (_, overflow) = U256([0, 0, 8, 0]).overflowing_mul(U256([0, 0, 7, 0])); + assert!(overflow); } }