diff --git a/ethcore/src/snapshot/mod.rs b/ethcore/src/snapshot/mod.rs index d496139ff..89901502b 100644 --- a/ethcore/src/snapshot/mod.rs +++ b/ethcore/src/snapshot/mod.rs @@ -464,14 +464,18 @@ impl StateRebuilder { Ok(()) } - /// Check for accounts missing code. Once all chunks have been fed, there should - /// be none. - pub fn check_missing(self) -> Result<(), Error> { + /// Finalize the restoration. Check for accounts missing code and make a dummy + /// journal entry. + /// Once all chunks have been fed, there should be nothing missing. + pub fn finalize(mut self, era: u64, id: H256) -> Result<(), ::error::Error> { let missing = self.missing_code.keys().cloned().collect::>(); - match missing.is_empty() { - true => Ok(()), - false => Err(Error::MissingCode(missing)), - } + if !missing.is_empty() { return Err(Error::MissingCode(missing).into()) } + + let mut batch = self.db.backing().transaction(); + self.db.journal_under(&mut batch, era, &id)?; + self.db.backing().write_buffered(batch); + + Ok(()) } /// Get the state root of the rebuilder. diff --git a/ethcore/src/snapshot/service.rs b/ethcore/src/snapshot/service.rs index a354f3fd3..ee39203ff 100644 --- a/ethcore/src/snapshot/service.rs +++ b/ethcore/src/snapshot/service.rs @@ -166,7 +166,7 @@ impl Restoration { } // check for missing code. - self.state.check_missing()?; + self.state.finalize(self.manifest.block_number, self.manifest.block_hash)?; // connect out-of-order chunks and verify chain integrity. self.blocks.finalize(self.canonical_hashes)?; diff --git a/ethcore/src/snapshot/tests/state.rs b/ethcore/src/snapshot/tests/state.rs index 854cd07d4..4b0a33c71 100644 --- a/ethcore/src/snapshot/tests/state.rs +++ b/ethcore/src/snapshot/tests/state.rs @@ -61,7 +61,7 @@ fn snap_and_restore() { state_hashes: state_hashes, block_hashes: Vec::new(), state_root: state_root, - block_number: 0, + block_number: 1000, block_hash: H256::default(), }).unwrap(); @@ -69,7 +69,7 @@ fn snap_and_restore() { db_path.push("db"); let db = { let new_db = Arc::new(Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap()); - let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::Archive); + let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::OverlayRecent); let reader = PackedReader::new(&snap_file).unwrap().unwrap(); let flag = AtomicBool::new(true); @@ -82,12 +82,13 @@ fn snap_and_restore() { } assert_eq!(rebuilder.state_root(), state_root); - rebuilder.check_missing().unwrap(); + rebuilder.finalize(1000, H256::default()).unwrap(); new_db }; - let new_db = journaldb::new(db, Algorithm::Archive, ::db::COL_STATE); + let new_db = journaldb::new(db, Algorithm::OverlayRecent, ::db::COL_STATE); + assert_eq!(new_db.earliest_era(), Some(1000)); compare_dbs(&old_db, new_db.as_hashdb()); } @@ -134,13 +135,18 @@ fn get_code_from_prev_chunk() { let db_cfg = DatabaseConfig::with_columns(::db::NUM_COLUMNS); let new_db = Arc::new(Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap()); - let mut rebuilder = StateRebuilder::new(new_db, Algorithm::Archive); - let flag = AtomicBool::new(true); + { + let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::OverlayRecent); + let flag = AtomicBool::new(true); - rebuilder.feed(&chunk1, &flag).unwrap(); - rebuilder.feed(&chunk2, &flag).unwrap(); + rebuilder.feed(&chunk1, &flag).unwrap(); + rebuilder.feed(&chunk2, &flag).unwrap(); - rebuilder.check_missing().unwrap(); + rebuilder.finalize(1000, H256::random()).unwrap(); + } + + let state_db = journaldb::new(new_db, Algorithm::OverlayRecent, ::db::COL_STATE); + assert_eq!(state_db.earliest_era(), Some(1000)); } #[test] @@ -175,7 +181,7 @@ fn checks_flag() { db_path.push("db"); { let new_db = Arc::new(Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap()); - let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::Archive); + let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::OverlayRecent); let reader = PackedReader::new(&snap_file).unwrap().unwrap(); let flag = AtomicBool::new(false);