Skip to content

feat(auth): add ECDSA single sig and multisig authentication component#2083

Merged
bobbinth merged 11 commits into0xMiden:mainfrom
onurinanc:feat-ecdsa-auth
Nov 12, 2025
Merged

feat(auth): add ECDSA single sig and multisig authentication component#2083
bobbinth merged 11 commits into0xMiden:mainfrom
onurinanc:feat-ecdsa-auth

Conversation

@onurinanc
Copy link
Contributor

This PR implements the ECDSA Authentication Component for both single and multisig accounts.

Next Steps:

  • Implement the ECDSA Authentication Component in the rust-client withinmiden-client.
  • Implement the ECDSA Authentication Component in the web-client within miden-client.

Future Improvements:
This PR currently shares similar code patterns with the RpoFalcon512 and RpoFalcon512Multisig authentication components. A more pluggable design that unifies these authentication mechanisms into a single, configurable component will be explored.

@bobbinth
Copy link
Contributor

Thank you, @onurinanc! Once question (w/o having looked at the code): should this go into main rather than next? I think we wanted to include this into v0.12 release - and if so, it should go into main - but not sure if there are any significant breaking changes here.

@onurinanc
Copy link
Contributor Author

onurinanc commented Nov 10, 2025

@bobbinth I think there are no any breaking changes in this PR. I’ll update the base branch to main.

@onurinanc onurinanc changed the base branch from next to main November 10, 2025 16:11
Copy link
Collaborator

@mmagician mmagician left a comment

Choose a reason for hiding this comment

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

Just a superficial review on the MASM structure for now - I think we can reduce the diff significantly

Comment on lines +65 to +84
proc assert_new_tx(msg: BeWord)
push.IS_EXECUTED_FLAG
# => [[0, 0, 0, is_executed], MSG]

swapw
# => [MSG, IS_EXECUTED_FLAG]

push.EXECUTED_TXS_SLOT
# => [index, MSG, IS_EXECUTED_FLAG]

# Set the key value pair in the map to mark transaction as executed
exec.native_account::set_map_item
# => [OLD_MAP_ROOT, [0, 0, 0, is_executed]]

dropw drop drop drop
# => [is_executed]

assertz.err=ERR_TX_ALREADY_EXECUTED
# => []
end
Copy link
Collaborator

Choose a reason for hiding this comment

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

AFAICS, this is the same logic as in the falcon file?

In that case, it would be best to reduce code duplication and move this file into a common file (see e.g. https://github.com/0xMiden/miden-base/blob/b160cabba65b6af4bbc6473e12bf0692dff7c855/crates/miden-lib/asm/miden/auth/mod.masm)

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, this and other similar procedures can probably go into miden::auth::multisig module. But also, in the interest of time, I'm also fine keeping this as is for this PR and addressing de-duplication in a follow-up.

#! Where:
#! - init_num_of_approvers is the original number of approvers before the update
#! - new_num_of_approvers is the new number of approvers after the update
proc cleanup_pubkey_mapping(init_num_of_approvers: u32, new_num_of_approvers: u32)
Copy link
Collaborator

Choose a reason for hiding this comment

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

ditto

#! Locals:
#! 0: new_num_of_approvers
#! 1: init_num_of_approvers
pub proc update_signers_and_threshold.2(multisig_config_hash: BeWord)
Copy link
Collaborator

Choose a reason for hiding this comment

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

ditto

Copy link
Contributor

@bobbinth bobbinth left a comment

Choose a reason for hiding this comment

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

Looks good! Thank you! I reviewed all non-test code and left some comments inline - most of them are small nits and thoughts for the future.

exec.auth::create_tx_summary
# => [SALT, OUTPUT_NOTES_COMMITMENT, INPUT_NOTES_COMMITMENT, ACCOUNT_DELTA_COMMITMENT, PUB_KEY]

exec.auth::adv_insert_hqword
Copy link
Contributor

Choose a reason for hiding this comment

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

Not for this PR, but I believe we can now replace this with adv.insert_hqword instruction.

@Fumuran could you create an issue for this?

const.PUBLIC_KEY_SLOT=0

# Local Memory Addresses for multisig operations
const.NUM_OF_APPROVERS_LOC=0
Copy link
Contributor

Choose a reason for hiding this comment

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

Not from this PR, but I'm not seeing NUM_OF_APPROVERS_LOC. Maybe worth creating an issue to remove it. cc @partylikeits1983.

Comment on lines +65 to +84
proc assert_new_tx(msg: BeWord)
push.IS_EXECUTED_FLAG
# => [[0, 0, 0, is_executed], MSG]

swapw
# => [MSG, IS_EXECUTED_FLAG]

push.EXECUTED_TXS_SLOT
# => [index, MSG, IS_EXECUTED_FLAG]

# Set the key value pair in the map to mark transaction as executed
exec.native_account::set_map_item
# => [OLD_MAP_ROOT, [0, 0, 0, is_executed]]

dropw drop drop drop
# => [is_executed]

assertz.err=ERR_TX_ALREADY_EXECUTED
# => []
end
Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, this and other similar procedures can probably go into miden::auth::multisig module. But also, in the interest of time, I'm also fine keeping this as is for this PR and addressing de-duplication in a follow-up.

Comment on lines +31 to +42
pub proc auth_tx_ecdsa_k256_keccak(auth_args: BeWord)
dropw
# => [pad(16)]

# Fetch public key from storage.
# ---------------------------------------------------------------------------------------------
push.PUBLIC_KEY_SLOT exec.active_account::get_item
# => [PUB_KEY, pad(16)]

exec.ecdsa_k256_keccak::authenticate_transaction
# => [pad(16)]
end
Copy link
Contributor

Choose a reason for hiding this comment

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

Not for this PR, but we should start thinking about how to reduce code duplication. Ideally, instead of have two (or more) identical components that differ only in signature scheme used, we would have something like AuthBasicSinglesig and AuthBasicMultisig and the signature scheme would be defined internally.

There are at least two ways to do this:

  1. We could store the root of the signature procedure in the storage. In the case of single-sig authentication, the storage layout would be [PUB_KEY, VERIFY_PROC_ROOT]. Then, we'd just use dynexec instruction to execute the stored procedure.
  2. We could still keep just the public key in the storage and add an event to retrieve the type of the public key. Then, we could have a set of if-else statements to figure out which verification procedure to run for a given public key.

Both of these have their prons and cons:

  • The first approach is more extensible: we don't need to modify the code to add support for a new signature scheme. But, we can't easily "mix" different signature schemes (mostly relevant in the context of the multisig).
  • The second approach avoids the use of dynexec (which feels a bit risky) and it allows us to easily mix different signature schemes (e.g., in the same multisig we could have both ECDSA and Falcon public keys) - but it is not as extensible: adding a new signature scheme would require MASM code changes. It is also a bit more work as we'll need to get the public key type from the authenticator (though, we may need to do this for other reasons anyways).

There may be other approaches to reducing code duplication as well - e.g., something along the lines of #1956. But I haven't thought about this too much.

We should create an issue to discuss this and ideally come up with the improved approach for v0.13.0 release.

Copy link
Contributor

@bobbinth bobbinth left a comment

Choose a reason for hiding this comment

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

Looks good! Thank you! As mentioned in the pervious comments, I'll merge this as is, and we can work on code de-duplication in follow-up PRs and try to wrap up with work for v0.13 release.

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