mirror of
https://github.com/alexgo-io/stacks-puppet-node.git
synced 2026-01-12 16:53:21 +08:00
feat: handle tenure-height with at-block before epoch 3.0
Also including some other improvements from PR review.
This commit is contained in:
@@ -74,7 +74,7 @@ pub struct Environment<'a, 'b, 'hooks> {
|
||||
}
|
||||
|
||||
pub struct OwnedEnvironment<'a, 'hooks> {
|
||||
context: GlobalContext<'a, 'hooks>,
|
||||
pub(crate) context: GlobalContext<'a, 'hooks>,
|
||||
call_stack: CallStack,
|
||||
}
|
||||
|
||||
@@ -1964,18 +1964,6 @@ impl CallStack {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "testing"))]
|
||||
impl<'a, 'hooks> OwnedEnvironment<'a, 'hooks> {
|
||||
pub fn set_tenure_height(&mut self, tenure_height: u32) {
|
||||
self.context.database.begin();
|
||||
self.context
|
||||
.database
|
||||
.set_tenure_height(tenure_height)
|
||||
.unwrap();
|
||||
self.context.database.commit().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use stacks_common::types::chainstate::StacksAddress;
|
||||
|
||||
@@ -858,6 +858,12 @@ impl<'a> ClarityDatabase<'a> {
|
||||
|
||||
/// Returns the tenure height of the current block.
|
||||
pub fn get_tenure_height(&mut self) -> Result<u32> {
|
||||
if self.get_clarity_epoch_version()? < StacksEpochId::Epoch30 {
|
||||
// Before epoch 3.0, the tenure height was not stored in the
|
||||
// Clarity state. Instead, it was the same as the block height.
|
||||
return Ok(self.get_current_block_height());
|
||||
}
|
||||
|
||||
self.get_data(TENURE_HEIGHT_KEY)?
|
||||
.ok_or_else(|| {
|
||||
InterpreterError::Expect("No tenure height in stored Clarity state".into()).into()
|
||||
@@ -874,6 +880,11 @@ impl<'a> ClarityDatabase<'a> {
|
||||
/// tenure, this height must be incremented before evaluating any
|
||||
/// transactions in the block.
|
||||
pub fn set_tenure_height(&mut self, height: u32) -> Result<()> {
|
||||
if self.get_clarity_epoch_version()? < StacksEpochId::Epoch30 {
|
||||
return Err(Error::Interpreter(InterpreterError::Expect(
|
||||
"Setting tenure height in Clarity state is not supported before epoch 3.0".into(),
|
||||
)));
|
||||
}
|
||||
self.put_data(TENURE_HEIGHT_KEY, &height)
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,18 @@ mod simple_apply_eval;
|
||||
mod traits;
|
||||
mod variables;
|
||||
|
||||
#[cfg(any(test, feature = "testing"))]
|
||||
impl<'a, 'hooks> OwnedEnvironment<'a, 'hooks> {
|
||||
pub fn set_tenure_height(&mut self, tenure_height: u32) {
|
||||
self.context.database.begin();
|
||||
self.context
|
||||
.database
|
||||
.set_tenure_height(tenure_height)
|
||||
.unwrap();
|
||||
self.context.database.commit().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! epochs_template {
|
||||
($($epoch:ident,)*) => {
|
||||
#[template]
|
||||
@@ -160,7 +172,11 @@ impl MemoryEnvironmentGenerator {
|
||||
pub struct TopLevelMemoryEnvironmentGenerator(MemoryBackingStore);
|
||||
impl TopLevelMemoryEnvironmentGenerator {
|
||||
pub fn get_env(&mut self, epoch: StacksEpochId) -> OwnedEnvironment {
|
||||
let mut owned_env = OwnedEnvironment::new(self.0.as_clarity_db(), epoch);
|
||||
let mut db = self.0.as_clarity_db();
|
||||
db.begin();
|
||||
db.set_clarity_epoch_version(epoch).unwrap();
|
||||
db.commit().unwrap();
|
||||
let mut owned_env = OwnedEnvironment::new(db, epoch);
|
||||
if epoch >= StacksEpochId::Epoch30 {
|
||||
owned_env.set_tenure_height(1);
|
||||
}
|
||||
|
||||
@@ -164,11 +164,13 @@ impl ClarityTestSim {
|
||||
let cur_epoch = Self::check_and_bump_epoch(&mut store, &headers_db, &burn_db);
|
||||
|
||||
let mut db = store.as_clarity_db(&headers_db, &burn_db);
|
||||
db.begin();
|
||||
db.set_tenure_height(self.tenure_height as u32 + if new_tenure { 1 } else { 0 })
|
||||
.expect("FAIL: unable to set tenure height in Clarity database");
|
||||
db.commit()
|
||||
.expect("FAIL: unable to commit tenure height in Clarity database");
|
||||
if cur_epoch >= StacksEpochId::Epoch30 {
|
||||
db.begin();
|
||||
db.set_tenure_height(self.tenure_height as u32 + if new_tenure { 1 } else { 0 })
|
||||
.expect("FAIL: unable to set tenure height in Clarity database");
|
||||
db.commit()
|
||||
.expect("FAIL: unable to commit tenure height in Clarity database");
|
||||
}
|
||||
|
||||
let mut block_conn =
|
||||
ClarityBlockConnection::new_test_conn(store, &headers_db, &burn_db, cur_epoch);
|
||||
@@ -215,11 +217,13 @@ impl ClarityTestSim {
|
||||
debug!("Execute block in epoch {}", &cur_epoch);
|
||||
|
||||
let mut db = store.as_clarity_db(&headers_db, &burn_db);
|
||||
db.begin();
|
||||
db.set_tenure_height(self.tenure_height as u32 + if new_tenure { 1 } else { 0 })
|
||||
.expect("FAIL: unable to set tenure height in Clarity database");
|
||||
db.commit()
|
||||
.expect("FAIL: unable to commit tenure height in Clarity database");
|
||||
if cur_epoch >= StacksEpochId::Epoch30 {
|
||||
db.begin();
|
||||
db.set_tenure_height(self.tenure_height as u32 + if new_tenure { 1 } else { 0 })
|
||||
.expect("FAIL: unable to set tenure height in Clarity database");
|
||||
db.commit()
|
||||
.expect("FAIL: unable to commit tenure height in Clarity database");
|
||||
}
|
||||
let mut owned_env = OwnedEnvironment::new_toplevel(db);
|
||||
f(&mut owned_env)
|
||||
};
|
||||
|
||||
@@ -1395,3 +1395,61 @@ fn test_block_heights_across_versions_traits() {
|
||||
assert_eq!(Value::okay(Value::UInt(20)).unwrap(), res2.0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_block_heights_at_block() {
|
||||
let mut sim = ClarityTestSim::new();
|
||||
sim.epoch_bounds = vec![0, 1, 2, 3, 4, 5, 6, 7];
|
||||
|
||||
let contract_identifier = QualifiedContractIdentifier::local("test-contract").unwrap();
|
||||
|
||||
// Advance to epoch 3.0
|
||||
while sim.block_height <= 7 {
|
||||
sim.execute_next_block(|_env| {});
|
||||
}
|
||||
|
||||
let block_height = sim.block_height as u128;
|
||||
sim.execute_next_block_as_conn(|conn| {
|
||||
let epoch = conn.get_epoch();
|
||||
assert_eq!(epoch, StacksEpochId::Epoch30);
|
||||
|
||||
let contract =r#"
|
||||
(define-private (test-tenure) (at-block (unwrap-panic (get-block-info? id-header-hash u0)) tenure-height))
|
||||
(define-private (test-stacks) (at-block (unwrap-panic (get-block-info? id-header-hash u1)) stacks-block-height))
|
||||
"#;
|
||||
|
||||
conn.as_transaction(|clarity_db| {
|
||||
// Analyze the contract
|
||||
let (ast, analysis) = clarity_db.analyze_smart_contract(
|
||||
&contract_identifier,
|
||||
ClarityVersion::Clarity3,
|
||||
&contract,
|
||||
ASTRules::PrecheckSize,
|
||||
).unwrap();
|
||||
|
||||
// Publish the contract
|
||||
clarity_db
|
||||
.initialize_smart_contract(
|
||||
&contract_identifier,
|
||||
ClarityVersion::Clarity3,
|
||||
&ast,
|
||||
contract,
|
||||
None,
|
||||
|_, _| false,
|
||||
).unwrap();
|
||||
});
|
||||
|
||||
// Call the contracts and validate the results
|
||||
let mut tx = conn.start_transaction_processing();
|
||||
assert_eq!(
|
||||
Value::UInt(0),
|
||||
tx.eval_read_only(&contract_identifier, "(test-tenure)")
|
||||
.unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Value::UInt(1),
|
||||
tx.eval_read_only(&contract_identifier, "(test-stacks)")
|
||||
.unwrap()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -101,8 +101,10 @@ fn new_block<'a, 'b>(
|
||||
block.as_free_transaction(|tx_conn| {
|
||||
tx_conn
|
||||
.with_clarity_db(|db| {
|
||||
let tenure_height = db.get_tenure_height().unwrap_or(0);
|
||||
db.set_tenure_height(tenure_height + 1).unwrap();
|
||||
if db.get_clarity_epoch_version().unwrap() >= StacksEpochId::Epoch30 {
|
||||
let tenure_height = db.get_tenure_height().unwrap_or(0);
|
||||
db.set_tenure_height(tenure_height + 1).unwrap();
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Reference in New Issue
Block a user