Merge branch 'master' of github.com:ethcore/parity
This commit is contained in:
		
						commit
						a01d5f5c4a
					
				@ -254,7 +254,7 @@ pub mod ecies {
 | 
				
			|||||||
	use crypto::*;
 | 
						use crypto::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Encrypt a message with a public key
 | 
						/// Encrypt a message with a public key
 | 
				
			||||||
	pub fn encrypt(public: &Public, plain: &[u8]) -> Result<Bytes, CryptoError> {
 | 
						pub fn encrypt(public: &Public, shared_mac: &[u8], plain: &[u8]) -> Result<Bytes, CryptoError> {
 | 
				
			||||||
		use ::rcrypto::digest::Digest;
 | 
							use ::rcrypto::digest::Digest;
 | 
				
			||||||
		use ::rcrypto::sha2::Sha256;
 | 
							use ::rcrypto::sha2::Sha256;
 | 
				
			||||||
		use ::rcrypto::hmac::Hmac;
 | 
							use ::rcrypto::hmac::Hmac;
 | 
				
			||||||
@ -284,13 +284,14 @@ pub mod ecies {
 | 
				
			|||||||
				let cipher_iv = &msgd[64..(64 + 16 + plain.len())];
 | 
									let cipher_iv = &msgd[64..(64 + 16 + plain.len())];
 | 
				
			||||||
				hmac.input(cipher_iv);
 | 
									hmac.input(cipher_iv);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								hmac.input(shared_mac);
 | 
				
			||||||
			hmac.raw_result(&mut msgd[(64 + 16 + plain.len())..]);
 | 
								hmac.raw_result(&mut msgd[(64 + 16 + plain.len())..]);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		Ok(msg)
 | 
							Ok(msg)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Decrypt a message with a secret key
 | 
						/// Decrypt a message with a secret key
 | 
				
			||||||
	pub fn decrypt(secret: &Secret, encrypted: &[u8]) -> Result<Bytes, CryptoError> {
 | 
						pub fn decrypt(secret: &Secret, shared_mac: &[u8], encrypted: &[u8]) -> Result<Bytes, CryptoError> {
 | 
				
			||||||
		use ::rcrypto::digest::Digest;
 | 
							use ::rcrypto::digest::Digest;
 | 
				
			||||||
		use ::rcrypto::sha2::Sha256;
 | 
							use ::rcrypto::sha2::Sha256;
 | 
				
			||||||
		use ::rcrypto::hmac::Hmac;
 | 
							use ::rcrypto::hmac::Hmac;
 | 
				
			||||||
@ -322,6 +323,7 @@ pub mod ecies {
 | 
				
			|||||||
		// Verify tag
 | 
							// Verify tag
 | 
				
			||||||
		let mut hmac = Hmac::new(Sha256::new(), &mkey);
 | 
							let mut hmac = Hmac::new(Sha256::new(), &mkey);
 | 
				
			||||||
		hmac.input(cipher_with_iv);
 | 
							hmac.input(cipher_with_iv);
 | 
				
			||||||
 | 
							hmac.input(shared_mac);
 | 
				
			||||||
		let mut mac = H256::new();
 | 
							let mut mac = H256::new();
 | 
				
			||||||
		hmac.raw_result(&mut mac);
 | 
							hmac.raw_result(&mut mac);
 | 
				
			||||||
		if &mac[..] != msg_mac {
 | 
							if &mac[..] != msg_mac {
 | 
				
			||||||
@ -405,4 +407,20 @@ mod tests {
 | 
				
			|||||||
		let pair = KeyPair::from_secret(h256_from_hex("6f7b0d801bc7b5ce7bbd930b84fd0369b3eb25d09be58d64ba811091046f3aa2")).unwrap();
 | 
							let pair = KeyPair::from_secret(h256_from_hex("6f7b0d801bc7b5ce7bbd930b84fd0369b3eb25d09be58d64ba811091046f3aa2")).unwrap();
 | 
				
			||||||
		assert_eq!(pair.public().hex(), "101b3ef5a4ea7a1c7928e24c4c75fd053c235d7b80c22ae5c03d145d0ac7396e2a4ffff9adee3133a7b05044a5cee08115fd65145e5165d646bde371010d803c");
 | 
							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[..]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -279,7 +279,7 @@ impl EncryptedConnection {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/// Create an encrypted connection out of the handshake. Consumes a handshake object.
 | 
						/// Create an encrypted connection out of the handshake. Consumes a handshake object.
 | 
				
			||||||
	pub fn new(handshake: &mut Handshake) -> Result<EncryptedConnection, UtilError> {
 | 
						pub fn new(handshake: &mut Handshake) -> Result<EncryptedConnection, UtilError> {
 | 
				
			||||||
		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();
 | 
							let mut nonce_material = H512::new();
 | 
				
			||||||
		if handshake.originated {
 | 
							if handshake.originated {
 | 
				
			||||||
			handshake.remote_nonce.copy_to(&mut nonce_material[0..32]);
 | 
								handshake.remote_nonce.copy_to(&mut nonce_material[0..32]);
 | 
				
			||||||
 | 
				
			|||||||
@ -85,7 +85,8 @@ pub struct Discovery {
 | 
				
			|||||||
	discovery_id: NodeId,
 | 
						discovery_id: NodeId,
 | 
				
			||||||
	discovery_nodes: HashSet<NodeId>,
 | 
						discovery_nodes: HashSet<NodeId>,
 | 
				
			||||||
	node_buckets: Vec<NodeBucket>,
 | 
						node_buckets: Vec<NodeBucket>,
 | 
				
			||||||
	send_queue: VecDeque<Datagramm>
 | 
						send_queue: VecDeque<Datagramm>,
 | 
				
			||||||
 | 
						check_timestamps: bool,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct TableUpdates {
 | 
					pub struct TableUpdates {
 | 
				
			||||||
@ -107,6 +108,7 @@ impl Discovery {
 | 
				
			|||||||
			node_buckets: (0..NODE_BINS).map(|_| NodeBucket::new()).collect(),
 | 
								node_buckets: (0..NODE_BINS).map(|_| NodeBucket::new()).collect(),
 | 
				
			||||||
			udp_socket: socket,
 | 
								udp_socket: socket,
 | 
				
			||||||
			send_queue: VecDeque::new(),
 | 
								send_queue: VecDeque::new(),
 | 
				
			||||||
 | 
								check_timestamps: true,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -344,20 +346,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<Option<TableUpdates>, NetworkError> {
 | 
						fn on_ping(&mut self, rlp: &UntrustedRlp, node: &NodeId, from: &SocketAddr) -> Result<Option<TableUpdates>, NetworkError> {
 | 
				
			||||||
		trace!(target: "discovery", "Got Ping from {:?}", &from);
 | 
							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 source = try!(NodeEndpoint::from_rlp(&try!(rlp.at(1))));
 | 
				
			||||||
		let dest = try!(NodeEndpoint::from_rlp(&try!(rlp.at(2))));
 | 
							let dest = try!(NodeEndpoint::from_rlp(&try!(rlp.at(2))));
 | 
				
			||||||
		let timestamp: u64 = try!(rlp.val_at(3));
 | 
							let timestamp: u64 = try!(rlp.val_at(3));
 | 
				
			||||||
		if timestamp < time::get_time().sec as u64{
 | 
							try!(self.check_timestamp(timestamp));
 | 
				
			||||||
			debug!(target: "discovery", "Expired ping");
 | 
					 | 
				
			||||||
			return Err(NetworkError::Expired);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		let mut added_map = HashMap::new();
 | 
							let mut added_map = HashMap::new();
 | 
				
			||||||
		let entry = NodeEntry { id: node.clone(), endpoint: source.clone() };
 | 
							let entry = NodeEntry { id: node.clone(), endpoint: source.clone() };
 | 
				
			||||||
		if !entry.endpoint.is_valid() || !entry.endpoint.is_global() {
 | 
							if !entry.endpoint.is_valid() || !entry.endpoint.is_global() {
 | 
				
			||||||
@ -381,9 +383,7 @@ impl Discovery {
 | 
				
			|||||||
		// TODO: validate pong packet
 | 
							// TODO: validate pong packet
 | 
				
			||||||
		let dest = try!(NodeEndpoint::from_rlp(&try!(rlp.at(0))));
 | 
							let dest = try!(NodeEndpoint::from_rlp(&try!(rlp.at(0))));
 | 
				
			||||||
		let timestamp: u64 = try!(rlp.val_at(2));
 | 
							let timestamp: u64 = try!(rlp.val_at(2));
 | 
				
			||||||
		if timestamp < time::get_time().sec as u64 {
 | 
							try!(self.check_timestamp(timestamp));
 | 
				
			||||||
			return Err(NetworkError::Expired);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		let mut entry = NodeEntry { id: node.clone(), endpoint: dest };
 | 
							let mut entry = NodeEntry { id: node.clone(), endpoint: dest };
 | 
				
			||||||
		if !entry.endpoint.is_valid() {
 | 
							if !entry.endpoint.is_valid() {
 | 
				
			||||||
			debug!(target: "discovery", "Bad address: {:?}", entry);
 | 
								debug!(target: "discovery", "Bad address: {:?}", entry);
 | 
				
			||||||
@ -399,10 +399,7 @@ impl Discovery {
 | 
				
			|||||||
		trace!(target: "discovery", "Got FindNode from {:?}", &from);
 | 
							trace!(target: "discovery", "Got FindNode from {:?}", &from);
 | 
				
			||||||
		let target: NodeId = try!(rlp.val_at(0));
 | 
							let target: NodeId = try!(rlp.val_at(0));
 | 
				
			||||||
		let timestamp: u64 = try!(rlp.val_at(1));
 | 
							let timestamp: u64 = try!(rlp.val_at(1));
 | 
				
			||||||
		if timestamp < time::get_time().sec as u64 {
 | 
							try!(self.check_timestamp(timestamp));
 | 
				
			||||||
			return Err(NetworkError::Expired);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		let limit = (MAX_DATAGRAM_SIZE - 109) / 90;
 | 
							let limit = (MAX_DATAGRAM_SIZE - 109) / 90;
 | 
				
			||||||
		let nearest = Discovery::nearest_node_entries(&target, &self.node_buckets);
 | 
							let nearest = Discovery::nearest_node_entries(&target, &self.node_buckets);
 | 
				
			||||||
		if nearest.is_empty() {
 | 
							if nearest.is_empty() {
 | 
				
			||||||
@ -501,6 +498,7 @@ mod tests {
 | 
				
			|||||||
	use network::node_table::*;
 | 
						use network::node_table::*;
 | 
				
			||||||
	use crypto::KeyPair;
 | 
						use crypto::KeyPair;
 | 
				
			||||||
	use std::str::FromStr;
 | 
						use std::str::FromStr;
 | 
				
			||||||
 | 
						use rustc_serialize::hex::FromHex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[test]
 | 
						#[test]
 | 
				
			||||||
	fn discovery() {
 | 
						fn discovery() {
 | 
				
			||||||
@ -540,7 +538,7 @@ mod tests {
 | 
				
			|||||||
	#[test]
 | 
						#[test]
 | 
				
			||||||
	fn removes_expired() {
 | 
						fn removes_expired() {
 | 
				
			||||||
		let key = KeyPair::create().unwrap();
 | 
							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);
 | 
							let mut discovery = Discovery::new(&key, ep.address.clone(), ep.clone(), 0);
 | 
				
			||||||
		for _ in 0..1200 {
 | 
							for _ in 0..1200 {
 | 
				
			||||||
			discovery.add_node(NodeEntry { id: NodeId::random(), endpoint: ep.clone() });
 | 
								discovery.add_node(NodeEntry { id: NodeId::random(), endpoint: ep.clone() });
 | 
				
			||||||
@ -549,4 +547,70 @@ mod tests {
 | 
				
			|||||||
		let removed = discovery.check_expired(true).len();
 | 
							let removed = discovery.check_expired(true).len();
 | 
				
			||||||
		assert!(removed > 0);
 | 
							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());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -15,9 +15,11 @@
 | 
				
			|||||||
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | 
					// along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::sync::Arc;
 | 
					use std::sync::Arc;
 | 
				
			||||||
 | 
					use rand::random;
 | 
				
			||||||
use mio::*;
 | 
					use mio::*;
 | 
				
			||||||
use mio::tcp::*;
 | 
					use mio::tcp::*;
 | 
				
			||||||
use hash::*;
 | 
					use hash::*;
 | 
				
			||||||
 | 
					use rlp::*;
 | 
				
			||||||
use sha3::Hashable;
 | 
					use sha3::Hashable;
 | 
				
			||||||
use bytes::Bytes;
 | 
					use bytes::Bytes;
 | 
				
			||||||
use crypto::*;
 | 
					use crypto::*;
 | 
				
			||||||
@ -36,8 +38,12 @@ enum HandshakeState {
 | 
				
			|||||||
	New,
 | 
						New,
 | 
				
			||||||
	/// Waiting for auth packet
 | 
						/// Waiting for auth packet
 | 
				
			||||||
	ReadingAuth,
 | 
						ReadingAuth,
 | 
				
			||||||
 | 
						/// Waiting for extended auth packet
 | 
				
			||||||
 | 
						ReadingAuthEip8,
 | 
				
			||||||
	/// Waiting for ack packet
 | 
						/// Waiting for ack packet
 | 
				
			||||||
	ReadingAck,
 | 
						ReadingAck,
 | 
				
			||||||
 | 
						/// Waiting for extended ack packet
 | 
				
			||||||
 | 
						ReadingAckEip8,
 | 
				
			||||||
	/// Ready to start a session
 | 
						/// Ready to start a session
 | 
				
			||||||
	StartSession,
 | 
						StartSession,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -57,9 +63,11 @@ pub struct Handshake {
 | 
				
			|||||||
	/// Connection nonce
 | 
						/// Connection nonce
 | 
				
			||||||
	pub nonce: H256,
 | 
						pub nonce: H256,
 | 
				
			||||||
	/// Handshake public key
 | 
						/// Handshake public key
 | 
				
			||||||
	pub remote_public: Public,
 | 
						pub remote_ephemeral: Public,
 | 
				
			||||||
	/// Remote connection nonce.
 | 
						/// Remote connection nonce.
 | 
				
			||||||
	pub remote_nonce: H256,
 | 
						pub remote_nonce: H256,
 | 
				
			||||||
 | 
						/// Remote RLPx protocol version.
 | 
				
			||||||
 | 
						pub remote_version: u64,
 | 
				
			||||||
	/// A copy of received encryped auth packet 
 | 
						/// A copy of received encryped auth packet 
 | 
				
			||||||
	pub auth_cipher: Bytes,
 | 
						pub auth_cipher: Bytes,
 | 
				
			||||||
	/// A copy of received encryped ack packet 
 | 
						/// A copy of received encryped ack packet 
 | 
				
			||||||
@ -68,9 +76,12 @@ pub struct Handshake {
 | 
				
			|||||||
	pub expired: bool,
 | 
						pub expired: bool,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const AUTH_PACKET_SIZE: usize = 307;
 | 
					const V4_AUTH_PACKET_SIZE: usize = 307;
 | 
				
			||||||
const ACK_PACKET_SIZE: usize = 210;
 | 
					const V4_ACK_PACKET_SIZE: usize = 210;
 | 
				
			||||||
const HANDSHAKE_TIMEOUT: u64 = 5000;
 | 
					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 {
 | 
					impl Handshake {
 | 
				
			||||||
	/// Create a new handshake object
 | 
						/// Create a new handshake object
 | 
				
			||||||
@ -82,8 +93,9 @@ impl Handshake {
 | 
				
			|||||||
			state: HandshakeState::New,
 | 
								state: HandshakeState::New,
 | 
				
			||||||
			ecdhe: try!(KeyPair::create()),
 | 
								ecdhe: try!(KeyPair::create()),
 | 
				
			||||||
			nonce: nonce.clone(),
 | 
								nonce: nonce.clone(),
 | 
				
			||||||
			remote_public: Public::new(),
 | 
								remote_ephemeral: Public::new(),
 | 
				
			||||||
			remote_nonce: H256::new(),
 | 
								remote_nonce: H256::new(),
 | 
				
			||||||
 | 
								remote_version: PROTOCOL_VERSION,
 | 
				
			||||||
			auth_cipher: Bytes::new(),
 | 
								auth_cipher: Bytes::new(),
 | 
				
			||||||
			ack_cipher: Bytes::new(),
 | 
								ack_cipher: Bytes::new(),
 | 
				
			||||||
			expired: false,
 | 
								expired: false,
 | 
				
			||||||
@ -115,11 +127,11 @@ impl Handshake {
 | 
				
			|||||||
		self.originated = originated;
 | 
							self.originated = originated;
 | 
				
			||||||
		io.register_timer(self.connection.token, HANDSHAKE_TIMEOUT).ok();
 | 
							io.register_timer(self.connection.token, HANDSHAKE_TIMEOUT).ok();
 | 
				
			||||||
		if originated {
 | 
							if originated {
 | 
				
			||||||
			try!(self.write_auth(host));
 | 
								try!(self.write_auth(host.secret(), host.id()));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else {
 | 
							else {
 | 
				
			||||||
			self.state = HandshakeState::ReadingAuth;
 | 
								self.state = HandshakeState::ReadingAuth;
 | 
				
			||||||
			self.connection.expect(AUTH_PACKET_SIZE);
 | 
								self.connection.expect(V4_AUTH_PACKET_SIZE);
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		Ok(())
 | 
							Ok(())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -134,20 +146,28 @@ impl Handshake {
 | 
				
			|||||||
		if !self.expired() {
 | 
							if !self.expired() {
 | 
				
			||||||
			io.clear_timer(self.connection.token).unwrap();
 | 
								io.clear_timer(self.connection.token).unwrap();
 | 
				
			||||||
			match self.state {
 | 
								match self.state {
 | 
				
			||||||
 | 
									HandshakeState::New => {}
 | 
				
			||||||
				HandshakeState::ReadingAuth => {
 | 
									HandshakeState::ReadingAuth => {
 | 
				
			||||||
					if let Some(data) = try!(self.connection.readable()) {
 | 
										if let Some(data) = try!(self.connection.readable()) {
 | 
				
			||||||
						try!(self.read_auth(host, &data));
 | 
											try!(self.read_auth(host.secret(), &data));
 | 
				
			||||||
						try!(self.write_ack());
 | 
										};
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									HandshakeState::ReadingAuthEip8 => {
 | 
				
			||||||
 | 
										if let Some(data) = try!(self.connection.readable()) {
 | 
				
			||||||
 | 
											try!(self.read_auth_eip8(host.secret(), &data));
 | 
				
			||||||
					};
 | 
										};
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				HandshakeState::ReadingAck => {
 | 
									HandshakeState::ReadingAck => {
 | 
				
			||||||
					if let Some(data) = try!(self.connection.readable()) {
 | 
										if let Some(data) = try!(self.connection.readable()) {
 | 
				
			||||||
						try!(self.read_ack(host, &data));
 | 
											try!(self.read_ack(host.secret(), &data));
 | 
				
			||||||
						self.state = HandshakeState::StartSession;
 | 
										};
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									HandshakeState::ReadingAckEip8 => {
 | 
				
			||||||
 | 
										if let Some(data) = try!(self.connection.readable()) {
 | 
				
			||||||
 | 
											try!(self.read_ack_eip8(host.secret(), &data));
 | 
				
			||||||
					};
 | 
										};
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				HandshakeState::StartSession => {},
 | 
									HandshakeState::StartSession => {},
 | 
				
			||||||
				_ => { panic!("Unexpected state"); }
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if self.state != HandshakeState::StartSession {
 | 
								if self.state != HandshakeState::StartSession {
 | 
				
			||||||
				try!(io.update_registration(self.connection.token));
 | 
									try!(io.update_registration(self.connection.token));
 | 
				
			||||||
@ -190,48 +210,105 @@ impl Handshake {
 | 
				
			|||||||
		Ok(())
 | 
							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
 | 
						/// Parse, validate and confirm auth message
 | 
				
			||||||
	fn read_auth(&mut self, host: &HostInfo, data: &[u8]) -> Result<(), UtilError> {
 | 
						fn read_auth(&mut self, secret: &Secret, data: &[u8]) -> Result<(), UtilError> {
 | 
				
			||||||
		trace!(target:"net", "Received handshake auth to {:?}", self.connection.socket.peer_addr());
 | 
							trace!(target:"net", "Received handshake auth from {:?}", self.connection.socket.peer_addr());
 | 
				
			||||||
		if data.len() != AUTH_PACKET_SIZE {
 | 
							if data.len() != V4_AUTH_PACKET_SIZE {
 | 
				
			||||||
			debug!(target:"net", "Wrong auth packet size");
 | 
								debug!(target:"net", "Wrong auth packet size");
 | 
				
			||||||
			return Err(From::from(NetworkError::BadProtocol));
 | 
								return Err(From::from(NetworkError::BadProtocol));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		self.auth_cipher = data.to_vec();
 | 
							self.auth_cipher = data.to_vec();
 | 
				
			||||||
		let auth = try!(ecies::decrypt(host.secret(), data));
 | 
							match ecies::decrypt(secret, &[], data) {
 | 
				
			||||||
		let (sig, rest) = auth.split_at(65);
 | 
								Ok(auth) => {
 | 
				
			||||||
		let (hepubk, rest) = rest.split_at(32);
 | 
									let (sig, rest) = auth.split_at(65);
 | 
				
			||||||
		let (pubk, rest) = rest.split_at(64);
 | 
									let (_, rest) = rest.split_at(32);
 | 
				
			||||||
		let (nonce, _) = rest.split_at(32);
 | 
									let (pubk, rest) = rest.split_at(64);
 | 
				
			||||||
		self.id.clone_from_slice(pubk);
 | 
									let (nonce, _) = rest.split_at(32);
 | 
				
			||||||
		self.remote_nonce.clone_from_slice(nonce);
 | 
									try!(self.set_auth(secret, sig, pubk, nonce, PROTOCOL_VERSION));
 | 
				
			||||||
		let shared = try!(ecdh::agree(host.secret(), &self.id));
 | 
									try!(self.write_ack());
 | 
				
			||||||
		let signature = Signature::from_slice(sig);
 | 
								}
 | 
				
			||||||
		let spub = try!(ec::recover(&signature, &(&shared ^ &self.remote_nonce)));
 | 
								Err(_) => {
 | 
				
			||||||
		self.remote_public = spub.clone();
 | 
									// Try to interpret as EIP-8 packet
 | 
				
			||||||
		if &spub.sha3()[..] != hepubk {
 | 
									let total = (((data[0] as u16) << 8 | (data[1] as u16)) as usize) + 2;
 | 
				
			||||||
			trace!(target:"net", "Handshake hash mismath with {:?}", self.connection.socket.peer_addr());
 | 
									if total < V4_AUTH_PACKET_SIZE {
 | 
				
			||||||
			return Err(From::from(NetworkError::Auth));
 | 
										debug!(target:"net", "Wrong EIP8 auth packet size");
 | 
				
			||||||
		};
 | 
										return Err(From::from(NetworkError::BadProtocol));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									let rest = total - data.len();
 | 
				
			||||||
 | 
									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(())
 | 
							Ok(())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Parse and validate ack message
 | 
						/// 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());
 | 
							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");
 | 
								debug!(target:"net", "Wrong ack packet size");
 | 
				
			||||||
			return Err(From::from(NetworkError::BadProtocol));
 | 
								return Err(From::from(NetworkError::BadProtocol));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		self.ack_cipher = data.to_vec();
 | 
							self.ack_cipher = data.to_vec();
 | 
				
			||||||
		let ack = try!(ecies::decrypt(host.secret(), data));
 | 
							match ecies::decrypt(secret, &[], data) {
 | 
				
			||||||
		self.remote_public.clone_from_slice(&ack[0..64]);
 | 
								Ok(ack) => {
 | 
				
			||||||
		self.remote_nonce.clone_from_slice(&ack[64..(64+32)]);
 | 
									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 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 = total - data.len();
 | 
				
			||||||
 | 
									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(())
 | 
							Ok(())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Sends auth message
 | 
						/// 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());
 | 
							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 mut data = [0u8; /*Signature::SIZE*/ 65 + /*H256::SIZE*/ 32 + /*Public::SIZE*/ 64 + /*H256::SIZE*/ 32 + 1]; //TODO: use associated constants
 | 
				
			||||||
		let len = data.len();
 | 
							let len = data.len();
 | 
				
			||||||
@ -243,16 +320,16 @@ impl Handshake {
 | 
				
			|||||||
			let (nonce, _) = rest.split_at_mut(32);
 | 
								let (nonce, _) = rest.split_at_mut(32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0)
 | 
								// 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);
 | 
								try!(crypto::ec::sign(self.ecdhe.secret(), &(&shared ^ &self.nonce))).copy_to(sig);
 | 
				
			||||||
			self.ecdhe.public().sha3_into(hepubk);
 | 
								self.ecdhe.public().sha3_into(hepubk);
 | 
				
			||||||
			host.id().copy_to(pubk);
 | 
								public.copy_to(pubk);
 | 
				
			||||||
			self.nonce.copy_to(nonce);
 | 
								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.auth_cipher = message.clone();
 | 
				
			||||||
		self.connection.send(message);
 | 
							self.connection.send(message);
 | 
				
			||||||
		self.connection.expect(ACK_PACKET_SIZE);
 | 
							self.connection.expect(V4_ACK_PACKET_SIZE);
 | 
				
			||||||
		self.state = HandshakeState::ReadingAck;
 | 
							self.state = HandshakeState::ReadingAck;
 | 
				
			||||||
		Ok(())
 | 
							Ok(())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -269,10 +346,222 @@ impl Handshake {
 | 
				
			|||||||
			self.ecdhe.public().copy_to(epubk);
 | 
								self.ecdhe.public().copy_to(epubk);
 | 
				
			||||||
			self.nonce.copy_to(nonce);
 | 
								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.ack_cipher = message.clone();
 | 
				
			||||||
		self.connection.send(message);
 | 
							self.connection.send(message);
 | 
				
			||||||
		self.state = HandshakeState::StartSession;
 | 
							self.state = HandshakeState::StartSession;
 | 
				
			||||||
		Ok(())
 | 
							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::<usize>() % 100];
 | 
				
			||||||
 | 
							rlp.append_raw(pad, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							let encoded = rlp.drain();
 | 
				
			||||||
 | 
							let len = (encoded.len() + ECIES_OVERHEAD) as u16;
 | 
				
			||||||
 | 
							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);
 | 
				
			||||||
 | 
							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);
 | 
				
			||||||
 | 
							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]
 | 
				
			||||||
 | 
						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);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,7 @@ extern crate rand;
 | 
				
			|||||||
use bytes::*;
 | 
					use bytes::*;
 | 
				
			||||||
use sha3::*;
 | 
					use sha3::*;
 | 
				
			||||||
use hash::*;
 | 
					use hash::*;
 | 
				
			||||||
 | 
					use rlp::encode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Alphabet to use when creating words for insertion into tries.
 | 
					/// Alphabet to use when creating words for insertion into tries.
 | 
				
			||||||
pub enum Alphabet {
 | 
					pub enum Alphabet {
 | 
				
			||||||
@ -39,6 +40,8 @@ pub enum ValueMode {
 | 
				
			|||||||
	Mirror,
 | 
						Mirror,
 | 
				
			||||||
	/// Randomly (50:50) 1 or 32 byte randomly string.
 | 
						/// Randomly (50:50) 1 or 32 byte randomly string.
 | 
				
			||||||
	Random,
 | 
						Random,
 | 
				
			||||||
 | 
						/// RLP-encoded index.
 | 
				
			||||||
 | 
						Index,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Standard test map for profiling tries.
 | 
					/// 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.
 | 
						/// Create the standard map (set of keys and values) for the object's fields.
 | 
				
			||||||
	pub fn make(&self) -> Vec<(Bytes, Bytes)> {
 | 
						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 low = b"abcdef";
 | 
				
			||||||
		let mid = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_";
 | 
							let mid = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let mut d: Vec<(Bytes, Bytes)> = Vec::new();
 | 
							let mut d: Vec<(Bytes, Bytes)> = Vec::new();
 | 
				
			||||||
		let mut seed = H256::new();
 | 
							for index in 0..self.count {
 | 
				
			||||||
		for _ in 0..self.count {
 | 
					 | 
				
			||||||
			let k = match self.alphabet {
 | 
								let k = match self.alphabet {
 | 
				
			||||||
				Alphabet::All => Self::random_bytes(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, &mut 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, &mut 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, &mut 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.push((k, v))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		d
 | 
							d
 | 
				
			||||||
 | 
				
			|||||||
@ -687,31 +687,10 @@ mod tests {
 | 
				
			|||||||
	use super::*;
 | 
						use super::*;
 | 
				
			||||||
	use nibbleslice::*;
 | 
						use nibbleslice::*;
 | 
				
			||||||
	use rlp::*;
 | 
						use rlp::*;
 | 
				
			||||||
	use rand::random;
 | 
						use bytes::ToPretty;
 | 
				
			||||||
	use std::collections::HashSet;
 | 
					 | 
				
			||||||
	use bytes::{ToPretty,Bytes,Populatable};
 | 
					 | 
				
			||||||
	use super::super::node::*;
 | 
						use super::super::node::*;
 | 
				
			||||||
	use super::super::trietraits::*;
 | 
						use super::super::trietraits::*;
 | 
				
			||||||
 | 
						use super::super::standardmap::*;
 | 
				
			||||||
	fn random_key(alphabet: &[u8], min_count: usize, journal_count: usize) -> Vec<u8> {
 | 
					 | 
				
			||||||
		let mut ret: Vec<u8> = Vec::new();
 | 
					 | 
				
			||||||
		let r = min_count + if journal_count > 0 {random::<usize>() % journal_count} else {0};
 | 
					 | 
				
			||||||
		for _ in 0..r {
 | 
					 | 
				
			||||||
			ret.push(alphabet[random::<usize>() % alphabet.len()]);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		ret
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	fn random_value_indexed(j: usize) -> Bytes {
 | 
					 | 
				
			||||||
		match random::<usize>() % 2 {
 | 
					 | 
				
			||||||
			0 => encode(&j).to_vec(),
 | 
					 | 
				
			||||||
			_ => {
 | 
					 | 
				
			||||||
				let mut h = H256::new();
 | 
					 | 
				
			||||||
				h.as_slice_mut()[31] = j as u8;
 | 
					 | 
				
			||||||
				encode(&h).to_vec()
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn populate_trie<'db>(db: &'db mut HashDB, root: &'db mut H256, v: &[(Vec<u8>, Vec<u8>)]) -> TrieDBMut<'db> {
 | 
						fn populate_trie<'db>(db: &'db mut HashDB, root: &'db mut H256, v: &[(Vec<u8>, Vec<u8>)]) -> TrieDBMut<'db> {
 | 
				
			||||||
		let mut t = TrieDBMut::new(db, root);
 | 
							let mut t = TrieDBMut::new(db, root);
 | 
				
			||||||
@ -756,20 +735,18 @@ mod tests {
 | 
				
			|||||||
		};*/
 | 
							};*/
 | 
				
			||||||
//		panic!();
 | 
					//		panic!();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							let mut seed = H256::new();
 | 
				
			||||||
		for test_i in 0..1 {
 | 
							for test_i in 0..1 {
 | 
				
			||||||
			if test_i % 50 == 0 {
 | 
								if test_i % 50 == 0 {
 | 
				
			||||||
				debug!("{:?} of 10000 stress tests done", test_i);
 | 
									debug!("{:?} of 10000 stress tests done", test_i);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			let mut x: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
 | 
								let x = StandardMap {
 | 
				
			||||||
			let mut got: HashSet<Vec<u8>> = HashSet::new();
 | 
									alphabet: Alphabet::Custom(b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_".to_vec()),
 | 
				
			||||||
			let alphabet = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_";
 | 
									min_key: 5,
 | 
				
			||||||
			for j in 0..100usize {
 | 
									journal_key: 0,
 | 
				
			||||||
				let key = random_key(alphabet, 5, 0);
 | 
									value_mode: ValueMode::Index,
 | 
				
			||||||
				if !got.contains(&key) {
 | 
									count: 100,
 | 
				
			||||||
					x.push((key.clone(), random_value_indexed(j)));
 | 
								}.make_with(&mut seed);
 | 
				
			||||||
					got.insert(key);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			let real = trie_root(x.clone());
 | 
								let real = trie_root(x.clone());
 | 
				
			||||||
			let mut memdb = MemoryDB::new();
 | 
								let mut memdb = MemoryDB::new();
 | 
				
			||||||
@ -1049,13 +1026,16 @@ mod tests {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	#[test]
 | 
						#[test]
 | 
				
			||||||
	fn stress() {
 | 
						fn stress() {
 | 
				
			||||||
 | 
							let mut seed = H256::new();
 | 
				
			||||||
		for _ in 0..50 {
 | 
							for _ in 0..50 {
 | 
				
			||||||
			let mut x: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
 | 
								let x = StandardMap {
 | 
				
			||||||
			let alphabet = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_";
 | 
									alphabet: Alphabet::Custom(b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_".to_vec()),
 | 
				
			||||||
			for j in 0..4u32 {
 | 
									min_key: 5,
 | 
				
			||||||
				let key = random_key(alphabet, 5, 1);
 | 
									journal_key: 0,
 | 
				
			||||||
				x.push((key, encode(&j).to_vec()));
 | 
									value_mode: ValueMode::Index,
 | 
				
			||||||
			}
 | 
									count: 4,
 | 
				
			||||||
 | 
								}.make_with(&mut seed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			let real = trie_root(x.clone());
 | 
								let real = trie_root(x.clone());
 | 
				
			||||||
			let mut memdb = MemoryDB::new();
 | 
								let mut memdb = MemoryDB::new();
 | 
				
			||||||
			let mut root = H256::new();
 | 
								let mut root = H256::new();
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										290
									
								
								util/src/uint.rs
									
									
									
									
									
								
							
							
						
						
									
										290
									
								
								util/src/uint.rs
									
									
									
									
									
								
							@ -265,53 +265,60 @@ macro_rules! uint_overflowing_mul {
 | 
				
			|||||||
				mov %rax, $0
 | 
									mov %rax, $0
 | 
				
			||||||
				mov %rdx, $1
 | 
									mov %rdx, $1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				mov $6, %rax
 | 
									mov $5, %rax
 | 
				
			||||||
				mulq $9
 | 
									mulq $10
 | 
				
			||||||
				add %rax, $1
 | 
									add %rax, $1
 | 
				
			||||||
 | 
									adc $$0, %rdx
 | 
				
			||||||
				mov %rdx, $2
 | 
									mov %rdx, $2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				mov $5, %rax
 | 
									mov $5, %rax
 | 
				
			||||||
				mulq $10
 | 
									mulq $11
 | 
				
			||||||
				add %rax, $1
 | 
					 | 
				
			||||||
				adc %rdx, $2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				mov $6, %rax
 | 
					 | 
				
			||||||
				mulq $10
 | 
					 | 
				
			||||||
				add %rax, $2
 | 
									add %rax, $2
 | 
				
			||||||
 | 
									adc $$0, %rdx
 | 
				
			||||||
				mov %rdx, $3
 | 
									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
 | 
									mov $5, %rax
 | 
				
			||||||
				mulq $12
 | 
									mulq $12
 | 
				
			||||||
				add %rax, $3
 | 
									add %rax, $3
 | 
				
			||||||
				adc $$0, %rdx
 | 
									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
 | 
									or %rdx, %rcx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				cmpq $$0, %rcx
 | 
									cmpq $$0, %rcx
 | 
				
			||||||
@ -351,7 +358,7 @@ macro_rules! uint_overflowing_mul {
 | 
				
			|||||||
				: /* $5 */ "m"(self_t[0]), /* $6 */ "m"(self_t[1]), /* $7 */  "m"(self_t[2]),
 | 
									: /* $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]),
 | 
									  /* $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])
 | 
									  /* $11 */ "m"(other_t[2]), /* $12 */ "m"(other_t[3])
 | 
				
			||||||
           		: "rax", "rdx", "rbx"
 | 
					           		: "rax", "rdx"
 | 
				
			||||||
				:
 | 
									:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			);
 | 
								);
 | 
				
			||||||
@ -1629,31 +1636,30 @@ mod tests {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
						#[test]
 | 
				
			||||||
    fn u256_multi_subs() {
 | 
						fn u256_multi_subs() {
 | 
				
			||||||
        let (result, _) = U256([0, 0, 0, 0]).overflowing_sub(U256([0, 0, 0, 0]));
 | 
							let (result, _) = U256([0, 0, 0, 0]).overflowing_sub(U256([0, 0, 0, 0]));
 | 
				
			||||||
        assert_eq!(result, 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]));
 | 
							let (result, _) = U256([0, 0, 0, 1]).overflowing_sub(U256([0, 0, 0, 1]));
 | 
				
			||||||
        assert_eq!(result, U256([0, 0, 0, 0]));
 | 
							assert_eq!(result, U256([0, 0, 0, 0]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (_, overflow) = U256([0, 0, 2, 1]).overflowing_sub(U256([0, 0, 3, 1]));
 | 
							let (_, overflow) = U256([0, 0, 2, 1]).overflowing_sub(U256([0, 0, 3, 1]));
 | 
				
			||||||
        assert!(overflow);
 | 
							assert!(overflow);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (result, overflow) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])
 | 
							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]));
 | 
													.overflowing_sub(U256([::std::u64::MAX/2, ::std::u64::MAX/2, ::std::u64::MAX/2, ::std::u64::MAX/2]));
 | 
				
			||||||
        assert!(!overflow);
 | 
							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);
 | 
							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]));
 | 
							let (result, overflow) = U256([0, 0, 0, 1]).overflowing_sub(U256([0, 0, 1, 0]));
 | 
				
			||||||
        assert!(!overflow);
 | 
							assert!(!overflow);
 | 
				
			||||||
        assert_eq!(U256([0, 0, ::std::u64::MAX, 0]), result);
 | 
							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]
 | 
						#[test]
 | 
				
			||||||
	fn u512_multi_subs() {
 | 
						fn u512_multi_subs() {
 | 
				
			||||||
@ -1671,76 +1677,156 @@ mod tests {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[test]
 | 
						#[test]
 | 
				
			||||||
	fn u256_multi_muls() {
 | 
						fn u256_multi_carry_all() {
 | 
				
			||||||
        let (result, _) = U256([0, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0]));
 | 
							let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0]));
 | 
				
			||||||
        assert_eq!(U256([0, 0, 0, 0]), result);
 | 
							assert_eq!(U256([1, ::std::u64::MAX-1, 0, 0]), result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([1, 0, 0, 0]));
 | 
							let (result, _) = U256([0, ::std::u64::MAX, 0, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0]));
 | 
				
			||||||
        assert_eq!(U256([1, 0, 0, 0]), result);
 | 
							assert_eq!(U256([0, 1, ::std::u64::MAX-1, 0]), result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (result, _) = U256([5, 0, 0, 0]).overflowing_mul(U256([5, 0, 0, 0]));
 | 
							let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0]));
 | 
				
			||||||
        assert_eq!(U256([25, 0, 0, 0]), result);
 | 
							assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX-1, 0]), result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (result, _) = U256([0, 5, 0, 0]).overflowing_mul(U256([0, 5, 0, 0]));
 | 
							let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, 0, 0]));
 | 
				
			||||||
        assert_eq!(U256([0, 0, 25, 0]), result);
 | 
							assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX-1, 0]), result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (result, _) = U256([0, 0, 0, 1]).overflowing_mul(U256([1, 0, 0, 0]));
 | 
							let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])
 | 
				
			||||||
        assert_eq!(U256([0, 0, 0, 1]), result);
 | 
								.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([0, 0, 0, 5]).overflowing_mul(U256([2, 0, 0, 0]));
 | 
							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([0, 0, 0, 10]), result);
 | 
							assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1]), result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (result, _) = U256([0, 0, 1, 0]).overflowing_mul(U256([0, 5, 0, 0]));
 | 
							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([0, 0, 0, 5]), result);
 | 
							assert_eq!(U256([1, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX-1]), result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (result, _) = U256([0, 0, 8, 0]).overflowing_mul(U256([0, 0, 7, 0]));
 | 
							let (result, _) = U256([::std::u64::MAX, 0, 0, 0]).overflowing_mul(
 | 
				
			||||||
        assert_eq!(U256([0, 0, 0, 0]), result);
 | 
								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([2, 0, 0, 0]).overflowing_mul(U256([0, 5, 0, 0]));
 | 
							let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])
 | 
				
			||||||
        assert_eq!(U256([0, 10, 0, 0]), result);
 | 
								.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, 0, 0, 0]).overflowing_mul(U256([::std::u64::MAX, 0, 0, 0]));
 | 
							let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0])
 | 
				
			||||||
        assert_eq!(U256([1, ::std::u64::MAX-1, 0, 0]), result);
 | 
								.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([0, 0, 0, ::std::u64::MAX]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX]));
 | 
							let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, 0, 0])
 | 
				
			||||||
        assert_eq!(U256([0, 0, 0, 0]), result);
 | 
								.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([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX]));
 | 
							let (result, _) = U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX])
 | 
				
			||||||
        assert_eq!(U256([0, 0, 0, ::std::u64::MAX]), result);
 | 
								.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, ::std::u64::MAX, ::std::u64::MAX])
 | 
							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]));
 | 
								.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, ::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() {
 | 
				
			||||||
 | 
							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([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([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, 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, 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([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();
 | 
				
			||||||
 | 
							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]
 | 
					    #[test]
 | 
				
			||||||
    fn u256_multi_muls_overflow() {
 | 
					    fn u256_multi_muls_overflow() {
 | 
				
			||||||
        let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0]));
 | 
							let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0]));
 | 
				
			||||||
        assert!(!overflow);
 | 
							assert!(!overflow);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX]));
 | 
							let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX]));
 | 
				
			||||||
        assert!(!overflow);
 | 
							assert!(!overflow);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (_, overflow) = U256([0, 1, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX]));
 | 
							let (_, overflow) = U256([0, 1, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX]));
 | 
				
			||||||
        assert!(overflow);
 | 
							assert!(overflow);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (_, overflow) = U256([0, 1, 0, 0]).overflowing_mul(U256([0, 1, 0, 0]));
 | 
							let (_, overflow) = U256([0, 1, 0, 0]).overflowing_mul(U256([0, 1, 0, 0]));
 | 
				
			||||||
        assert!(!overflow);
 | 
							assert!(!overflow);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (_, overflow) = U256([0, 1, 0, ::std::u64::MAX]).overflowing_mul(U256([0, 1, 0, ::std::u64::MAX]));
 | 
							let (_, overflow) = U256([0, 1, 0, ::std::u64::MAX]).overflowing_mul(U256([0, 1, 0, ::std::u64::MAX]));
 | 
				
			||||||
        assert!(overflow);
 | 
							assert!(overflow);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (_, overflow) = U256([0, ::std::u64::MAX, 0, 0]).overflowing_mul(U256([0, ::std::u64::MAX, 0, 0]));
 | 
							let (_, overflow) = U256([0, ::std::u64::MAX, 0, 0]).overflowing_mul(U256([0, ::std::u64::MAX, 0, 0]));
 | 
				
			||||||
        assert!(!overflow);
 | 
							assert!(!overflow);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([10, 0, 0, 0]));
 | 
							let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([10, 0, 0, 0]));
 | 
				
			||||||
        assert!(!overflow);
 | 
							assert!(!overflow);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (_, overflow) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX / 2]));
 | 
							let (_, overflow) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX / 2]));
 | 
				
			||||||
        assert!(!overflow);
 | 
							assert!(!overflow);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (_, overflow) = U256([0, 0, 8, 0]).overflowing_mul(U256([0, 0, 7, 0]));
 | 
							let (_, overflow) = U256([0, 0, 8, 0]).overflowing_mul(U256([0, 0, 7, 0]));
 | 
				
			||||||
        assert!(overflow);
 | 
							assert!(overflow);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user