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

Conditionally include stdio.h and stdlib.h #1148

Closed
wants to merge 2 commits into from

Conversation

tcharding
Copy link
Contributor

@tcharding tcharding commented Nov 2, 2022

Currently in order to use secp256k1 in WASM builds one must patch into the build system empty header files for stdlib.h and stdio.h [0].

  • Patch 1: Removes the unconditional include of stdio.h based on the presence of USE_EXTERNAL_DEFAULT_CALLBACKS and VERIFY.
  • Patch 2: Introduces PREALLOC_INTERFACE_ONLY and ifndef guards any calls to malloc and friends as well as the include of stdio.h.

Works towards fixing: #1095

1095 does not mention string.h but it is a problem as well. I cannot work out how to resolve it so attempting to push this in without it. Happy to extend this further if anyone has any ideas.

Notes on testing

I could not work out how to test this in rust-secp256k1 so the I have not proved that this PR removes the requirement to include empty headers described above.

[0] - https://github.com/rust-bitcoin/rust-secp256k1/blob/master/secp256k1-sys/depend/secp256k1.c.patch

@tcharding tcharding changed the title Conditionally depend on stdio.h Conditionally depend on stdio.h Nov 2, 2022
@real-or-random
Copy link
Contributor

real-or-random commented Nov 3, 2022

Fix: #1095

Can you remove the magic word fix? I think this PR solves #1095 only partly (stdlib.h).

src/util.h Outdated Show resolved Hide resolved
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.

Concept ACK, thanks!

This is a good opportunity to move the definitions of CHECK and TEST_FAILURE (but probably not EXPECT to tests.c, if you're willing to add a commit. Otherwise we can do it in a follow-up PR.

@tcharding
Copy link
Contributor Author

tcharding commented Nov 3, 2022

Fix: #1095

Can you remove the magic word fix? I think this PR solves #1095 only partly (stdlib.h).

bah, sloppy work by me. I'll try first to fix the stdlib.h issue in this PR as well. Not sure off the top of my head about string.h (referring to rust-secp256k1/ now) because we have a bunch of function declarations in there as well. Will investigate further, sorry for doing half a job.

@tcharding
Copy link
Contributor Author

Concept ACK, thanks!

This is a good opportunity to move the definitions of CHECK and TEST_FAILURE (but probably not EXPECT to tests.c, if you're willing to add a commit. Otherwise we can do it in a follow-up PR.

Sure thing, happy to look into it.

@tcharding tcharding marked this pull request as draft November 4, 2022 02:14
@tcharding
Copy link
Contributor Author

tcharding commented Nov 4, 2022

Concept ACK, thanks!

This is a good opportunity to move the definitions of CHECK and TEST_FAILURE (but probably not EXPECT to tests.c, if you're willing to add a commit. Otherwise we can do it in a follow-up PR.

EDIT: I realised after posting that all these files are either tests of benches, so I did #1149

I must be missing something, CHECK is used in a whole bunch of files, how can we move the definition to tests.c? Is there another header file that it could go in, is that what you meant?

git grep -l ' CHECK\('
src/bench.c
src/bench_ecmult.c
src/bench_internal.c
src/ecmult_impl.h
src/modules/ecdh/bench_impl.h
src/modules/ecdh/tests_impl.h
src/modules/extrakeys/tests_exhaustive_impl.h
src/modules/extrakeys/tests_impl.h
src/modules/recovery/bench_impl.h
src/modules/recovery/tests_exhaustive_impl.h
src/modules/recovery/tests_impl.h
src/modules/schnorrsig/bench_impl.h
src/modules/schnorrsig/tests_exhaustive_impl.h
src/modules/schnorrsig/tests_impl.h
src/tests.c
src/tests_exhaustive.c
src/util.h
src/valgrind_ctime_test.c

@tcharding
Copy link
Contributor Author

This is a good opportunity to move the definitions of CHECK and TEST_FAILURE

I had a play with this @real-or-random but got stuck, leaving for another day. The investigation did lead me however to the observation, now implemented in patch 1, to conditionally include stdio.h based on VERIFY.

@tcharding tcharding changed the title Conditionally depend on stdio.h Conditionally include stdio.h and stdlib.h Nov 16, 2022
@tcharding tcharding marked this pull request as ready for review November 16, 2022 03:00
Copy link
Contributor

@jonasnick jonasnick left a comment

Choose a reason for hiding this comment

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

ACK mod nit for the first commit

As for the second commit, if I compile with PREALLOC_INTERFACE_ONLY defined, I get a bunch of errors and warnings. I tried to fix them in my branch until I realized that stdlib is still needed for checked_malloc/realloc, i.e., compilation of my branch with ./configure CPPFLAGS="-DPREALLOC_INTERFACE_ONLY -DUSE_EXTERNAL_DEFAULT_CALLBACKS" will error out because of that (if we manage to get this to work nonetheless we should add a CI test for PREALLOC_INTERFACE_ONLY that at least tests successful compilation).

src/util.h Outdated
Comment on lines 17 to 19
#ifndef USE_EXTERNAL_DEFAULT_CALLBACKS
#include <stdio.h>
#endif

#ifdef VERIFY
#include <stdio.h>
#endif
Copy link
Contributor

@jonasnick jonasnick Nov 18, 2022

Choose a reason for hiding this comment

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

maybe

#if defined(VERIFY) || !defined(USE_EXTERNAL_DEFAULT_CALLBACKS)
#include <stdio.h>
#endif

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cheers, rebased and used the suggestion in patch 1.

Can a maintainer please confirm you guys use this process, that this rebasing to keep the PR consisting of only the valid patch series.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, that's the process.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks mate.

The header `stdio.h` is only needed in code ifdef guarded by
`USE_EXTERNAL_DEFAULT_CALLBACKS` and also (indirectly) by `VERIFY`, we
can therefore guard the include statement in the same manner.

The reason for doing this as that wasm builds downstream have to patch
in an empty `stdio.h` file in order to build because of the
unconditional include.
If we are using the preallocated interface only then stdlib.h is not
required. Currently we unconditionally include it.

Add ifdef guards around any code that uses malloc and friends and then
conditionally include `stdlib.h` based on `PREALLOC_INTERFACE_ONLY`.

The benefit of this patch is that downstream users who wish to build
libsecp256k1 into WASM will not need to patch into their build an empty
`stdlib.h` file.
@tcharding
Copy link
Contributor Author

Any clues on the CI fail crew?

./build-aux/test-driver: line 109: 3245 Aborted (core dumped) "$@" > $log_file 2>&1
FAIL: tests

Can I view $log_file in any way?

@sipa
Copy link
Contributor

sipa commented Nov 21, 2022

@real-or-random
Copy link
Contributor

api.cirrus-ci.com/v1/task/6006563169632256/logs/cat_tests_log.log

Oh that's a failure that's expected to occur with a certain low (but still too high to be annoying) probability, see #367 if you're interested in the details. I've restarted the job.

@tcharding
Copy link
Contributor Author

Thanks!

@real-or-random
Copy link
Contributor

To be honest, I think we should take a step back and first discuss whether we would like to separate the headers as I suggested in #1095 (comment). That looks like a very fundamental change but it should be backwards compatible. That would be cleaner and it would make this PR here obsolete.


Let me still comment on the PR.

As for the second commit, if I compile with PREALLOC_INTERFACE_ONLY defined, I get a bunch of errors and warnings. I tried to fix them in my branch until I realized that stdlib is still needed for checked_malloc/realloc, i.e., compilation of my branch with ./configure CPPFLAGS="-DPREALLOC_INTERFACE_ONLY -DUSE_EXTERNAL_DEFAULT_CALLBACKS" will error out because of that

The proper way to do this is to just wrap the malloc/realloc calls in checked_malloc/realloc in util.h in #ifndef PREALLOC_INTERFACE_ONLY (instead the context creation function). Then all malloc calls (and only these) will be gone if you set PREALLOC_INTERFACE_ONLY.

Before I came to this realization, I was about to comment that I think we don't want to change secp256k1_context_preallocated_clone. Cloning a context into preallocated memory should be fine even if the users sets PREALLOC_INTERFACE_ONLY (and the function doesn't need stdlib.h). But yeah, if we simply wrap inside of checked_malloc/realloc in util.h, then secp256k1_context_preallocated_clone should work.

In general, it's a little bit inelegant to make secp256k1_context_create simply return NULL when PREALLOC_INTERFACE_ONLY is set. Can we instead call a callback, e.g.,

            secp256k1_callback_call(&default_illegal_callback, "Use secp256k1_context_preallocated_create instead when compiled with PREALLOC_INTERFACE_ONLY");

Arguably that's maybe not terribly useful if you also set USE_EXTERNAL_DEFAULT_CALLBACKS and don't have a proper way to abort, but it's certainly better than returning just NULL.

(if we manage to get this to work nonetheless we should add a CI test for PREALLOC_INTERFACE_ONLY that at least tests successful compilation).

Well testing is another problem. Many of the tests currently error out when they can't call secp256k1_context_create...

@tcharding
Copy link
Contributor Author

Thanks @real-or-random, I don't think chopping up headers is a good task for someone new to a project, I'm going to leave this one for now. Will move the PR to draft for the discussion to indicate its not a merge candidate.

@tcharding tcharding marked this pull request as draft November 23, 2022 00:07
@tcharding
Copy link
Contributor Author

No forward path, closing.

@tcharding tcharding closed this Mar 20, 2023
@real-or-random
Copy link
Contributor

No forward path, closing.

Indeed. It's tracked in #1095, I hope I can come back to this soon. This is a major pain point for users.

uncomputable added a commit to uncomputable/simplicity that referenced this pull request Nov 26, 2023
stddef.h is available for wasm while stdio.h is not available.

See bitcoin-core/secp256k1#1149
See bitcoin-core/secp256k1#1148
uncomputable added a commit to uncomputable/simplicity that referenced this pull request Dec 1, 2023
stddef.h is available for wasm while stdio.h is not available.

See bitcoin-core/secp256k1#1149
See bitcoin-core/secp256k1#1148
roconnor-blockstream pushed a commit to BlockstreamResearch/simplicity that referenced this pull request Dec 2, 2023
stddef.h is available for wasm while stdio.h is not available.

See bitcoin-core/secp256k1#1149
See bitcoin-core/secp256k1#1148
roconnor-blockstream pushed a commit to BlockstreamResearch/simplicity that referenced this pull request May 7, 2024
stddef.h is available for wasm while stdio.h is not available.

See bitcoin-core/secp256k1#1149
See bitcoin-core/secp256k1#1148
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

4 participants