Skip to content

Commit

Permalink
Merge branch 'yuji/fix-bp-tree-pruning' (#2264)
Browse files Browse the repository at this point in the history
* origin/yuji/fix-bp-tree-pruning:
  add changelog
  fix pruning bp merkle tree
  • Loading branch information
Gianmarco Fraccaroli authored and brentstone committed Dec 13, 2023
2 parents 7aa149b + fc0cfd3 commit 01345a8
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 23 deletions.
2 changes: 2 additions & 0 deletions .changelog/unreleased/bug-fixes/2264-fix-bp-tree-pruning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Fix to skip pruning BridgePool Merkle trees when no signed nonce
([\#2264](https://github.com/anoma/namada/issues/2264))
10 changes: 2 additions & 8 deletions apps/src/lib/node/ledger/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,11 +591,8 @@ mod tests {
);
let new_epoch_start = BlockHeight(1);
let signed_root_key = bridge_pool::get_signed_root_key();
// the first nonce isn't written for a test skipping pruning
let nonce = Uint::default();
let root_proof =
BridgePoolRootProof::new((KeccakHash::default(), nonce));
let bytes = types::encode(&root_proof);
storage.write(&signed_root_key, bytes).unwrap();

storage
.begin_block(BlockHash::default(), new_epoch_start)
Expand All @@ -622,11 +619,8 @@ mod tests {
.write(&key, types::encode(&value))
.expect("write failed");

// the second nonce isn't written for a test skipping pruning
let nonce = nonce + 1;
let root_proof =
BridgePoolRootProof::new((KeccakHash::default(), nonce));
let bytes = types::encode(&root_proof);
storage.write(&signed_root_key, bytes).unwrap();

storage.block.epoch = storage.block.epoch.next();
storage.block.pred_epochs.new_epoch(new_epoch_start);
Expand Down
14 changes: 9 additions & 5 deletions apps/src/lib/node/ledger/storage/rocksdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1453,17 +1453,21 @@ impl DB for RocksDB {
&self,
height: BlockHeight,
last_height: BlockHeight,
) -> Result<Uint> {
) -> Result<Option<Uint>> {
let nonce_key = bridge_pool::get_signed_root_key();
let bytes = if height == BlockHeight(0) || height >= last_height {
self.read_subspace_val(&nonce_key)?
} else {
self.read_subspace_val_with_height(&nonce_key, height, last_height)?
};
let bytes = bytes.expect("Signed root should exist");
let bp_root_proof = BridgePoolRootProof::try_from_slice(&bytes)
.map_err(Error::BorshCodingError)?;
Ok(bp_root_proof.data.1)
match bytes {
Some(bytes) => {
let bp_root_proof = BridgePoolRootProof::try_from_slice(&bytes)
.map_err(Error::BorshCodingError)?;
Ok(Some(bp_root_proof.data.1))
}
None => Ok(None),
}
}

fn write_replay_protection_entry(
Expand Down
4 changes: 2 additions & 2 deletions core/src/ledger/storage/mockdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,8 +593,8 @@ impl DB for MockDB {
&self,
_height: BlockHeight,
_last_height: BlockHeight,
) -> Result<Uint> {
Ok(Uint::default())
) -> Result<Option<Uint>> {
Ok(None)
}

fn write_replay_protection_entry(
Expand Down
29 changes: 21 additions & 8 deletions core/src/ledger/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ pub trait DB: std::fmt::Debug {
&self,
height: BlockHeight,
last_height: BlockHeight,
) -> Result<Uint>;
) -> Result<Option<Uint>>;

/// Write a replay protection entry
fn write_replay_protection_entry(
Expand Down Expand Up @@ -1178,7 +1178,10 @@ where
}

// Prune the BridgePool subtree stores with invalid nonce
let mut epoch = self.get_oldest_epoch_with_valid_nonce()?;
let mut epoch = match self.get_oldest_epoch_with_valid_nonce()? {
Some(epoch) => epoch,
None => return Ok(()),
};
while oldest_epoch < epoch {
epoch = epoch.prev();
self.db.prune_merkle_tree_store(
Expand Down Expand Up @@ -1216,11 +1219,15 @@ where
}

/// Get oldest epoch which has the valid signed nonce of the bridge pool
pub fn get_oldest_epoch_with_valid_nonce(&self) -> Result<Epoch> {
fn get_oldest_epoch_with_valid_nonce(&self) -> Result<Option<Epoch>> {
let last_height = self.get_last_block_height();
let current_nonce = self
let current_nonce = match self
.db
.read_bridge_pool_signed_nonce(last_height, last_height)?;
.read_bridge_pool_signed_nonce(last_height, last_height)?
{
Some(nonce) => nonce,
None => return Ok(None),
};
let (mut epoch, _) = self.get_last_epoch();
// We don't need to check the older epochs because their Merkle tree
// snapshots have been already removed
Expand All @@ -1235,13 +1242,19 @@ where
Some(h) => h,
None => continue,
};
let nonce =
self.db.read_bridge_pool_signed_nonce(height, last_height)?;
let nonce = match self
.db
.read_bridge_pool_signed_nonce(height, last_height)?
{
Some(nonce) => nonce,
// skip pruning when the old epoch doesn't have the signed nonce
None => break,
};
if nonce < current_nonce {
break;
}
}
Ok(epoch)
Ok(Some(epoch))
}

/// Check it the given transaction's hash is already present in storage
Expand Down

0 comments on commit 01345a8

Please sign in to comment.