Skip to content

Commit

Permalink
Merge branch 'develop' into feat/sqlite-upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
ASuciuX committed Jul 8, 2024
2 parents 443fd11 + 2e2283f commit 3341a31
Show file tree
Hide file tree
Showing 17 changed files with 526 additions and 132 deletions.
41 changes: 37 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ 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).

## Unreleased

### Added
## [Unreleased]

- Added support for Clarity 3
- Keywords / variable
Expand All @@ -19,9 +17,45 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
- `get-tenure-info?` added
- `get-block-info?` removed

## [2.5.0.0.5]

### Added

- Added configuration option `connections.antientropy_retry` (#4932)

### Changed

- Set default antientropy_retry to run once per hour (#4935)

## [2.5.0.0.4]

### Added

- Adds the solo stacking scenarios to the stateful property-based testing strategy for PoX-4 (#4725)
- Add signer-key to synthetic stack-aggregation-increase event (#4728)
- Implement the assumed total commit with carry-over (ATC-C) strategy for denying opportunistic Bitcoin miners from mining Stacks at a discount (#4733)
- Adding support for stacks-block-height and tenure-height in Clarity 3 (#4745)
- Preserve PeerNetwork struct when transitioning to 3.0 (#4767)
- Implement singer monitor server error (#4773)
- Pull current stacks signer out into v1 implementation and create placeholder v0 mod (#4778)
- Create new block signature message type for v0 signer (#4787)
- Isolate the rusqlite dependency in stacks-common and clarity behind a cargo feature (#4791)
- Add next_initiative_delay config option to control how frequently the miner checks if a new burnchain block has been processed (#4795)
- Various performance improvements and cleanup

### Changed

- Downgraded log messages about transactions from warning to info (#4697)
- Fix race condition between the signer binary and the /v2/pox endpoint (#4738)
- Make node config mock_miner item hot-swappable (#4743)
- Mandates that a burnchain block header be resolved by a BurnchainHeaderReader, which will resolve a block height to at most one burnchain header (#4748)
- Optional config option to resolve DNS of bootstrap nodes (#4749)
- Limit inventory syncs with new peers (#4750)
- Update /v2/fees/transfer to report the median transaction fee estimate for a STX-transfer of 180 bytes (#4754)
- Reduce connection spamming in stackerdb (#4759)
- Remove deprecated signer cli commands (#4772)
- Extra pair of signer slots got introduced at the epoch 2.5 boundary (#4845, #4868, #4891)
- Never consider Stacks chain tips that are not on the canonical burn chain #4886 (#4893)

### Fixed

Expand All @@ -44,7 +78,6 @@ This is the first consensus-critical release for Nakamoto. Nodes which do not up

**This is a required release before Nakamoto rules are enabled in 3.0.**


### Timing of Release from 2.5 to 3.0

Activating Nakamoto will include two epochs:
Expand Down
5 changes: 5 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ Branch names should use a prefix that conveys the overall goal of the branch:
- `test/more-coverage` for branches that only add more tests
- `refactor/formatting-fix` for refactors

The branch suffix must only include ASCII lowercase and uppercase letters,
digits, underscores, periods and dashes.

The full branch name must be max 128 characters long.

### Merging PRs from Forks

PRs from forks or opened by contributors without commit access require
Expand Down
14 changes: 7 additions & 7 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ RUN apk add --no-cache musl-dev

RUN mkdir /out

RUN cd testnet/stacks-node && cargo build --features monitoring_prom,slog_json --release
RUN cargo build --features monitoring_prom,slog_json --release

RUN cp target/release/stacks-node /out

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.debian
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ COPY . .

RUN mkdir /out

RUN cd testnet/stacks-node && cargo build --features monitoring_prom,slog_json --release
RUN cargo build --features monitoring_prom,slog_json --release

RUN cp target/release/stacks-node /out

Expand Down
200 changes: 189 additions & 11 deletions clarity/src/vm/analysis/type_checker/v2_1/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use crate::vm::costs::{
analysis_typecheck_cost, cost_functions, runtime_cost, ClarityCostFunctionReference,
CostErrors, CostOverflowingMath, CostTracker, ExecutionCost, LimitedCostTracker,
};
use crate::vm::diagnostic::Diagnostic;
use crate::vm::functions::define::DefineFunctionsParsed;
use crate::vm::functions::NativeFunctions;
use crate::vm::representations::SymbolicExpressionType::{
Expand Down Expand Up @@ -151,7 +152,130 @@ impl TypeChecker<'_, '_> {

pub type TypeResult = CheckResult<TypeSignature>;

pub fn compute_typecheck_cost<T: CostTracker>(
track: &mut T,
t1: &TypeSignature,
t2: &TypeSignature,
) -> Result<ExecutionCost, CostErrors> {
let t1_size = t1.type_size().map_err(|_| CostErrors::CostOverflow)?;
let t2_size = t2.type_size().map_err(|_| CostErrors::CostOverflow)?;
track.compute_cost(
ClarityCostFunction::AnalysisTypeCheck,
&[std::cmp::max(t1_size, t2_size).into()],
)
}

pub fn check_argument_len(expected: usize, args_len: usize) -> Result<(), CheckErrors> {
if args_len != expected {
Err(CheckErrors::IncorrectArgumentCount(expected, args_len))
} else {
Ok(())
}
}

impl FunctionType {
pub fn check_args_visitor_2_1<T: CostTracker>(
&self,
accounting: &mut T,
arg_type: &TypeSignature,
arg_index: usize,
accumulated_type: Option<&TypeSignature>,
) -> (
Option<Result<ExecutionCost, CostErrors>>,
CheckResult<Option<TypeSignature>>,
) {
match self {
// variadic stops checking cost at the first error...
FunctionType::Variadic(expected_type, _) => {
let cost = Some(compute_typecheck_cost(accounting, expected_type, arg_type));
let admitted = match expected_type.admits_type(&StacksEpochId::Epoch21, arg_type) {
Ok(admitted) => admitted,
Err(e) => return (cost, Err(e.into())),
};
if !admitted {
return (
cost,
Err(CheckErrors::TypeError(expected_type.clone(), arg_type.clone()).into()),
);
}
(cost, Ok(None))
}
FunctionType::ArithmeticVariadic => {
let cost = Some(compute_typecheck_cost(
accounting,
&TypeSignature::IntType,
arg_type,
));
if arg_index == 0 {
let return_type = match arg_type {
TypeSignature::IntType => Ok(Some(TypeSignature::IntType)),
TypeSignature::UIntType => Ok(Some(TypeSignature::UIntType)),
_ => Err(CheckErrors::UnionTypeError(
vec![TypeSignature::IntType, TypeSignature::UIntType],
arg_type.clone(),
)
.into()),
};
(cost, return_type)
} else {
let return_type = accumulated_type
.ok_or_else(|| CheckErrors::Expects("Failed to set accumulated type for arg indices >= 1 in variadic arithmetic".into()).into());
let check_result = return_type.and_then(|return_type| {
if arg_type != return_type {
Err(
CheckErrors::TypeError(return_type.clone(), arg_type.clone())
.into(),
)
} else {
Ok(None)
}
});
(cost, check_result)
}
}
// For the fixed function types, the visitor will just
// tell the processor that any results greater than the args len
// do not need to be stored, because an error will occur before
// further checking anyways
FunctionType::Fixed(FixedFunction {
args: arg_types, ..
}) => {
if arg_index >= arg_types.len() {
// note: argument count will be wrong?
return (
None,
Err(CheckErrors::IncorrectArgumentCount(arg_types.len(), arg_index).into()),
);
}
return (None, Ok(None));
}
// For the following function types, the visitor will just
// tell the processor that any results greater than len 1 or 2
// do not need to be stored, because an error will occur before
// further checking anyways
FunctionType::ArithmeticUnary | FunctionType::UnionArgs(..) => {
if arg_index >= 1 {
return (
None,
Err(CheckErrors::IncorrectArgumentCount(1, arg_index).into()),
);
}
return (None, Ok(None));
}
FunctionType::ArithmeticBinary
| FunctionType::ArithmeticComparison
| FunctionType::Binary(..) => {
if arg_index >= 2 {
return (
None,
Err(CheckErrors::IncorrectArgumentCount(2, arg_index).into()),
);
}
return (None, Ok(None));
}
}
}

pub fn check_args_2_1<T: CostTracker>(
&self,
accounting: &mut T,
Expand Down Expand Up @@ -1017,17 +1141,23 @@ impl<'a, 'b> TypeChecker<'a, 'b> {
args: &[SymbolicExpression],
context: &TypingContext,
) -> TypeResult {
let mut types_returned = self.type_check_all(args, context)?;

let last_return = types_returned
.pop()
.ok_or(CheckError::new(CheckErrors::CheckerImplementationFailure))?;

for type_return in types_returned.iter() {
if type_return.is_response_type() {
return Err(CheckErrors::UncheckedIntermediaryResponses.into());
let mut last_return = None;
let mut return_failure = Ok(());
for ix in 0..args.len() {
let type_return = self.type_check(&args[ix], context)?;
if ix + 1 < args.len() {
if type_return.is_response_type() {
return_failure = Err(CheckErrors::UncheckedIntermediaryResponses);
}
} else {
last_return = Some(type_return);
}
}

let last_return = last_return
.ok_or_else(|| CheckError::new(CheckErrors::CheckerImplementationFailure))?;
return_failure?;

Ok(last_return)
}

Expand All @@ -1052,8 +1182,56 @@ impl<'a, 'b> TypeChecker<'a, 'b> {
epoch: StacksEpochId,
clarity_version: ClarityVersion,
) -> TypeResult {
let typed_args = self.type_check_all(args, context)?;
func_type.check_args(self, &typed_args, epoch, clarity_version)
if epoch <= StacksEpochId::Epoch2_05 {
let typed_args = self.type_check_all(args, context)?;
return func_type.check_args(self, &typed_args, epoch, clarity_version);
}
// use func_type visitor pattern
let mut accumulated_type = None;
let mut total_costs = vec![];
let mut check_result = Ok(());
let mut accumulated_types = Vec::new();
for (arg_ix, arg_expr) in args.iter().enumerate() {
let arg_type = self.type_check(arg_expr, context)?;
if check_result.is_ok() {
let (costs, result) = func_type.check_args_visitor_2_1(
self,
&arg_type,
arg_ix,
accumulated_type.as_ref(),
);
// add the accumulated type and total cost *before*
// checking for an error: we want the subsequent error handling
// to account for this cost
accumulated_types.push(arg_type);
total_costs.extend(costs);

match result {
Ok(Some(returned_type)) => {
accumulated_type = Some(returned_type);
}
Ok(None) => {}
Err(e) => {
check_result = Err(e);
}
};
}
}
if let Err(mut check_error) = check_result {
if let CheckErrors::IncorrectArgumentCount(expected, _actual) = check_error.err {
check_error.err = CheckErrors::IncorrectArgumentCount(expected, args.len());
check_error.diagnostic = Diagnostic::err(&check_error.err)
}
// accumulate the checking costs
// the reason we do this now (instead of within the loop) is for backwards compatibility
for cost in total_costs.into_iter() {
self.add_cost(cost?)?;
}

return Err(check_error);
}
// otherwise, just invoke the normal checking routine
func_type.check_args(self, &accumulated_types, epoch, clarity_version)
}

fn get_function_type(&self, function_name: &str) -> Option<FunctionType> {
Expand Down
Loading

0 comments on commit 3341a31

Please sign in to comment.