diff --git a/res/ethereum/frontier.json b/res/ethereum/frontier.json index 0be9336aa..6394a9010 100644 --- a/res/ethereum/frontier.json +++ b/res/ethereum/frontier.json @@ -1,4 +1,5 @@ { + "name": "Frontier", "engineName": "Ethash", "params": { "accountStartNonce": "0x00", diff --git a/res/ethereum/frontier_test.json b/res/ethereum/frontier_test.json index 25f5ae16c..8ee1cafd9 100644 --- a/res/ethereum/frontier_test.json +++ b/res/ethereum/frontier_test.json @@ -1,4 +1,5 @@ { + "engineName": "Frontier (Test)", "engineName": "Ethash", "params": { "accountStartNonce": "0x00", @@ -30,4 +31,4 @@ "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } }, "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "linear": { "base": 15, "word": 3 } } } } -} \ No newline at end of file +} diff --git a/res/ethereum/homestead_test.json b/res/ethereum/homestead_test.json index 8d005be62..ee73d0ed3 100644 --- a/res/ethereum/homestead_test.json +++ b/res/ethereum/homestead_test.json @@ -1,4 +1,5 @@ { + "name": "Homestead (Test)", "engineName": "Ethash", "params": { "accountStartNonce": "0x00", diff --git a/res/ethereum/morden.json b/res/ethereum/morden.json index 033c0651c..79f9f3d99 100644 --- a/res/ethereum/morden.json +++ b/res/ethereum/morden.json @@ -1,4 +1,5 @@ { + "name": "Morden", "engineName": "Ethash", "params": { "accountStartNonce": "0x0100000", @@ -31,4 +32,4 @@ "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "linear": { "base": 15, "word": 3 } } }, "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } } -} \ No newline at end of file +} diff --git a/res/ethereum/olympic.json b/res/ethereum/olympic.json index 0b04e5499..4318d9230 100644 --- a/res/ethereum/olympic.json +++ b/res/ethereum/olympic.json @@ -1,4 +1,5 @@ { + "name": "Olympic", "engineName": "Ethash", "params": { "accountStartNonce": "0x00", @@ -38,4 +39,4 @@ "6c386a4b26f73c802f34673f7248bb118f97424a": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }, "e4157b34ea9615cfbde6b4fda419828124b70c78": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } } -} \ No newline at end of file +} diff --git a/res/null_morden.json b/res/null_morden.json index 7f069cb4e..46507ff95 100644 --- a/res/null_morden.json +++ b/res/null_morden.json @@ -1,4 +1,5 @@ { + "name": "Morden", "engineName": "NullEngine", "params": { "accountStartNonce": "0x0100000", @@ -31,4 +32,4 @@ "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "linear": { "base": 15, "word": 3 } } }, "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } } -} \ No newline at end of file +} diff --git a/src/bin/client.rs b/src/bin/client.rs index 5a3e907be..5ef177c64 100644 --- a/src/bin/client.rs +++ b/src/bin/client.rs @@ -1,15 +1,34 @@ extern crate ethcore_util as util; extern crate ethcore; extern crate rustc_serialize; +extern crate log; extern crate env_logger; use std::io::*; +use std::env; +use log::{LogRecord, LogLevelFilter}; +use env_logger::LogBuilder; use util::hash::*; use ethcore::service::ClientService; use ethcore::ethereum; +fn setup_log() { + let format = |record: &LogRecord| { + format!("{} - {}", record.level(), record.args()) + }; + + let mut builder = LogBuilder::new(); + builder.format(format).filter(None, LogLevelFilter::Info); + + if env::var("RUST_LOG").is_ok() { + builder.parse(&env::var("RUST_LOG").unwrap()); + } + + builder.init().unwrap(); +} + fn main() { - ::env_logger::init().ok(); + setup_log(); let spec = ethereum::new_frontier(); let mut _service = ClientService::start(spec).unwrap(); loop { diff --git a/src/block.rs b/src/block.rs index 016c72641..b93d52a60 100644 --- a/src/block.rs +++ b/src/block.rs @@ -297,7 +297,7 @@ fn enact_block() { let mut db = OverlayDB::new_temp(); engine.spec().ensure_db_good(&mut db); - let e = enact(&orig_bytes, engine.deref(), db, &genesis_header, &vec![genesis_header.hash()]).unwrap(); + let e = enact_and_seal(&orig_bytes, engine.deref(), db, &genesis_header, &vec![genesis_header.hash()]).unwrap(); assert_eq!(e.rlp_bytes(), orig_bytes); diff --git a/src/client.rs b/src/client.rs index c933e7817..4905fe094 100644 --- a/src/client.rs +++ b/src/client.rs @@ -113,6 +113,7 @@ impl Client { let db = DB::open_default(state_path.to_str().unwrap()).unwrap(); let mut state_db = OverlayDB::new(db); engine.spec().ensure_db_good(&mut state_db); + state_db.commit().expect("Error commiting genesis state to state DB"); Ok(Client { chain: chain.clone(), @@ -161,6 +162,7 @@ impl Client { }; if let Err(e) = verify_block_final(&header, result.block().header()) { warn!(target: "client", "Stage 4 block verification failed for {}\nError: {:?}", header.hash(), e); + return; } self.chain.write().unwrap().insert_block(&bytes); //TODO: err here? diff --git a/src/ethereum/ethash.rs b/src/ethereum/ethash.rs index 2d99bfa56..310b7b766 100644 --- a/src/ethereum/ethash.rs +++ b/src/ethereum/ethash.rs @@ -41,8 +41,9 @@ impl Engine for Ethash { // Bestow uncle rewards let current_number = fields.header.number(); for u in fields.uncles.iter() { - fields.state.add_balance(u.author(), &(reward * U256::from((8 + u.number() - current_number) / 8))); + fields.state.add_balance(u.author(), &(reward * U256::from(8 + u.number() - current_number) / U256::from(8))); } + fields.state.commit(); } @@ -128,4 +129,23 @@ fn on_close_block() { assert_eq!(b.state().balance(&Address::zero()), U256::from_str("4563918244f40000").unwrap()); } +#[test] +fn on_close_block_with_uncle() { + use super::*; + let engine = new_morden().to_engine().unwrap(); + let genesis_header = engine.spec().genesis_header(); + let mut db = OverlayDB::new_temp(); + engine.spec().ensure_db_good(&mut db); + let last_hashes = vec![genesis_header.hash()]; + let mut b = OpenBlock::new(engine.deref(), db, &genesis_header, &last_hashes, Address::zero(), vec![]); + let mut uncle = Header::new(); + let uncle_author = address_from_hex("ef2d6d194084c2de36e0dabfce45d046b37d1106"); + uncle.author = uncle_author.clone(); + b.push_uncle(uncle).unwrap(); + + let b = b.close(); + assert_eq!(b.state().balance(&Address::zero()), U256::from_str("478eae0e571ba000").unwrap()); + assert_eq!(b.state().balance(&uncle_author), U256::from_str("3cb71f51fc558000").unwrap()); +} + // TODO: difficulty test diff --git a/src/service.rs b/src/service.rs index 6f3294ce6..da91451f9 100644 --- a/src/service.rs +++ b/src/service.rs @@ -20,6 +20,7 @@ impl ClientService { pub fn start(spec: Spec) -> Result { let mut net_service = try!(NetworkService::start()); info!("Starting {}", net_service.host_info()); + info!("Configured for {} using {} engine", spec.name, spec.engine_name); let mut dir = env::home_dir().unwrap(); dir.push(".parity"); dir.push(H64::from(spec.genesis_header().hash()).hex()); diff --git a/src/spec.rs b/src/spec.rs index c9e3383eb..80ea99f40 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -65,6 +65,8 @@ impl GenesisAccount { /// chain and those to be interpreted by the active chain engine. #[derive(Debug)] pub struct Spec { + // User friendly spec name + pub name: String, // What engine are we using for this? pub engine_name: String, @@ -196,6 +198,7 @@ impl FromJson for Spec { Spec { + name: json["name"].as_string().unwrap().to_string(), engine_name: json["engineName"].as_string().unwrap().to_string(), engine_params: json_to_rlp_map(&json["params"]), builtins: builtins, @@ -218,11 +221,16 @@ impl Spec { /// Ensure that the given state DB has the trie nodes in for the genesis state. pub fn ensure_db_good(&self, db: &mut HashDB) { if !db.contains(&self.state_root()) { - let mut root = H256::new(); - let mut t = SecTrieDBMut::new(db, &mut root); - for (address, account) in self.genesis_state.iter() { - t.insert(address.as_slice(), &account.rlp()); + info!("Populating genesis state..."); + let mut root = H256::new(); + { + let mut t = SecTrieDBMut::new(db, &mut root); + for (address, account) in self.genesis_state.iter() { + t.insert(address.as_slice(), &account.rlp()); + } } + assert!(db.contains(&self.state_root())); + info!("Genesis state is ready"); } } diff --git a/src/sync/tests.rs b/src/sync/tests.rs index bc0e171d2..84a8bf21f 100644 --- a/src/sync/tests.rs +++ b/src/sync/tests.rs @@ -187,7 +187,7 @@ impl<'p> TestIo<'p> { } impl<'p> SyncIo for TestIo<'p> { - fn disable_peer(&mut self, _peer_id: &PeerId) { + fn disable_peer(&mut self, _peer_id: PeerId) { } fn respond(&mut self, packet_id: PacketId, data: Vec) -> Result<(), UtilError> { @@ -257,7 +257,7 @@ impl TestNet { for client in 0..self.peers.len() { if peer != client { let mut p = self.peers.get_mut(peer).unwrap(); - p.sync.on_peer_connected(&mut TestIo::new(&mut p.chain, &mut p.queue, Some(client as PeerId)), &(client as PeerId)); + p.sync.on_peer_connected(&mut TestIo::new(&mut p.chain, &mut p.queue, Some(client as PeerId)), client as PeerId); } } } @@ -269,7 +269,7 @@ impl TestNet { Some(packet) => { let mut p = self.peers.get_mut(packet.recipient).unwrap(); trace!("--- {} -> {} ---", peer, packet.recipient); - p.sync.on_packet(&mut TestIo::new(&mut p.chain, &mut p.queue, Some(peer as PeerId)), &(peer as PeerId), packet.packet_id, &packet.data); + p.sync.on_packet(&mut TestIo::new(&mut p.chain, &mut p.queue, Some(peer as PeerId)), peer as PeerId, packet.packet_id, &packet.data); trace!("----------------"); }, None => {}