Skip to content
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

Optimize ecrecover ASM #840

Merged
merged 48 commits into from
Jan 31, 2023
Merged

Optimize ecrecover ASM #840

merged 48 commits into from
Jan 31, 2023

Conversation

wborgeaud
Copy link
Contributor

Optimize ECDSA verification assembly by using GLV + wNAF + MSM.
An average ETH (valid) tx signature takes 37678 cycles to verify (currently 90089).

@wborgeaud wborgeaud requested a review from unzvfu December 9, 2022 10:42
Copy link
Contributor

@unzvfu unzvfu left a comment

Choose a reason for hiding this comment

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

Nice work! Good to go, modulo a few minor things.

Some notes on things that aren't part of the pull request:

  • nit: You can remove most of the SWAPs in ecrecover by changing the order of DUPs and PUSHs; something like %ecrecover_input_check; PUSH 27; SWAP3; SUB; DUP4; %secp_liftx should suffice.
  • ecrecover_input_check verifies that both r and s are less than secp256k1n. This is what appears in, for example, some documents, however the Yellow paper says that s should be less than secp256k1n / 2 + 1. I suggest we work out which one it is and document the choice in the code.
  • Line 60 of ecrecover.asm, looks like it should be SWAP6 not SWAP5?!
  • Comment on line 18 of curve_add.asm should say 'second' instead of 'first' (but note review comments about how those checks might not be necessary)

evm/src/cpu/kernel/asm/curve/secp256k1/curve_add.asm Outdated Show resolved Hide resolved
evm/src/cpu/kernel/asm/curve/secp256k1/precomputation.asm Outdated Show resolved Hide resolved
evm/src/memory/segments.rs Outdated Show resolved Hide resolved
evm/src/memory/segments.rs Outdated Show resolved Hide resolved
evm/src/memory/segments.rs Outdated Show resolved Hide resolved
evm/src/memory/segments.rs Outdated Show resolved Hide resolved
Copy link
Contributor Author

@wborgeaud wborgeaud left a comment

Choose a reason for hiding this comment

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

  • nit: You can remove most of the SWAPs in ecrecover by changing the order of DUPs and PUSHs; something like %ecrecover_input_check; PUSH 27; SWAP3; SUB; DUP4; %secp_liftx should suffice.

Good catch. This code predates the introduction of %stack, so I've just changed it to use it.

  • ecrecover_input_check verifies that both r and s are less than secp256k1n. This is what appears in, for example, some documents, however the Yellow paper says that s should be less than secp256k1n / 2 + 1. I suggest we work out which one it is and document the choice in the code.

So the s < secp256k1n / 2 + 1 is for signature verification on the network. For ecrecover, the condition is indeed s < secp256k1n (see equation (210) in the Yellow Paper). Don't ask me why they are different...

  • Line 60 of ecrecover.asm, looks like it should be SWAP6 not SWAP5?!

Hm why? SWAPi swaps the 1st and i+1th element of the stack. Here we want to swap the 1st and 6th (s) element of the stack.

// stack: r^(-1), r^(-1), y, hash, x, s, retdest
SWAP5
// stack: s, r^(-1), y, hash, x, r^(-1), retdest
  • Comment on line 18 of curve_add.asm should say 'second' instead of 'first' (but note review comments about how those checks might not be necessary)

👍

@unzvfu
Copy link
Contributor

unzvfu commented Jan 31, 2023

  • Line 60 of ecrecover.asm, looks like it should be SWAP6 not SWAP5?!

Hm why? SWAPi swaps the 1st and i+1th element of the stack. Here we want to swap the 1st and 6th (s) element of the stack.

Oops, you're right, ignore that comment.

@wborgeaud wborgeaud merged commit ca002ae into main Jan 31, 2023
@wborgeaud wborgeaud deleted the evm_secp_glv branch January 31, 2023 18:23
Nashtare pushed a commit to topos-protocol/plonky2 that referenced this pull request Feb 2, 2023
* windowed mul

* Working

* Window of 4 bits

* Fix

* Comments

* Unroll loop

* Unroll loop

* remove global

* Minor

* Minor

* Implement `CALLVALUE, CALLDATALOAD, CALLDATASIZE, CALLDATACOPY` in interpreter

* Minor

* Doesn't work

* Minor

* Minor

* wnaf msm

* Working hardcoded values: 28657 opcodes

* Working wnaf

* Small wnaf optim

* Precompute works

* Working together

* Bump to 129 bits

* Working glv decomposition

* Working MSM with GLV

* Almost working

* Working

* ECC test folder

* Working with real sig data

* Fix tests + Clippy

* Minor

* Cleaning

* Comments

* Cleaning

* Smaller glv test file

* Print opcode count at the end of interpreter run

* More constants

* Add z3 proof that the GLV scalars are 129-bit or less

* Minor change to z3 proof

* Minor

* Hamish's suggestion

* Working

* Cleaning

* Clippy

* PR feedback

* Minor PR feedback
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.

2 participants