From 409d495b426d79bdf68ccef13452d753c4426c07 Mon Sep 17 00:00:00 2001
From: Aton <jcx631678546@gmail.com>
Date: Mon, 7 Jan 2019 17:17:05 +0800
Subject: [PATCH] fix bug for revert (#1341)

* must pass sub_matches to function, so that could get `<num>` in revert
* revert should del current best index block, not prev block
---
 substrate/core/cli/src/lib.rs       |  2 +-
 substrate/core/client/db/src/lib.rs | 23 ++++++++++++++---------
 2 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/substrate/core/cli/src/lib.rs b/substrate/core/cli/src/lib.rs
index dc3c96f9cd5..b70420f5889 100644
--- a/substrate/core/cli/src/lib.rs
+++ b/substrate/core/cli/src/lib.rs
@@ -422,7 +422,7 @@ where
 	} else if let Some(sub_matches) = matches.subcommand_matches("revert") {
 		revert_chain::<F>(
 			get_db_path_for_subcommand(matches, sub_matches)?,
-			matches,
+			sub_matches,
 			spec
 		)?;
 		return Ok(Action::ExecutedInternally);
diff --git a/substrate/core/client/db/src/lib.rs b/substrate/core/client/db/src/lib.rs
index 72ee2c772e4..9df93e45b56 100644
--- a/substrate/core/client/db/src/lib.rs
+++ b/substrate/core/client/db/src/lib.rs
@@ -854,6 +854,9 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
 	fn revert(&self, n: NumberFor<Block>) -> Result<NumberFor<Block>, client::error::Error> {
 		use client::blockchain::HeaderBackend;
 		let mut best = self.blockchain.info()?.best_number;
+		// if the best is lower to n(less then 256), just use best number in case overflow
+		let n = if best < n { best } else { n };
+
 		for c in 0 .. n.as_() {
 			if best == As::sa(0) {
 				return Ok(As::sa(c))
@@ -862,18 +865,20 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
 			match self.storage.state_db.revert_one() {
 				Some(commit) => {
 					apply_state_commit(&mut transaction, commit);
-					let _removed = best.clone();
-					best -= As::sa(1);
-					let header = self.blockchain.header(BlockId::Number(best))?.ok_or_else(
+					let removed = self.blockchain.header(BlockId::Number(best))?.ok_or_else(
 						|| client::error::ErrorKind::UnknownBlock(
-							format!("Error reverting to {}. Block header not found.", best)))?;
+							format!("Error reverting to {}. Block hash not found.", best)))?;
 
-					let lookup_key = ::utils::number_and_hash_to_lookup_key(header.number().clone(), header.hash().clone());
-					transaction.put(columns::META, meta_keys::BEST_BLOCK, &lookup_key);
-					transaction.delete(columns::KEY_LOOKUP, header.hash().as_ref());
+					best -= As::sa(1);  // prev block
+					let hash = self.blockchain.hash(best)?.ok_or_else(
+						|| client::error::ErrorKind::UnknownBlock(
+							format!("Error reverting to {}. Block hash not found.", best)))?;
+					let key = ::utils::number_and_hash_to_lookup_key(best.clone(), hash.clone());
+					transaction.put(columns::META, meta_keys::BEST_BLOCK, &key);
+					transaction.delete(columns::KEY_LOOKUP, removed.hash().as_ref());
 					self.storage.db.write(transaction).map_err(db_err)?;
-					self.blockchain.update_meta(header.hash().clone(), best.clone(), true, false);
-					self.blockchain.leaves.write().revert(header.hash().clone(), header.number().clone(), header.parent_hash().clone());
+					self.blockchain.update_meta(hash, best, true, false);
+					self.blockchain.leaves.write().revert(removed.hash().clone(), removed.number().clone(), removed.parent_hash().clone());
 				}
 				None => return Ok(As::sa(c))
 			}
-- 
GitLab