diff --git a/CHANGELOG.md b/CHANGELOG.md index d6ab837573..368ff525c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to the versioning scheme outlined in the [README.md](README.md). +## [2.3.0.0.2] + +This is a high-priority hotfix release to address a bug in the +stacks-node miner logic which could impact miner availability. + +This release is compatible with chainstate directories from 2.3.0.0.x and 2.1.0.0.x + ## [2.3.0.0.1] This is a hotfix release to update: diff --git a/clarity/src/vm/analysis/errors.rs b/clarity/src/vm/analysis/errors.rs index ffcf8c27c7..76895c1325 100644 --- a/clarity/src/vm/analysis/errors.rs +++ b/clarity/src/vm/analysis/errors.rs @@ -35,6 +35,7 @@ pub enum CheckErrors { ValueOutOfBounds, TypeSignatureTooDeep, ExpectedName, + SupertypeTooLarge, // match errors BadMatchOptionSyntax(Box), @@ -320,6 +321,7 @@ impl DiagnosableError for CheckErrors { fn message(&self) -> String { match &self { CheckErrors::ExpectedLiteral => "expected a literal argument".into(), + CheckErrors::SupertypeTooLarge => "supertype of two types is too large".into(), CheckErrors::BadMatchOptionSyntax(source) => format!("match on a optional type uses the following syntax: (match input some-name if-some-expression if-none-expression). Caused by: {}", source.message()), diff --git a/clarity/src/vm/types/signatures.rs b/clarity/src/vm/types/signatures.rs index b2ec129a76..48b13a320f 100644 --- a/clarity/src/vm/types/signatures.rs +++ b/clarity/src/vm/types/signatures.rs @@ -1073,8 +1073,9 @@ impl TypeSignature { let entry_out = Self::least_supertype_v2_0(entry_a, entry_b)?; type_map_out.insert(name.clone(), entry_out); } - Ok(TupleTypeSignature::try_from(type_map_out).map(|x| x.into()) - .expect("ERR: least_supertype_v2_0 attempted to construct a too-large supertype of two types")) + Ok(TupleTypeSignature::try_from(type_map_out) + .map(|x| x.into()) + .map_err(|_| CheckErrors::SupertypeTooLarge)?) } ( SequenceType(SequenceSubtype::ListType(ListTypeData { @@ -1095,7 +1096,7 @@ impl TypeSignature { }; let max_len = cmp::max(len_a, len_b); Ok(Self::list_of(entry_type, *max_len) - .expect("ERR: least_supertype_v2_0 attempted to construct a too-large supertype of two types")) + .map_err(|_| CheckErrors::SupertypeTooLarge)?) } (ResponseType(resp_a), ResponseType(resp_b)) => { let ok_type = @@ -1174,8 +1175,9 @@ impl TypeSignature { let entry_out = Self::least_supertype_v2_1(entry_a, entry_b)?; type_map_out.insert(name.clone(), entry_out); } - Ok(TupleTypeSignature::try_from(type_map_out).map(|x| x.into()) - .expect("ERR: least_supertype_v2_1 attempted to construct a too-large supertype of two types")) + Ok(TupleTypeSignature::try_from(type_map_out) + .map(|x| x.into()) + .map_err(|_| CheckErrors::SupertypeTooLarge)?) } ( SequenceType(SequenceSubtype::ListType(ListTypeData { @@ -1196,7 +1198,7 @@ impl TypeSignature { }; let max_len = cmp::max(len_a, len_b); Ok(Self::list_of(entry_type, *max_len) - .expect("ERR: least_supertype_v2_1 attempted to construct a too-large supertype of two types")) + .map_err(|_| CheckErrors::SupertypeTooLarge)?) } (ResponseType(resp_a), ResponseType(resp_b)) => { let ok_type = diff --git a/src/chainstate/stacks/db/transactions.rs b/src/chainstate/stacks/db/transactions.rs index e4461722d8..596ff4f035 100644 --- a/src/chainstate/stacks/db/transactions.rs +++ b/src/chainstate/stacks/db/transactions.rs @@ -329,6 +329,9 @@ pub fn handle_clarity_runtime_error(error: clarity_error) -> ClarityRuntimeTxErr err_type: "short return/panic", } } + clarity_error::Interpreter(InterpreterError::Unchecked(CheckErrors::SupertypeTooLarge)) => { + ClarityRuntimeTxError::Rejectable(error) + } clarity_error::Interpreter(InterpreterError::Unchecked(check_error)) => { ClarityRuntimeTxError::AnalysisError(check_error) } @@ -1115,6 +1118,12 @@ impl StacksChainState { } } } + if let clarity_error::Analysis(err) = &other_error { + if let CheckErrors::SupertypeTooLarge = err.err { + info!("Transaction {} is problematic and should have prevented this block from being relayed", tx.txid()); + return Err(Error::ClarityError(other_error)); + } + } // this analysis isn't free -- convert to runtime error let mut analysis_cost = clarity_tx.cost_so_far(); analysis_cost