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

schnorrsig API overhaul #844

Merged
merged 9 commits into from Jul 3, 2021

Conversation

jonasnick
Copy link
Contributor

@jonasnick jonasnick commented Nov 2, 2020

This is a work in progress because I wanted to put this up for discussion before writing tests. It addresses the TODOs that didn't make it in the schnorrsig PR and changes the APIs of schnorrsig_sign, schnorrsig_verify and hardened_nonce_function.

  • Ideally, the new aux_rand32 argument for sign would be const, but didn't find a solution I was happy with.
  • Support for variable length message signing and verification supports the suggested BIP amendment for such messages.
  • sign_custom with its opaque config object allows adding more arguments later without having to change the API again. Perhaps there are other sensible customization options, but I'm thinking of sign-to-contract/covert-channel in particular. It would require adding the fields unsigned char *s2c_data32 and secp256k1_s2c_opening *s2c_opening to the config struct. The former is the data to commit to and the latter is written to by sign_custom. (EDIT: see below)

@jonasnick
Copy link
Contributor Author

ping :)

@sipa
Copy link
Contributor

sipa commented Dec 18, 2020

Concept ACK

@elichai
Copy link
Contributor

elichai commented Dec 19, 2020

Can we use an opaque "array" struct for the config instead of using malloc? this will still allow us to extend the struct while also supporting platforms without heap allocation

@jonasnick
Copy link
Contributor Author

@elichai Yeah good point, I agree that we should avoid dynamic memory allocation... and was hoping for suggestions :)

The opaque array struct wouldn't be fully backwards compatible because it only works if the caller is linked to the correct version of libsecp. In my limited understanding, I can count three reasonable options if we want to avoid malloc and be binary backwards compatible:

  1. Use a versioned struct as in the Linux kernel. I implemented this variant in a branch but I don't know enough of the implications, i.e. how well this works with ffi.
  2. Make space for future additions in the object by making the opaque byte array extra large or adding dummy members if we'd use a public struct instead.
  3. Allocate it on the scratch space and work on optionally providing stack space to the scratch space (instead of having it malloc). That's not exactly backwards compatible either because the provided scratch space may become to small.

In case 1 and 2 we should document that the struct size may change between versions such that no one relies on this (otherwise it seems like this would become super complex)

Copy link
Contributor

@real-or-random real-or-random left a comment

Choose a reason for hiding this comment

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

Am I right that the user can still create config objects simply on the stack? This should be the case, we shouldn't force the user to have malloc.

But if the answer to this question is yes, then I think we could get rid of the create/destroy functions entirely. Config objects will be small, it's fine and natural to use the stack. And if the user really wants dynamic memory, she can call still call malloc.

Or do we think the size of the config object isn't statically given? This is true for example for the context object. Here, the size depends on the flags. (Although you could argue that there are only four types of contexts with known static sizes...) But here I don't think this will be case for config objects.

src/modules/schnorrsig/main_impl.h Outdated Show resolved Hide resolved
include/secp256k1_schnorrsig.h Outdated Show resolved Hide resolved
@real-or-random
Copy link
Contributor

Ah sorry, I haven't seen your previous comment @jonasnick.

I think what I have in mind is similar to 1. but even simpler.

As long as we keep this an opaque object with manipulation functions provided by us, and we give the caller a way to figure out it's size (e.g. for FFI/dynamic alloc), versioning should not be necessary. Am I right?

@apoelstra
Copy link
Contributor

@real-or-random the problem is that the "manipulation functions provided by us" need to use malloc.

@jonasnick
Copy link
Contributor Author

I implemented & pushed option 1, the versioned struct, after playing with it here. The only downside is that if we add fields, we have to make sure that the new struct is in fact larger than the old one - on all supported compilers and platforms. We already make an assumption on the biggest alignment, so that should help figuring out when to add dummy fields.

I also mentioned above that there would be issues with FFI, but there are actually none. The concern in the issue I linked to was essentially that a struct could change out from under the bindings, but that's exactly what versioned structs prevent.

I'll add the missing tests and documentation.

As long as we keep this an opaque object

@real-or-random callers can't put an opaque object on the stack because they can't statically determine its size.

@jonasnick
Copy link
Contributor Author

jonasnick commented Jan 22, 2021

I pushed a new version of this PR with two major changes:

  1. The versioned struct for extra sign_custom parameters is removed. Versioned structs are useful for forward compatibility (i.e. application expecting newer library actually calls older library), but it's not clear what to do in case we add sign to contract members to the struct, but the library doesn't understand S2C yet. We can abort, but that's not really forward compatibility. Instead it's a simple struct now with a magic value which can be used to achieve backward compatibility. If we decide to change the struct, we also change the magic which then acts as a version number and allows libsecp to distinguish between different structs.
  2. The schnorrsig_sign function only accepts 32-byte messages again. Also, I added the public secp256k1_tagged_sha256 function to create tagged hashes according to BIP-340. The schnorrsig_sign doc explains that for messages that are not 32 bytes, one should use secp256k1_tagged_sha256 with a domain seperator. schnorrsig_sign_custom still allows truly signing variable length messages. As such, with libsecp both methods for variable length messages can be used, but one is clearly recommended to not confuse users and that's the one that currently has the most adoption (Taproot, DLCs, Lightning offers). And the additional tag argument to secp256k1_tagged_sha256 makes it harder to miss domain separation.

I also added tests and docs. Since this PR doesn't contradict the discussed BIP-340 changes, I removed the WIP status.

@jonasnick jonasnick changed the title WIP: schnorrsig API overhaul schnorrsig API overhaul Jan 22, 2021
jesseposner added a commit to jesseposner/secp256k1-zkp that referenced this pull request Feb 24, 2021
This commit is based on code changes proposed in
bitcoin-core/secp256k1#844.

Responds to comment:
BlockstreamResearch#117 (comment)
jesseposner added a commit to jesseposner/secp256k1-zkp that referenced this pull request Feb 25, 2021
This commit is based on code changes proposed in
bitcoin-core/secp256k1#844.

Responds to comment:
BlockstreamResearch#117 (comment)
@jonasnick
Copy link
Contributor Author

Rebased on top of master because cirrus wasn't included in this branch.

Copy link
Contributor

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ack 6450368

@sipa
Copy link
Contributor

sipa commented Mar 17, 2021

API looks good, code review ACK. Feel like squashing in the fixup?

@jonasnick
Copy link
Contributor Author

Done.

@jonasnick
Copy link
Contributor Author

rebased

@jonasnick
Copy link
Contributor Author

The new leak sanitizer in CI detected a missing context_destroy in the tagged_sha256_tests. Fixed & squashed.

Copy link
Contributor

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ack 439ed2f

Glad we came to a "resolution" on the forward-compat issue.

Copy link

@ariard ariard left a comment

Choose a reason for hiding this comment

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

Mostly nits, SGTM

include/secp256k1_schnorrsig.h Show resolved Hide resolved
include/secp256k1_schnorrsig.h Show resolved Hide resolved
include/secp256k1.h Show resolved Hide resolved
include/secp256k1_schnorrsig.h Outdated Show resolved Hide resolved
include/secp256k1_schnorrsig.h Outdated Show resolved Hide resolved
@ariard
Copy link

ariard commented Jun 24, 2021

utACK 66ff2fa

Thanks for taking the nits.

@apoelstra
Copy link
Contributor

utACK the fixup commit

@jonasnick
Copy link
Contributor Author

squashed the comment fixup commit

This makes the default sign function easier to use while allowing more granular
control through sign_custom.

Tests for sign_custom follow in a later commit.
Gives users the ability to hash messages to 32 byte before they are signed while
allowing efficient domain separation through the tag.
Varlen message support for the default sign function comes from recommending
tagged_sha256. sign_custom on the other hand gets the ability to directly sign
message of any length. This also implies signing and verification support for
the empty message (NULL) with msglen 0.

Tests for variable lengths follow in a later commit.
This simplifies the interface of sign_custom and allows adding more parameters
later in a backward compatible way.
@real-or-random real-or-random self-requested a review June 28, 2021 07:53
Copy link
Contributor

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ack 5f6ceaf

@ariard
Copy link

ariard commented Jun 30, 2021

utACK 5f6ceaf

Copy link

@LLFourn LLFourn left a comment

Choose a reason for hiding this comment

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

utACK 5f6ceaf

@real-or-random real-or-random merged commit 0440945 into bitcoin-core:master Jul 3, 2021
fanquake added a commit to bitcoin-core/gui that referenced this pull request Aug 3, 2021
…stream

c020cba Squashed 'src/secp256k1/' changes from efad3506a8..be8d9c262f (Pieter Wuille)

Pull request description:

  This updates our src/secp256k1 subtree to the lastest upstream master. Notable changes:
  * New schnorrsig API (bitcoin-core/secp256k1#844), which adds support for variable-length messages (not used in BIP341/342 transaction signing, so not relevant for us, but it changes the API, and makes some other simplifications). Some of our call sites had to be adapted.
  * Don't use asm optimizations for `gen_context` (bitcoin-core/secp256k1#965). This fixes #22441.
  * Various testing/CI improvements

ACKs for top commit:
  hebasto:
    ACK e4ffb44
  jonatack:
    Light ACK e4ffb44 debug built (debian clang 13.0), ran bitcoind node/tests/git-subtree-check.sh, lightly reviewed the diff and API changes
  fanquake:
    ACK e4ffb44

Tree-SHA512: 89a5c3019ec010d578e84bcef756d2c679420c5c768bcdece673405c4e10955179c5a1339aafc68b8b74b1e3912e147bf2f392f44f15af73791d93f6537960b3
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Aug 4, 2021
c020cba Squashed 'src/secp256k1/' changes from efad350..be8d9c2 (Pieter Wuille)

Pull request description:

  This updates our src/secp256k1 subtree to the lastest upstream master. Notable changes:
  * New schnorrsig API (bitcoin-core/secp256k1#844), which adds support for variable-length messages (not used in BIP341/342 transaction signing, so not relevant for us, but it changes the API, and makes some other simplifications). Some of our call sites had to be adapted.
  * Don't use asm optimizations for `gen_context` (bitcoin-core/secp256k1#965). This fixes bitcoin#22441.
  * Various testing/CI improvements

ACKs for top commit:
  hebasto:
    ACK e4ffb44
  jonatack:
    Light ACK e4ffb44 debug built (debian clang 13.0), ran bitcoind node/tests/git-subtree-check.sh, lightly reviewed the diff and API changes
  fanquake:
    ACK e4ffb44

Tree-SHA512: 89a5c3019ec010d578e84bcef756d2c679420c5c768bcdece673405c4e10955179c5a1339aafc68b8b74b1e3912e147bf2f392f44f15af73791d93f6537960b3
UdjinM6 pushed a commit to UdjinM6/dash that referenced this pull request Aug 10, 2021
…stream

c020cba Squashed 'src/secp256k1/' changes from efad350..be8d9c2 (Pieter Wuille)

Pull request description:

  This updates our src/secp256k1 subtree to the lastest upstream master. Notable changes:
  * New schnorrsig API (bitcoin-core/secp256k1#844), which adds support for variable-length messages (not used in BIP341/342 transaction signing, so not relevant for us, but it changes the API, and makes some other simplifications). Some of our call sites had to be adapted.
  * Don't use asm optimizations for `gen_context` (bitcoin-core/secp256k1#965). This fixes bitcoin#22441.
  * Various testing/CI improvements

ACKs for top commit:
  hebasto:
    ACK e4ffb44
  jonatack:
    Light ACK e4ffb44 debug built (debian clang 13.0), ran bitcoind node/tests/git-subtree-check.sh, lightly reviewed the diff and API changes
  fanquake:
    ACK e4ffb44

Tree-SHA512: 89a5c3019ec010d578e84bcef756d2c679420c5c768bcdece673405c4e10955179c5a1339aafc68b8b74b1e3912e147bf2f392f44f15af73791d93f6537960b3
5tefan pushed a commit to 5tefan/dash that referenced this pull request Aug 12, 2021
…stream

c020cba Squashed 'src/secp256k1/' changes from efad350..be8d9c2 (Pieter Wuille)

Pull request description:

  This updates our src/secp256k1 subtree to the lastest upstream master. Notable changes:
  * New schnorrsig API (bitcoin-core/secp256k1#844), which adds support for variable-length messages (not used in BIP341/342 transaction signing, so not relevant for us, but it changes the API, and makes some other simplifications). Some of our call sites had to be adapted.
  * Don't use asm optimizations for `gen_context` (bitcoin-core/secp256k1#965). This fixes bitcoin#22441.
  * Various testing/CI improvements

ACKs for top commit:
  hebasto:
    ACK e4ffb44
  jonatack:
    Light ACK e4ffb44 debug built (debian clang 13.0), ran bitcoind node/tests/git-subtree-check.sh, lightly reviewed the diff and API changes
  fanquake:
    ACK e4ffb44

Tree-SHA512: 89a5c3019ec010d578e84bcef756d2c679420c5c768bcdece673405c4e10955179c5a1339aafc68b8b74b1e3912e147bf2f392f44f15af73791d93f6537960b3
gades pushed a commit to cosanta/cosanta-core that referenced this pull request Nov 5, 2023
…stream

c020cba Squashed 'src/secp256k1/' changes from efad350..be8d9c2 (Pieter Wuille)

Pull request description:

  This updates our src/secp256k1 subtree to the lastest upstream master. Notable changes:
  * New schnorrsig API (bitcoin-core/secp256k1#844), which adds support for variable-length messages (not used in BIP341/342 transaction signing, so not relevant for us, but it changes the API, and makes some other simplifications). Some of our call sites had to be adapted.
  * Don't use asm optimizations for `gen_context` (bitcoin-core/secp256k1#965). This fixes bitcoin#22441.
  * Various testing/CI improvements

ACKs for top commit:
  hebasto:
    ACK e4ffb44
  jonatack:
    Light ACK e4ffb44 debug built (debian clang 13.0), ran bitcoind node/tests/git-subtree-check.sh, lightly reviewed the diff and API changes
  fanquake:
    ACK e4ffb44

Tree-SHA512: 89a5c3019ec010d578e84bcef756d2c679420c5c768bcdece673405c4e10955179c5a1339aafc68b8b74b1e3912e147bf2f392f44f15af73791d93f6537960b3
gades pushed a commit to piratecash/pirate that referenced this pull request Dec 9, 2023
…stream

c020cba Squashed 'src/secp256k1/' changes from efad350..be8d9c2 (Pieter Wuille)

Pull request description:

  This updates our src/secp256k1 subtree to the lastest upstream master. Notable changes:
  * New schnorrsig API (bitcoin-core/secp256k1#844), which adds support for variable-length messages (not used in BIP341/342 transaction signing, so not relevant for us, but it changes the API, and makes some other simplifications). Some of our call sites had to be adapted.
  * Don't use asm optimizations for `gen_context` (bitcoin-core/secp256k1#965). This fixes bitcoin#22441.
  * Various testing/CI improvements

ACKs for top commit:
  hebasto:
    ACK e4ffb44
  jonatack:
    Light ACK e4ffb44 debug built (debian clang 13.0), ran bitcoind node/tests/git-subtree-check.sh, lightly reviewed the diff and API changes
  fanquake:
    ACK e4ffb44

Tree-SHA512: 89a5c3019ec010d578e84bcef756d2c679420c5c768bcdece673405c4e10955179c5a1339aafc68b8b74b1e3912e147bf2f392f44f15af73791d93f6537960b3
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.

None yet

8 participants