Skip to content

feat: use clarity-serialization in clarity #6310

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 34 commits into
base: develop
Choose a base branch
from

Conversation

Jiloc
Copy link
Contributor

@Jiloc Jiloc commented Jul 21, 2025

Description

Points for Discussion from #6297:

  • Error handling: In clarity-serialization, I consolidated all error types into a single CodecError enum with a 1:1 match with the original errors in clarity. However, when converting back to the older error types using From<CodecError>, some variants don’t have a clear or meaningful equivalent. I’ve routed them through generic catch-all cases. Even if the current code doesn't reach those conversions, I am not happy with this mapping strategy and am open to suggestions!
  • Retro-compatibility of ClarityName and ContractName: The guarded_string! macro for these types now returns the new CodecError instead of a RuntimeErrorType.
  • Feel free to throw any other topic you think would be worth discussing!

Applicable issues

  • fixes #

Additional info (benefits, drawbacks, caveats)

Checklist

  • Test coverage for new or modified code paths
  • Changelog is updated
  • Required documentation changes (e.g., docs/rpc/openapi.yaml and rpc-endpoints.md for v2 endpoints, event-dispatcher.md for new events)
  • New clarity functions have corresponding PR in clarity-benchmarking repo
  • New integration test(s) added to bitcoin-tests.yml

@Jiloc Jiloc added this to the 3.2.0.0.0 milestone Jul 21, 2025
@Jiloc Jiloc self-assigned this Jul 21, 2025
@Jiloc Jiloc requested review from a team as code owners July 21, 2025 14:50
@Jiloc Jiloc marked this pull request as draft July 21, 2025 14:51
@Jiloc Jiloc moved this to Status: 💻 In Progress in Stacks Core Eng Jul 21, 2025
@Jiloc Jiloc modified the milestones: 3.2.0.0.0, 3.2.0.0.1 Jul 21, 2025
) -> Result<TupleTypeSignature> {
if let SymbolicExpressionType::List(ref name_type_pairs) = type_def.expr {
let mapped_key_types = parse_name_type_pairs(epoch, name_type_pairs, accounting)?;
TupleTypeSignature::try_from(mapped_key_types).map_err(CheckErrors::from)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert this error conversion

Copy link
Contributor Author

@Jiloc Jiloc Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in b0957e3

}
}
}

/// Parsing functions.
impl TypeSignature {
pub trait TypeSignatureExt {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a docstring explaining this trait.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, seeing this massive trait and the traits above it, all of which only seem to exist because SymbolicExpression isn't in clarity-serialization, I'm inclined to take back what I said earlier about keeping SymbolicExpression in clarity. Please instead move SymbolicExpression and its ilk to clarity-serialization so these traits can be removed. We'll just port the feature flags from clarity to clarity-serialization.

Copy link
Contributor Author

@Jiloc Jiloc Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a comment for now, but I am open to revisit this if you think otherwise! The main reasons I initially avoided moving this in clarity-serialization was because most of these functions require both for SymbolicExpression and CostTracker which I saw more as a runtime construct and more appropriate for clarity. CostTracker also depends on ClarityCostFunction, ExecutionCost, and CostErrors.

But with the latest changes I already needed to move ExecutionCost and CostErrors into clarity-serialization, so I’m open to also moving ClarityCostFunction and CostTracker if you think that would be cleaner. Let me know what you prefer!

@@ -236,6 +238,22 @@ impl From<ClarityError> for CliError {
}
}

impl From<ClarityCodecError> for CliError {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please drop

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 40a95ee

@@ -537,6 +537,12 @@ impl From<InterpreterError> for Error {
}
}

impl From<CodecError> for Error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please drop

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 40a95ee

Copy link
Member

@jcnelson jcnelson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your continued work on separating out Clarity serialization code from clarity. There are a few show-stopping issues that must be addressed, which are detailed in my comments, but I'll summarize below.

  • Error types in Clarity are generally consensus-critical. In particular, InterpreterError and CheckErrors are handled differently in transaction-processing -- the former marks a block as invalid, while the latter can be mined. The replacement of both of these variants and others with CodecErrors is a consensus-critical bug that must be reverted throughout.

  • There is a lot of code churn here that has arisen from the fact that SymbolicExpression is in clarity, not clarity-serialization. This has lead to the need for several traits whose only purpose is to allow types defined in clarity-serialization to continue to have their existing methods which either took SymbolicExpression-based types as arguments or returned a SymbolicExpression-based type. This code churn can and should be avoided, since all of this is consensus-critical. I think it would be better to move SymbolicExpression to clarity-serialization, even though it would mean that feature flags in clarity would need to be duplicated in clarity-serialization.

@github-project-automation github-project-automation bot moved this from Status: In Review to Status: 💻 In Progress in Stacks Core Eng Aug 4, 2025
Comment on lines +1611 to +1615
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub struct FunctionIdentifier {
identifier: String,
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed for the StackTrace type used in Error

IOError(IncomparableError<std::io::Error>),
BadTypeError(CheckErrors),
DeserializationError(String),
DeserializeExpected(Box<TypeSignature>),
Copy link
Contributor Author

@Jiloc Jiloc Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

originally, this was DeserializeExpected(TypeSignature) does this change cause any problems?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine, because AFAIK we never match on whether or not a substructure is a Box<T> anywhere in the codebase (that would be very weird).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain the reason for the change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same reason as for #6310 (comment). But if you prefer I could move even this change to the separate PR

@@ -12,11 +12,12 @@ readme = "README.md"
[dependencies]
lazy_static = { workspace = true }
regex = { version = "1", default-features = false }
rusqlite = { workspace = true, optional = true }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needed for implementing ToSql and FromSql for ExecutionCost, and defining InterpreterError::SqliteError(IncomparableError<SqliteError>)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this might need some thought. I thought clarity-serialization was supposed to be able to run in WASM? If so, then rusqlite can't be a required dependency IIRC.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't be a problem in this case, rustqlite will only be included if built with the rusqlite feature. If building this with

cargo build -p clarity-serialization --features "wasm-web" (for js support)
cargo build -p clarity-serialization --features "wasm-deterministic" (for deterministic environment like CosmWasm)

it will still work!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the structs remaining in this file (e.g. FunctionSignature, FixedFunction, etc.) and their implementations, were not originally needed in clarity-serialization, but since we are going to rename this into clarity-types I was thinking of moving them all. Any opinions?

}
}
}

/// Parsing functions.
impl TypeSignature {
pub trait TypeSignatureExt {
Copy link
Contributor Author

@Jiloc Jiloc Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a comment for now, but I am open to revisit this if you think otherwise! The main reasons I initially avoided moving this in clarity-serialization was because most of these functions require both for SymbolicExpression and CostTracker which I saw more as a runtime construct and more appropriate for clarity. CostTracker also depends on ClarityCostFunction, ExecutionCost, and CostErrors.

But with the latest changes I already needed to move ExecutionCost and CostErrors into clarity-serialization, so I’m open to also moving ClarityCostFunction and CostTracker if you think that would be cleaner. Let me know what you prefer!

@Jiloc Jiloc moved this from Status: 💻 In Progress to Status: In Review in Stacks Core Eng Aug 6, 2025
@Jiloc Jiloc requested review from jcnelson and fdefelici August 6, 2025 19:03
pub type CheckResult<T> = Result<T, CheckError>;

#[derive(Debug, PartialEq)]
pub enum CheckErrors {
Copy link
Contributor Author

@Jiloc Jiloc Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would it be consensus breaking if we modify CheckErrors to Box all TypeSignature and Value in order to remove #![allow(clippy::result_large_err)]?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that should be fine, because we don't ever check a type's substructure to see if it contains a Box<T>.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given it will be require a big amount of line changes, I'll just do it in a separate PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for completeness, here is the PR that boxes the data in some errors and fixes all the clippy::result_large_err warnings. No need to review it now of course :)

@Jiloc Jiloc requested a review from a team as a code owner August 7, 2025 21:20
@Jiloc Jiloc mentioned this pull request Aug 7, 2025
5 tasks
Copy link
Member

@moodmosaic moodmosaic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've opened a PR as a follow-up to expand input coverage further, in line with #6355.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Status: In Review
Development

Successfully merging this pull request may close these issues.

Refactor clarity to enable lightweight serialization crate
4 participants