Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
rollback chain head (#4010)
* purge blocks after hardforking

* update fork block info
  • Loading branch information
simonjiao committed Feb 26, 2024
1 parent 01cab2c commit a953701
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 2 deletions.
1 change: 1 addition & 0 deletions node/src/node.rs
Expand Up @@ -308,6 +308,7 @@ impl NodeService {
let start_time = SystemTime::now();
storage_instance.check_upgrade()?;
storage_instance.barnard_hard_fork(config.clone())?;
storage_instance.dragon_hard_fork(config.clone())?;
let upgrade_time = SystemTime::now().duration_since(start_time)?;
let storage = Arc::new(Storage::new(storage_instance)?);
registry.put_shared(storage.clone()).await?;
Expand Down
18 changes: 17 additions & 1 deletion storage/src/chain_info/mod.rs
Expand Up @@ -5,7 +5,7 @@ use crate::storage::{ColumnFamily, InnerStorage, KVStore};
use crate::{StorageVersion, CHAIN_INFO_PREFIX_NAME};
use anyhow::Result;
use starcoin_crypto::HashValue;
use starcoin_types::startup_info::{BarnardHardFork, SnapshotRange, StartupInfo};
use starcoin_types::startup_info::{BarnardHardFork, DragonHardFork, SnapshotRange, StartupInfo};
use std::convert::{TryFrom, TryInto};

#[derive(Clone)]
Expand All @@ -28,6 +28,7 @@ impl ChainInfoStorage {
const STORAGE_VERSION_KEY: &'static str = "storage_version";
const SNAPSHOT_RANGE_KEY: &'static str = "snapshot_height";
const BARNARD_HARD_FORK: &'static str = "barnard_hard_fork";
const DRAGON_HARD_FORK: &'static str = "dragon_hard_fork";

pub fn get_startup_info(&self) -> Result<Option<StartupInfo>> {
self.get(Self::STARTUP_INFO_KEY.as_bytes())
Expand Down Expand Up @@ -111,4 +112,19 @@ impl ChainInfoStorage {
barnard_hard_fork.try_into()?,
)
}

pub fn get_dragon_hard_fork(&self) -> Result<Option<DragonHardFork>> {
self.get(Self::DRAGON_HARD_FORK.as_bytes())
.and_then(|bytes| match bytes {
Some(bytes) => Ok(Some(bytes.try_into()?)),
None => Ok(None),
})
}

pub fn save_dragon_hard_fork(&self, dragon_hard_fork: DragonHardFork) -> Result<()> {
self.put_sync(
Self::DRAGON_HARD_FORK.as_bytes().to_vec(),
dragon_hard_fork.try_into()?,
)
}
}
8 changes: 8 additions & 0 deletions storage/src/storage.rs
Expand Up @@ -118,6 +118,14 @@ impl StorageInstance {
}
Ok(())
}

pub fn dragon_hard_fork(&mut self, config: Arc<NodeConfig>) -> Result<()> {
if config.net().id().chain_id().is_main() {
info!("dragon_hard_fork in");
return DBUpgrade::dragon_hard_fork(self);
}
Ok(())
}
}

impl InnerStore for StorageInstance {
Expand Down
60 changes: 59 additions & 1 deletion storage/src/upgrade.rs
Expand Up @@ -16,7 +16,7 @@ use once_cell::sync::Lazy;
use starcoin_crypto::HashValue;
use starcoin_logger::prelude::{debug, info, warn};
use starcoin_types::block::BlockNumber;
use starcoin_types::startup_info::{BarnardHardFork, StartupInfo};
use starcoin_types::startup_info::{BarnardHardFork, DragonHardFork, StartupInfo};
use starcoin_types::transaction::Transaction;
use std::cmp::Ordering;

Expand All @@ -30,6 +30,14 @@ pub static BARNARD_HARD_FORK_HASH: Lazy<HashValue> = Lazy::new(|| {
.expect("")
});

pub static DRAGON_HARD_FORK_HEIGHT: BlockNumber = 16801958;
pub static DRAGON_HARD_FORK_HASH: Lazy<HashValue> = Lazy::new(|| {
HashValue::from_hex_literal(
"0xbef8d0af3b358af9fe25f7383fd2580679c54fe2ce7ff7a7434785ba6d11b943",
)
.expect("")
});

impl DBUpgrade {
pub fn check_upgrade(instance: &mut StorageInstance) -> Result<()> {
let version_in_db = {
Expand Down Expand Up @@ -233,4 +241,54 @@ impl DBUpgrade {
}
Ok(())
}

pub fn dragon_hard_fork(instance: &mut StorageInstance) -> Result<()> {
let block_storage = BlockStorage::new(instance.clone());
let chain_info_storage = ChainInfoStorage::new(instance.clone());
let hard_fork = chain_info_storage.get_dragon_hard_fork()?;

let fork_info = DragonHardFork::new(DRAGON_HARD_FORK_HEIGHT, *DRAGON_HARD_FORK_HASH);
if hard_fork == Some(fork_info.clone()) {
info!("dragon hard forked");
return Ok(());
}

let block = block_storage.get_block_by_hash(*DRAGON_HARD_FORK_HASH)?;
if let Some(block) = block {
if block.header().number() == DRAGON_HARD_FORK_HEIGHT {
info!("dragon hard fork rollback height");
let mut to_deleted = vec![];
let mut iter = block_storage.header_store.iter()?;
iter.seek_to_first();
for item in iter {
let (id, block_header) = item?;
if block_header.number() > DRAGON_HARD_FORK_HEIGHT {
to_deleted.push(id);
}
}
let block_info_storage = BlockInfoStorage::new(instance.clone());
let mut processed_count = 0;
for id in to_deleted {
block_info_storage.remove(id)?;
block_storage.delete_block(id)?;
processed_count += 1;
if processed_count % 10000 == 0 {
info!(
"dragon hard fork rollback height processed items: {}",
processed_count
);
}
}
if processed_count % 10000 != 0 {
info!(
"dragon hard fork rollback height processed items: {}",
processed_count
);
}
chain_info_storage.save_dragon_hard_fork(fork_info)?;
chain_info_storage.save_startup_info(StartupInfo::new(*DRAGON_HARD_FORK_HASH))?;
}
}
Ok(())
}
}
37 changes: 37 additions & 0 deletions types/src/startup_info.rs
Expand Up @@ -281,3 +281,40 @@ impl TryInto<Vec<u8>> for BarnardHardFork {
self.encode()
}
}

#[derive(Eq, PartialEq, Hash, Deserialize, Serialize, Clone, Debug)]
pub struct DragonHardFork {
// block whose number is greater than `number` will be purged
number: BlockNumber,
hash: HashValue,
}

impl DragonHardFork {
pub fn new(number: BlockNumber, hash: HashValue) -> Self {
Self { number, hash }
}

pub fn get_number(&self) -> BlockNumber {
self.number
}

pub fn get_hash(&self) -> HashValue {
self.hash
}
}

impl TryFrom<Vec<u8>> for DragonHardFork {
type Error = anyhow::Error;

fn try_from(value: Vec<u8>) -> Result<Self> {
DragonHardFork::decode(value.as_slice())
}
}

impl TryInto<Vec<u8>> for DragonHardFork {
type Error = anyhow::Error;

fn try_into(self) -> Result<Vec<u8>> {
self.encode()
}
}

0 comments on commit a953701

Please sign in to comment.