From 847cb36c6fd245c511cb7eb63dea753c0896b1bd Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 25 Nov 2016 18:38:21 +0100 Subject: [PATCH] chain verifier does not have hardcoded network constants --- Cargo.lock | 13 ++++ Cargo.toml | 1 + message/Cargo.toml | 1 + message/src/common/mod.rs | 4 -- message/src/error.rs | 5 +- message/src/lib.rs | 3 +- message/src/message/message.rs | 3 +- message/src/message/message_header.rs | 9 +-- network/Cargo.toml | 8 +++ .../src/common => network/src}/consensus.rs | 2 +- network/src/lib.rs | 8 +++ {message/src/common => network/src}/magic.rs | 59 +++++++++++++----- p2p/Cargo.toml | 5 +- p2p/src/io/handshake.rs | 5 +- p2p/src/io/read_any_message.rs | 8 ++- p2p/src/io/read_header.rs | 8 ++- p2p/src/io/read_message.rs | 8 ++- p2p/src/lib.rs | 1 + p2p/src/net/accept_connection.rs | 3 +- p2p/src/net/config.rs | 3 +- p2p/src/net/connect.rs | 2 +- p2p/src/net/connection.rs | 2 +- p2p/src/util/peer.rs | 2 +- pbtc/commands/import.rs | 2 +- pbtc/commands/start.rs | 2 +- pbtc/config.rs | 8 +-- pbtc/main.rs | 1 + sync/Cargo.toml | 1 + sync/src/blocks_writer.rs | 20 +++---- sync/src/lib.rs | 11 ++-- sync/src/synchronization_verifier.rs | 8 +-- verification/Cargo.toml | 17 +++--- verification/src/chain_verifier.rs | 60 +++++++++---------- verification/src/lib.rs | 14 +++-- verification/src/utils.rs | 27 +++++---- 35 files changed, 202 insertions(+), 132 deletions(-) create mode 100644 network/Cargo.toml rename {message/src/common => network/src}/consensus.rs (95%) create mode 100644 network/src/lib.rs rename {message/src/common => network/src}/magic.rs (60%) diff --git a/Cargo.lock b/Cargo.lock index cff2828d..e8642092 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,7 @@ dependencies = [ "ethcore-devtools 1.3.0", "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "network 0.1.0", "parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "primitives 0.1.0", "script 0.1.0", @@ -328,6 +329,7 @@ dependencies = [ "bitcrypto 0.1.0", "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "chain 0.1.0", + "network 0.1.0", "primitives 0.1.0", "serialization 0.1.0", ] @@ -391,6 +393,14 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "network" +version = "0.1.0" +dependencies = [ + "chain 0.1.0", + "serialization 0.1.0", +] + [[package]] name = "nix" version = "0.7.0" @@ -461,6 +471,7 @@ dependencies = [ "futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "message 0.1.0", + "network 0.1.0", "ns-dns-tokio 0.1.0 (git+https://github.com/debris/abstract-ns)", "parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "primitives 0.1.0", @@ -506,6 +517,7 @@ dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "message 0.1.0", "miner 0.1.0", + "network 0.1.0", "p2p 0.1.0", "script 0.1.0", "sync 0.1.0", @@ -674,6 +686,7 @@ dependencies = [ "message 0.1.0", "miner 0.1.0", "murmur3 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "network 0.1.0", "p2p 0.1.0", "parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "primitives 0.1.0", diff --git a/Cargo.toml b/Cargo.toml index 07eb1989..87ca3390 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ clap = { version = "2", features = ["yaml"] } chain = { path = "chain" } keys = { path = "keys" } message = { path = "message" } +network = { path = "network" } miner = { path = "miner" } p2p = { path = "p2p" } script = { path = "script" } diff --git a/message/Cargo.toml b/message/Cargo.toml index cfc720c4..aa1cc4a6 100644 --- a/message/Cargo.toml +++ b/message/Cargo.toml @@ -10,3 +10,4 @@ bitcrypto = { path = "../crypto" } chain = { path = "../chain" } primitives = { path = "../primitives" } serialization = { path = "../serialization" } +network = { path = "../network" } diff --git a/message/src/common/mod.rs b/message/src/common/mod.rs index e58dbad4..c8e01464 100644 --- a/message/src/common/mod.rs +++ b/message/src/common/mod.rs @@ -3,10 +3,8 @@ mod block_header_and_ids; mod block_transactions; mod block_transactions_request; mod command; -mod consensus; mod inventory; mod ip; -mod magic; mod port; mod prefilled_transaction; mod service; @@ -16,10 +14,8 @@ pub use self::block_header_and_ids::BlockHeaderAndIDs; pub use self::block_transactions::BlockTransactions; pub use self::block_transactions_request::BlockTransactionsRequest; pub use self::command::Command; -pub use self::consensus::ConsensusParams; pub use self::inventory::{InventoryVector, InventoryType}; pub use self::ip::IpAddress; -pub use self::magic::Magic; pub use self::port::Port; pub use self::prefilled_transaction::PrefilledTransaction; pub use self::service::Services; diff --git a/message/src/error.rs b/message/src/error.rs index 3086ab17..c9ae397e 100644 --- a/message/src/error.rs +++ b/message/src/error.rs @@ -9,10 +9,8 @@ pub enum Error { Deserialize, /// Command has wrong format or is unsupported. InvalidCommand, - /// Network magic is not supported. - InvalidMagic, /// Network magic comes from different network. - WrongMagic, + InvalidMagic, /// Invalid checksum. InvalidChecksum, /// Invalid version. @@ -37,7 +35,6 @@ impl error::Error for Error { Error::Deserialize => "Message Deserialization Error", Error::InvalidCommand => "Invalid Message Command", Error::InvalidMagic => "Invalid Network Magic", - Error::WrongMagic => "Wrong Network Magic", Error::InvalidChecksum => "Invalid message chacksum", Error::InvalidVersion => "Unsupported protocol version", } diff --git a/message/src/lib.rs b/message/src/lib.rs index 874cb91c..cdc3a75d 100644 --- a/message/src/lib.rs +++ b/message/src/lib.rs @@ -3,6 +3,7 @@ extern crate bitcrypto as crypto; extern crate chain; extern crate primitives; extern crate serialization as ser; +extern crate network; pub mod common; mod message; @@ -12,7 +13,7 @@ mod error; pub use primitives::{hash, bytes}; -pub use common::{Command, Magic, Services}; +pub use common::{Command, Services}; pub use message::{Message, MessageHeader, Payload, to_raw_message}; pub use serialization::{serialize_payload, deserialize_payload}; pub use error::{Error, MessageResult}; diff --git a/message/src/message/message.rs b/message/src/message/message.rs index 8c740ee4..68f91e36 100644 --- a/message/src/message/message.rs +++ b/message/src/message/message.rs @@ -1,6 +1,7 @@ use ser::Stream; use bytes::{TaggedBytes, Bytes}; -use common::{Magic, Command}; +use network::Magic; +use common::Command; use serialization::serialize_payload; use {Payload, MessageResult, MessageHeader}; diff --git a/message/src/message/message_header.rs b/message/src/message/message_header.rs index b1725d16..3737fd8a 100644 --- a/message/src/message/message_header.rs +++ b/message/src/message/message_header.rs @@ -1,7 +1,8 @@ use hash::H32; use ser::{Serializable, Stream, Reader}; use crypto::checksum; -use common::{Command, Magic}; +use network::Magic; +use common::Command; use Error; #[derive(Debug, PartialEq)] @@ -31,9 +32,9 @@ impl MessageHeader { let mut reader = Reader::new(data); let magic: u32 = try!(reader.read()); - let magic = try!(Magic::from_u32(magic)); + let magic = Magic::from(magic); if expected != magic { - return Err(Error::WrongMagic); + return Err(Error::InvalidMagic); } let header = MessageHeader { @@ -61,7 +62,7 @@ impl Serializable for MessageHeader { mod tests { use bytes::Bytes; use ser::serialize; - use common::Magic; + use network::Magic; use super::MessageHeader; #[test] diff --git a/network/Cargo.toml b/network/Cargo.toml new file mode 100644 index 00000000..930d034e --- /dev/null +++ b/network/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "network" +version = "0.1.0" +authors = ["debris "] + +[dependencies] +serialization = { path = "../serialization" } +chain = { path = "../chain" } diff --git a/message/src/common/consensus.rs b/network/src/consensus.rs similarity index 95% rename from message/src/common/consensus.rs rename to network/src/consensus.rs index cc24791c..6c37bb68 100644 --- a/message/src/common/consensus.rs +++ b/network/src/consensus.rs @@ -14,7 +14,7 @@ pub struct ConsensusParams { impl ConsensusParams { pub fn with_magic(magic: Magic) -> Self { match magic { - Magic::Mainnet => ConsensusParams { + Magic::Mainnet | Magic::Other(_) => ConsensusParams { bip16_time: 1333238400, // Apr 1 2012 bip65_height: 388381, // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0 }, diff --git a/network/src/lib.rs b/network/src/lib.rs new file mode 100644 index 00000000..1b266d51 --- /dev/null +++ b/network/src/lib.rs @@ -0,0 +1,8 @@ +extern crate chain; +extern crate serialization as ser; + +mod consensus; +mod magic; + +pub use consensus::ConsensusParams; +pub use magic::Magic; diff --git a/message/src/common/magic.rs b/network/src/magic.rs similarity index 60% rename from message/src/common/magic.rs rename to network/src/magic.rs index 55297061..05f712ab 100644 --- a/message/src/common/magic.rs +++ b/network/src/magic.rs @@ -3,21 +3,28 @@ use ser::{Stream, Serializable}; use chain::Block; -use Error; use super::ConsensusParams; const MAGIC_MAINNET: u32 = 0xD9B4BEF9; const MAGIC_TESTNET: u32 = 0x0709110B; const MAGIC_REGTEST: u32 = 0xDAB5BFFA; +const MAX_NBITS_MAINNET: u32 = 0x1d00ffff; +const MAX_NBITS_TESTNET: u32 = 0x1d00ffff; +const MAX_NBITS_REGTEST: u32 = 0x207fffff; + /// Bitcoin network /// https://bitcoin.org/en/glossary/mainnet #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum Magic { /// The original and main network for Bitcoin transactions, where satoshis have real economic value. Mainnet, + /// The main bitcoin testnet. Testnet, + /// Bitcoin regtest network. Regtest, + /// Any other network. By default behaves like bitcoin mainnet. + Other(u32), } impl From for u32 { @@ -26,23 +33,34 @@ impl From for u32 { Magic::Mainnet => MAGIC_MAINNET, Magic::Testnet => MAGIC_TESTNET, Magic::Regtest => MAGIC_REGTEST, + Magic::Other(magic) => magic, + } + } +} + +impl From for Magic { + fn from(u: u32) -> Self { + match u { + MAGIC_MAINNET => Magic::Mainnet, + MAGIC_TESTNET => Magic::Testnet, + MAGIC_REGTEST => Magic::Regtest, + other => Magic::Other(other), } } } impl Magic { - pub fn from_u32(magic: u32) -> Result { - match magic { - MAGIC_MAINNET => Ok(Magic::Mainnet), - MAGIC_TESTNET => Ok(Magic::Testnet), - MAGIC_REGTEST => Ok(Magic::Regtest), - _ => Err(Error::InvalidMagic), + pub fn max_nbits(&self) -> u32 { + match *self { + Magic::Mainnet | Magic::Other(_) => MAX_NBITS_MAINNET, + Magic::Testnet => MAX_NBITS_TESTNET, + Magic::Regtest => MAX_NBITS_REGTEST, } } pub fn port(&self) -> u16 { match *self { - Magic::Mainnet => 8333, + Magic::Mainnet | Magic::Other(_) => 8333, Magic::Testnet => 18333, Magic::Regtest => 18444, } @@ -50,7 +68,7 @@ impl Magic { pub fn rpc_port(&self) -> u16 { match *self { - Magic::Mainnet => 8332, + Magic::Mainnet | Magic::Other(_) => 8332, Magic::Testnet => 18332, Magic::Regtest => 18443, } @@ -58,7 +76,7 @@ impl Magic { pub fn genesis_block(&self) -> Block { match *self { - Magic::Mainnet => "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000".into(), + Magic::Mainnet | Magic::Other(_) => "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000".into(), Magic::Testnet => "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff001d1aa4ae180101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000".into(), Magic::Regtest => "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff7f20020000000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000".into(), } @@ -77,18 +95,27 @@ impl Serializable for Magic { #[cfg(test)] mod tests { - use Error; - use super::{Magic, MAGIC_MAINNET, MAGIC_TESTNET, MAGIC_REGTEST}; + use super::{ + Magic, MAGIC_MAINNET, MAGIC_TESTNET, MAGIC_REGTEST, + MAX_NBITS_MAINNET, MAX_NBITS_TESTNET, MAX_NBITS_REGTEST, + }; #[test] fn test_network_magic_number() { assert_eq!(MAGIC_MAINNET, Magic::Mainnet.into()); assert_eq!(MAGIC_TESTNET, Magic::Testnet.into()); assert_eq!(MAGIC_REGTEST, Magic::Regtest.into()); - assert_eq!(Magic::from_u32(MAGIC_MAINNET).unwrap(), Magic::Mainnet); - assert_eq!(Magic::from_u32(MAGIC_TESTNET).unwrap(), Magic::Testnet); - assert_eq!(Magic::from_u32(MAGIC_REGTEST).unwrap(), Magic::Regtest); - assert_eq!(Magic::from_u32(0).unwrap_err(), Error::InvalidMagic); + assert_eq!(Magic::Mainnet, MAGIC_MAINNET.into()); + assert_eq!(Magic::Testnet, MAGIC_TESTNET.into()); + assert_eq!(Magic::Regtest, MAGIC_REGTEST.into()); + assert_eq!(Magic::Other(0), 0.into()); + } + + #[test] + fn test_network_max_nbits() { + assert_eq!(Magic::Mainnet.max_nbits(), MAX_NBITS_MAINNET); + assert_eq!(Magic::Testnet.max_nbits(), MAX_NBITS_TESTNET); + assert_eq!(Magic::Regtest.max_nbits(), MAX_NBITS_REGTEST); } #[test] diff --git a/p2p/Cargo.toml b/p2p/Cargo.toml index 9d48d3c9..bc8a9b40 100644 --- a/p2p/Cargo.toml +++ b/p2p/Cargo.toml @@ -15,7 +15,8 @@ abstract-ns = "0.2.1" ns-dns-tokio = { git = "https://github.com/debris/abstract-ns", path = "ns-dns-tokio" } csv = "0.14.7" -primitives = { path = "../primitives"} +primitives = { path = "../primitives" } bitcrypto = { path = "../crypto" } message = { path = "../message" } -serialization = { path = "../serialization"} +serialization = { path = "../serialization" } +network = { path = "../network" } diff --git a/p2p/src/io/handshake.rs b/p2p/src/io/handshake.rs index 3c28ca9e..c967df58 100644 --- a/p2p/src/io/handshake.rs +++ b/p2p/src/io/handshake.rs @@ -2,7 +2,7 @@ use std::{io, cmp}; use futures::{Future, Poll, Async}; use message::{Message, MessageResult, Error}; use message::types::{Version, Verack}; -use message::common::Magic; +use network::Magic; use io::{write_message, WriteMessage, ReadMessage, read_message}; pub fn handshake(a: A, magic: Magic, version: Version, min_version: u32) -> Handshake where A: io::Write + io::Read { @@ -199,7 +199,8 @@ mod tests { use futures::Future; use bytes::Bytes; use ser::Stream; - use message::{Magic, Message}; + use network::Magic; + use message::Message; use message::types::Verack; use message::types::version::{Version, V0, V106, V70001}; use super::{handshake, accept_handshake, HandshakeResult}; diff --git a/p2p/src/io/read_any_message.rs b/p2p/src/io/read_any_message.rs index d8d37fed..ec58acf2 100644 --- a/p2p/src/io/read_any_message.rs +++ b/p2p/src/io/read_any_message.rs @@ -2,7 +2,8 @@ use std::io; use futures::{Future, Poll, Async}; use tokio_core::io::{read_exact, ReadExact}; use crypto::checksum; -use message::{Error, MessageHeader, MessageResult, Magic, Command}; +use network::Magic; +use message::{Error, MessageHeader, MessageResult, Command}; use bytes::Bytes; use io::{read_header, ReadHeader}; @@ -68,7 +69,8 @@ impl Future for ReadAnyMessage where A: io::Read { mod tests { use futures::Future; use bytes::Bytes; - use message::{Magic, Error}; + use network::Magic; + use message::Error; use super::read_any_message; #[test] @@ -79,7 +81,7 @@ mod tests { let expected = (name, nonce); assert_eq!(read_any_message(raw.as_ref(), Magic::Mainnet).wait().unwrap(), Ok(expected)); - assert_eq!(read_any_message(raw.as_ref(), Magic::Testnet).wait().unwrap(), Err(Error::WrongMagic)); + assert_eq!(read_any_message(raw.as_ref(), Magic::Testnet).wait().unwrap(), Err(Error::InvalidMagic)); } #[test] diff --git a/p2p/src/io/read_header.rs b/p2p/src/io/read_header.rs index 9b9a0ab8..4e8ee5bd 100644 --- a/p2p/src/io/read_header.rs +++ b/p2p/src/io/read_header.rs @@ -1,7 +1,8 @@ use std::io; use futures::{Future, Poll, Async}; use tokio_core::io::{ReadExact, read_exact}; -use message::{MessageHeader, MessageResult, Magic}; +use message::{MessageHeader, MessageResult}; +use network::Magic; pub fn read_header(a: A, magic: Magic) -> ReadHeader where A: io::Read { ReadHeader { @@ -30,7 +31,8 @@ impl Future for ReadHeader where A: io::Read { mod tests { use futures::Future; use bytes::Bytes; - use message::{Magic, MessageHeader, Error}; + use network::Magic; + use message::{MessageHeader, Error}; use super::read_header; #[test] @@ -44,7 +46,7 @@ mod tests { }; assert_eq!(read_header(raw.as_ref(), Magic::Mainnet).wait().unwrap().1, Ok(expected)); - assert_eq!(read_header(raw.as_ref(), Magic::Testnet).wait().unwrap().1, Err(Error::WrongMagic)); + assert_eq!(read_header(raw.as_ref(), Magic::Testnet).wait().unwrap().1, Err(Error::InvalidMagic)); } #[test] diff --git a/p2p/src/io/read_message.rs b/p2p/src/io/read_message.rs index 5947c27c..227de3f8 100644 --- a/p2p/src/io/read_message.rs +++ b/p2p/src/io/read_message.rs @@ -1,7 +1,8 @@ use std::io; use std::marker::PhantomData; use futures::{Poll, Future, Async}; -use message::{MessageResult, Error, Magic, Payload}; +use network::Magic; +use message::{MessageResult, Error, Payload}; use io::{read_header, ReadHeader, read_payload, ReadPayload}; pub fn read_message(a: A, magic: Magic, version: u32) -> ReadMessage @@ -74,7 +75,8 @@ impl Future for ReadMessage where A: io::Read, M: Payload { mod tests { use futures::Future; use bytes::Bytes; - use message::{Magic, Error}; + use network::Magic; + use message::Error; use message::types::{Ping, Pong}; use super::read_message; @@ -83,7 +85,7 @@ mod tests { let raw: Bytes = "f9beb4d970696e6700000000000000000800000083c00c765845303b6da97786".into(); let ping = Ping::new(u64::from_str_radix("8677a96d3b304558", 16).unwrap()); assert_eq!(read_message(raw.as_ref(), Magic::Mainnet, 0).wait().unwrap().1, Ok(ping)); - assert_eq!(read_message::(raw.as_ref(), Magic::Testnet, 0).wait().unwrap().1, Err(Error::WrongMagic)); + assert_eq!(read_message::(raw.as_ref(), Magic::Testnet, 0).wait().unwrap().1, Err(Error::InvalidMagic)); assert_eq!(read_message::(raw.as_ref(), Magic::Mainnet, 0).wait().unwrap().1, Err(Error::InvalidCommand)); } diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs index 7a0bbb0d..09d40264 100644 --- a/p2p/src/lib.rs +++ b/p2p/src/lib.rs @@ -15,6 +15,7 @@ extern crate bitcrypto as crypto; extern crate message; extern crate primitives; extern crate serialization as ser; +extern crate network; mod io; mod net; diff --git a/p2p/src/net/accept_connection.rs b/p2p/src/net/accept_connection.rs index af915b13..c7120a15 100644 --- a/p2p/src/net/accept_connection.rs +++ b/p2p/src/net/accept_connection.rs @@ -3,7 +3,8 @@ use std::time::Duration; use futures::{Future, Poll}; use tokio_core::reactor::Handle; use tokio_core::net::TcpStream; -use message::{MessageResult, Magic}; +use network::Magic; +use message::{MessageResult}; use io::{accept_handshake, AcceptHandshake, Deadline, deadline}; use net::{Config, Connection}; diff --git a/p2p/src/net/config.rs b/p2p/src/net/config.rs index 1c71d183..e54425d0 100644 --- a/p2p/src/net/config.rs +++ b/p2p/src/net/config.rs @@ -1,5 +1,6 @@ use std::net::SocketAddr; -use message::common::{Magic, Services, NetAddress}; +use network::Magic; +use message::common::{Services, NetAddress}; use message::types::version::{Version, V0, V106, V70001}; use util::time::{Time, RealTime}; use util::nonce::{NonceGenerator, RandomNonce}; diff --git a/p2p/src/net/connect.rs b/p2p/src/net/connect.rs index 7b78fa77..dda8e12d 100644 --- a/p2p/src/net/connect.rs +++ b/p2p/src/net/connect.rs @@ -4,8 +4,8 @@ use std::net::SocketAddr; use futures::{Future, Poll, Async}; use tokio_core::reactor::Handle; use tokio_core::net::{TcpStream, TcpStreamNew}; +use network::Magic; use message::Error; -use message::common::Magic; use message::types::Version; use io::{handshake, Handshake, Deadline, deadline}; use net::{Config, Connection}; diff --git a/p2p/src/net/connection.rs b/p2p/src/net/connection.rs index 603d58d6..a3d55bcb 100644 --- a/p2p/src/net/connection.rs +++ b/p2p/src/net/connection.rs @@ -1,5 +1,5 @@ use std::net; -use message::Magic; +use network::Magic; use message::common::Services; use io::SharedTcpStream; diff --git a/p2p/src/util/peer.rs b/p2p/src/util/peer.rs index f19d746b..3999835b 100644 --- a/p2p/src/util/peer.rs +++ b/p2p/src/util/peer.rs @@ -1,5 +1,5 @@ use std::net::SocketAddr; -use message::Magic; +use network::Magic; pub type PeerId = usize; diff --git a/pbtc/commands/import.rs b/pbtc/commands/import.rs index c89747d3..d65245f3 100644 --- a/pbtc/commands/import.rs +++ b/pbtc/commands/import.rs @@ -8,7 +8,7 @@ pub fn import(cfg: Config, matches: &ArgMatches) -> Result<(), String> { // TODO: this might be unnecessary here! try!(init_db(&cfg, &db)); - let mut writer = create_sync_blocks_writer(db); + let mut writer = create_sync_blocks_writer(db, cfg.magic); let blk_path = matches.value_of("PATH").expect("PATH is required in cli.yml; qed"); let blk_dir = try!(::import::open_blk_dir(blk_path).map_err(|_| "Import directory does not exist".to_owned())); diff --git a/pbtc/commands/start.rs b/pbtc/commands/start.rs index 1cd872b8..e2e46da1 100644 --- a/pbtc/commands/start.rs +++ b/pbtc/commands/start.rs @@ -32,7 +32,7 @@ pub fn start(cfg: config::Config) -> Result<(), String> { }; let sync_handle = el.handle(); - let sync_connection_factory = create_sync_connection_factory(&sync_handle, cfg.magic.consensus_params(), db); + let sync_connection_factory = create_sync_connection_factory(&sync_handle, cfg.magic, db); let p2p = try!(p2p::P2P::new(p2p_cfg, sync_connection_factory, el.handle()).map_err(|x| x.to_string())); try!(p2p.run().map_err(|_| "Failed to start p2p module")); diff --git a/pbtc/config.rs b/pbtc/config.rs index 95e4b47c..af3afda0 100644 --- a/pbtc/config.rs +++ b/pbtc/config.rs @@ -1,6 +1,6 @@ use std::net; use clap; -use message::Magic; +use network::Magic; use {USER_AGENT, REGTEST_USER_AGENT}; pub struct Config { @@ -29,18 +29,18 @@ pub fn parse(matches: &clap::ArgMatches) -> Result { }; let (in_connections, out_connections) = match magic { - Magic::Testnet | Magic::Mainnet => (10, 10), + Magic::Testnet | Magic::Mainnet | Magic::Other(_) => (10, 10), Magic::Regtest => (1, 0), }; let p2p_threads = match magic { - Magic::Testnet | Magic::Mainnet => 4, + Magic::Testnet | Magic::Mainnet | Magic::Other(_) => 4, Magic::Regtest => 1, }; // to skip idiotic 30 seconds delay in test-scripts let user_agent = match magic { - Magic::Testnet | Magic::Mainnet => USER_AGENT, + Magic::Testnet | Magic::Mainnet | Magic::Other(_) => USER_AGENT, Magic::Regtest => REGTEST_USER_AGENT, }; diff --git a/pbtc/main.rs b/pbtc/main.rs index e524839e..93071fae 100644 --- a/pbtc/main.rs +++ b/pbtc/main.rs @@ -12,6 +12,7 @@ extern crate chain; extern crate keys; extern crate script; extern crate message; +extern crate network; extern crate p2p; extern crate sync; extern crate import; diff --git a/sync/Cargo.toml b/sync/Cargo.toml index 33105fe2..6412467e 100644 --- a/sync/Cargo.toml +++ b/sync/Cargo.toml @@ -26,6 +26,7 @@ script = { path = "../script" } serialization = { path = "../serialization" } test-data = { path = "../test-data" } verification = { path = "../verification" } +network = { path = "../network" } [features] dev = [] diff --git a/sync/src/blocks_writer.rs b/sync/src/blocks_writer.rs index 8cb891a9..8bd15f54 100644 --- a/sync/src/blocks_writer.rs +++ b/sync/src/blocks_writer.rs @@ -1,8 +1,9 @@ use std::sync::Arc; use chain; use db; -use super::Error; +use network::Magic; use verification::{Verify, ChainVerifier}; +use super::Error; pub struct BlocksWriter { storage: Arc, @@ -10,10 +11,10 @@ pub struct BlocksWriter { } impl BlocksWriter { - pub fn new(storage: db::SharedStore) -> BlocksWriter { + pub fn new(storage: db::SharedStore, network: Magic) -> BlocksWriter { BlocksWriter { storage: storage.clone(), - verifier: ChainVerifier::new(storage), + verifier: ChainVerifier::new(storage, network), } } @@ -32,18 +33,17 @@ impl BlocksWriter { #[cfg(test)] mod tests { - use db; - use db::Store; use std::sync::Arc; + use db::{self, Store}; + use network::Magic; + use {test_data, verification}; use super::super::Error; use super::BlocksWriter; - use test_data; - use verification; #[test] fn blocks_writer_appends_blocks() { let db = Arc::new(db::TestStorage::with_genesis_block()); - let mut blocks_target = BlocksWriter::new(db.clone()); + let mut blocks_target = BlocksWriter::new(db.clone(), Magic::Testnet); blocks_target.append_block(test_data::block_h1()).expect("Expecting no error"); assert_eq!(db.best_block().expect("Block is inserted").number, 1); } @@ -51,7 +51,7 @@ mod tests { #[test] fn blocks_writer_verification_error() { let db = Arc::new(db::TestStorage::with_genesis_block()); - let mut blocks_target = BlocksWriter::new(db.clone()); + let mut blocks_target = BlocksWriter::new(db.clone(), Magic::Testnet); match blocks_target.append_block(test_data::block_h2()).unwrap_err() { Error::OutOfOrderBlock => (), _ => panic!("Unexpected error"), @@ -62,7 +62,7 @@ mod tests { #[test] fn blocks_writer_out_of_order_block() { let db = Arc::new(db::TestStorage::with_genesis_block()); - let mut blocks_target = BlocksWriter::new(db.clone()); + let mut blocks_target = BlocksWriter::new(db.clone(), Magic::Testnet); let wrong_block = test_data::block_builder() .header().parent(test_data::genesis().hash()).build() diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 319072cb..854512a0 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -21,6 +21,7 @@ extern crate serialization as ser; #[cfg(test)] extern crate ethcore_devtools as devtools; extern crate rand; +extern crate network; mod best_headers_chain; mod blocks_writer; @@ -42,7 +43,7 @@ mod synchronization_verifier; use std::sync::Arc; use parking_lot::RwLock; use tokio_core::reactor::Handle; -use message::common::ConsensusParams; +use network::Magic; /// Sync errors. #[derive(Debug)] @@ -56,12 +57,12 @@ pub enum Error { } /// Create blocks writer. -pub fn create_sync_blocks_writer(db: db::SharedStore) -> blocks_writer::BlocksWriter { - blocks_writer::BlocksWriter::new(db) +pub fn create_sync_blocks_writer(db: db::SharedStore, network: Magic) -> blocks_writer::BlocksWriter { + blocks_writer::BlocksWriter::new(db, network) } /// Create inbound synchronization connections factory for given `db`. -pub fn create_sync_connection_factory(handle: &Handle, consensus_params: ConsensusParams, db: db::SharedStore) -> p2p::LocalSyncNodeRef { +pub fn create_sync_connection_factory(handle: &Handle, network: Magic, db: db::SharedStore) -> p2p::LocalSyncNodeRef { use synchronization_chain::Chain as SyncChain; use synchronization_executor::LocalSynchronizationTaskExecutor as SyncExecutor; use local_node::LocalNode as SyncNode; @@ -74,7 +75,7 @@ pub fn create_sync_connection_factory(handle: &Handle, consensus_params: Consens let sync_executor = SyncExecutor::new(sync_chain.clone()); let sync_server = Arc::new(SynchronizationServer::new(sync_chain.clone(), sync_executor.clone())); let sync_client_core = SynchronizationClientCore::new(SynchronizationConfig::new(), handle, sync_executor.clone(), sync_chain.clone()); - let verifier = AsyncVerifier::new(consensus_params, sync_chain, sync_client_core.clone()); + let verifier = AsyncVerifier::new(network, sync_chain, sync_client_core.clone()); let sync_client = SynchronizationClient::new(sync_client_core, verifier); let sync_node = Arc::new(SyncNode::new(sync_server, sync_client, sync_executor)); SyncConnectionFactory::with_local_node(sync_node) diff --git a/sync/src/synchronization_verifier.rs b/sync/src/synchronization_verifier.rs index 67bb95e7..dd1dca29 100644 --- a/sync/src/synchronization_verifier.rs +++ b/sync/src/synchronization_verifier.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use std::sync::mpsc::{channel, Sender, Receiver}; use parking_lot::Mutex; use chain::{Block, Transaction}; -use message::common::ConsensusParams; +use network::{Magic, ConsensusParams}; use primitives::hash::H256; use verification::{ChainVerifier, Verify as VerificationVerify}; use synchronization_chain::ChainRef; @@ -48,16 +48,16 @@ pub struct AsyncVerifier { impl AsyncVerifier { /// Create new async verifier - pub fn new(consensus_params: ConsensusParams, chain: ChainRef, sink: Arc>) -> Self { + pub fn new(network: Magic, chain: ChainRef, sink: Arc>) -> Self { let (verification_work_sender, verification_work_receiver) = channel(); let storage = chain.read().storage(); - let verifier = ChainVerifier::new(storage); + let verifier = ChainVerifier::new(storage, network); AsyncVerifier { verification_work_sender: verification_work_sender, verification_worker_thread: Some(thread::Builder::new() .name("Sync verification thread".to_string()) .spawn(move || { - AsyncVerifier::verification_worker_proc(sink, chain, consensus_params, verifier, verification_work_receiver) + AsyncVerifier::verification_worker_proc(sink, chain, network.consensus_params(), verifier, verification_work_receiver) }) .expect("Error creating verification thread")) } diff --git a/verification/Cargo.toml b/verification/Cargo.toml index 9f14090a..73b967a4 100644 --- a/verification/Cargo.toml +++ b/verification/Cargo.toml @@ -4,18 +4,17 @@ version = "0.1.0" authors = ["Nikolay Volf "] [dependencies] +byteorder = "0.5" +parking_lot = "0.3" +linked-hash-map = "0.3" +time = "0.1" +log = "0.3" + ethcore-devtools = { path = "../devtools" } primitives = { path = "../primitives" } chain = { path = "../chain" } serialization = { path = "../serialization" } -parking_lot = "0.3" -linked-hash-map = "0.3" test-data = { path = "../test-data" } -byteorder = "0.5" -time = "0.1" script = { path = "../script" } -log = "0.3" - -[dependencies.db] -path = "../db" -features = ["dev"] +network = { path = "../network" } +db = { path = "../db", features = ["dev"] } diff --git a/verification/src/chain_verifier.rs b/verification/src/chain_verifier.rs index b60424c9..eb6c770f 100644 --- a/verification/src/chain_verifier.rs +++ b/verification/src/chain_verifier.rs @@ -1,7 +1,8 @@ //! Bitcoin chain verifier -use std::collections::HashSet; +use std::collections::BTreeSet; use db::{self, BlockRef, BlockLocation}; +use network::Magic; use super::{Verify, VerificationResult, Chain, Error, TransactionError, ContinueVerify}; use {chain, utils}; @@ -18,16 +19,18 @@ pub struct ChainVerifier { verify_clocktimeverify: bool, skip_pow: bool, skip_sig: bool, + network: Magic, } impl ChainVerifier { - pub fn new(store: db::SharedStore) -> Self { + pub fn new(store: db::SharedStore, network: Magic) -> Self { ChainVerifier { store: store, verify_p2sh: false, verify_clocktimeverify: false, skip_pow: false, - skip_sig: false + skip_sig: false, + network: network, } } @@ -55,7 +58,7 @@ impl ChainVerifier { fn ordered_verify(&self, block: &chain::Block, at_height: u32) -> Result<(), Error> { // check that difficulty matches the adjusted level - if let Some(work) = self.work_required(at_height) { + if let Some(work) = self.work_required(block, at_height) { if !self.skip_pow && work != block.header().nbits { trace!(target: "verification", "pow verification error at height: {}", at_height); trace!(target: "verification", "expected work: {}, got {}", work, block.header().nbits); @@ -202,7 +205,7 @@ impl ChainVerifier { } // target difficulty threshold - if !self.skip_pow && !utils::check_nbits(&hash, block.header().nbits) { + if !self.skip_pow && !utils::check_nbits(self.network.max_nbits(), &hash, block.header().nbits) { return Err(Error::Pow); } @@ -275,7 +278,7 @@ impl ChainVerifier { } fn median_timestamp(&self, block: &chain::Block) -> Option { - let mut timestamps = HashSet::new(); + let mut timestamps = BTreeSet::new(); let mut block_ref = block.block_header.previous_header_hash.clone().into(); // TODO: optimize it, so it does not make 11 redundant queries each time for _ in 0..11 { @@ -288,21 +291,19 @@ impl ChainVerifier { } if timestamps.len() > 2 { - let mut timestamps: Vec<_> = timestamps.into_iter().collect(); - timestamps.sort(); + let timestamps: Vec<_> = timestamps.into_iter().collect(); Some(timestamps[timestamps.len() / 2]) } else { None } } - fn work_required(&self, height: u32) -> Option { + fn work_required(&self, block: &chain::Block, height: u32) -> Option { if height == 0 { return None; } - // should this be best_header or parent header? - // regtest do not pass with previous header, but, imo checking with best is a bit weird, mk - let previous_header = self.store.best_header().expect("self.height != 0; qed"); + let previous_ref = block.block_header.previous_header_hash.clone().into(); + let previous_header = self.store.block_header(previous_ref).expect("self.height != 0; qed"); if utils::is_retarget_height(height) { let retarget_ref = (height - utils::RETARGETING_INTERVAL).into(); @@ -314,7 +315,7 @@ impl ChainVerifier { // nbits of last block let last_nbits = previous_header.nbits; - return Some(utils::work_required_retarget(retarget_timestamp, last_timestamp, last_nbits)); + return Some(utils::work_required_retarget(self.network.max_nbits(), retarget_timestamp, last_timestamp, last_nbits)); } // TODO: if.testnet @@ -356,20 +357,19 @@ impl ContinueVerify for ChainVerifier { #[cfg(test)] mod tests { - + use std::sync::Arc; + use db::{TestStorage, Storage, Store, BlockStapler}; + use network::Magic; + use devtools::RandomTempPath; + use {script, test_data}; use super::ChainVerifier; use super::super::{Verify, Chain, Error, TransactionError}; - use db::{TestStorage, Storage, Store, BlockStapler}; - use test_data; - use std::sync::Arc; - use devtools::RandomTempPath; - use script; #[test] fn verify_orphan() { let storage = TestStorage::with_blocks(&vec![test_data::genesis()]); let b2 = test_data::block_h2(); - let verifier = ChainVerifier::new(Arc::new(storage)); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet); assert_eq!(Chain::Orphan, verifier.verify(&b2).unwrap()); } @@ -378,7 +378,7 @@ mod tests { fn verify_smoky() { let storage = TestStorage::with_blocks(&vec![test_data::genesis()]); let b1 = test_data::block_h1(); - let verifier = ChainVerifier::new(Arc::new(storage)); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet); assert_eq!(Chain::Main, verifier.verify(&b1).unwrap()); } @@ -391,7 +391,7 @@ mod tests { ] ); let b1 = test_data::block_h170(); - let verifier = ChainVerifier::new(Arc::new(storage)); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet); assert_eq!(Chain::Main, verifier.verify(&b1).unwrap()); } @@ -403,7 +403,7 @@ mod tests { ] ); let b170 = test_data::block_h170(); - let verifier = ChainVerifier::new(Arc::new(storage)); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet); let should_be = Err(Error::Transaction( 1, @@ -437,7 +437,7 @@ mod tests { .merkled_header().parent(genesis.hash()).build() .build(); - let verifier = ChainVerifier::new(Arc::new(storage)).pow_skip().signatures_skip(); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip().signatures_skip(); let expected = Err(Error::Transaction( 1, @@ -473,7 +473,7 @@ mod tests { .merkled_header().parent(genesis.hash()).build() .build(); - let verifier = ChainVerifier::new(Arc::new(storage)).pow_skip().signatures_skip(); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip().signatures_skip(); let expected = Ok(Chain::Main); assert_eq!(expected, verifier.verify(&block)); @@ -511,7 +511,7 @@ mod tests { .merkled_header().parent(genesis.hash()).build() .build(); - let verifier = ChainVerifier::new(Arc::new(storage)).pow_skip().signatures_skip(); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip().signatures_skip(); let expected = Ok(Chain::Main); assert_eq!(expected, verifier.verify(&block)); @@ -548,7 +548,7 @@ mod tests { .merkled_header().parent(genesis.hash()).build() .build(); - let verifier = ChainVerifier::new(Arc::new(storage)).pow_skip().signatures_skip(); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip().signatures_skip(); let expected = Err(Error::Transaction(2, TransactionError::Overspend)); assert_eq!(expected, verifier.verify(&block)); @@ -592,7 +592,7 @@ mod tests { .merkled_header().parent(best_hash).build() .build(); - let verifier = ChainVerifier::new(Arc::new(storage)).pow_skip().signatures_skip(); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip().signatures_skip(); let expected = Ok(Chain::Main); @@ -644,7 +644,7 @@ mod tests { .merkled_header().parent(genesis.hash()).build() .build(); - let verifier = ChainVerifier::new(Arc::new(storage)).pow_skip().signatures_skip(); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip().signatures_skip(); let expected = Err(Error::MaximumSigops); assert_eq!(expected, verifier.verify(&block)); @@ -670,7 +670,7 @@ mod tests { .merkled_header().parent(genesis.hash()).build() .build(); - let verifier = ChainVerifier::new(Arc::new(storage)).pow_skip().signatures_skip(); + let verifier = ChainVerifier::new(Arc::new(storage), Magic::Testnet).pow_skip().signatures_skip(); let expected = Err(Error::CoinbaseOverspend { expected_max: 5000000000, diff --git a/verification/src/lib.rs b/verification/src/lib.rs index 7fdfc1fd..9096ffca 100644 --- a/verification/src/lib.rs +++ b/verification/src/lib.rs @@ -1,17 +1,19 @@ //! Bitcoin blocks verification -extern crate db; -extern crate primitives; -extern crate chain; -extern crate serialization; +extern crate byteorder; extern crate parking_lot; extern crate linked_hash_map; -extern crate byteorder; extern crate time; -extern crate script; #[macro_use] extern crate log; +extern crate db; +extern crate chain; +extern crate network; +extern crate primitives; +extern crate serialization; +extern crate script; + #[cfg(test)] extern crate ethcore_devtools as devtools; #[cfg(test)] diff --git a/verification/src/utils.rs b/verification/src/utils.rs index 521887a0..6dfbeef9 100644 --- a/verification/src/utils.rs +++ b/verification/src/utils.rs @@ -21,10 +21,6 @@ const MAX_TIMESPAN: u32 = TARGET_TIMESPAN_SECONDS * RETARGETING_FACTOR; // Target number of blocks, 2 weaks, 2016 pub const RETARGETING_INTERVAL: u32 = TARGET_TIMESPAN_SECONDS / TARGET_SPACING_SECONDS; -pub const MAX_NBITS_MAINNET: u32 = 0x1d00ffff; -pub const MAX_NBITS_TESTNET: u32 = 0x1d00ffff; -pub const MAX_NBITS_REGTEST: u32 = 0x207fffff; - pub fn is_retarget_height(height: u32) -> bool { height % RETARGETING_INTERVAL == 0 } @@ -34,10 +30,10 @@ fn retarget_timespan(retarget_timestamp: u32, last_timestamp: u32) -> u32 { range_constrain(timespan as u32, MIN_TIMESPAN, MAX_TIMESPAN) } -pub fn work_required_retarget(retarget_timestamp: u32, last_timestamp: u32, last_nbits: u32) -> u32 { +pub fn work_required_retarget(max_nbits: u32, retarget_timestamp: u32, last_timestamp: u32, last_nbits: u32) -> u32 { // ignore overflows here let mut retarget = Compact::new(last_nbits).to_u256().unwrap_or_else(|x| x); - let maximum = Compact::new(MAX_NBITS_MAINNET).to_u256().unwrap_or_else(|x| x); + let maximum = Compact::new(max_nbits).to_u256().unwrap_or_else(|x| x); // multiplication overflow potential retarget = retarget * U256::from(retarget_timespan(retarget_timestamp, last_timestamp)); @@ -59,8 +55,10 @@ fn range_constrain(value: u32, min: u32, max: u32) -> u32 { } /// Simple nbits check that does not require 256-bit arithmetic -pub fn check_nbits(hash: &H256, n_bits: u32) -> bool { - if n_bits > MAX_NBITS_REGTEST { return false; } +pub fn check_nbits(max_nbits: u32, hash: &H256, n_bits: u32) -> bool { + if n_bits > max_nbits { + return false; + } let hash_bytes: &[u8] = &**hash; @@ -137,6 +135,7 @@ pub fn p2sh_sigops(output: &Script, input_ref: &Script) -> usize { #[cfg(test)] mod tests { + use network::Magic; use super::{block_reward_satoshi, check_nbits}; use hash::H256; @@ -154,29 +153,31 @@ mod tests { #[test] fn nbits() { + let max_nbits = Magic::Regtest.max_nbits(); + // strictly equal let hash = H256::from_reversed_str("00000000000000001bc330000000000000000000000000000000000000000000"); let nbits = 0x181bc330u32; - assert!(check_nbits(&hash, nbits)); + assert!(check_nbits(max_nbits, &hash, nbits)); // nbits match but not equal (greater) let hash = H256::from_reversed_str("00000000000000001bc330000000000000000000000000000000000000000001"); let nbits = 0x181bc330u32; - assert!(!check_nbits(&hash, nbits)); + assert!(!check_nbits(max_nbits, &hash, nbits)); // greater let hash = H256::from_reversed_str("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); let nbits = 0x181bc330u32; - assert!(!check_nbits(&hash, nbits)); + assert!(!check_nbits(max_nbits, &hash, nbits)); // some real examples let hash = H256::from_reversed_str("000000000000000001f942eb4bfa0aeccb6a14c268f4c72d5fff17270da771b9"); let nbits = 404129525; - assert!(check_nbits(&hash, nbits)); + assert!(check_nbits(max_nbits, &hash, nbits)); let hash = H256::from_reversed_str("00000000000000000e753ef636075711efd2cbf5a8473c7c5b67755a3701e0c2"); let nbits = 404129525; - assert!(check_nbits(&hash, nbits)); + assert!(check_nbits(max_nbits, &hash, nbits)); } }