From f6b7884a1dcdd6382f522ae38c4f6d29222f40c7 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 14 Mar 2016 02:00:22 +0100 Subject: [PATCH] Allow configuration of target gas limit. --- ethcore/src/block.rs | 10 +++++----- ethcore/src/client/client.rs | 5 ++--- ethcore/src/client/mod.rs | 2 +- ethcore/src/client/test_client.rs | 2 +- ethcore/src/engine.rs | 2 +- ethcore/src/ethereum/ethash.rs | 7 +++---- miner/src/miner.rs | 19 +++++++++++++++++-- parity/main.rs | 10 ++++++++++ 8 files changed, 40 insertions(+), 17 deletions(-) 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..cbea020ba 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -380,15 +380,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 +396,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/miner/src/miner.rs b/miner/src/miner.rs index ad403150d..43f11f9c4 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,12 +123,14 @@ 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, + transactions ); *self.sealing_block.lock().unwrap() = b; } diff --git a/parity/main.rs b/parity/main.rs index 8562b416d..0039d2ba6 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -115,6 +115,7 @@ API and Console Options: Sealing/Mining Options: --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. @@ -178,6 +179,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 +305,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(|_| { @@ -485,6 +494,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());