From 35740204a1b212131afea502b49af4632aec8913 Mon Sep 17 00:00:00 2001
From: Antioch Peverell <apeverell@protonmail.com>
Date: Sat, 6 Mar 2021 21:40:20 +0000
Subject: [PATCH] no more conversion to support v2 blocks (#3587)

get_block simply returns None if v2 support required
---
 chain/src/chain.rs             | 102 +--------------------------------
 chain/src/store.rs             |  43 --------------
 servers/src/common/adapters.rs |   6 +-
 3 files changed, 5 insertions(+), 146 deletions(-)

diff --git a/chain/src/chain.rs b/chain/src/chain.rs
index 6d2a07739..47d1ec756 100644
--- a/chain/src/chain.rs
+++ b/chain/src/chain.rs
@@ -35,15 +35,13 @@ use crate::types::{
 };
 use crate::util::secp::pedersen::{Commitment, RangeProof};
 use crate::util::RwLock;
-use crate::ChainStore;
-use grin_core::ser;
 use grin_store::Error::NotFoundErr;
+use std::collections::HashMap;
 use std::fs::{self, File};
 use std::path::{Path, PathBuf};
 use std::sync::atomic::{AtomicUsize, Ordering};
 use std::sync::Arc;
 use std::time::{Duration, Instant};
-use std::{collections::HashMap, io::Cursor};
 
 /// Orphan pool size is limited by MAX_ORPHAN_SIZE
 pub const MAX_ORPHAN_SIZE: usize = 200;
@@ -173,10 +171,6 @@ impl Chain {
 	) -> Result<Chain, Error> {
 		let store = Arc::new(store::ChainStore::new(&db_root)?);
 
-		// DB migrations to be run prior to the chain being used.
-		// Migrate full blocks to protocol version v3.
-		Chain::migrate_db_v2_v3(&store)?;
-
 		// open the txhashset, creating a new one if necessary
 		let mut txhashset = txhashset::TxHashSet::open(db_root.clone(), store.clone(), None)?;
 
@@ -273,43 +267,6 @@ impl Chain {
 		res
 	}
 
-	/// We plan to support receiving blocks with CommitOnly inputs.
-	/// We also need to support relaying blocks with FeaturesAndCommit inputs to peers.
-	/// So we need a way to convert blocks from CommitOnly to FeaturesAndCommit.
-	/// Validating the inputs against the utxo_view allows us to look the outputs up.
-	pub fn convert_block_v2(&self, block: Block) -> Result<Block, Error> {
-		debug!(
-			"convert_block_v2: {} at {} ({} -> v2)",
-			block.header.hash(),
-			block.header.height,
-			block.inputs().version_str(),
-		);
-
-		if block.inputs().is_empty() {
-			return Ok(Block {
-				header: block.header,
-				body: block.body.replace_inputs(Inputs::FeaturesAndCommit(vec![])),
-			});
-		}
-
-		let mut header_pmmr = self.header_pmmr.write();
-		let mut txhashset = self.txhashset.write();
-		let inputs: Vec<_> =
-			txhashset::extending_readonly(&mut header_pmmr, &mut txhashset, |ext, batch| {
-				let previous_header = batch.get_previous_header(&block.header)?;
-				pipe::rewind_and_apply_fork(&previous_header, ext, batch)?;
-				ext.extension
-					.utxo_view(ext.header_extension)
-					.validate_inputs(&block.inputs(), batch)
-					.map(|outputs| outputs.into_iter().map(|(out, _)| out).collect())
-			})?;
-		let inputs = inputs.as_slice().into();
-		Ok(Block {
-			header: block.header,
-			body: block.body.replace_inputs(inputs),
-		})
-	}
-
 	fn determine_status(
 		&self,
 		head: Option<Tip>,
@@ -401,11 +358,6 @@ impl Chain {
 		// Only do this once we know the header PoW is valid.
 		self.check_orphan(&b, opts)?;
 
-		// We can only reliably convert to "v2" if not an orphan (may spend output from previous block).
-		// We convert from "v3" to "v2" by looking up outputs to be spent.
-		// This conversion also ensures a block received in "v2" has valid input features (prevents malleability).
-		let b = self.convert_block_v2(b)?;
-
 		let (maybe_new_head, prev_head) = {
 			let mut header_pmmr = self.header_pmmr.write();
 			let mut txhashset = self.txhashset.write();
@@ -1367,58 +1319,6 @@ impl Chain {
 		self.header_pmmr.read().get_header_hash_by_height(height)
 	}
 
-	/// Migrate our local db from v2 to v3.
-	/// "commit only" inputs.
-	fn migrate_db_v2_v3(store: &ChainStore) -> Result<(), Error> {
-		if store.batch()?.is_blocks_v3_migrated()? {
-			// Previously migrated so skipping.
-			debug!("migrate_db_v2_v3: previously migrated, skipping");
-			return Ok(());
-		}
-		let mut total = 0;
-		let mut keys_to_migrate = vec![];
-		for (k, v) in store.batch()?.blocks_raw_iter()? {
-			total += 1;
-
-			// We want to migrate all blocks that cannot be read via v3 protocol version.
-			let block_v3: Result<Block, _> =
-				ser::deserialize(&mut Cursor::new(&v), ProtocolVersion(3));
-			if block_v3.is_err() {
-				let block_v2: Result<Block, _> =
-					ser::deserialize(&mut Cursor::new(&v), ProtocolVersion(2));
-				if block_v2.is_ok() {
-					keys_to_migrate.push(k);
-				}
-			}
-		}
-		debug!(
-			"migrate_db_v2_v3: {} (of {}) blocks to migrate",
-			keys_to_migrate.len(),
-			total,
-		);
-		let mut count = 0;
-		keys_to_migrate
-			.chunks(100)
-			.try_for_each(|keys| {
-				let batch = store.batch()?;
-				for key in keys {
-					batch.migrate_block(&key, ProtocolVersion(2), ProtocolVersion(3))?;
-					count += 1;
-				}
-				batch.commit()?;
-				debug!("migrate_db_v2_v3: successfully migrated {} blocks", count);
-				Ok(())
-			})
-			.and_then(|_| {
-				// Set flag to indicate we have migrated all blocks in the db.
-				// We will skip migration in the future.
-				let batch = store.batch()?;
-				batch.set_blocks_v3_migrated(true)?;
-				batch.commit()?;
-				Ok(())
-			})
-	}
-
 	/// Gets the block header in which a given output appears in the txhashset.
 	pub fn get_header_for_output(&self, commit: Commitment) -> Result<BlockHeader, Error> {
 		let header_pmmr = self.header_pmmr.read();
diff --git a/chain/src/store.rs b/chain/src/store.rs
index 3db41ad4b..ca28bf00d 100644
--- a/chain/src/store.rs
+++ b/chain/src/store.rs
@@ -46,11 +46,6 @@ pub const NRD_KERNEL_ENTRY_PREFIX: u8 = b'k';
 const BLOCK_SUMS_PREFIX: u8 = b'M';
 const BLOCK_SPENT_PREFIX: u8 = b'S';
 
-/// Prefix for various boolean flags stored in the db.
-const BOOL_FLAG_PREFIX: u8 = b'B';
-/// Boolean flag for v3 migration.
-const BLOCKS_V3_MIGRATED: &str = "blocks_v3_migrated";
-
 /// All chain-related database operations
 pub struct ChainStore {
 	db: store::Store,
@@ -219,44 +214,6 @@ impl<'a> Batch<'a> {
 		Ok(())
 	}
 
-	/// DB flag representing full migration of blocks to v3 version.
-	/// Default to false if flag not present.
-	pub fn is_blocks_v3_migrated(&self) -> Result<bool, Error> {
-		let migrated: Option<BoolFlag> = self
-			.db
-			.get_ser(&to_key(BOOL_FLAG_PREFIX, BLOCKS_V3_MIGRATED))?;
-		match migrated {
-			None => Ok(false),
-			Some(x) => Ok(x.into()),
-		}
-	}
-
-	/// Set DB flag representing full migration of blocks to v3 version.
-	pub fn set_blocks_v3_migrated(&self, migrated: bool) -> Result<(), Error> {
-		self.db.put_ser(
-			&to_key(BOOL_FLAG_PREFIX, BLOCKS_V3_MIGRATED)[..],
-			&BoolFlag(migrated),
-		)?;
-		Ok(())
-	}
-
-	/// Migrate a block stored in the db reading from one protocol version and writing
-	/// with new protocol version.
-	pub fn migrate_block(
-		&self,
-		key: &[u8],
-		from_version: ProtocolVersion,
-		to_version: ProtocolVersion,
-	) -> Result<(), Error> {
-		let block: Option<Block> = self.db.get_with(key, move |_, mut v| {
-			ser::deserialize(&mut v, from_version).map_err(From::from)
-		})?;
-		if let Some(block) = block {
-			self.db.put_ser_with_version(key, &block, to_version)?;
-		}
-		Ok(())
-	}
-
 	/// Low level function to delete directly by raw key.
 	pub fn delete(&self, key: &[u8]) -> Result<(), Error> {
 		self.db.delete(key)
diff --git a/servers/src/common/adapters.rs b/servers/src/common/adapters.rs
index 4043207ea..95503b727 100644
--- a/servers/src/common/adapters.rs
+++ b/servers/src/common/adapters.rs
@@ -378,12 +378,14 @@ where
 	}
 
 	/// Gets a full block by its hash.
-	/// Will convert to v2 compatibility based on peer protocol version.
+	/// We only support v3 blocks since HF4.
+	/// If a peer is requesting a block and only appears to support v2
+	/// then ignore the request.
 	fn get_block(&self, h: Hash, peer_info: &PeerInfo) -> Option<core::Block> {
 		self.chain()
 			.get_block(&h)
 			.map(|b| match peer_info.version.value() {
-				0..=2 => self.chain().convert_block_v2(b).ok(),
+				0..=2 => None,
 				3..=ProtocolVersion::MAX => Some(b),
 			})
 			.unwrap_or(None)