parity pruning-journaldb

parity pruning-journaldb

tags
Tech
Updated Time
Dec 1, 2024 03:50 AM
Published
Nov 6, 2022 02:57 AM
Created Date
Apr 17, 2019
Font
slug
AI-generated
Date
author
obsidian-url
tableKey
Description
Social Image
category
BlockchainTech
키워드
 
 
*참고
우선 Warp/Fast Sync와 Pruning 옵션은 별개로 생각해야 한다
fasf sync에
ethcore/sync
/light_sync/mod.rs
→ AncestorSarch(search for a common ancestor with the best chain)에
Prehistoric이란것. .(prehistoric block found. TODO:start to roll back CHTs
snapshot.rs
 
util/journaldb/src/lib.rs
 
각 pruning mode 에대해
archive : 모든 history 유지
overlayRecent(fast) : (default) memory overay 최근 history만 가져옴
EarlyMerge(light) : journalDB가 backing db key가 ancient인지 recent인지에 대한 정보를 유지, non-canon인 것들 revert되고 backing db에서 지워진다.
RefCounted(basic) References are counted in disk-backed DB.
//! `JournalDB` interface and implementation. ... /// Journal database operating strategy. #[derive(Debug, PartialEq, Clone, Copy)] pub enum Algorithm { /// Keep all keys forever. Archive, /// Ancient and recent history maintained separately; recent history lasts for particular /// number of blocks. /// /// Inserts go into backing database, journal retains knowledge of whether backing DB key is /// ancient or recent. Non-canon inserts get explicitly reverted and removed from backing DB. EarlyMerge, /// Ancient and recent history maintained separately; recent history lasts for particular /// number of blocks. /// /// Inserts go into memory overlay, which is tried for key fetches. Memory overlay gets /// flushed in backing only at end of recent history. OverlayRecent, /// Ancient and recent history maintained separately; recent history lasts for particular /// number of blocks. /// /// References are counted in disk-backed DB. RefCounted, } impl str::FromStr for Algorithm { type Err = String; fn from_str(s: &str) -> Result<Self, Self::Err> { match s { "archive" => Ok(Algorithm::Archive), "light" => Ok(Algorithm::EarlyMerge), "fast" => Ok(Algorithm::OverlayRecent), "basic" => Ok(Algorithm::RefCounted), e => Err(format!("Invalid algorithm: {}", e)), } } } impl Algorithm { /// Returns static str describing journal database algorithm. pub fn as_str(&self) -> &'static str { match *self { Algorithm::Archive => "archive", Algorithm::EarlyMerge => "light", Algorithm::OverlayRecent => "fast", Algorithm::RefCounted => "basic", } } ...
 
overlay
earlymergedb.rs
Disk-backed 'HashDB' implementation.
OverayDB처럼 memory overlay
OverayDB와 다르게, remove명령이 즉시 영향을 주지는 않는다. 어느정도 지나야함
/// journal format: /// ```text /// [era, 0] => [ id, [insert_0, ...], [remove_0, ...] ] /// [era, 1] => [ id, [insert_0, ...], [remove_0, ...] ] /// [era, n] => [ ... ] /// ```
new commit시에,
recent history queue의 모든 블록에대한 journal을 만들고, 삽입되었거나 삭제되었던 모든 key를 기록
era에 따라 journal이 정렬되며, 여러 commit은 같은 era를 공유할수 있음
queue와 비슷한 데이터구조이지만 각 항목 tuple(불변한순서가 있는 객체의 집합)
queue에서 튜플을 제거할때가 되면(era가 recent history에서 ancient history로 넘어가면) 튜플에서 그 커밋만 canonical한것으로 간주되며, 이 커밋은 메인 backing db에 보관되고 다른 커밋들은 revert됨.
backing db에서 (적절히 사용가능한) 키를 삭제하고 recent history queue에 다시 넣을수 있지만, non-canonical에 대한 커밋 작업을 모두 수행
original 키가 여전히 필요하고 삭제되지 않아야할때는, original key의 reference count를 유지한다.
 
  • backing db에 보관되는것 : canonical(ancient)
  • revert되는것 : non-canonical(recent)
  • original key가 필요하면 reference count를 유지
 
counter
 
recent에서 ancient이 되는 각 커밋 블록에 대해 다음을 수행
canonical 이면:
insert: Ignored (backing db에 남음)
deletes : enacted.(queue에 다시 추가될수도)
recent history queue에서 참조하는것을 확인.(memory overay이므로, 참조되는것은 backing db에서 삭제될 우선순위에서 밀려남)
 
non-canonical이면
insert : reverted. (queue)
recent history queue에서 참조하는것을 확인.(memory overay이므로, 참조되는것은 backing db에서 삭제될 우선순위에서 밀려남)
deletes : ignored.(queue에 다시추가되지 않음)
/// The semantics of the `counter` are: /// ```text /// insert key k: /// counter already contains k: count += 1 /// counter doesn't contain k: /// backing db contains k: count = 1 /// backing db doesn't contain k: insert into backing db, count = 0 /// delete key k: /// counter contains k (count is asserted to be non-zero): /// count > 1: counter -= 1 /// count == 1: remove counter /// count == 0: remove key from backing db /// counter doesn't contain k: remove key from backing db /// ``` /// ///Practically, this means that for each commit block turning from recent to ancient we do the ///following: /// ```text /// is_canonical: /// inserts: Ignored (left alone in the backing database). /// deletes: Enacted; however, recent history queue is checked for ongoing references. This is /// reduced as a preference to deletion from the backing database. /// !is_canonical: /// inserts: Reverted; however, recent history queue is checked for ongoing references. This is /// reduced as a preference to deletion from the backing database. /// deletes: Ignored (they were never inserted). /// ``` /// /// TODO: `store_reclaim_period`
 
 
 
overayrecentdb.rs
JournalDB` over in-memory overlay
 
 
parity/cli/mod.rs
auto, archive,fast 세가지
archive는 no pruning
fast는 maintain journal overlay, Fast but 50MB used
auto는 use the method most recently synced or default to fast if none synced
 
... ["Footprint Options"] ... ARG arg_pruning: (String) = "auto", or |c: &Config| c.footprint.as_ref()?.pruning.clone(), "--pruning=[METHOD]", "Configure pruning of the state/storage trie. METHOD may be one of auto, archive, fast: archive - keep all state trie data. No pruning. fast - maintain journal overlay. Fast but 50MB used. auto - use the method most recently synced or default to fast if none synced.", ARG arg_pruning_history: (u64) = 64u64, or |c: &Config| c.footprint.as_ref()?.pruning_history.clone(), "--pruning-history=[NUM]", "Set a minimum number of recent states to keep in memory when pruning is active.", ARG arg_pruning_memory: (usize) = 32usize, or |c: &Config| c.footprint.as_ref()?.pruning_memory.clone(), "--pruning-memory=[MB]", "The ideal amount of memory in megabytes to use to store recent states. As many states as possible will be kept within this limit, and at least --pruning-history states will always be kept.",
 
ethcore/light/src
cht.rs
/client
ethcore/src
/client
client.rs
prune_ancient,
config.rs
impl Default for ClientConfig { fn default() -> Self { let mb = 1024 * 1024; ClientConfig { ... pruning: journaldb::Algorithm::OverlayRecent, ... } } }
 
ethcore/typs/src
pruning_info.rs
/// Client pruning info. See module-level docs for more details. #[derive(Debug, Clone)] pub struct PruningInfo { /// The first block which everything can be served after. pub earliest_chain: u64, /// The first block where state requests may be served. pub earliest_state: u64, }
이게 끝
 
parity/params를 보면,
#[derive(Debug, PartialEq)] pub enum Pruning { Specific(Algorithm), Auto, } impl Default for Pruning { fn default() -> Self { Pruning::Auto } }
Pruning의 Default는 Auto이고, Specific(Algorithm)으로 설정 가능
 
parity/user_defaults.rs
Algorithm
impl Default for UserDefaults { fn default() -> Self { UserDefaults { is_first_launch: true, pruning: Algorithm::OverlayRecent, tracing: false, fat_db: false, mode: Mode::Active, } } }
User Defaults는 OverlayRecent
 
 
  • Fast (OverlayRecent): keep all the full states of the B[-i] blocks; geth Fast 모드와 같다
  • Light (EarlyMerge): keep all the states of the B[-i] blocks but in differential (so it is smaller than fast but slower access)
 
 
이전에 준우님이 공유해준 내용

CHT(Canonical Hash Trie)

  • Merkle Trie 내에서 historical block number와 canonical hash를 맵핑
  • 블록헤더를 trie root(블록들의 해시의 accumulation)에 맞게 discard하는 것과 특정 블록의 해시가 이전에 검증된 것임을 증명하는 것을 가능케 한다(?)
  • PIP CHT는 2048 블록마다 생성된다
  • 이것은 client로 하여금 체크포인트를 부트스트랩하는 것을 약간 어렵게 만들지만, 이를 통해 라이트 노드는 풀노드에게 질의 없이도 CHT-Chain을 최신으로 유지할 수 있다.

How to prune?

  • CHT를 이용하여 pruning의 구현을 제안한다
  • 즉, 풀노드는 대부분의 ranges of blocks를 discard하고, 그들이 discard한 ranges에 해당하는 CHT만을 유지하면 된다.
  • Kademlia Node Identifier와 유사한 방식으로, 풀노드는 특정 ranges of block과 receipt를 유지하도록 요구받을 것이다 → 그들이 유지하도록 요구받은 블록을 제공하지 못할 경우, misbehavior로 간주될 것이다
  • 또 다른 방법은, 블록 넘버가 아닌 블록 해시의 prefix에 기반하여 serving blocks의 책임을 갖는 것이다 → 이는 well-partitioned mesh가 되게 하지만, sync는 많이 비효율적으로 될 것이다

Pruning Modes

  • Archive (Archive): keep all states; geth Archive 모드와 같다
  • Fast (OverlayRecent): keep all the full states of the B[-i] blocks; geth Fast 모드와 같다
  • Light (EarlyMerge): keep all the states of the B[-i] blocks but in differential (so it is smaller than fast but slower access)
  • Basic (RefCounted): keep all the states of the B[-i] blocks like with OverlayRecent but remove states after x changes (so we have only the xth last changes)
 

Reference


 
 
관심 주제를 선택해주세요. 선택하지 않으면 모든 글을 구독합니다.