Skip to content

Commit

Permalink
Merge pull request #3424 from stacks-network/release/2.05.0.6.0
Browse files Browse the repository at this point in the history
Release/2.05.0.6.0
  • Loading branch information
jcnelson authored Dec 1, 2022
2 parents a0393e4 + b96ae32 commit a71871a
Show file tree
Hide file tree
Showing 47 changed files with 2,406 additions and 582 deletions.
7 changes: 6 additions & 1 deletion .cargo/config
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
[alias]
stacks-node = "run --package stacks-node --"
stacks-node = "run --package stacks-node --"

# Needed by perf to generate flamegraphs.
#[target.x86_64-unknown-linux-gnu]
#linker = "/usr/bin/clang"
#rustflags = ["-Clink-arg=-fuse-ld=lld", "-Clink-arg=-Wl,--no-rosegment"]
1 change: 1 addition & 0 deletions .github/workflows/bitcoin-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ jobs:
- tests::neon_integrations::test_problematic_blocks_are_not_relayed_or_stored
- tests::neon_integrations::test_problematic_microblocks_are_not_mined
- tests::neon_integrations::test_problematic_microblocks_are_not_relayed_or_stored
- tests::neon_integrations::bad_microblock_pubkey
steps:
- uses: actions/checkout@v2
- name: Download docker image
Expand Down
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,30 @@ 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.05.0.6.0]

### Changed

- The `/v2/neighbors` endpoint now reports a node's bootstrap peers, so other
nodes can find high-quality nodes to boot from (#3401)
- If there are two or more Stacks chain tips that are tied for the canonical
tip, the node deterministically chooses one _independent_ of the arrival order
(#3419).
- If Stacks blocks for a different fork arrive out-of-order and, in doing so,
constitute a better fork than the fork the node considers canonical, the node
will update the canonical Stacks tip pointer in the sortition DB before
processing the next sortition (#3419).

### Fixed

- The node keychain no longer maintains any internal state, but instead derives
keys based on the chain tip the miner is building off of. This prevents the
node from accidentally producing an invalid block that reuses a microblock
public key hash (#3387).
- If a node mines an invalid block for some reason, it will no longer stall
forever. Instead, it will detect that its last-mined block is not the chain
tip, and resume mining (#3406).

## [2.05.0.5.0]

### Changed
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ stacks_common = { package = "stacks-common", features = ["default", "testing"],

[features]
default = ["developer-mode"]
profile-sqlite = []
disable-costs = []
developer-mode = []
monitoring_prom = ["prometheus"]
slog_json = ["slog-json", "stacks_common/slog_json", "clarity/slog_json"]
Expand Down
4 changes: 3 additions & 1 deletion clarity/src/vm/analysis/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ pub enum CheckErrors {
UncheckedIntermediaryResponses,

CouldNotDetermineMatchTypes,
CouldNotDetermineType,

// Checker runtime failures
TypeAlreadyAnnotatedFailure,
Expand Down Expand Up @@ -342,6 +343,7 @@ impl DiagnosableError for CheckErrors {
CheckErrors::CouldNotDetermineResponseOkType => format!("attempted to obtain 'ok' value from response, but 'ok' type is indeterminate"),
CheckErrors::CouldNotDetermineResponseErrType => format!("attempted to obtain 'err' value from response, but 'err' type is indeterminate"),
CheckErrors::CouldNotDetermineMatchTypes => format!("attempted to match on an (optional) or (response) type where either the some, ok, or err type is indeterminate. you may wish to use unwrap-panic or unwrap-err-panic instead."),
CheckErrors::CouldNotDetermineType => format!("type of expression cannot be determined"),
CheckErrors::BadTupleFieldName => format!("invalid tuple field name"),
CheckErrors::ExpectedTuple(type_signature) => format!("expecting tuple, found '{}'", type_signature),
CheckErrors::NoSuchTupleField(field_name, tuple_signature) => format!("cannot find field '{}' in tuple '{}'", field_name, tuple_signature),
Expand Down Expand Up @@ -409,7 +411,7 @@ impl DiagnosableError for CheckErrors {
CheckErrors::InvalidUTF8Encoding => format!("invalid UTF8 encoding"),
CheckErrors::InvalidSecp65k1Signature => format!("invalid seckp256k1 signature"),
CheckErrors::TypeAlreadyAnnotatedFailure | CheckErrors::CheckerImplementationFailure => {
format!("internal error - please file an issue on github.com/blockstack/blockstack-core")
format!("internal error - please file an issue on https://github.com/stacks-network/stacks-blockchain")
},
CheckErrors::UncheckedIntermediaryResponses => format!("intermediary responses in consecutive statements must be checked"),
CheckErrors::CostComputationFailed(s) => format!("contract cost computation failed: {}", s),
Expand Down
14 changes: 8 additions & 6 deletions clarity/src/vm/analysis/type_checker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ impl FunctionType {
check_arguments_at_least(1, args)?;
for found_type in args.iter() {
analysis_typecheck_cost(accounting, expected_type, found_type)?;
if !expected_type.admits_type(found_type) {
if !expected_type.admits_type(found_type)? {
return Err(CheckErrors::TypeError(
expected_type.clone(),
found_type.clone(),
Expand All @@ -164,7 +164,7 @@ impl FunctionType {
for (expected_type, found_type) in arg_types.iter().map(|x| &x.signature).zip(args)
{
analysis_typecheck_cost(accounting, expected_type, found_type)?;
if !expected_type.admits_type(found_type) {
if !expected_type.admits_type(found_type)? {
return Err(CheckErrors::TypeError(
expected_type.clone(),
found_type.clone(),
Expand All @@ -179,7 +179,7 @@ impl FunctionType {
let found_type = &args[0];
for expected_type in arg_types.iter() {
analysis_typecheck_cost(accounting, expected_type, found_type)?;
if expected_type.admits_type(found_type) {
if expected_type.admits_type(found_type)? {
return Ok(return_type.clone());
}
}
Expand Down Expand Up @@ -259,14 +259,16 @@ impl FunctionType {
.ok_or_else(|| CheckErrors::NoSuchContract(contract.name.to_string()))?;
let trait_definition = db
.get_defined_trait(&trait_id.contract_identifier, &trait_id.name)
.unwrap()
.map_err(|_| {
CheckErrors::NoSuchContract(trait_id.contract_identifier.to_string())
})?
.ok_or(CheckErrors::NoSuchContract(
trait_id.contract_identifier.to_string(),
))?;
contract_to_check.check_trait_compliance(trait_id, &trait_definition)?;
}
(expected_type, value) => {
if !expected_type.admits(&value) {
if !expected_type.admits(&value)? {
let actual_type = TypeSignature::type_of(&value);
return Err(
CheckErrors::TypeError(expected_type.clone(), actual_type).into()
Expand Down Expand Up @@ -438,7 +440,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> {
let actual_type = self.type_check(expr, context)?;
analysis_typecheck_cost(self, expected_type, &actual_type)?;

if !expected_type.admits_type(&actual_type) {
if !expected_type.admits_type(&actual_type)? {
let mut err: CheckError =
CheckErrors::TypeError(expected_type.clone(), actual_type).into();
err.set_expression(expr);
Expand Down
8 changes: 4 additions & 4 deletions clarity/src/vm/analysis/type_checker/natives/maps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub fn check_special_fetch_entry(

let option_type = TypeSignature::new_option(value_type.clone())?;

if !expected_key_type.admits_type(&key_type) {
if !expected_key_type.admits_type(&key_type)? {
return Err(CheckError::new(CheckErrors::TypeError(
expected_key_type.clone(),
key_type,
Expand Down Expand Up @@ -91,7 +91,7 @@ pub fn check_special_delete_entry(
)?;
analysis_typecheck_cost(&mut checker.cost_track, expected_key_type, &key_type)?;

if !expected_key_type.admits_type(&key_type) {
if !expected_key_type.admits_type(&key_type)? {
return Err(CheckError::new(CheckErrors::TypeError(
expected_key_type.clone(),
key_type,
Expand Down Expand Up @@ -132,12 +132,12 @@ fn check_set_or_insert_entry(
analysis_typecheck_cost(&mut checker.cost_track, expected_key_type, &key_type)?;
analysis_typecheck_cost(&mut checker.cost_track, expected_value_type, &value_type)?;

if !expected_key_type.admits_type(&key_type) {
if !expected_key_type.admits_type(&key_type)? {
return Err(CheckError::new(CheckErrors::TypeError(
expected_key_type.clone(),
key_type,
)));
} else if !expected_value_type.admits_type(&value_type) {
} else if !expected_value_type.admits_type(&value_type)? {
return Err(CheckError::new(CheckErrors::TypeError(
expected_value_type.clone(),
value_type,
Expand Down
2 changes: 1 addition & 1 deletion clarity/src/vm/analysis/type_checker/natives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ fn check_special_set_var(
)?;
analysis_typecheck_cost(&mut checker.cost_track, &value_type, &expected_value_type)?;

if !expected_value_type.admits_type(&value_type) {
if !expected_value_type.admits_type(&value_type)? {
return Err(CheckError::new(CheckErrors::TypeError(
expected_value_type.clone(),
value_type,
Expand Down
6 changes: 3 additions & 3 deletions clarity/src/vm/analysis/type_checker/natives/sequences.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,16 +302,16 @@ pub fn check_special_as_max_len(
)))
}
TypeSignature::SequenceType(BufferType(_)) => Ok(TypeSignature::OptionalType(Box::new(
TypeSignature::SequenceType(BufferType(BufferLength::try_from(expected_len).unwrap())),
TypeSignature::SequenceType(BufferType(BufferLength::try_from(expected_len)?)),
))),
TypeSignature::SequenceType(StringType(ASCII(_))) => Ok(TypeSignature::OptionalType(
Box::new(TypeSignature::SequenceType(StringType(ASCII(
BufferLength::try_from(expected_len).unwrap(),
BufferLength::try_from(expected_len)?,
)))),
)),
TypeSignature::SequenceType(StringType(UTF8(_))) => Ok(TypeSignature::OptionalType(
Box::new(TypeSignature::SequenceType(StringType(UTF8(
StringUTF8Length::try_from(expected_len).unwrap(),
StringUTF8Length::try_from(expected_len)?,
)))),
)),
_ => Err(CheckErrors::ExpectedSequence(sequence).into()),
Expand Down
20 changes: 20 additions & 0 deletions clarity/src/vm/analysis/type_checker/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,9 @@ fn test_index_of() {
"(index-of 0xfedb \"a\")",
"(index-of u\"a\" \"a\")",
"(index-of \"a\" u\"a\")",
"(index-of (list) none)", // cannot determine type of list element
"(index-of (list) (ok u1))", // cannot determine complete type of list element
"(index-of (list) (err none))", // cannot determine complete type of list element
];

let bad_expected = [
Expand All @@ -671,6 +674,9 @@ fn test_index_of() {
TypeSignature::min_string_ascii(),
TypeSignature::min_string_utf8(),
),
CheckErrors::CouldNotDetermineType,
CheckErrors::CouldNotDetermineType,
CheckErrors::CouldNotDetermineType,
];

for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) {
Expand Down Expand Up @@ -962,6 +968,20 @@ fn test_native_as_max_len() {
&format!("{}", type_check_helper(&good_test).unwrap())
);
}

let bad = [
"(as-max-len? \"\" u1048577)",
"(as-max-len? u\"\" u1048577)",
"(as-max-len? 0x01 u1048577)",
];
let bad_expected = [
CheckErrors::ValueTooLarge,
CheckErrors::ValueTooLarge,
CheckErrors::ValueTooLarge,
];
for (bad_test, expected) in bad.iter().zip(bad_expected.iter()) {
assert_eq!(expected, &type_check_helper(&bad_test).unwrap_err().err);
}
}

#[test]
Expand Down
4 changes: 2 additions & 2 deletions clarity/src/vm/analysis/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,15 +196,15 @@ impl ContractAnalysis {
(Some(FunctionType::Fixed(func)), None)
| (None, Some(FunctionType::Fixed(func))) => {
let args_sig = func.args.iter().map(|a| a.signature.clone()).collect();
if !expected_sig.check_args_trait_compliance(args_sig) {
if !expected_sig.check_args_trait_compliance(args_sig)? {
return Err(CheckErrors::BadTraitImplementation(
trait_name,
func_name.to_string(),
)
.into());
}

if !expected_sig.returns.admits_type(&func.returns) {
if !expected_sig.returns.admits_type(&func.returns)? {
return Err(CheckErrors::BadTraitImplementation(
trait_name,
func_name.to_string(),
Expand Down
4 changes: 2 additions & 2 deletions clarity/src/vm/callables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ impl DefinedFunction {
);
}
_ => {
if !type_sig.admits(value) {
if !type_sig.admits(value)? {
return Err(
CheckErrors::TypeValueError(type_sig.clone(), value.clone()).into()
);
Expand Down Expand Up @@ -225,7 +225,7 @@ impl DefinedFunction {
))?;

let args = self.arg_types.iter().map(|a| a.clone()).collect();
if !expected_sig.check_args_trait_compliance(args) {
if !expected_sig.check_args_trait_compliance(args)? {
return Err(
CheckErrors::BadTraitImplementation(trait_name, self.name.to_string()).into(),
);
Expand Down
4 changes: 4 additions & 0 deletions clarity/src/vm/costs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -865,6 +865,10 @@ fn compute_cost(

fn add_cost(s: &mut TrackerData, cost: ExecutionCost) -> std::result::Result<(), CostErrors> {
s.total.add(&cost)?;
if cfg!(feature = "disable-costs") {
// Disable check for exceeding the cost limit to allow mining large blocks for profiling purposes.
return Ok(());
}
if s.total.exceeds(&s.limit) {
Err(CostErrors::CostBalanceExceeded(
s.total.clone(),
Expand Down
18 changes: 9 additions & 9 deletions clarity/src/vm/database/clarity_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,7 @@ impl<'a> ClarityDatabase<'a> {
value: Value,
variable_descriptor: &DataVariableMetadata,
) -> Result<ValueResult> {
if !variable_descriptor.value_type.admits(&value) {
if !variable_descriptor.value_type.admits(&value)? {
return Err(
CheckErrors::TypeValueError(variable_descriptor.value_type.clone(), value).into(),
);
Expand Down Expand Up @@ -971,7 +971,7 @@ impl<'a> ClarityDatabase<'a> {
key_value: &Value,
map_descriptor: &DataMapMetadata,
) -> Result<Value> {
if !map_descriptor.key_type.admits(key_value) {
if !map_descriptor.key_type.admits(key_value)? {
return Err(CheckErrors::TypeValueError(
map_descriptor.key_type.clone(),
(*key_value).clone(),
Expand All @@ -998,7 +998,7 @@ impl<'a> ClarityDatabase<'a> {
key_value: &Value,
map_descriptor: &DataMapMetadata,
) -> Result<ValueResult> {
if !map_descriptor.key_type.admits(key_value) {
if !map_descriptor.key_type.admits(key_value)? {
return Err(CheckErrors::TypeValueError(
map_descriptor.key_type.clone(),
(*key_value).clone(),
Expand Down Expand Up @@ -1109,12 +1109,12 @@ impl<'a> ClarityDatabase<'a> {
return_if_exists: bool,
map_descriptor: &DataMapMetadata,
) -> Result<ValueResult> {
if !map_descriptor.key_type.admits(&key_value) {
if !map_descriptor.key_type.admits(&key_value)? {
return Err(
CheckErrors::TypeValueError(map_descriptor.key_type.clone(), key_value).into(),
);
}
if !map_descriptor.value_type.admits(&value) {
if !map_descriptor.value_type.admits(&value)? {
return Err(
CheckErrors::TypeValueError(map_descriptor.value_type.clone(), value).into(),
);
Expand Down Expand Up @@ -1155,7 +1155,7 @@ impl<'a> ClarityDatabase<'a> {
key_value: &Value,
map_descriptor: &DataMapMetadata,
) -> Result<ValueResult> {
if !map_descriptor.key_type.admits(key_value) {
if !map_descriptor.key_type.admits(key_value)? {
return Err(CheckErrors::TypeValueError(
map_descriptor.key_type.clone(),
(*key_value).clone(),
Expand Down Expand Up @@ -1375,7 +1375,7 @@ impl<'a> ClarityDatabase<'a> {
asset: &Value,
key_type: &TypeSignature,
) -> Result<PrincipalData> {
if !key_type.admits(asset) {
if !key_type.admits(asset)? {
return Err(CheckErrors::TypeValueError(key_type.clone(), (*asset).clone()).into());
}

Expand Down Expand Up @@ -1417,7 +1417,7 @@ impl<'a> ClarityDatabase<'a> {
principal: &PrincipalData,
key_type: &TypeSignature,
) -> Result<()> {
if !key_type.admits(asset) {
if !key_type.admits(asset)? {
return Err(CheckErrors::TypeValueError(key_type.clone(), (*asset).clone()).into());
}

Expand All @@ -1441,7 +1441,7 @@ impl<'a> ClarityDatabase<'a> {
asset: &Value,
key_type: &TypeSignature,
) -> Result<()> {
if !key_type.admits(asset) {
if !key_type.admits(asset)? {
return Err(CheckErrors::TypeValueError(key_type.clone(), (*asset).clone()).into());
}

Expand Down
Loading

0 comments on commit a71871a

Please sign in to comment.