feat: add analysis error for use of block-height in Clarity 3

This commit is contained in:
Brice Dobry
2024-05-08 12:00:45 -04:00
parent 7a63f899e8
commit 02e3d89a15
3 changed files with 27 additions and 0 deletions

View File

@@ -136,6 +136,7 @@ pub enum CheckErrors {
GetBurnBlockInfoExpectPropertyName,
NameAlreadyUsed(String),
ReservedWord(String),
// expect a function, or applying a function to a list
NonFunctionApplication,
@@ -408,6 +409,7 @@ impl DiagnosableError for CheckErrors {
CheckErrors::GetBlockInfoExpectPropertyName => "missing property name for block info introspection".into(),
CheckErrors::GetBurnBlockInfoExpectPropertyName => "missing property name for burn block info introspection".into(),
CheckErrors::NameAlreadyUsed(name) => format!("defining '{}' conflicts with previous value", name),
CheckErrors::ReservedWord(name) => format!("{name} is a reserved word"),
CheckErrors::NonFunctionApplication => "expecting expression of type function".into(),
CheckErrors::ExpectedListApplication => "expecting expression of type list".into(),
CheckErrors::ExpectedSequence(found_type) => format!("expecting expression of type 'list', 'buff', 'string-ascii' or 'string-utf8' - found '{}'", found_type),

View File

@@ -84,3 +84,21 @@ impl FunctionType {
}
}
}
fn is_reserved_word_v3(word: &str) -> bool {
match word {
"block-height" => true,
_ => false,
}
}
/// Is this a reserved word that should trigger an analysis error for the given
/// Clarity version? Note that most of the reserved words do not trigger an
/// analysis error, but will trigger an error at runtime. This should likely be
/// changed in a future Clarity version.
pub fn is_reserved_word(word: &str, version: ClarityVersion) -> bool {
match version {
ClarityVersion::Clarity1 | ClarityVersion::Clarity2 => false,
ClarityVersion::Clarity3 => is_reserved_word_v3(word),
}
}

View File

@@ -19,6 +19,7 @@ use std::collections::BTreeMap;
use hashbrown::{HashMap, HashSet};
use crate::vm::analysis::errors::{CheckError, CheckErrors, CheckResult};
use crate::vm::analysis::type_checker::is_reserved_word;
use crate::vm::analysis::types::ContractAnalysis;
use crate::vm::contexts::MAX_CONTEXT_DEPTH;
use crate::vm::representations::{ClarityName, SymbolicExpression};
@@ -128,6 +129,7 @@ impl TraitContext {
}
pub struct ContractContext {
clarity_version: ClarityVersion,
contract_identifier: QualifiedContractIdentifier,
map_types: HashMap<ClarityName, (TypeSignature, TypeSignature)>,
variable_types: HashMap<ClarityName, TypeSignature>,
@@ -147,6 +149,7 @@ impl ContractContext {
clarity_version: ClarityVersion,
) -> ContractContext {
ContractContext {
clarity_version,
contract_identifier,
variable_types: HashMap::new(),
private_function_types: HashMap::new(),
@@ -168,6 +171,10 @@ impl ContractContext {
}
pub fn check_name_used(&self, name: &str) -> CheckResult<()> {
if is_reserved_word(name, self.clarity_version) {
return Err(CheckError::new(CheckErrors::ReservedWord(name.to_string())));
}
if self.variable_types.contains_key(name)
|| self.persisted_variable_types.contains_key(name)
|| self.private_function_types.contains_key(name)