Skip to content
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
5 changes: 3 additions & 2 deletions stackslib/src/clarity_vm/database/marf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1628,9 +1628,10 @@ impl ClarityBackingStore for EphemeralMarfStore<'_> {
/// Otherwise, use the disk-backed one.
fn get_open_chain_tip_height(&mut self) -> u32 {
if let EphemeralTip::RAM(..) = &self.open_tip {
self.ephemeral_marf
return self.ephemeral_marf
.get_open_chain_tip_height()
.expect("Attempted to get the open chain tip from an unopened context.");
.expect("Attempted to get the open chain tip from an unopened context.")
+ self.base_tip_height;
}

self.read_only_marf.get_open_chain_tip_height()
Expand Down
45 changes: 45 additions & 0 deletions stackslib/src/clarity_vm/tests/ephemeral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use std::fs;

use clarity::vm::ast::ASTRules;
use proptest::prelude::*;
use rand::seq::SliceRandom;
use rand::thread_rng;
use stacks_common::types::chainstate::StacksBlockId;
Expand Down Expand Up @@ -431,6 +432,50 @@ fn test_ephemeral_nakamoto_block_replay_simple() {
}
}

#[test]
fn prop_ephemeral_tip_height_matches_current() {
proptest!(|(n in 1usize..=12)| {
let path = format!("/tmp/{}.marf", function_name!());
if fs::metadata(&path).is_ok() {
fs::remove_dir_all(&path).unwrap();
}

let mut marfed_kv = MarfedKV::open(
&path,
None,
Some(MARFOpenOpts::new(
TrieHashCalculationMode::Deferred,
"noop",
false,
)),
)
.unwrap();

let target_block_id = StacksBlockId([0xf0; 32]);
let mut tip = StacksBlockId::sentinel();
for blk in 0..n {
let final_block_id = StacksBlockId([(blk as u8) + 1; 32]);
let mut marf = marfed_kv.begin(&tip, &target_block_id);
let keys_and_values = vec![(
format!("key-{}", blk),
format!("value-{}", blk)
)];
marf.put_all_data(keys_and_values).unwrap();
marf.commit_to(&final_block_id).unwrap();
tip = final_block_id;
}

let ephemeral_tip = StacksBlockId([0xee; 32]);
let mut marf_ephemeral =
marfed_kv.begin_ephemeral(&tip, &ephemeral_tip).unwrap();

// Invariant: ephemeral tip height equals current height.
let height = marf_ephemeral.get_current_block_height();
let open_height = marf_ephemeral.get_open_chain_tip_height();
prop_assert_eq!(height, open_height);
});
}

// Test TODO:
// * nakamoto boot plan with Clarity smart contracts which exercise the Clarity DB thoroghly
// * stacks 2.x test