Skip to content

Commit

Permalink
feat: advance burn and stacks chain tips independently (#1506)
Browse files Browse the repository at this point in the history
* block height changes

* use get_block_height to mean stacks specifically

* separate chaintip advancing

* change chaintip back to u32 and no burn increment on stacks advance

* fix tests with burn changes

* add back mineEmptyBlock(s)

* fix up some double advance bugs

* error on advance_stacks if epoch < 3

* handle advance_stacks errors in tests

* add more rust tests and stub out simnet 3 tests

* mine_empty_stacks* should return Result

* clean up fixtures

* add session command testing

* remove redundant evaluate_at_block epoch 3 test

* change error message for advance_stacks_chaintip

* add generic interpreter chain_tip advance which acts differently in epoch pre-3 vs 3

* chaintip -> chain_tip

* add back the advance_chain_tip help

---------

Co-authored-by: brady.ouren <bouren@hiro.sh>
  • Loading branch information
tippenein and brady.ouren committed Jul 26, 2024
1 parent 0cd1b95 commit efeadc5
Show file tree
Hide file tree
Showing 7 changed files with 317 additions and 19 deletions.
45 changes: 41 additions & 4 deletions components/clarinet-sdk-wasm/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,18 @@ impl SDK {
session.interpreter.get_block_height()
}

#[wasm_bindgen(getter, js_name=stacksBlockHeight)]
pub fn stacks_block_height(&mut self) -> u32 {
let session = self.get_session_mut();
session.interpreter.get_block_height()
}

#[wasm_bindgen(getter, js_name=burnBlockHeight)]
pub fn burn_block_height(&mut self) -> u32 {
let session = self.get_session_mut();
session.interpreter.get_burn_block_height()
}

#[wasm_bindgen(getter, js_name=currentEpoch)]
pub fn current_epoch(&mut self) -> String {
let session = self.get_session_mut();
Expand Down Expand Up @@ -911,14 +923,39 @@ impl SDK {

#[wasm_bindgen(js_name=mineEmptyBlock)]
pub fn mine_empty_block(&mut self) -> u32 {
let session = self.get_session_mut();
session.advance_chain_tip(1)
self.mine_empty_burn_block()
}

#[wasm_bindgen(js_name=mineEmptyBlocks)]
pub fn mine_empty_blocks(&mut self, count: Option<u32>) -> u32 {
self.mine_empty_burn_blocks(count)
}
#[wasm_bindgen(js_name=mineEmptyStacksBlock)]
pub fn mine_empty_stacks_block(&mut self) -> Result<u32, String> {
let session = self.get_session_mut();
match session.advance_stacks_chain_tip(1) {
Ok(new_height) => Ok(new_height),
Err(_) => Err("use mineEmptyBurnBlock in epoch lower than 3.0".to_string()),
}
}

#[wasm_bindgen(js_name=mineEmptyStacksBlocks)]
pub fn mine_empty_stacks_blocks(&mut self, count: Option<u32>) -> Result<u32, String> {
let session = self.get_session_mut();
match session.advance_stacks_chain_tip(count.unwrap_or(1)) {
Ok(new_height) => Ok(new_height),
Err(_) => Err("use mineEmptyBurnBlocks in epoch lower than 3.0".to_string()),
}
}

#[wasm_bindgen(js_name=mineEmptyBurnBlock)]
pub fn mine_empty_burn_block(&mut self) -> u32 {
let session = self.get_session_mut();
session.advance_burn_chain_tip(1)
}
#[wasm_bindgen(js_name=mineEmptyBurnBlocks)]
pub fn mine_empty_burn_blocks(&mut self, count: Option<u32>) -> u32 {
let session = self.get_session_mut();
session.advance_chain_tip(count.unwrap_or(1))
session.advance_burn_chain_tip(count.unwrap_or(1))
}

#[wasm_bindgen(js_name=runSnippet)]
Expand Down
21 changes: 21 additions & 0 deletions components/clarinet-sdk/node/tests/fixtures/Clarinet3.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[project]
name = 'fixtures'
description = 'sample project to test clarinet-sdk wasm'
telemetry = false
cache_dir = './.cache'
requirements = []

[contracts.multiplier-trait]
path = 'contracts/multiplier-trait.clar'
clarity_version = 3
epoch = 3.0

[contracts.multiplier-contract]
path = 'contracts/multiplier-contract.clar'
clarity_version = 3
epoch = 3.0

[contracts.counter]
path = 'contracts/counter.clar'
clarity_version = 3
epoch = 3.0
20 changes: 20 additions & 0 deletions components/clarinet-sdk/node/tests/simnet-usage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ describe("basic simnet interactions", () => {
simnet.mineEmptyBlocks(4);
expect(simnet.blockHeight).toBe(blockHeight + 5);
});
it("can not mine empty stacks block in pre-3.0", () => {
expect(() => simnet.mineEmptyStacksBlock()).toThrowError(
"use mineEmptyBurnBlock in epoch lower than 3.0"
);
})

it("exposes devnet stacks accounts", () => {
const accounts = simnet.getAccounts();
Expand Down Expand Up @@ -83,6 +88,21 @@ describe("basic simnet interactions", () => {
});
});

describe("simnet epoch 3", () => {
it("can mine empty blocks", () => {
simnet.setEpoch("3.0");
const blockHeight = simnet.stacksBlockHeight;
const burnBlockHeight = simnet.burnBlockHeight;
simnet.mineEmptyStacksBlock();
expect(simnet.stacksBlockHeight).toBe(blockHeight + 1);
expect(simnet.burnBlockHeight).toBe(burnBlockHeight);
simnet.mineEmptyStacksBlocks(4);
expect(simnet.stacksBlockHeight).toBe(blockHeight + 5);
simnet.mineEmptyBurnBlocks(4);
expect(simnet.burnBlockHeight).toBe(burnBlockHeight + 4);
expect(simnet.stacksBlockHeight).toBe(blockHeight + 9);
})
})
describe("simnet can run arbitrary snippets", () => {
it("can run simple snippets", () => {
const res = simnet.execute("(+ 1 2)");
Expand Down
10 changes: 9 additions & 1 deletion components/clarity-repl/src/repl/datastore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,14 @@ impl BurnDatastore {
}
}

pub fn advance_chain_tip(&mut self, count: u32) {
pub fn get_current_epoch(&self) -> StacksEpochId {
self.current_epoch
}

pub fn get_current_block_height(&self) -> u32 {
self.chain_height
}
pub fn advance_chain_tip(&mut self, count: u32) -> u32 {
let cur_height = self.chain_height;
let current_lookup_id = *self
.block_id_lookup
Expand All @@ -399,6 +406,7 @@ impl BurnDatastore {
self.chain_height += count;
self.open_chain_tip = height_to_id(self.chain_height);
self.current_chain_tip = self.open_chain_tip;
self.chain_height
}

pub fn set_current_epoch(&mut self, epoch: StacksEpochId) {
Expand Down
93 changes: 86 additions & 7 deletions components/clarity-repl/src/repl/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1099,11 +1099,31 @@ impl ClarityInterpreter {
}

pub fn advance_chain_tip(&mut self, count: u32) -> u32 {
self.burn_datastore.advance_chain_tip(count);
let new_height = self.datastore.advance_chain_tip(count);
let current_epoch = self.burn_datastore.get_current_epoch();
if current_epoch < StacksEpochId::Epoch30 {
self.advance_burn_chain_tip(count)
} else {
match self.advance_stacks_chain_tip(count) {
Ok(count) => count,
Err(_) => unreachable!("Epoch checked already"),
}
}
}

pub fn advance_burn_chain_tip(&mut self, count: u32) -> u32 {
let new_height = self.burn_datastore.advance_chain_tip(count);
let _ = self.datastore.advance_chain_tip(count);
self.set_tenure_height();
new_height
}
pub fn advance_stacks_chain_tip(&mut self, count: u32) -> Result<u32, String> {
let current_epoch = self.burn_datastore.get_current_epoch();
if current_epoch < StacksEpochId::Epoch30 {
Err("only burn chain height can be advanced in epoch lower than 3.0".to_string())
} else {
Ok(self.datastore.advance_chain_tip(count))
}
}

pub fn set_tenure_height(&mut self) {
let block_height = self.get_block_height();
Expand All @@ -1122,6 +1142,10 @@ impl ClarityInterpreter {
self.datastore.get_current_block_height()
}

pub fn get_burn_block_height(&mut self) -> u32 {
self.burn_datastore.get_current_block_height()
}

fn credit_token(&mut self, account: String, token: String, value: u128) {
self.accounts.insert(account.clone());
match self.tokens.entry(token) {
Expand Down Expand Up @@ -1184,6 +1208,7 @@ impl ClarityInterpreter {
#[cfg(test)]
mod tests {
use super::*;
use crate::analysis::Settings as AnalysisSettings;
use crate::{
repl::session::BOOT_CONTRACTS_DATA, test_fixtures::clarity_contract::ClarityContractBuilder,
};
Expand Down Expand Up @@ -1259,14 +1284,68 @@ mod tests {
assert_eq!(interpreter.get_block_height(), 0);
}

#[test]
fn test_advance_stacks_chain_tip_pre_epoch_3() {
let mut interpreter =
ClarityInterpreter::new(StandardPrincipalData::transient(), Settings::default());
interpreter
.burn_datastore
.set_current_epoch(StacksEpochId::Epoch2_05);
let count = 5;
let initial_block_height = interpreter.get_burn_block_height();
assert_ne!(interpreter.advance_stacks_chain_tip(count), Ok(count));
assert_eq!(interpreter.get_burn_block_height(), initial_block_height);
assert_eq!(interpreter.get_block_height(), initial_block_height);
}
#[test]
fn test_advance_stacks_chain_tip() {
let wasm_settings = Settings {
analysis: AnalysisSettings::default(),
clarity_wasm_mode: true,
show_timings: false,
};
let mut interpreter =
ClarityInterpreter::new(StandardPrincipalData::transient(), wasm_settings);
interpreter
.burn_datastore
.set_current_epoch(StacksEpochId::Epoch30);
let count = 5;
let initial_block_height = interpreter.get_burn_block_height();
assert_eq!(interpreter.advance_stacks_chain_tip(count), Ok(count));
assert_eq!(interpreter.get_burn_block_height(), initial_block_height);
assert_eq!(interpreter.get_block_height(), initial_block_height + count);
}
#[test]
fn test_advance_chain_tip_pre_epoch3() {
let mut interpreter =
ClarityInterpreter::new(StandardPrincipalData::transient(), Settings::default());
interpreter
.burn_datastore
.set_current_epoch(StacksEpochId::Epoch2_05);
let count = 5;
let initial_block_height = interpreter.get_block_height();
interpreter.advance_burn_chain_tip(count);
assert_eq!(interpreter.get_block_height(), initial_block_height + count);
assert_eq!(
interpreter.get_burn_block_height(),
initial_block_height + count
);
}
#[test]
fn test_advance_chain_tip() {
let mut interpreter =
ClarityInterpreter::new(StandardPrincipalData::transient(), Settings::default());
interpreter
.burn_datastore
.set_current_epoch(StacksEpochId::Epoch30);
let count = 5;
let initial_block_height = interpreter.get_block_height();
interpreter.advance_chain_tip(count);
interpreter.advance_burn_chain_tip(count);
assert_eq!(interpreter.get_block_height(), initial_block_height + count);
assert_eq!(
interpreter.get_burn_block_height(),
initial_block_height + count
);
}

#[test]
Expand Down Expand Up @@ -1730,7 +1809,7 @@ mod tests {
),
);

interpreter.advance_chain_tip(10);
interpreter.advance_burn_chain_tip(10);

let result = interpreter.call_contract_fn(
&contract_id,
Expand Down Expand Up @@ -1762,7 +1841,7 @@ mod tests {
let mut interpreter =
ClarityInterpreter::new(StandardPrincipalData::transient(), Settings::default());

interpreter.advance_chain_tip(1);
interpreter.advance_burn_chain_tip(1);

let snippet = [
"(define-read-only (get-height)",
Expand Down Expand Up @@ -1815,7 +1894,7 @@ mod tests {
let mut interpreter =
ClarityInterpreter::new(StandardPrincipalData::transient(), Settings::default());

interpreter.advance_chain_tip(1);
interpreter.advance_burn_chain_tip(1);

let snippet = [
"(define-read-only (get-height)",
Expand Down Expand Up @@ -1868,7 +1947,7 @@ mod tests {
),
);

interpreter.advance_chain_tip(10);
interpreter.advance_burn_chain_tip(10);

let result = interpreter.call_contract_fn(
&contract_id,
Expand Down
Loading

0 comments on commit efeadc5

Please sign in to comment.