Skip to content

Feat/ed25519-verify#7196

Open
rob-stacks wants to merge 6 commits into
stacks-network:pox-wf-integrationfrom
rob-stacks:feat/ed25519-verify
Open

Feat/ed25519-verify#7196
rob-stacks wants to merge 6 commits into
stacks-network:pox-wf-integrationfrom
rob-stacks:feat/ed25519-verify

Conversation

@rob-stacks
Copy link
Copy Markdown
Contributor

@rob-stacks rob-stacks commented May 11, 2026

Description

This patch adds the ed25519-verify clarity function as well as an infrastructure for ed25519 curves.

(ed25519-verify 0x68656c6c6f20776f726c64 0x7e8346b0d9ef1151608df9d436c646b9df23758b292e0df400032f2603417724a25997d81a95a8997a55252813589b9409893df1ec75249a5b6f38753232810e 0xec172b93ad5e563bf49683c1397357b1af93d4e937abda610c10ccc6112217c0)

It expects "(buff 1024), (buff 64), (buff 32)" and returns bool (if the signature is verified)

The message buffer can be between 0 and 1024 bytes.

The signature is 64 bytes.

The public key is 32 bytes.

Cost has been profiled to 7880 units and veries very little based on the size of the message (can be between 0 and 1024) so probably it could be kept as fixed and not linear as soon as the clarity6 costs table is pushed.

Applicable issues

  • fixes #

Additional info (benefits, drawbacks, caveats)

Checklist

  • Test coverage for new or modified code paths
  • For new Clarity features or consensus changes, add property tests (see docs/property-testing.md)
  • Changelog fragment(s) or "no changelog" label added (see changelog.d/README.md)
  • Required documentation changes (e.g., rpc/openapi.yaml for RPC endpoints, event-dispatcher.md for new events)
  • New clarity functions have corresponding PR in clarity-benchmarking repo

@rob-stacks rob-stacks marked this pull request as ready for review May 11, 2026 13:45
@coveralls
Copy link
Copy Markdown

coveralls commented May 11, 2026

Coverage Report for CI Build 25802863122

Warning

Build has drifted: This PR's base is out of sync with its target branch, so coverage data may include unrelated changes.
Quick fix: rebase this PR. Learn more →

Coverage decreased (-3.2%) to 82.754%

Details

  • Coverage decreased (-3.2%) from the base build.
  • Patch coverage: 61 uncovered changes across 4 files (160 of 221 lines covered, 72.4%).
  • 9829 coverage regressions across 165 files.

Uncovered Changes

File Changed Covered %
stacks-common/src/util/ed25519.rs 140 110 78.57%
clarity/src/vm/functions/crypto.rs 50 34 68.0%
clarity/src/vm/analysis/type_checker/v2_1/natives/mod.rs 12 0 0.0%
clarity/src/vm/costs/costs_4.rs 3 0 0.0%

Coverage Regressions

9829 previously-covered lines in 165 files lost coverage.

Top 10 Files by Coverage Loss Lines Losing Coverage Coverage
stackslib/src/chainstate/stacks/transaction.rs 524 85.27%
stackslib/src/config/mod.rs 385 67.36%
stackslib/src/net/chat.rs 363 85.47%
stackslib/src/chainstate/burn/db/sortdb.rs 354 85.41%
stackslib/src/chainstate/stacks/db/transactions.rs 342 93.23%
clarity/src/vm/docs/mod.rs 335 53.21%
stackslib/src/net/codec.rs 325 74.87%
stackslib/src/net/db.rs 273 86.72%
stackslib/src/chainstate/stacks/db/blocks.rs 270 86.62%
stackslib/src/chainstate/burn/operations/leader_key_register.rs 265 45.05%

Coverage Stats

Coverage Status
Relevant Lines: 217333
Covered Lines: 179851
Line Coverage: 82.75%
Coverage Strength: 16956172.2 hits per line

💛 - Coveralls

};

const ED25519VERIFY_API: SpecialAPI = SpecialAPI {
input_type: "(buff), (buff 64), (buff 32)",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
input_type: "(buff), (buff 64), (buff 32)",
input_type: "(buff 1048576), (buff 64), (buff 32)",

output_type: "bool",
signature: "(ed25519-verify message signature public-key)",
description: "The `ed25519-verify` function verifies that the provided signature of the message
was signed with the private key that generated the public key.",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please add the description of the outputs here as well.


// Verify the signature
self.key
.verify(msg, &ed25519_sig)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we should use verify_strict here, to avoid issues with signature malleability.

args: &[SymbolicExpression],
context: &TypingContext,
) -> Result<TypeSignature, StaticCheckError> {
check_argument_count(3, args)?;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same comment from #7187: If #7179 merges before this, it could use the new functions described #7179 (comment).

) -> Result<Value, VmExecutionError> {
// (ed25519-verify message signature public-key)
// message: (buff MAX_VALUE_SIZE), signature: (buff 64), public-key: (buff 32)
check_argument_count(3, args)?;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If #7179 merges before this, it could use the new functions described #7179 (comment).

// message: (buff MAX_VALUE_SIZE), signature: (buff 64), public-key: (buff 32)
check_argument_count(3, args)?;

runtime_cost(ClarityCostFunction::Ed25519verify, exec_state, 0)?;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this should pass in the message length.

/// SHA256 hashing the seed bytes until a private key is found.
///
/// If `seed` is a valid private key, it will be returned without hashing.
/// The returned private key's compress_public flag will be `true`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this is copy/pasted from secp256k1. This private key doesn't have a compress_public flag.


#[tag(t_prop)]
#[test]
fn prop_ed25519_verify_accepts_valid_signatures(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you also add proptests where the message/signature/pubkey is tampered with and verify that it is always caught? Also after changing to use the strict verification, test the non-strict cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants