diff --git a/.travis.yml b/.travis.yml index 0c614ca5d..6ae41379e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,10 +33,6 @@ addons: - libcurl4-openssl-dev - libelf-dev - libdw-dev -before_script: | - sudo add-apt-repository "deb http://ppa.launchpad.net/giskou/librocksdb/ubuntu trusty main" && - sudo apt-get update && - sudo apt-get install -y --force-yes librocksdb script: - cargo build --release --verbose ${FEATURES} - cargo test --release --verbose ${FEATURES} ${TARGETS} diff --git a/Cargo.lock b/Cargo.lock index 8bf57cb6a..dfe37dbb4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,18 +1,18 @@ [root] name = "parity" -version = "0.9.99" +version = "1.1.0" dependencies = [ "clippy 0.0.50 (registry+https://github.com/rust-lang/crates.io-index)", "ctrlc 1.1.1 (git+https://github.com/tomusdrw/rust-ctrlc.git)", "daemonize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 0.6.78 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 0.9.99", - "ethcore-devtools 0.9.99", - "ethcore-rpc 0.9.99", - "ethcore-util 0.9.99", - "ethminer 0.9.99", - "ethsync 0.9.99", + "ethcore 1.1.0", + "ethcore-devtools 1.1.0", + "ethcore-rpc 1.1.0", + "ethcore-util 1.1.0", + "ethminer 1.1.0", + "ethsync 1.1.0", "fdlimit 0.1.0", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -162,7 +162,7 @@ name = "docopt" version = "0.6.78" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "regex 0.1.55 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -178,7 +178,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.55 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -197,7 +197,7 @@ dependencies = [ [[package]] name = "ethash" -version = "0.9.99" +version = "1.1.0" dependencies = [ "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -206,14 +206,14 @@ dependencies = [ [[package]] name = "ethcore" -version = "0.9.99" +version = "1.1.0" dependencies = [ "clippy 0.0.50 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethash 0.9.99", - "ethcore-devtools 0.9.99", - "ethcore-util 0.9.99", + "ethash 1.1.0", + "ethcore-devtools 1.1.0", + "ethcore-util 1.1.0", "heapsize 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -225,21 +225,21 @@ dependencies = [ [[package]] name = "ethcore-devtools" -version = "0.9.99" +version = "1.1.0" dependencies = [ "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethcore-rpc" -version = "0.9.99" +version = "1.1.0" dependencies = [ "clippy 0.0.50 (registry+https://github.com/rust-lang/crates.io-index)", - "ethash 0.9.99", - "ethcore 0.9.99", - "ethcore-util 0.9.99", - "ethminer 0.9.99", - "ethsync 0.9.99", + "ethash 1.1.0", + "ethcore 1.1.0", + "ethcore-util 1.1.0", + "ethminer 1.1.0", + "ethsync 1.1.0", "jsonrpc-core 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-http-server 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -253,7 +253,7 @@ dependencies = [ [[package]] name = "ethcore-util" -version = "0.9.99" +version = "1.1.0" dependencies = [ "arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "bigint 0.1.0", @@ -263,7 +263,7 @@ dependencies = [ "elastic-array 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)", - "ethcore-devtools 0.9.99", + "ethcore-devtools 1.1.0", "heapsize 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "igd 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -288,12 +288,12 @@ dependencies = [ [[package]] name = "ethminer" -version = "0.9.99" +version = "1.1.0" dependencies = [ "clippy 0.0.50 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 0.9.99", - "ethcore-util 0.9.99", + "ethcore 1.1.0", + "ethcore-util 1.1.0", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", @@ -302,13 +302,13 @@ dependencies = [ [[package]] name = "ethsync" -version = "0.9.99" +version = "1.1.0" dependencies = [ "clippy 0.0.50 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 0.9.99", - "ethcore-util 0.9.99", - "ethminer 0.9.99", + "ethcore 1.1.0", + "ethcore-util 1.1.0", + "ethminer 1.1.0", "heapsize 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -343,7 +343,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.55 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -406,7 +406,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hyper 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.55 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "xmltree 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -687,12 +687,12 @@ dependencies = [ [[package]] name = "regex" -version = "0.1.55" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -701,6 +701,11 @@ name = "regex-syntax" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "regex-syntax" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rocksdb" version = "0.4.3" diff --git a/Cargo.toml b/Cargo.toml index 351041119..782dd1c79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Ethcore client." name = "parity" -version = "0.9.99" +version = "1.1.0" license = "GPL-3.0" authors = ["Ethcore "] build = "build.rs" diff --git a/devtools/Cargo.toml b/devtools/Cargo.toml index ce0260936..19178fbfe 100644 --- a/devtools/Cargo.toml +++ b/devtools/Cargo.toml @@ -3,7 +3,7 @@ description = "Ethcore development/test/build tools" homepage = "http://ethcore.io" license = "GPL-3.0" name = "ethcore-devtools" -version = "0.9.99" +version = "1.1.0" authors = ["Ethcore "] [dependencies] diff --git a/ethash/Cargo.toml b/ethash/Cargo.toml index e2a2ec4d8..70d08249c 100644 --- a/ethash/Cargo.toml +++ b/ethash/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ethash" -version = "0.9.99" +version = "1.1.0" authors = ["arkpar "] [dependencies] diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 7eb34670f..6f3986391 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -171,7 +171,7 @@ pub struct SealedBlock { impl<'x> OpenBlock<'x> { /// Create a new OpenBlock ready for transaction pushing. - pub fn new(engine: &'x Engine, db: Box, parent: &Header, last_hashes: LastHashes, author: Address, extra_data: Bytes) -> Self { + pub fn new(engine: &'x Engine, db: Box, parent: &Header, last_hashes: LastHashes, author: Address, gas_floor_target: U256, extra_data: Bytes) -> Self { let mut r = OpenBlock { block: ExecutedBlock::new(State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce())), engine: engine, @@ -185,7 +185,7 @@ impl<'x> OpenBlock<'x> { r.block.base.header.extra_data = extra_data; r.block.base.header.note_dirty(); - engine.populate_from_parent(&mut r.block.base.header, parent); + engine.populate_from_parent(&mut r.block.base.header, parent, gas_floor_target); engine.on_new_block(&mut r.block); r } @@ -347,7 +347,7 @@ pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Head } } - let mut b = OpenBlock::new(engine, db, parent, last_hashes, header.author().clone(), header.extra_data().clone()); + let mut b = OpenBlock::new(engine, db, parent, last_hashes, header.author().clone(), x!(3141562), header.extra_data().clone()); b.set_difficulty(*header.difficulty()); b.set_gas_limit(*header.gas_limit()); b.set_timestamp(header.timestamp()); @@ -391,7 +391,7 @@ mod tests { let mut db = db_result.take(); engine.spec().ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; - let b = OpenBlock::new(engine.deref(), db, &genesis_header, last_hashes, Address::zero(), vec![]); + let b = OpenBlock::new(engine.deref(), db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]); let b = b.close(); let _ = b.seal(engine.deref(), vec![]); } @@ -405,7 +405,7 @@ mod tests { let mut db_result = get_temp_journal_db(); let mut db = db_result.take(); engine.spec().ensure_db_good(db.as_hashdb_mut()); - let b = OpenBlock::new(engine.deref(), db, &genesis_header, vec![genesis_header.hash()], Address::zero(), vec![]).close().seal(engine.deref(), vec![]).unwrap(); + let b = OpenBlock::new(engine.deref(), db, &genesis_header, vec![genesis_header.hash()], Address::zero(), x!(3141562), vec![]).close().seal(engine.deref(), vec![]).unwrap(); let orig_bytes = b.rlp_bytes(); let orig_db = b.drain(); diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index d748cc4ee..0bd371c0f 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -109,6 +109,11 @@ pub struct Client where V: Verifier { } const HISTORY: u64 = 1000; +// DO NOT TOUCH THIS ANY MORE UNLESS YOU REALLY KNOW WHAT YOU'RE DOING. +// Altering it will force a blanket DB update for *all* JournalDB-derived +// databases. +// Instead, add/upgrade the version string of the individual JournalDB-derived database +// of which you actually want force an upgrade. const CLIENT_DB_VER_STR: &'static str = "5.2"; impl Client { @@ -380,15 +385,13 @@ impl Client where V: Verifier { } impl BlockChainClient for Client where V: Verifier { - - // TODO [todr] Should be moved to miner crate eventually. fn try_seal(&self, block: ClosedBlock, seal: Vec) -> Result { block.try_seal(self.engine.deref().deref(), seal) } // TODO [todr] Should be moved to miner crate eventually. - fn prepare_sealing(&self, author: Address, extra_data: Bytes, transactions: Vec) -> Option { + fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec) -> Option { let engine = self.engine.deref().deref(); let h = self.chain.best_block_hash(); @@ -398,6 +401,7 @@ impl BlockChainClient for Client where V: Verifier { match self.chain.block_header(&h) { Some(ref x) => x, None => {return None} }, self.build_last_hashes(h.clone()), author, + gas_floor_target, extra_data, ); diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index e46d0b570..88e07d0b1 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -110,7 +110,7 @@ pub trait BlockChainClient : Sync + Send { // TODO [todr] Should be moved to miner crate eventually. /// Returns ClosedBlock prepared for sealing. - fn prepare_sealing(&self, author: Address, extra_data: Bytes, transactions: Vec) -> Option; + fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec) -> Option; // TODO [todr] Should be moved to miner crate eventually. /// Attempts to seal given block. Returns `SealedBlock` on success and the same block in case of error. diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 140b8d91f..d6a5707e5 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -215,7 +215,7 @@ impl BlockChainClient for TestBlockChainClient { unimplemented!(); } - fn prepare_sealing(&self, _author: Address, _extra_data: Bytes, _transactions: Vec) -> Option { + fn prepare_sealing(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes, _transactions: Vec) -> Option { unimplemented!() } diff --git a/ethcore/src/engine.rs b/ethcore/src/engine.rs index 83e1986fd..0b2ce8ae2 100644 --- a/ethcore/src/engine.rs +++ b/ethcore/src/engine.rs @@ -85,7 +85,7 @@ pub trait Engine : Sync + Send { /// Don't forget to call Super::populate_from_parent when subclassing & overriding. // TODO: consider including State in the params. - fn populate_from_parent(&self, header: &mut Header, parent: &Header) { + fn populate_from_parent(&self, header: &mut Header, parent: &Header, _gas_floor_target: U256) { header.difficulty = parent.difficulty; header.gas_limit = parent.gas_limit; header.note_dirty(); diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index a882f66ae..406777251 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -92,10 +92,9 @@ impl Engine for Ethash { } } - fn populate_from_parent(&self, header: &mut Header, parent: &Header) { + fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256) { header.difficulty = self.calculate_difficuty(header, parent); header.gas_limit = { - let gas_floor_target: U256 = x!(3141562); let gas_limit = parent.gas_limit; let bound_divisor = self.u256_param("gasLimitBoundDivisor"); if gas_limit < gas_floor_target { @@ -300,7 +299,7 @@ mod tests { let mut db = db_result.take(); engine.spec().ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; - let b = OpenBlock::new(engine.deref(), db, &genesis_header, last_hashes, Address::zero(), vec![]); + let b = OpenBlock::new(engine.deref(), db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]); let b = b.close(); assert_eq!(b.state().balance(&Address::zero()), U256::from_str("4563918244f40000").unwrap()); } @@ -313,7 +312,7 @@ mod tests { let mut db = db_result.take(); engine.spec().ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; - let mut b = OpenBlock::new(engine.deref(), db, &genesis_header, last_hashes, Address::zero(), vec![]); + let mut b = OpenBlock::new(engine.deref(), db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]); let mut uncle = Header::new(); let uncle_author = address_from_hex("ef2d6d194084c2de36e0dabfce45d046b37d1106"); uncle.author = uncle_author.clone(); diff --git a/ethcore/src/evm/tests.rs b/ethcore/src/evm/tests.rs index dc84a9a05..445c0be41 100644 --- a/ethcore/src/evm/tests.rs +++ b/ethcore/src/evm/tests.rs @@ -55,7 +55,7 @@ struct FakeExt { info: EnvInfo, schedule: Schedule, balances: HashMap, - calls: HashSet + calls: HashSet, } impl FakeExt { @@ -346,7 +346,7 @@ fn test_log_empty(factory: super::Factory) { assert_eq!(gas_left, U256::from(99_619)); assert_eq!(ext.logs.len(), 1); assert_eq!(ext.logs[0].topics.len(), 0); - assert_eq!(ext.logs[0].data, vec![]); + assert!(ext.logs[0].data.is_empty()); } evm_test!{test_log_sender: test_log_sender_jit, test_log_sender_int} diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index ed0b02788..797684d1d 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -133,7 +133,7 @@ fn can_mine() { let client_result = get_test_client_with_blocks(vec![dummy_blocks[0].clone()]); let client = client_result.reference(); - let b = client.prepare_sealing(Address::default(), vec![], vec![]).unwrap(); + let b = client.prepare_sealing(Address::default(), x!(31415926), vec![], vec![]).unwrap(); assert_eq!(*b.block().header().parent_hash(), BlockView::new(&dummy_blocks[0]).header_view().sha3()); assert!(client.try_seal(b, vec![]).is_ok()); diff --git a/evmjit/Cargo.toml b/evmjit/Cargo.toml index 9449af82d..6586a360e 100644 --- a/evmjit/Cargo.toml +++ b/evmjit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "evmjit" -version = "0.9.99" +version = "1.1.0" authors = ["debris "] [lib] diff --git a/miner/Cargo.toml b/miner/Cargo.toml index b450ece73..cd56aee9e 100644 --- a/miner/Cargo.toml +++ b/miner/Cargo.toml @@ -3,7 +3,7 @@ description = "Ethminer library" homepage = "http://ethcore.io" license = "GPL-3.0" name = "ethminer" -version = "0.9.99" +version = "1.1.0" authors = ["Ethcore "] build = "build.rs" diff --git a/miner/src/miner.rs b/miner/src/miner.rs index ad403150d..6d5b3086e 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -19,7 +19,7 @@ use std::sync::{Mutex, RwLock, Arc}; use std::sync::atomic; use std::sync::atomic::AtomicBool; -use util::{H256, U256, Address, Bytes}; +use util::{H256, U256, Address, Bytes, Uint}; use ethcore::views::{BlockView}; use ethcore::client::{BlockChainClient, BlockId}; use ethcore::block::{ClosedBlock}; @@ -34,8 +34,10 @@ pub struct Miner { // for sealing... sealing_enabled: AtomicBool, sealing_block: Mutex>, + gas_floor_target: RwLock, author: RwLock
, extra_data: RwLock, + } impl Default for Miner { @@ -44,6 +46,7 @@ impl Default for Miner { transaction_queue: Mutex::new(TransactionQueue::new()), sealing_enabled: AtomicBool::new(false), sealing_block: Mutex::new(None), + gas_floor_target: RwLock::new(U256::zero()), author: RwLock::new(Address::default()), extra_data: RwLock::new(Vec::new()), } @@ -66,6 +69,11 @@ impl Miner { self.extra_data.read().unwrap().clone() } + /// Get the extra_data that we will seal blocks wuth. + fn gas_floor_target(&self) -> U256 { + self.gas_floor_target.read().unwrap().clone() + } + /// Set the author that we will seal blocks as. pub fn set_author(&self, author: Address) { *self.author.write().unwrap() = author; @@ -76,6 +84,11 @@ impl Miner { *self.extra_data.write().unwrap() = extra_data; } + /// Set the gas limit we wish to target when sealing a new block. + pub fn set_gas_floor_target(&self, target: U256) { + *self.gas_floor_target.write().unwrap() = target; + } + /// Set minimal gas price of transaction to be accepted for mining. pub fn set_minimal_gas_price(&self, min_gas_price: U256) { self.transaction_queue.lock().unwrap().set_minimal_gas_price(min_gas_price); @@ -110,10 +123,12 @@ impl MinerService for Miner { fn prepare_sealing(&self, chain: &BlockChainClient) { let no_of_transactions = 128; + // TODO: should select transactions orm queue according to gas limit of block. let transactions = self.transaction_queue.lock().unwrap().top_transactions(no_of_transactions); let b = chain.prepare_sealing( self.author(), + self.gas_floor_target(), self.extra_data(), transactions, ); diff --git a/parity/main.rs b/parity/main.rs index d7e92d6ff..26e3e4b78 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -78,72 +78,88 @@ Usage: parity [options] Protocol Options: - --chain CHAIN Specify the blockchain type. CHAIN may be either a JSON chain specification file - or olympic, frontier, homestead, mainnet, morden, or testnet [default: homestead]. - --testnet Equivalent to --chain testnet (geth-compatible). - --networkid INDEX Override the network identifier from the chain we are on. - --pruning METHOD Configure pruning of the state/storage trie. METHOD may be one of: archive, - basic (experimental), fast (experimental) [default: archive]. - -d --datadir PATH Specify the database & configuration directory path [default: $HOME/.parity] - --db-path PATH Specify the database & configuration directory path [default: $HOME/.parity] - --keys-path PATH Specify the path for JSON key files to be found [default: $HOME/.web3/keys] + --chain CHAIN Specify the blockchain type. CHAIN may be either a + JSON chain specification file or olympic, frontier, + homestead, mainnet, morden, or testnet + [default: homestead]. + -d --db-path PATH Specify the database & configuration directory path + [default: $HOME/.parity]. + --keys-path PATH Specify the path for JSON key files to be found + [default: $HOME/.web3/keys]. --identity NAME Specify your node's name. Networking Options: - --port PORT Override the port on which the node should listen [default: 30303]. + --port PORT Override the port on which the node should listen + [default: 30303]. --peers NUM Try to maintain that many peers [default: 25]. - --nat METHOD Specify method to use for determining public address. Must be one of: any, none, - upnp, extip:(IP) [default: any]. - --bootnodes NODES Specify additional comma-separated bootnodes. - --no-bootstrap Don't bother trying to connect to standard bootnodes. + --nat METHOD Specify method to use for determining public + address. Must be one of: any, none, upnp, + extip: [default: any]. + --network-id INDEX Override the network identifier from the chain we + are on. + --bootnodes NODES Override the bootnodes from our chain. NODES should + be comma-delimited enodes. --no-discovery Disable new peer discovery. - --node-key KEY Specify node secret key, either as 64-character hex string or input to SHA3 operation. + --node-key KEY Specify node secret key, either as 64-character hex + string or input to SHA3 operation. API and Console Options: -j --jsonrpc Enable the JSON-RPC API sever. - --jsonrpc-addr HOST Specify the hostname portion of the JSONRPC API server [default: 127.0.0.1]. - --jsonrpc-port PORT Specify the port portion of the JSONRPC API server [default: 8545]. - --jsonrpc-cors URL Specify CORS header for JSON-RPC API responses [default: null]. - --jsonrpc-apis APIS Specify the APIs available through the JSONRPC interface. APIS is a comma-delimited - list of API name. Possible name are web3, eth and net. [default: web3,eth,net,personal]. - - --rpc Equivalent to --jsonrpc (geth-compatible). - --rpcaddr HOST Equivalent to --jsonrpc-addr HOST (geth-compatible). - --rpcport PORT Equivalent to --jsonrpc-port PORT (geth-compatible). - --rpcapi APIS Equivalent to --jsonrpc-apis APIS (geth-compatible). - --rpccorsdomain URL Equivalent to --jsonrpc-cors URL (geth-compatible). + --jsonrpc-addr HOST Specify the hostname portion of the JSONRPC API + server [default: 127.0.0.1]. + --jsonrpc-port PORT Specify the port portion of the JSONRPC API server + [default: 8545]. + --jsonrpc-cors URL Specify CORS header for JSON-RPC API responses + [default: null]. + --jsonrpc-apis APIS Specify the APIs available through the JSONRPC + interface. APIS is a comma-delimited list of API + name. Possible name are web3, eth and net. + [default: web3,eth,net,personal]. Sealing/Mining Options: - --gas-price WEI Minimum amount of Wei to be paid for a transaction to be accepted for mining [default: 20000000000]. - --author ADDRESS Specify the block author (aka "coinbase") address for sending block rewards - from sealed blocks [default: 0037a6b811ffeb6e072da21179d11b1406371c63]. - --extra-data STRING Specify a custom extra-data for authored blocks, no more than 32 characters. + --gas-price WEI Minimum amount of Wei to be paid for a transaction + to be accepted for mining [default: 20000000000]. + --gas-floor-target GAS Amount of gas per block to target when sealing a new + block [default: 4712388]. + --author ADDRESS Specify the block author (aka "coinbase") address + for sending block rewards from sealed blocks + [default: 0037a6b811ffeb6e072da21179d11b1406371c63]. + --extra-data STRING Specify a custom extra-data for authored blocks, no + more than 32 characters. -Memory Footprint Options: - --cache-pref-size BYTES Specify the prefered size of the blockchain cache in bytes [default: 16384]. - --cache-max-size BYTES Specify the maximum size of the blockchain cache in bytes [default: 262144]. - --queue-max-size BYTES Specify the maximum size of memory to use for block queue [default: 52428800]. - --cache MEGABYTES Set total amount of cache to use for the entire system, mutually exclusive with - other cache options (geth-compatible). +Footprint Options: + --pruning METHOD Configure pruning of the state/storage trie. METHOD + may be one of: archive, basic (experimental), fast + (experimental) [default: archive]. + --cache-pref-size BYTES Specify the prefered size of the blockchain cache in + bytes [default: 16384]. + --cache-max-size BYTES Specify the maximum size of the blockchain cache in + bytes [default: 262144]. + --queue-max-size BYTES Specify the maximum size of memory to use for block + queue [default: 52428800]. + --cache MEGABYTES Set total amount of discretionary memory to use for + the entire system, overrides other cache and queue + options. -Geth-Compatibility Options +Geth-compatibility Options: --datadir PATH Equivalent to --db-path PATH. --testnet Equivalent to --chain testnet. - --networkid INDEX Override the network identifier from the chain we are on. + --networkid INDEX Equivalent to --network-id INDEX. + --maxpeers COUNT Equivalent to --peers COUNT. + --nodekey KEY Equivalent to --node-key KEY. + --nodiscover Equivalent to --no-discovery. --rpc Equivalent to --jsonrpc. --rpcaddr HOST Equivalent to --jsonrpc-addr HOST. --rpcport PORT Equivalent to --jsonrpc-port PORT. --rpcapi APIS Equivalent to --jsonrpc-apis APIS. --rpccorsdomain URL Equivalent to --jsonrpc-cors URL. - --maxpeers COUNT Equivalent to --peers COUNT. - --nodekey KEY Equivalent to --node-key KEY. - --nodiscover Equivalent to --no-discovery. --gasprice WEI Equivalent to --gas-price WEI. --etherbase ADDRESS Equivalent to --author ADDRESS. --extradata STRING Equivalent to --extra-data STRING. Miscellaneous Options: - -l --logging LOGGING Specify the logging level. Must conform to the same format as RUST_LOG. + -l --logging LOGGING Specify the logging level. Must conform to the same + format as RUST_LOG. -v --version Show information about version. -h --help Show this screen. "#; @@ -161,8 +177,8 @@ struct Args { flag_cache: Option, flag_keys_path: String, flag_bootnodes: Option, + flag_network_id: Option, flag_pruning: String, - flag_no_bootstrap: bool, flag_port: u16, flag_peers: usize, flag_no_discovery: bool, @@ -178,6 +194,7 @@ struct Args { flag_jsonrpc_apis: String, flag_author: String, flag_gas_price: String, + flag_gas_floor_target: String, flag_extra_data: Option, flag_logging: Option, flag_version: bool, @@ -303,6 +320,13 @@ impl Configuration { }) } + fn gas_floor_target(&self) -> U256 { + let d = &self.args.flag_gas_floor_target; + U256::from_dec_str(d).unwrap_or_else(|_| { + die!("{}: Invalid target gas floor given. Must be a decimal unsigned 256-bit number.", d) + }) + } + fn gas_price(&self) -> U256 { let d = self.args.flag_gasprice.as_ref().unwrap_or(&self.args.flag_gas_price); U256::from_dec_str(d).unwrap_or_else(|_| { @@ -345,15 +369,15 @@ impl Configuration { } fn init_nodes(&self, spec: &Spec) -> Vec { - let mut r = if self.args.flag_no_bootstrap { Vec::new() } else { spec.nodes().clone() }; - if let Some(ref x) = self.args.flag_bootnodes { - r.extend(x.split(',').map(|s| { + match self.args.flag_bootnodes { + Some(ref x) if x.len() > 0 => x.split(',').map(|s| { Self::normalize_enode(s).unwrap_or_else(|| { die!("{}: Invalid node address format given for a boot node.", s) }) - })); + }).collect(), + Some(_) => Vec::new(), + None => spec.nodes().clone(), } - r } #[cfg_attr(feature="dev", allow(useless_format))] @@ -390,7 +414,7 @@ impl Configuration { match self.args.flag_cache { Some(mb) => { client_config.blockchain.max_cache_size = mb * 1024 * 1024; - client_config.blockchain.pref_cache_size = client_config.blockchain.max_cache_size / 2; + client_config.blockchain.pref_cache_size = client_config.blockchain.max_cache_size * 3 / 4; } None => { client_config.blockchain.pref_cache_size = self.args.flag_cache_pref_size; @@ -411,8 +435,8 @@ impl Configuration { fn sync_config(&self, spec: &Spec) -> SyncConfig { let mut sync_config = SyncConfig::default(); - sync_config.network_id = self.args.flag_networkid.as_ref().map_or(spec.network_id(), |id| { - U256::from_str(id).unwrap_or_else(|_| die!("{}: Invalid index given with --networkid", id)) + sync_config.network_id = self.args.flag_network_id.as_ref().or(self.args.flag_networkid.as_ref()).map_or(spec.network_id(), |id| { + U256::from_str(id).unwrap_or_else(|_| die!("{}: Invalid index given with --network-id/--networkid", id)) }); sync_config } @@ -485,6 +509,7 @@ impl Configuration { // Miner let miner = Miner::new(); miner.set_author(self.author()); + miner.set_gas_floor_target(self.gas_floor_target()); miner.set_extra_data(self.extra_data()); miner.set_minimal_gas_price(self.gas_price()); diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index fa89041d8..88b69e82c 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Ethcore jsonrpc" name = "ethcore-rpc" -version = "0.9.99" +version = "1.1.0" license = "GPL-3.0" authors = ["Ethcore Personal for PersonalClient where A: AccountProvider + 'static { |(pass, )| { let store = take_weak!(self.accounts); match store.new_account(&pass) { - Ok(address) => Ok(Value::String(format!("{:?}", address))), + Ok(address) => Ok(Value::String(format!("0x{:?}", address))), Err(_) => Err(Error::internal_error()) } } diff --git a/rpc/src/v1/tests/helpers/account_provider.rs b/rpc/src/v1/tests/helpers/account_provider.rs index 66f085f74..ce5b76b44 100644 --- a/rpc/src/v1/tests/helpers/account_provider.rs +++ b/rpc/src/v1/tests/helpers/account_provider.rs @@ -42,6 +42,7 @@ impl TestAccount { /// Test account provider. pub struct TestAccountProvider { accounts: RwLock>, + pub adds: RwLock>, } impl TestAccountProvider { @@ -49,6 +50,7 @@ impl TestAccountProvider { pub fn new(accounts: HashMap) -> Self { TestAccountProvider { accounts: RwLock::new(accounts), + adds: RwLock::new(vec![]), } } } @@ -69,9 +71,13 @@ impl AccountProvider for TestAccountProvider { } } - fn new_account(&self, _pass: &str) -> Result { - unimplemented!() + fn new_account(&self, pass: &str) -> Result { + let mut adds = self.adds.write().unwrap(); + let address = Address::from(adds.len() as u64 + 2); + adds.push(pass.to_owned()); + Ok(address) } + fn account_secret(&self, _account: &Address) -> Result { unimplemented!() } diff --git a/rpc/src/v1/tests/mod.rs b/rpc/src/v1/tests/mod.rs index 3374bad36..21085a0fd 100644 --- a/rpc/src/v1/tests/mod.rs +++ b/rpc/src/v1/tests/mod.rs @@ -20,3 +20,4 @@ mod eth; mod net; mod web3; mod helpers; +mod personal; diff --git a/rpc/src/v1/tests/personal.rs b/rpc/src/v1/tests/personal.rs new file mode 100644 index 000000000..261527c47 --- /dev/null +++ b/rpc/src/v1/tests/personal.rs @@ -0,0 +1,59 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use std::sync::Arc; +use jsonrpc_core::IoHandler; +use v1::tests::helpers::{TestAccount, TestAccountProvider}; +use v1::{PersonalClient, Personal}; +use util::numbers::*; +use std::collections::*; + +fn accounts_provider() -> Arc { + let mut accounts = HashMap::new(); + accounts.insert(Address::from(1), TestAccount::new("test")); + let ap = TestAccountProvider::new(accounts); + Arc::new(ap) +} + +fn setup() -> (Arc, IoHandler) { + let test_provider = accounts_provider(); + let personal = PersonalClient::new(&test_provider); + let io = IoHandler::new(); + io.add_delegate(personal.to_delegate()); + (test_provider, io) +} + +#[test] +fn accounts() { + let (_test_provider, io) = setup(); + + let request = r#"{"jsonrpc": "2.0", "method": "personal_listAccounts", "params": [], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":["0x0000000000000000000000000000000000000001"],"id":1}"#; + + assert_eq!(io.handle_request(request), Some(response.to_owned())); +} + + +#[test] +fn new_account() { + let (_test_provider, io) = setup(); + + let request = r#"{"jsonrpc": "2.0", "method": "personal_newAccount", "params": ["pass"], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000002","id":1}"#; + + assert_eq!(io.handle_request(request), Some(response.to_owned())); +} + diff --git a/sync/Cargo.toml b/sync/Cargo.toml index 8cd59333d..877f4e6c8 100644 --- a/sync/Cargo.toml +++ b/sync/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Ethcore blockchain sync" name = "ethsync" -version = "0.9.99" +version = "1.1.0" license = "GPL-3.0" authors = ["Ethcore "] build = "build.rs" diff --git a/util/bigint/src/uint.rs b/util/bigint/src/uint.rs index ea617d570..c3cc6b753 100644 --- a/util/bigint/src/uint.rs +++ b/util/bigint/src/uint.rs @@ -1948,8 +1948,6 @@ mod tests { #[test] fn u256_multi_muls() { - use hash::*; - let (result, _) = U256([0, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0])); assert_eq!(U256([0, 0, 0, 0]), result); @@ -1979,23 +1977,6 @@ mod tests { let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, ::std::u64::MAX])); assert_eq!(U256([0, 0, 0, ::std::u64::MAX]), result); - - let x1 = U256::from_str("0000000000000000000000000000000000000000000000000000012365124623").unwrap(); - let x2sqr_right = U256::from_str("000000000000000000000000000000000000000000014baeef72e0378e2328c9").unwrap(); - let x1sqr = x1 * x1; - assert_eq!(H256::from(x2sqr_right), H256::from(x1sqr)); - let x1cube = x1sqr * x1; - let x1cube_right = U256::from_str("0000000000000000000000000000000001798acde139361466f712813717897b").unwrap(); - assert_eq!(H256::from(x1cube_right), H256::from(x1cube)); - let x1quad = x1cube * x1; - let x1quad_right = U256::from_str("000000000000000000000001adbdd6bd6ff027485484b97f8a6a4c7129756dd1").unwrap(); - assert_eq!(H256::from(x1quad_right), H256::from(x1quad)); - let x1penta = x1quad * x1; - let x1penta_right = U256::from_str("00000000000001e92875ac24be246e1c57e0507e8c46cc8d233b77f6f4c72993").unwrap(); - assert_eq!(H256::from(x1penta_right), H256::from(x1penta)); - let x1septima = x1penta * x1; - let x1septima_right = U256::from_str("00022cca1da3f6e5722b7d3cc5bbfb486465ebc5a708dd293042f932d7eee119").unwrap(); - assert_eq!(H256::from(x1septima_right), H256::from(x1septima)); } #[test] diff --git a/util/src/bytes.rs b/util/src/bytes.rs index 5a4500ae6..0683ea4df 100644 --- a/util/src/bytes.rs +++ b/util/src/bytes.rs @@ -177,7 +177,7 @@ impl BytesConvertable for T where T: AsRef<[u8]> { #[test] fn bytes_convertable() { assert_eq!(vec![0x12u8, 0x34].bytes(), &[0x12u8, 0x34]); - assert_eq!([0u8; 0].bytes(), &[]); + assert!([0u8; 0].as_slice().is_empty()); } /// Simple trait to allow for raw population of a Sized object from a byte slice. diff --git a/util/src/journaldb/earlymergedb.rs b/util/src/journaldb/earlymergedb.rs index 7f0f50da2..7cb00b993 100644 --- a/util/src/journaldb/earlymergedb.rs +++ b/util/src/journaldb/earlymergedb.rs @@ -171,7 +171,7 @@ impl EarlyMergeDB { trace!(target: "jdb.fine", "replay_keys: (end) refs={:?}", refs); } - fn kill_keys(deletes: &Vec, refs: &mut HashMap, batch: &DBTransaction, from: RemoveFrom, trace: bool) { + fn kill_keys(deletes: &[H256], refs: &mut HashMap, batch: &DBTransaction, from: RemoveFrom, trace: bool) { // with a kill on {queue_refs: 1, in_archive: true}, we have two options: // - convert to {queue_refs: 1, in_archive: false} (i.e. remove it from the conceptual archive) // - convert to {queue_refs: 0, in_archive: true} (i.e. remove it from the conceptual queue) @@ -340,8 +340,10 @@ impl JournalDB for EarlyMergeDB { } } + + #[cfg_attr(feature="dev", allow(cyclomatic_complexity))] fn commit(&mut self, now: u64, id: &H256, end: Option<(u64, H256)>) -> Result { - // journal format: + // journal format: // [era, 0] => [ id, [insert_0, ...], [remove_0, ...] ] // [era, 1] => [ id, [insert_0, ...], [remove_0, ...] ] // [era, n] => [ ... ] @@ -473,7 +475,7 @@ impl JournalDB for EarlyMergeDB { if trace { trace!(target: "jdb.ops", " Finalising: {:?}", inserts); } - for k in inserts.iter() { + for k in &inserts { match refs.get(k).cloned() { None => { // [in archive] -> SHIFT remove -> SHIFT insert None->Some{queue_refs: 1, in_archive: true} -> TAKE remove Some{queue_refs: 1, in_archive: true}->None -> TAKE insert @@ -489,7 +491,7 @@ impl JournalDB for EarlyMergeDB { Self::set_already_in(&batch, k); refs.insert(k.clone(), RefInfo{ queue_refs: x - 1, in_archive: true }); } - Some( RefInfo{queue_refs: _, in_archive: true} ) => { + Some( RefInfo{in_archive: true, ..} ) => { // Invalid! Reinserted the same key twice. warn!("Key {} inserted twice into same fork.", k); } @@ -936,7 +938,7 @@ mod tests { assert!(jdb.can_reconstruct_refs()); assert!(!jdb.exists(&foo)); } - + #[test] fn reopen_test() { let mut dir = ::std::env::temp_dir(); @@ -971,7 +973,7 @@ mod tests { jdb.commit(7, &b"7".sha3(), Some((3, b"3".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); } - + #[test] fn reopen_remove_three() { init_log(); @@ -1025,7 +1027,7 @@ mod tests { assert!(!jdb.exists(&foo)); } } - + #[test] fn reopen_fork() { let mut dir = ::std::env::temp_dir(); diff --git a/util/src/misc.rs b/util/src/misc.rs index 39ccbf2da..8dcd25988 100644 --- a/util/src/misc.rs +++ b/util/src/misc.rs @@ -70,7 +70,7 @@ pub fn contents(name: &str) -> Result { /// Get the standard version string for this software. pub fn version() -> String { - format!("Parity/v{}-{}-{}/{}-{}-{}/rustc{}", env!("CARGO_PKG_VERSION"), short_sha(), commit_date().replace("-", ""), Target::arch(), Target::os(), Target::env(), rustc_version::version()) + format!("Parity/v{}-unstable-{}-{}/{}-{}-{}/rustc{}", env!("CARGO_PKG_VERSION"), short_sha(), commit_date().replace("-", ""), Target::arch(), Target::os(), Target::env(), rustc_version::version()) } /// Get the standard version data for this software. @@ -85,4 +85,4 @@ pub fn version_data() -> Bytes { s.append(&format!("{}", rustc_version::version())); s.append(&&Target::os()[0..2]); s.out() -} \ No newline at end of file +} diff --git a/util/src/network/discovery.rs b/util/src/network/discovery.rs index a381b49f8..d755c58e7 100644 --- a/util/src/network/discovery.rs +++ b/util/src/network/discovery.rs @@ -18,7 +18,6 @@ use bytes::Bytes; use std::net::SocketAddr; use std::collections::{HashSet, HashMap, BTreeMap, VecDeque}; use std::mem; -use std::cmp; use std::default::Default; use mio::*; use mio::udp::*; @@ -298,7 +297,7 @@ impl Discovery { return; } Err(e) => { - warn!("UDP send error: {:?}, address: {:?}", e, &data.address); + debug!("UDP send error: {:?}, address: {:?}", e, &data.address); return; } } @@ -318,7 +317,7 @@ impl Discovery { }), Ok(_) => None, Err(e) => { - warn!("Error reading UPD socket: {:?}", e); + debug!("Error reading UPD socket: {:?}", e); None } } @@ -407,27 +406,34 @@ impl Discovery { let target: NodeId = try!(rlp.val_at(0)); let timestamp: u64 = try!(rlp.val_at(1)); try!(self.check_timestamp(timestamp)); - let limit = (MAX_DATAGRAM_SIZE - 109) / 90; let nearest = Discovery::nearest_node_entries(&target, &self.node_buckets); if nearest.is_empty() { return Ok(None); } - let mut rlp = RlpStream::new_list(1); - rlp.begin_list(cmp::min(limit, nearest.len())); - for n in 0 .. nearest.len() { - rlp.begin_list(4); - nearest[n].endpoint.to_rlp(&mut rlp); - rlp.append(&nearest[n].id); - if (n + 1) % limit == 0 || n == nearest.len() - 1 { - self.send_packet(PACKET_NEIGHBOURS, &from, &rlp.drain()); - trace!(target: "discovery", "Sent {} Neighbours to {:?}", n, &from); - rlp = RlpStream::new_list(1); - rlp.begin_list(cmp::min(limit, nearest.len() - n)); - } + let mut packets = Discovery::prepare_neighbours_packets(&nearest); + for p in packets.drain(..) { + self.send_packet(PACKET_NEIGHBOURS, &from, &p); } + trace!(target: "discovery", "Sent {} Neighbours to {:?}", nearest.len(), &from); Ok(None) } + fn prepare_neighbours_packets(nearest: &[NodeEntry]) -> Vec { + let limit = (MAX_DATAGRAM_SIZE - 109) / 90; + let chunks = nearest.chunks(limit); + let packets = chunks.map(|c| { + let mut rlp = RlpStream::new_list(1); + rlp.begin_list(c.len()); + for n in 0 .. c.len() { + rlp.begin_list(4); + c[n].endpoint.to_rlp(&mut rlp); + rlp.append(&c[n].id); + } + rlp.out() + }); + packets.collect() + } + fn on_neighbours(&mut self, rlp: &UntrustedRlp, _node: &NodeId, from: &SocketAddr) -> Result, NetworkError> { // TODO: validate packet let mut added = HashMap::new(); @@ -506,6 +512,24 @@ mod tests { use crypto::KeyPair; use std::str::FromStr; use rustc_serialize::hex::FromHex; + use rlp::*; + + #[test] + fn find_node() { + let mut nearest = Vec::new(); + let node = Node::from_str("enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@127.0.0.1:7770").unwrap(); + for _ in 0..1000 { + nearest.push( NodeEntry { id: node.id.clone(), endpoint: node.endpoint.clone() }); + } + + let packets = Discovery::prepare_neighbours_packets(&nearest); + assert_eq!(packets.len(), 77); + for p in &packets[0..76] { + assert!(p.len() > 1280/2); + assert!(p.len() <= 1280); + } + assert!(packets.last().unwrap().len() > 0); + } #[test] fn discovery() { diff --git a/util/src/table.rs b/util/src/table.rs index 5ba572289..c3b2006cf 100644 --- a/util/src/table.rs +++ b/util/src/table.rs @@ -40,7 +40,7 @@ impl Default for Table } // There is default but clippy does not detect it? -#[allow(new_without_default)] +#[cfg_attr(feature="dev", allow(new_without_default))] impl Table where Row: Eq + Hash + Clone, Col: Eq + Hash {