Skip to content

Commit

Permalink
fix: burn-block-height in at-block at epoch 3.x (#1668)
Browse files Browse the repository at this point in the history
* fix: burn-block-height in at-block at epoch 3.x

* refactor: address review with an explicit match
  • Loading branch information
hugocaillard authored Feb 7, 2025
1 parent b2f3415 commit e9b078c
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 12 deletions.
26 changes: 17 additions & 9 deletions components/clarity-repl/src/repl/datastore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,7 @@ impl Datastore {
if epoch == self.current_epoch {
return;
}
clarity_datastore.put("vm-epoch::epoch-version", &format!("{:08x}", epoch as u32));
self.current_epoch = epoch;
self.current_epoch_start_height = self.stacks_chain_height;
if epoch >= StacksEpochId::Epoch30 {
Expand Down Expand Up @@ -989,16 +990,23 @@ impl BurnStateDB for Datastore {
}

fn get_tip_burn_block_height(&self) -> Option<u32> {
let current_chain_tip = self.current_chain_tip.borrow();
if let Some(height) = self.get_burn_block_height_for_block(&current_chain_tip) {
return Some(height);
}
use StacksEpochId::*;
match self.current_epoch {
Epoch10 | Epoch20 | Epoch2_05 | Epoch21 | Epoch22 | Epoch23 | Epoch24 | Epoch25 => {
let current_chain_tip = self.current_chain_tip.borrow();
if let Some(height) = self.get_burn_block_height_for_block(&current_chain_tip) {
return Some(height);
}

return self
.remote_block_info_cache
.borrow()
.get(&current_chain_tip)
.map(|block| block.burn_block_height);
self.remote_block_info_cache
.borrow()
.get(&current_chain_tip)
.map(|block| block.burn_block_height)
}
// preserve the 3.0 and 3.1 special behavior of burn-block-height
// https://github.com/stacks-network/stacks-core/pull/5524
Epoch30 | Epoch31 => Some(self.burn_chain_height),
}
}

fn get_tip_sortition_id(&self) -> Option<SortitionId> {
Expand Down
119 changes: 117 additions & 2 deletions components/clarity-repl/src/repl/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1693,8 +1693,7 @@ mod tests {

let _ = session.advance_burn_chain_tip(10000);

assert_eq!(session.process_console_input("(at-block (unwrap-panic (get-stacks-block-info? id-header-hash u19000)) burn-block-height)").1[0], "u18999".green().to_string());
assert_eq!(session.process_console_input("(at-block (unwrap-panic (get-stacks-block-info? id-header-hash u20000)) burn-block-height)").1[0], "u19999".green().to_string());
assert_eq!(session.process_console_input("(at-block (unwrap-panic (get-stacks-block-info? id-header-hash u19000)) burn-block-height)").1[0], "u20021".green().to_string());
}

#[test]
Expand Down Expand Up @@ -1813,4 +1812,120 @@ mod tests {

assert!(time_block_2 - time_block_1 == 600);
}

#[test]
fn burn_block_height_behavior_epoch2_5() {
let settings = SessionSettings::default();
let mut session = Session::new(settings);
session.start().expect("session could not start");
session.update_epoch(StacksEpochId::Epoch25);

let snippet = [
"(define-read-only (get-burn (height uint))",
" (let ((id (unwrap-panic (get-block-info? id-header-hash height))))",
" (at-block id burn-block-height)))",
]
.join("\n");

let contract = ClarityContractBuilder::new()
.code_source(snippet)
.clarity_version(ClarityVersion::Clarity2)
.epoch(StacksEpochId::Epoch25)
.build();

session.deploy_contract(&contract, false, None).unwrap();
session.advance_burn_chain_tip(10);

let result = run_session_snippet(&mut session, "block-height");
assert_eq!(result, Value::UInt(10));
let result = run_session_snippet(&mut session, "burn-block-height");
assert_eq!(result, Value::UInt(9));
let result = run_session_snippet(
&mut session,
format!("(contract-call? .{} get-burn u6)", contract.name).as_str(),
);
assert_eq!(result, Value::UInt(5));
}

#[test]
fn burn_block_height_behavior_epoch3_0() {
// test that clarinet preserves the 3.0 and 3.1 special behavior of burn-block-height
// https://github.com/stacks-network/stacks-core/pull/5524
let settings = SessionSettings::default();
let mut session = Session::new(settings);
session.start().expect("session could not start");
session.update_epoch(StacksEpochId::Epoch30);

let snippet = [
"(define-read-only (get-burn (height uint))",
" (let ((id (unwrap-panic (get-stacks-block-info? id-header-hash height))))",
" (at-block id burn-block-height)))",
]
.join("\n");

let contract = ClarityContractBuilder::new()
.code_source(snippet)
.clarity_version(ClarityVersion::Clarity3)
.epoch(StacksEpochId::Epoch30)
.build();

session.deploy_contract(&contract, false, None).unwrap();
session.advance_burn_chain_tip(10);

let result = run_session_snippet(&mut session, "stacks-block-height");
assert_eq!(result, Value::UInt(11));
let result = run_session_snippet(&mut session, "burn-block-height");
assert_eq!(result, Value::UInt(11));
let result = run_session_snippet(
&mut session,
format!("(contract-call? .{} get-burn u8)", contract.name).as_str(),
);
assert_eq!(result, Value::UInt(11));
}

#[test]
fn burn_block_height_behavior_epoch3_0_contract_in_2_5() {
let settings = SessionSettings::default();
let mut session = Session::new(settings);
session.start().expect("session could not start");
session.update_epoch(StacksEpochId::Epoch25);

let snippet = [
"(define-read-only (get-burn (height uint))",
" (let ((id (unwrap-panic (get-block-info? id-header-hash height))))",
" (at-block id burn-block-height)))",
]
.join("\n");

let contract = ClarityContractBuilder::new()
.name("contract-2-5")
.code_source(snippet.clone())
.clarity_version(ClarityVersion::Clarity2)
.epoch(StacksEpochId::Epoch25)
.build();

session.deploy_contract(&contract, false, None).unwrap();
session.advance_burn_chain_tip(10);

session.update_epoch(StacksEpochId::Epoch30);

session.advance_burn_chain_tip(10);

let result = run_session_snippet(&mut session, "stacks-block-height");
assert_eq!(result, Value::UInt(21));

// calling a 2.5 contract in epoch 3.0 has the same behavior as epoch 2.5

let result = run_session_snippet(
&mut session,
format!("(contract-call? .{} get-burn u8)", contract.name).as_str(),
);
assert_eq!(result, Value::UInt(7));

let result = run_session_snippet(
&mut session,
format!("(contract-call? .{} get-burn u18)", contract.name).as_str(),
);
assert_eq!(result, Value::UInt(21));
}
}
2 changes: 1 addition & 1 deletion components/clarity-repl/tests/session_with_remote_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ fn it_can_get_heights() {
assert_eq!(result, Value::UInt(42000));
let snippet = format!("(at-block {hash} burn-block-height)");
let result = eval_snippet(&mut session, &snippet);
assert_eq!(result, Value::UInt(5560));
assert_eq!(result, Value::UInt(6603));
let snippet = format!("(at-block {hash} tenure-height)");
let result = eval_snippet(&mut session, &snippet);
assert_eq!(result, Value::UInt(3302));
Expand Down

0 comments on commit e9b078c

Please sign in to comment.