From ffc5819ee63a9c0577d84004492482b11f2fe55b Mon Sep 17 00:00:00 2001 From: Jeff Bencin Date: Wed, 27 Nov 2024 13:45:01 -0500 Subject: [PATCH] fix: `burn-block-height` inside `at-block` context --- clarity/src/vm/database/clarity_db.rs | 62 +++++++++++++++------------ clarity/src/vm/functions/database.rs | 5 +-- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/clarity/src/vm/database/clarity_db.rs b/clarity/src/vm/database/clarity_db.rs index 4f6f3f7781..525ea00e01 100644 --- a/clarity/src/vm/database/clarity_db.rs +++ b/clarity/src/vm/database/clarity_db.rs @@ -1075,35 +1075,41 @@ impl<'a> ClarityDatabase<'a> { /// block height (i.e. that returned by `get_index_block_header_hash` for /// `get_current_block_height`). pub fn get_current_burnchain_block_height(&mut self) -> Result { - let cur_stacks_height = self.store.get_current_block_height(); + let epoch = self.get_clarity_epoch_version()?; + match epoch { + // Special case to preserve possibly incorrect behavior (inside at-block) in Epoch 3.0 + StacksEpochId::Epoch30 => { + self.burn_state_db + .get_tip_burn_block_height() + .ok_or_else(|| { + InterpreterError::Expect("Failed to get burnchain tip height.".into()) + .into() + }) + } + _ => { + let cur_stacks_height = self.store.get_current_block_height(); + + // Before epoch 3.0, we can only access the burn block associated with the last block + let last_mined_bhh = if epoch.clarity_uses_tip_burn_block() { + // In epoch 3+, we can access the current burnchain block + self.get_index_block_header_hash(cur_stacks_height) + .or_else(|_| self.get_index_block_header_hash(cur_stacks_height - 1))? + } else if cur_stacks_height == 0 { + return Ok(self.burn_state_db.get_burn_start_height()); + } else { + // Safety note: normal subtraction is safe here, because we've already checked + // that cur_stacks_height > 0. + self.get_index_block_header_hash(cur_stacks_height - 1)? + }; - // Before epoch 3.0, we can only access the burn block associated with the last block - if !self - .get_clarity_epoch_version()? - .clarity_uses_tip_burn_block() - { - if cur_stacks_height == 0 { - return Ok(self.burn_state_db.get_burn_start_height()); - }; - // Safety note: normal subtraction is safe here, because we've already checked - // that cur_stacks_height > 0. - let last_mined_bhh = self.get_index_block_header_hash(cur_stacks_height - 1)?; - - self.get_burnchain_block_height(&last_mined_bhh) - .ok_or_else(|| { - InterpreterError::Expect(format!( - "Block header hash '{}' must return for provided stacks block height {}", - &last_mined_bhh, cur_stacks_height - )) - .into() - }) - } else { - // In epoch 3+, we can access the current burnchain block - self.burn_state_db - .get_tip_burn_block_height() - .ok_or_else(|| { - InterpreterError::Expect("Failed to get burnchain tip height.".into()).into() - }) + self.get_burnchain_block_height(&last_mined_bhh) + .ok_or_else(|| { + InterpreterError::Expect(format!( + "Block header hash '{last_mined_bhh}' must return for provided stacks block height {cur_stacks_height}" + )) + .into() + }) + } } } diff --git a/clarity/src/vm/functions/database.rs b/clarity/src/vm/functions/database.rs index ff14507ead..167248401a 100644 --- a/clarity/src/vm/functions/database.rs +++ b/clarity/src/vm/functions/database.rs @@ -915,9 +915,8 @@ pub fn special_get_burn_block_info( }; // Note: We assume that we will not have a height bigger than u32::MAX. - let height_value = match u32::try_from(height_value) { - Ok(result) => result, - _ => return Ok(Value::none()), + let Ok(height_value) = u32::try_from(height_value) else { + return Ok(Value::none()); }; match block_info_prop {