Backports for beta (#1628)
* Remove soft-fork stuff. * Fix tests. * Fix "pending" parameter on RPC block requests (#1602) * Initial commit. * Pending blocks work. * Address grumbles. * Fix up for new API. * Fixed test
This commit is contained in:
parent
b7caa24c2e
commit
68dfae8f06
@ -9,8 +9,7 @@
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||
"frontierCompatibilityModeLimit": "0x118c30",
|
||||
"daoRescueSoftFork": false
|
||||
"frontierCompatibilityModeLimit": "0x118c30"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -9,8 +9,7 @@
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||
"frontierCompatibilityModeLimit": "0x118c30",
|
||||
"daoRescueSoftFork": false
|
||||
"frontierCompatibilityModeLimit": "0x118c30"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -9,8 +9,7 @@
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||
"frontierCompatibilityModeLimit": "0x118c30",
|
||||
"daoRescueSoftFork": true
|
||||
"frontierCompatibilityModeLimit": "0x118c30"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -9,8 +9,7 @@
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||
"frontierCompatibilityModeLimit": "0xffffffffffffffff",
|
||||
"daoRescueSoftFork": false
|
||||
"frontierCompatibilityModeLimit": "0xffffffffffffffff"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -9,8 +9,7 @@
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||
"frontierCompatibilityModeLimit": 0,
|
||||
"daoRescueSoftFork": false
|
||||
"frontierCompatibilityModeLimit": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -9,8 +9,7 @@
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||
"frontierCompatibilityModeLimit": 0,
|
||||
"daoRescueSoftFork": true
|
||||
"frontierCompatibilityModeLimit": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -9,8 +9,7 @@
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"registrar": "",
|
||||
"frontierCompatibilityModeLimit": "0x789b0",
|
||||
"daoRescueSoftFork": false
|
||||
"frontierCompatibilityModeLimit": "0x789b0"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -9,8 +9,7 @@
|
||||
"durationLimit": "0x08",
|
||||
"blockReward": "0x14D1120D7B160000",
|
||||
"registrar": "5e70c0bbcd5636e0f9f9316e9f8633feb64d4050",
|
||||
"frontierCompatibilityModeLimit": "0xffffffffffffffff",
|
||||
"daoRescueSoftFork": false
|
||||
"frontierCompatibilityModeLimit": "0xffffffffffffffff"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -203,7 +203,6 @@ mod tests {
|
||||
timestamp: 0,
|
||||
difficulty: 0.into(),
|
||||
last_hashes: vec![],
|
||||
dao_rescue_block_gas_limit: None,
|
||||
gas_used: 0.into(),
|
||||
gas_limit: 0.into(),
|
||||
});
|
||||
@ -254,7 +253,7 @@ mod tests {
|
||||
spec.ensure_db_good(db.as_hashdb_mut());
|
||||
let last_hashes = vec![genesis_header.hash()];
|
||||
let vm_factory = Default::default();
|
||||
let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, addr, (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let b = b.close_and_lock();
|
||||
let seal = engine.generate_seal(b.block(), Some(&tap)).unwrap();
|
||||
assert!(b.try_seal(engine.deref(), seal).is_ok());
|
||||
|
@ -41,8 +41,18 @@ impl Block {
|
||||
pub fn is_good(b: &[u8]) -> bool {
|
||||
UntrustedRlp::new(b).as_val::<Block>().is_ok()
|
||||
}
|
||||
|
||||
/// Get the RLP-encoding of the block without the seal.
|
||||
pub fn rlp_bytes(&self, seal: Seal) -> Bytes {
|
||||
let mut block_rlp = RlpStream::new_list(3);
|
||||
self.header.stream_rlp(&mut block_rlp, seal);
|
||||
block_rlp.append(&self.transactions);
|
||||
block_rlp.append(&self.uncles);
|
||||
block_rlp.out()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Decodable for Block {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
if decoder.as_raw().len() != try!(decoder.as_rlp().payload_info()).total() {
|
||||
@ -142,9 +152,12 @@ impl ExecutedBlock {
|
||||
|
||||
/// Trait for a object that is a `ExecutedBlock`.
|
||||
pub trait IsBlock {
|
||||
/// Get the block associated with this object.
|
||||
/// Get the `ExecutedBlock` associated with this object.
|
||||
fn block(&self) -> &ExecutedBlock;
|
||||
|
||||
/// Get the base `Block` object associated with this.
|
||||
fn base(&self) -> &Block { &self.block().base }
|
||||
|
||||
/// Get the header associated with this object's block.
|
||||
fn header(&self) -> &Header { &self.block().base.header }
|
||||
|
||||
@ -183,7 +196,6 @@ pub struct OpenBlock<'x> {
|
||||
engine: &'x Engine,
|
||||
vm_factory: &'x EvmFactory,
|
||||
last_hashes: LastHashes,
|
||||
dao_rescue_block_gas_limit: Option<U256>,
|
||||
}
|
||||
|
||||
/// Just like `OpenBlock`, except that we've applied `Engine::on_close_block`, finished up the non-seal header fields,
|
||||
@ -195,7 +207,6 @@ pub struct ClosedBlock {
|
||||
block: ExecutedBlock,
|
||||
uncle_bytes: Bytes,
|
||||
last_hashes: LastHashes,
|
||||
dao_rescue_block_gas_limit: Option<U256>,
|
||||
unclosed_state: State,
|
||||
}
|
||||
|
||||
@ -226,7 +237,6 @@ impl<'x> OpenBlock<'x> {
|
||||
db: Box<JournalDB>,
|
||||
parent: &Header,
|
||||
last_hashes: LastHashes,
|
||||
dao_rescue_block_gas_limit: Option<U256>,
|
||||
author: Address,
|
||||
gas_range_target: (U256, U256),
|
||||
extra_data: Bytes,
|
||||
@ -237,7 +247,6 @@ impl<'x> OpenBlock<'x> {
|
||||
engine: engine,
|
||||
vm_factory: vm_factory,
|
||||
last_hashes: last_hashes,
|
||||
dao_rescue_block_gas_limit: dao_rescue_block_gas_limit,
|
||||
};
|
||||
|
||||
r.block.base.header.parent_hash = parent.hash();
|
||||
@ -294,7 +303,6 @@ impl<'x> OpenBlock<'x> {
|
||||
/// Get the environment info concerning this block.
|
||||
pub fn env_info(&self) -> EnvInfo {
|
||||
// TODO: memoise.
|
||||
const SOFT_FORK_BLOCK: u64 = 1_800_000;
|
||||
EnvInfo {
|
||||
number: self.block.base.header.number,
|
||||
author: self.block.base.header.author.clone(),
|
||||
@ -303,7 +311,6 @@ impl<'x> OpenBlock<'x> {
|
||||
last_hashes: self.last_hashes.clone(), // TODO: should be a reference.
|
||||
gas_used: self.block.receipts.last().map_or(U256::zero(), |r| r.gas_used),
|
||||
gas_limit: self.block.base.header.gas_limit.clone(),
|
||||
dao_rescue_block_gas_limit: if self.block.base.header.number == SOFT_FORK_BLOCK { Some(self.block.base.header.gas_limit) } else { self.dao_rescue_block_gas_limit },
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,7 +357,6 @@ impl<'x> OpenBlock<'x> {
|
||||
block: s.block,
|
||||
uncle_bytes: uncle_bytes,
|
||||
last_hashes: s.last_hashes,
|
||||
dao_rescue_block_gas_limit: s.dao_rescue_block_gas_limit,
|
||||
unclosed_state: unclosed_state,
|
||||
}
|
||||
}
|
||||
@ -410,7 +416,6 @@ impl ClosedBlock {
|
||||
engine: engine,
|
||||
vm_factory: vm_factory,
|
||||
last_hashes: self.last_hashes,
|
||||
dao_rescue_block_gas_limit: self.dao_rescue_block_gas_limit,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -480,7 +485,6 @@ pub fn enact(
|
||||
db: Box<JournalDB>,
|
||||
parent: &Header,
|
||||
last_hashes: LastHashes,
|
||||
dao_rescue_block_gas_limit: Option<U256>,
|
||||
vm_factory: &EvmFactory
|
||||
) -> Result<LockedBlock, Error> {
|
||||
{
|
||||
@ -490,7 +494,7 @@ pub fn enact(
|
||||
}
|
||||
}
|
||||
|
||||
let mut b = try!(OpenBlock::new(engine, vm_factory, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, header.author().clone(), (3141562.into(), 31415620.into()), header.extra_data().clone()));
|
||||
let mut b = try!(OpenBlock::new(engine, vm_factory, tracing, db, parent, last_hashes, header.author().clone(), (3141562.into(), 31415620.into()), header.extra_data().clone()));
|
||||
b.set_difficulty(*header.difficulty());
|
||||
b.set_gas_limit(*header.gas_limit());
|
||||
b.set_timestamp(header.timestamp());
|
||||
@ -508,12 +512,11 @@ pub fn enact_bytes(
|
||||
db: Box<JournalDB>,
|
||||
parent: &Header,
|
||||
last_hashes: LastHashes,
|
||||
dao_rescue_block_gas_limit: Option<U256>,
|
||||
vm_factory: &EvmFactory
|
||||
) -> Result<LockedBlock, Error> {
|
||||
let block = BlockView::new(block_bytes);
|
||||
let header = block.header();
|
||||
enact(&header, &block.transactions(), &block.uncles(), engine, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, vm_factory)
|
||||
enact(&header, &block.transactions(), &block.uncles(), engine, tracing, db, parent, last_hashes, vm_factory)
|
||||
}
|
||||
|
||||
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
|
||||
@ -525,11 +528,10 @@ pub fn enact_verified(
|
||||
db: Box<JournalDB>,
|
||||
parent: &Header,
|
||||
last_hashes: LastHashes,
|
||||
dao_rescue_block_gas_limit: Option<U256>,
|
||||
vm_factory: &EvmFactory
|
||||
) -> Result<LockedBlock, Error> {
|
||||
let view = BlockView::new(&block.bytes);
|
||||
enact(&block.header, &block.transactions, &view.uncles(), engine, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, vm_factory)
|
||||
enact(&block.header, &block.transactions, &view.uncles(), engine, tracing, db, parent, last_hashes, vm_factory)
|
||||
}
|
||||
|
||||
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards
|
||||
@ -541,11 +543,10 @@ pub fn enact_and_seal(
|
||||
db: Box<JournalDB>,
|
||||
parent: &Header,
|
||||
last_hashes: LastHashes,
|
||||
dao_rescue_block_gas_limit: Option<U256>,
|
||||
vm_factory: &EvmFactory
|
||||
) -> Result<SealedBlock, Error> {
|
||||
let header = BlockView::new(block_bytes).header_view();
|
||||
Ok(try!(try!(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, vm_factory)).seal(engine, header.seal())))
|
||||
Ok(try!(try!(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes, vm_factory)).seal(engine, header.seal())))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -565,7 +566,7 @@ mod tests {
|
||||
spec.ensure_db_good(db.as_hashdb_mut());
|
||||
let last_hashes = vec![genesis_header.hash()];
|
||||
let vm_factory = Default::default();
|
||||
let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let b = b.close_and_lock();
|
||||
let _ = b.seal(engine.deref(), vec![]);
|
||||
}
|
||||
@ -581,7 +582,7 @@ mod tests {
|
||||
let mut db = db_result.take();
|
||||
spec.ensure_db_good(db.as_hashdb_mut());
|
||||
let vm_factory = Default::default();
|
||||
let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap()
|
||||
let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap()
|
||||
.close_and_lock().seal(engine.deref(), vec![]).unwrap();
|
||||
let orig_bytes = b.rlp_bytes();
|
||||
let orig_db = b.drain();
|
||||
@ -589,7 +590,7 @@ mod tests {
|
||||
let mut db_result = get_temp_journal_db();
|
||||
let mut db = db_result.take();
|
||||
spec.ensure_db_good(db.as_hashdb_mut());
|
||||
let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], None, &Default::default()).unwrap();
|
||||
let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], &Default::default()).unwrap();
|
||||
|
||||
assert_eq!(e.rlp_bytes(), orig_bytes);
|
||||
|
||||
@ -609,7 +610,7 @@ mod tests {
|
||||
let mut db = db_result.take();
|
||||
spec.ensure_db_good(db.as_hashdb_mut());
|
||||
let vm_factory = Default::default();
|
||||
let mut open_block = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let mut open_block = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let mut uncle1_header = Header::new();
|
||||
uncle1_header.extra_data = b"uncle1".to_vec();
|
||||
let mut uncle2_header = Header::new();
|
||||
@ -624,7 +625,7 @@ mod tests {
|
||||
let mut db_result = get_temp_journal_db();
|
||||
let mut db = db_result.take();
|
||||
spec.ensure_db_good(db.as_hashdb_mut());
|
||||
let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], None, &Default::default()).unwrap();
|
||||
let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], &Default::default()).unwrap();
|
||||
|
||||
let bytes = e.rlp_bytes();
|
||||
assert_eq!(bytes, orig_bytes);
|
||||
|
@ -25,6 +25,7 @@ use error::{ImportError, ExecutionError, BlockError, ImportResult};
|
||||
use header::{BlockNumber, Header};
|
||||
use state::State;
|
||||
use spec::Spec;
|
||||
use basic_types::Seal;
|
||||
use engine::Engine;
|
||||
use views::HeaderView;
|
||||
use service::{NetSyncMessage, SyncMessage};
|
||||
@ -234,7 +235,7 @@ impl Client {
|
||||
let last_hashes = self.build_last_hashes(header.parent_hash.clone());
|
||||
let db = self.state_db.lock().unwrap().boxed_clone();
|
||||
|
||||
let enact_result = enact_verified(&block, engine, self.tracedb.tracing_enabled(), db, &parent, last_hashes, self.dao_rescue_block_gas_limit(header.parent_hash.clone()), &self.vm_factory);
|
||||
let enact_result = enact_verified(&block, engine, self.tracedb.tracing_enabled(), db, &parent, last_hashes, &self.vm_factory);
|
||||
if let Err(e) = enact_result {
|
||||
warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
||||
return Err(());
|
||||
@ -396,8 +397,10 @@ impl Client {
|
||||
/// Otherwise, this can fail (but may not) if the DB prunes state.
|
||||
pub fn state_at(&self, id: BlockID) -> Option<State> {
|
||||
// fast path for latest state.
|
||||
if let BlockID::Latest = id.clone() {
|
||||
return Some(self.state())
|
||||
match id.clone() {
|
||||
BlockID::Pending => return self.miner.pending_state().or_else(|| Some(self.state())),
|
||||
BlockID::Latest => return Some(self.state()),
|
||||
_ => {},
|
||||
}
|
||||
|
||||
let block_number = match self.block_number(id.clone()) {
|
||||
@ -454,7 +457,7 @@ impl Client {
|
||||
BlockID::Number(number) => Some(number),
|
||||
BlockID::Hash(ref hash) => self.chain.block_number(hash),
|
||||
BlockID::Earliest => Some(0),
|
||||
BlockID::Latest => Some(self.chain.best_block_number())
|
||||
BlockID::Latest | BlockID::Pending => Some(self.chain.best_block_number()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -463,7 +466,7 @@ impl Client {
|
||||
BlockID::Hash(hash) => Some(hash),
|
||||
BlockID::Number(number) => chain.block_hash(number),
|
||||
BlockID::Earliest => chain.block_hash(0),
|
||||
BlockID::Latest => Some(chain.best_block_hash())
|
||||
BlockID::Latest | BlockID::Pending => Some(chain.best_block_hash()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -491,7 +494,6 @@ impl BlockChainClient for Client {
|
||||
last_hashes: last_hashes,
|
||||
gas_used: U256::zero(),
|
||||
gas_limit: U256::max_value(),
|
||||
dao_rescue_block_gas_limit: self.dao_rescue_block_gas_limit(view.parent_hash()),
|
||||
};
|
||||
// that's just a copy of the state.
|
||||
let mut state = self.state();
|
||||
@ -535,6 +537,11 @@ impl BlockChainClient for Client {
|
||||
}
|
||||
|
||||
fn block(&self, id: BlockID) -> Option<Bytes> {
|
||||
if let &BlockID::Pending = &id {
|
||||
if let Some(block) = self.miner.pending_block() {
|
||||
return Some(block.rlp_bytes(Seal::Without));
|
||||
}
|
||||
}
|
||||
Self::block_hash(&self.chain, id).and_then(|hash| {
|
||||
self.chain.block(&hash)
|
||||
})
|
||||
@ -549,6 +556,11 @@ impl BlockChainClient for Client {
|
||||
}
|
||||
|
||||
fn block_total_difficulty(&self, id: BlockID) -> Option<U256> {
|
||||
if let &BlockID::Pending = &id {
|
||||
if let Some(block) = self.miner.pending_block() {
|
||||
return Some(*block.header.difficulty() + self.block_total_difficulty(BlockID::Latest).expect("blocks in chain have details; qed"));
|
||||
}
|
||||
}
|
||||
Self::block_hash(&self.chain, id).and_then(|hash| self.chain.block_details(&hash)).map(|d| d.total_difficulty)
|
||||
}
|
||||
|
||||
@ -802,7 +814,6 @@ impl MiningBlockChainClient for Client {
|
||||
self.state_db.lock().unwrap().boxed_clone(),
|
||||
&self.chain.block_header(&h).expect("h is best block hash: so it's header must exist: qed"),
|
||||
self.build_last_hashes(h.clone()),
|
||||
self.dao_rescue_block_gas_limit(h.clone()),
|
||||
author,
|
||||
gas_range_target,
|
||||
extra_data,
|
||||
|
@ -42,7 +42,7 @@ use header::{BlockNumber, Header};
|
||||
use transaction::{LocalizedTransaction, SignedTransaction};
|
||||
use log_entry::LocalizedLogEntry;
|
||||
use filter::Filter;
|
||||
use views::{HeaderView, BlockView};
|
||||
use views::{BlockView};
|
||||
use error::{ImportResult, ExecutionError};
|
||||
use receipt::LocalizedReceipt;
|
||||
use trace::LocalizedTrace;
|
||||
@ -216,28 +216,6 @@ pub trait BlockChainClient : Sync + Send {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Get `Some` gas limit of SOFT_FORK_BLOCK, or `None` if chain is not yet that long.
|
||||
fn dao_rescue_block_gas_limit(&self, chain_hash: H256) -> Option<U256> {
|
||||
const SOFT_FORK_BLOCK: u64 = 1800000;
|
||||
// shortcut if the canon chain is already known.
|
||||
if self.chain_info().best_block_number > SOFT_FORK_BLOCK + 1000 {
|
||||
return self.block_header(BlockID::Number(SOFT_FORK_BLOCK)).map(|header| HeaderView::new(&header).gas_limit());
|
||||
}
|
||||
// otherwise check according to `chain_hash`.
|
||||
if let Some(mut header) = self.block_header(BlockID::Hash(chain_hash)) {
|
||||
if HeaderView::new(&header).number() < SOFT_FORK_BLOCK {
|
||||
None
|
||||
} else {
|
||||
while HeaderView::new(&header).number() != SOFT_FORK_BLOCK {
|
||||
header = self.block_header(BlockID::Hash(HeaderView::new(&header).parent_hash())).expect("chain is complete; parent of chain entry must be in chain; qed");
|
||||
}
|
||||
Some(HeaderView::new(&header).gas_limit())
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extended client interface used for mining
|
||||
|
@ -233,7 +233,7 @@ impl TestBlockChainClient {
|
||||
BlockID::Hash(hash) => Some(hash),
|
||||
BlockID::Number(n) => self.numbers.read().unwrap().get(&(n as usize)).cloned(),
|
||||
BlockID::Earliest => self.numbers.read().unwrap().get(&0).cloned(),
|
||||
BlockID::Latest => self.numbers.read().unwrap().get(&(self.numbers.read().unwrap().len() - 1)).cloned()
|
||||
BlockID::Latest | BlockID::Pending => self.numbers.read().unwrap().get(&(self.numbers.read().unwrap().len() - 1)).cloned()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,9 +39,6 @@ pub struct EnvInfo {
|
||||
pub last_hashes: LastHashes,
|
||||
/// The gas used.
|
||||
pub gas_used: U256,
|
||||
|
||||
/// Block gas limit at DAO rescue block SOFT_FORK_BLOCK or None if not yet there.
|
||||
pub dao_rescue_block_gas_limit: Option<U256>,
|
||||
}
|
||||
|
||||
impl Default for EnvInfo {
|
||||
@ -54,7 +51,6 @@ impl Default for EnvInfo {
|
||||
gas_limit: 0.into(),
|
||||
last_hashes: vec![],
|
||||
gas_used: 0.into(),
|
||||
dao_rescue_block_gas_limit: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -70,7 +66,6 @@ impl From<ethjson::vm::Env> for EnvInfo {
|
||||
timestamp: e.timestamp.into(),
|
||||
last_hashes: (1..cmp::min(number + 1, 257)).map(|i| format!("{}", number - i).as_bytes().sha3()).collect(),
|
||||
gas_used: U256::zero(),
|
||||
dao_rescue_block_gas_limit: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,8 +39,6 @@ pub struct EthashParams {
|
||||
pub registrar: Address,
|
||||
/// Homestead transition block number.
|
||||
pub frontier_compatibility_mode_limit: u64,
|
||||
/// Enable the soft-fork logic.
|
||||
pub dao_rescue_soft_fork: bool,
|
||||
}
|
||||
|
||||
impl From<ethjson::spec::EthashParams> for EthashParams {
|
||||
@ -53,7 +51,6 @@ impl From<ethjson::spec::EthashParams> for EthashParams {
|
||||
block_reward: p.block_reward.into(),
|
||||
registrar: p.registrar.into(),
|
||||
frontier_compatibility_mode_limit: p.frontier_compatibility_mode_limit.into(),
|
||||
dao_rescue_soft_fork: p.dao_rescue_soft_fork.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -102,11 +99,7 @@ impl Engine for Ethash {
|
||||
if env_info.number < self.ethash_params.frontier_compatibility_mode_limit {
|
||||
Schedule::new_frontier()
|
||||
} else {
|
||||
let mut s = Schedule::new_homestead();
|
||||
if self.ethash_params.dao_rescue_soft_fork {
|
||||
s.reject_dao_transactions = env_info.dao_rescue_block_gas_limit.map_or(false, |x| x <= 4_000_000.into());
|
||||
}
|
||||
s
|
||||
Schedule::new_homestead()
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,7 +318,7 @@ mod tests {
|
||||
spec.ensure_db_good(db.as_hashdb_mut());
|
||||
let last_hashes = vec![genesis_header.hash()];
|
||||
let vm_factory = Default::default();
|
||||
let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let b = b.close();
|
||||
assert_eq!(b.state().balance(&Address::zero()), U256::from_str("4563918244f40000").unwrap());
|
||||
}
|
||||
@ -340,7 +333,7 @@ mod tests {
|
||||
spec.ensure_db_good(db.as_hashdb_mut());
|
||||
let last_hashes = vec![genesis_header.hash()];
|
||||
let vm_factory = Default::default();
|
||||
let mut b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let mut b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
|
||||
let mut uncle = Header::new();
|
||||
let uncle_author = address_from_hex("ef2d6d194084c2de36e0dabfce45d046b37d1106");
|
||||
uncle.author = uncle_author.clone();
|
||||
@ -369,7 +362,6 @@ mod tests {
|
||||
last_hashes: vec![],
|
||||
gas_used: 0.into(),
|
||||
gas_limit: 0.into(),
|
||||
dao_rescue_block_gas_limit: None,
|
||||
});
|
||||
|
||||
assert!(schedule.stack_limit > 0);
|
||||
@ -382,7 +374,6 @@ mod tests {
|
||||
last_hashes: vec![],
|
||||
gas_used: 0.into(),
|
||||
gas_limit: 0.into(),
|
||||
dao_rescue_block_gas_limit: None,
|
||||
});
|
||||
|
||||
assert!(!schedule.have_delegate_call);
|
||||
|
@ -33,11 +33,8 @@ use super::spec::*;
|
||||
pub fn new_olympic() -> Spec { Spec::load(include_bytes!("../../res/ethereum/olympic.json")) }
|
||||
|
||||
/// Create a new Frontier mainnet chain spec.
|
||||
pub fn new_frontier(dao_rescue: bool) -> Spec {
|
||||
Spec::load(match dao_rescue {
|
||||
true => include_bytes!("../../res/ethereum/frontier_dao_rescue.json"),
|
||||
false => include_bytes!("../../res/ethereum/frontier.json"),
|
||||
})
|
||||
pub fn new_frontier() -> Spec {
|
||||
Spec::load(include_bytes!("../../res/ethereum/frontier.json"))
|
||||
}
|
||||
|
||||
/// Create a new Frontier chain spec as though it never changes to Homestead.
|
||||
@ -89,7 +86,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn frontier() {
|
||||
let frontier = new_frontier(true);
|
||||
let frontier = new_frontier();
|
||||
|
||||
assert_eq!(frontier.state_root(), H256::from_str("d7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544").unwrap());
|
||||
let genesis = frontier.genesis_block();
|
||||
|
@ -319,7 +319,6 @@ mod tests {
|
||||
last_hashes: vec![],
|
||||
gas_used: 0.into(),
|
||||
gas_limit: 0.into(),
|
||||
dao_rescue_block_gas_limit: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,9 @@ use util::*;
|
||||
use util::Colour::White;
|
||||
use account_provider::AccountProvider;
|
||||
use views::{BlockView, HeaderView};
|
||||
use state::State;
|
||||
use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockID, CallAnalytics};
|
||||
use block::{ClosedBlock, IsBlock};
|
||||
use block::{ClosedBlock, IsBlock, Block};
|
||||
use error::*;
|
||||
use transaction::SignedTransaction;
|
||||
use receipt::{Receipt};
|
||||
@ -152,6 +153,16 @@ impl Miner {
|
||||
self.options.force_sealing || !self.options.new_work_notify.is_empty()
|
||||
}
|
||||
|
||||
/// Get `Some` `clone()` of the current pending block's state or `None` if we're not sealing.
|
||||
pub fn pending_state(&self) -> Option<State> {
|
||||
self.sealing_work.lock().unwrap().peek_last_ref().map(|b| b.block().fields().state.clone())
|
||||
}
|
||||
|
||||
/// Get `Some` `clone()` of the current pending block's state or `None` if we're not sealing.
|
||||
pub fn pending_block(&self) -> Option<Block> {
|
||||
self.sealing_work.lock().unwrap().peek_last_ref().map(|b| b.base().clone())
|
||||
}
|
||||
|
||||
/// Prepares new block for sealing including top transactions from queue.
|
||||
#[cfg_attr(feature="dev", allow(match_same_arms))]
|
||||
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
|
||||
@ -374,7 +385,6 @@ impl MinerService for Miner {
|
||||
last_hashes: last_hashes,
|
||||
gas_used: U256::zero(),
|
||||
gas_limit: U256::max_value(),
|
||||
dao_rescue_block_gas_limit: chain.dao_rescue_block_gas_limit(header.parent_hash().clone()),
|
||||
};
|
||||
// that's just a copy of the state.
|
||||
let mut state = block.state().clone();
|
||||
|
@ -33,7 +33,7 @@
|
||||
//! use ethcore::miner::{Miner, MinerService};
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let miner: Miner = Miner::with_spec(ethereum::new_frontier(true));
|
||||
//! let miner: Miner = Miner::with_spec(ethereum::new_frontier());
|
||||
//! // get status
|
||||
//! assert_eq!(miner.status().transactions_in_pending_queue, 0);
|
||||
//!
|
||||
|
@ -179,7 +179,6 @@ pub fn generate_dummy_client_with_spec_and_data<F>(get_test_spec: F, block_numbe
|
||||
db,
|
||||
&last_header,
|
||||
last_hashes.clone(),
|
||||
None,
|
||||
author.clone(),
|
||||
(3141562.into(), 31415620.into()),
|
||||
vec![]
|
||||
|
@ -33,7 +33,9 @@ pub enum BlockID {
|
||||
/// Earliest block (genesis).
|
||||
Earliest,
|
||||
/// Latest mined block.
|
||||
Latest
|
||||
Latest,
|
||||
/// Pending block.
|
||||
Pending,
|
||||
}
|
||||
|
||||
/// Uniquely identifies transaction.
|
||||
|
@ -53,8 +53,7 @@ mod tests {
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||
"frontierCompatibilityModeLimit" : "0x",
|
||||
"daoRescueSoftFork": true
|
||||
"frontierCompatibilityModeLimit" : "0x"
|
||||
}
|
||||
}
|
||||
}"#;
|
||||
|
@ -42,9 +42,6 @@ pub struct EthashParams {
|
||||
/// Homestead transition block number.
|
||||
#[serde(rename="frontierCompatibilityModeLimit")]
|
||||
pub frontier_compatibility_mode_limit: Uint,
|
||||
/// DAO rescue soft-fork?
|
||||
#[serde(rename="daoRescueSoftFork")]
|
||||
pub dao_rescue_soft_fork: bool,
|
||||
}
|
||||
|
||||
/// Ethash engine deserialization.
|
||||
@ -69,8 +66,7 @@ mod tests {
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||
"frontierCompatibilityModeLimit": "0x42",
|
||||
"daoRescueSoftFork": true
|
||||
"frontierCompatibilityModeLimit": "0x42"
|
||||
}
|
||||
}"#;
|
||||
|
||||
|
@ -63,8 +63,7 @@ mod tests {
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||
"frontierCompatibilityModeLimit" : "0x",
|
||||
"daoRescueSoftFork": false
|
||||
"frontierCompatibilityModeLimit" : "0x"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -45,9 +45,8 @@ Protocol Options:
|
||||
--fork POLICY Specifies the client's fork policy. POLICY must be
|
||||
one of:
|
||||
dogmatic - sticks rigidly to the standard chain.
|
||||
dao-soft - votes for the DAO-rescue soft-fork.
|
||||
normal - goes with whatever fork is decided but
|
||||
votes for none. [default: normal].
|
||||
none - goes with whatever fork is decided but
|
||||
votes for none. [default: none].
|
||||
|
||||
Account Options:
|
||||
--unlock ACCOUNTS Unlock ACCOUNTS for the duration of the execution.
|
||||
|
@ -49,8 +49,7 @@ pub struct Directories {
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub enum Policy {
|
||||
DaoSoft,
|
||||
Normal,
|
||||
None,
|
||||
Dogmatic,
|
||||
}
|
||||
|
||||
@ -126,33 +125,24 @@ impl Configuration {
|
||||
|
||||
pub fn policy(&self) -> Policy {
|
||||
match self.args.flag_fork.as_str() {
|
||||
"dao-soft" => Policy::DaoSoft,
|
||||
"normal" => Policy::Normal,
|
||||
"none" => Policy::None,
|
||||
"dogmatic" => Policy::Dogmatic,
|
||||
x => die!("{}: Invalid value given for --policy option. Use --help for more info.", x)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gas_floor_target(&self) -> U256 {
|
||||
if self.policy() == Policy::DaoSoft {
|
||||
3_141_592.into()
|
||||
} else {
|
||||
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)
|
||||
})
|
||||
}
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn gas_ceil_target(&self) -> U256 {
|
||||
if self.policy() == Policy::DaoSoft {
|
||||
3_141_592.into()
|
||||
} else {
|
||||
let d = &self.args.flag_gas_cap;
|
||||
U256::from_dec_str(d).unwrap_or_else(|_| {
|
||||
die!("{}: Invalid target gas ceiling given. Must be a decimal unsigned 256-bit number.", d)
|
||||
})
|
||||
}
|
||||
let d = &self.args.flag_gas_cap;
|
||||
U256::from_dec_str(d).unwrap_or_else(|_| {
|
||||
die!("{}: Invalid target gas ceiling given. Must be a decimal unsigned 256-bit number.", d)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn gas_price(&self) -> U256 {
|
||||
@ -198,7 +188,7 @@ impl Configuration {
|
||||
|
||||
pub fn spec(&self) -> Spec {
|
||||
match self.chain().as_str() {
|
||||
"frontier" | "homestead" | "mainnet" => ethereum::new_frontier(self.policy() != Policy::Dogmatic),
|
||||
"frontier" | "homestead" | "mainnet" => ethereum::new_frontier(),
|
||||
"morden" | "testnet" => ethereum::new_morden(),
|
||||
"olympic" => ethereum::new_olympic(),
|
||||
f => Spec::load(contents(f).unwrap_or_else(|_| {
|
||||
|
@ -97,7 +97,7 @@ use rpc::RpcServer;
|
||||
use signer::{SignerServer, new_token};
|
||||
use dapps::WebappServer;
|
||||
use io_handler::ClientIoHandler;
|
||||
use configuration::Configuration;
|
||||
use configuration::{Policy, Configuration};
|
||||
|
||||
fn main() {
|
||||
let conf = Configuration::parse();
|
||||
@ -206,6 +206,11 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
|
||||
warn!("NOTE that Signer will not ask you to confirm transactions from unlocked account.");
|
||||
}
|
||||
|
||||
// Check fork settings.
|
||||
if conf.policy() != Policy::None {
|
||||
warn!("Value given for --policy, yet no proposed forks exist. Ignoring.");
|
||||
}
|
||||
|
||||
// Secret Store
|
||||
let account_service = Arc::new(conf.account_service());
|
||||
|
||||
|
@ -199,8 +199,7 @@ const TRANSACTION_COUNT_SPEC: &'static [u8] = br#"{
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||
"frontierCompatibilityModeLimit": "0xffffffffffffffff",
|
||||
"daoRescueSoftFork": false
|
||||
"frontierCompatibilityModeLimit": "0xffffffffffffffff"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -28,7 +28,7 @@ pub enum BlockNumber {
|
||||
/// Earliest block (genesis)
|
||||
Earliest,
|
||||
/// Pending block (being mined)
|
||||
Pending
|
||||
Pending,
|
||||
}
|
||||
|
||||
impl Deserialize for BlockNumber {
|
||||
@ -63,8 +63,8 @@ impl Into<BlockID> for BlockNumber {
|
||||
match self {
|
||||
BlockNumber::Num(n) => BlockID::Number(n),
|
||||
BlockNumber::Earliest => BlockID::Earliest,
|
||||
// TODO: change this once blockid support pendingst,
|
||||
BlockNumber::Pending | BlockNumber::Latest => BlockID::Latest,
|
||||
BlockNumber::Latest => BlockID::Latest,
|
||||
BlockNumber::Pending => BlockID::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -87,7 +87,7 @@ mod tests {
|
||||
assert_eq!(BlockID::Number(100), BlockNumber::Num(100).into());
|
||||
assert_eq!(BlockID::Earliest, BlockNumber::Earliest.into());
|
||||
assert_eq!(BlockID::Latest, BlockNumber::Latest.into());
|
||||
assert_eq!(BlockID::Latest, BlockNumber::Pending.into());
|
||||
assert_eq!(BlockID::Pending, BlockNumber::Pending.into());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,10 +44,10 @@
|
||||
//! let mut service = NetworkService::new(NetworkConfiguration::new()).unwrap();
|
||||
//! service.start().unwrap();
|
||||
//! let dir = env::temp_dir();
|
||||
//! let miner = Miner::new(Default::default(), ethereum::new_frontier(true), None);
|
||||
//! let miner = Miner::new(Default::default(), ethereum::new_frontier(), None);
|
||||
//! let client = Client::new(
|
||||
//! ClientConfig::default(),
|
||||
//! ethereum::new_frontier(true),
|
||||
//! ethereum::new_frontier(),
|
||||
//! &dir,
|
||||
//! miner,
|
||||
//! service.io().channel()
|
||||
|
Loading…
Reference in New Issue
Block a user