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) {
|
||||||
|
Ok(auth) => {
|
||||||
let (sig, rest) = auth.split_at(65);
|
let (sig, rest) = auth.split_at(65);
|
||||||
let (hepubk, rest) = rest.split_at(32);
|
let (_, rest) = rest.split_at(32);
|
||||||
let (pubk, rest) = rest.split_at(64);
|
let (pubk, rest) = rest.split_at(64);
|
||||||
let (nonce, _) = rest.split_at(32);
|
let (nonce, _) = rest.split_at(32);
|
||||||
self.id.clone_from_slice(pubk);
|
try!(self.set_auth(secret, sig, pubk, nonce, PROTOCOL_VERSION));
|
||||||
self.remote_nonce.clone_from_slice(nonce);
|
try!(self.write_ack());
|
||||||
let shared = try!(ecdh::agree(host.secret(), &self.id));
|
}
|
||||||
let signature = Signature::from_slice(sig);
|
Err(_) => {
|
||||||
let spub = try!(ec::recover(&signature, &(&shared ^ &self.remote_nonce)));
|
// Try to interpret as EIP-8 packet
|
||||||
self.remote_public = spub.clone();
|
let total = (((data[0] as u16) << 8 | (data[1] as u16)) as usize) + 2;
|
||||||
if &spub.sha3()[..] != hepubk {
|
if total < V4_AUTH_PACKET_SIZE {
|
||||||
trace!(target:"net", "Handshake hash mismath with {:?}", self.connection.socket.peer_addr());
|
debug!(target:"net", "Wrong EIP8 auth packet size");
|
||||||
return Err(From::from(NetworkError::Auth));
|
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_ephemeral.clone_from_slice(&ack[0..64]);
|
||||||
self.remote_nonce.clone_from_slice(&ack[64..(64+32)]);
|
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();
|
||||||
|
180
util/src/uint.rs
180
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"
|
||||||
:
|
:
|
||||||
|
|
||||||
);
|
);
|
||||||
@ -1654,7 +1661,6 @@ mod tests {
|
|||||||
assert_eq!(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]), result);
|
assert_eq!(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, 0]), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn u512_multi_subs() {
|
fn u512_multi_subs() {
|
||||||
let (result, _) = U512([0, 0, 0, 0, 0, 0, 0, 0]).overflowing_sub(U512([0, 0, 0, 0, 0, 0, 0, 0]));
|
let (result, _) = U512([0, 0, 0, 0, 0, 0, 0, 0]).overflowing_sub(U512([0, 0, 0, 0, 0, 0, 0, 0]));
|
||||||
@ -1670,8 +1676,81 @@ mod tests {
|
|||||||
assert!(overflow);
|
assert!(overflow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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]
|
#[test]
|
||||||
fn u256_multi_muls() {
|
fn u256_multi_muls() {
|
||||||
|
use hash::*;
|
||||||
|
|
||||||
let (result, _) = U256([0, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0]));
|
let (result, _) = U256([0, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0]));
|
||||||
assert_eq!(U256([0, 0, 0, 0]), result);
|
assert_eq!(U256([0, 0, 0, 0]), result);
|
||||||
|
|
||||||
@ -1699,18 +1778,25 @@ mod tests {
|
|||||||
let (result, _) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 5, 0, 0]));
|
let (result, _) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 5, 0, 0]));
|
||||||
assert_eq!(U256([0, 10, 0, 0]), result);
|
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]));
|
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);
|
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 x1 = U256::from_str("0000000000000000000000000000000000000000000000000000012365124623").unwrap();
|
||||||
.overflowing_mul(U256([::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX, ::std::u64::MAX]));
|
let x2sqr_right = U256::from_str("000000000000000000000000000000000000000000014baeef72e0378e2328c9").unwrap();
|
||||||
assert_eq!(U256([1, 0, 0, 0]), result);
|
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]
|
||||||
|
Loading…
Reference in New Issue
Block a user