Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rollback chain head #4010

Merged
merged 2 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions node/src/node.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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()
}
}
Loading