This vastly shrinks the size of the context required for signing on devices with memory-mapped Flash.
Tables are generated by the new gen_context tool into a header.
This vastly shrinks the size of the context required for signing on devices with memory-mapped Flash.
Tables are generated by the new gen_context tool into a header.
src/
the right place to put this? A clear separation of library code and tools is preferable IMHO.
I reworked this yesterday so that it builds on the host using a “dumb” config that is universal and requires no dependencies. In practice, that means building without HAVE_CONFIG_H, since those values represent the target’s config.
I also swapped out the big char array for a direct creation of a secp256k1_ge_storage_t using SECP256K1_GE_STORAGE_CONST’s as suggested by @gmaxwell, as that will alleviate endian issues. As far as I can tell, this should allow someone to target mipseb-linux from mingw-win64 (my typical farfetched cross-compile scenario).
My branch is here: https://github.com/theuni/secp256k1/tree/static-init I didn’t really bother cleaning it up, it needs some naming/spacing/etc cleanups, but after discussion with @tdaede on IRC, he’s just going to incorporate some of the changes into his work here.
I think that the API should be the same, regardless of the implementation, so I don’t like passing in NULL context pointers.
This is also true of dyamically-generated but secretly-shared contexts. I don’t plan to address that use case in this patch, but it should be pretty easy to add without changing the API later.
@sipa, it’s an extra complication, not sure if I’d call it serious, but would be nice to do without.
What’s the recommended practice with respect to blinding? I’m currently just using secp256k1_context_create. Should I also be using secp256k1_context_randomize? Is once per application launch sufficient, or is it desirable to re-randomize after each signature? Use separate randomized contexts for signing and verification?
The obvious method for a shared context would just be a global variable holding the static context that is lazily initialized. Unfortunately, doing so requires threading primitives to be threadsafe.
This current patch just addresses a static context stored in ROM. I don’t think it’s in scope to address the other feature of a global context here.
Thomas: well I don’t think I want the complexity of two mechanisms to reduce memory footprint. This is the more flexible one, but slightly harder to use. On Jul 1, 2015 10:18 PM, “Thomas Daede” notifications@github.com wrote:
The obvious method for a shared context would just be a global variable holding the static context that is lazily initialized. Unfortunately, doing so requires threading primitives to be threadsafe.
This current patch just addresses a static context stored in ROM. I don’t think it’s in scope to address the other feature of a global context here.
— Reply to this email directly or view it on GitHub https://github.com/bitcoin/secp256k1/pull/254#issuecomment-117813932.
@voisine Well this library is experimental, and I would argue against using it for validation in any production system.
That said, your question makes it clear that the intended use isn’t clear. That should definitely be clarified in the header file and perhaps a README. I guess it should list this:
So, for the other use cases here (hidden context sharing) I don’t really see any good way to implement them.
Using a global variable to store a context if one has already been initialized can cause locking issues. In addition, calls to randomize while some other thread is signing would lead to very bad things. So I don’t think there’s any good way to deduplicate contexts behind the application’s back.
So basically, I think the current patch’s implementation is fine (with room to add a static validation table later, when a slower and smaller table option is made).
Also, to be clear, this patch does not reduce memory footprint. Rather, it moves the footprint from RAM to ROM. On a desktop machine, it only bloats the size of the library.
95@@ -95,6 +96,11 @@ AC_ARG_ENABLE(endomorphism,
96 AS_HELP_STRING([--enable-endomorphism],[enable endomorphism (default is no)]),
97 [use_endomorphism=$enableval],
98 [use_endomorphism=no])
99+
100+AC_ARG_ENABLE(ecmult_static_context,
101+ AS_HELP_STRING([--enable-ecmult-static-context],[enable ecmult static context for signing (default is no)]),
78@@ -75,6 +79,9 @@ static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context_t *c
79 secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*16 + i]);
80 }
81 }
82+#else
83+ ctx->prec = (secp256k1_ge_storage_t (*)[64][16])secp256k1_ecmult_static_context;
0@@ -0,0 +1,63 @@
1+/**********************************************************************
2+ * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell *
@sipa You might have a look at https://github.com/theuni/secp256k1/tree/static-init2. Don’t bother looking at individual commits and keep in mind that it’s just a rough POC.
This makes the context (which really wouldn’t be a context anymore, it could be renamed to something more apt) const, so that it’s unaffected by blinding operations. Instead, a new blinding structure is passed in when needed.
Additionally, the initial blinding value is static to avoid race conditions for applications creating static contexts/blinds at startup. As a result, NULL could be passed in place of the blind, in which case the static blind would be used.
I believe this solves several issues at once:
If you’re onboard with the concept, I’ll clean it up and keep working.
@theuni I don’t understand what advantage you see from the caller now having two contexts they must carry around.
Perhaps you expect them to create and destroy the blinding around each operation? If so this would somewhat undermine it; as it would lose the accumulation of unpredictability.
As a random aside, please don’t introduce any more “_t” named types in the interface. typedefs ending with _t are namespace reserved by posix.
@gmaxwell It’s my understanding that the blinding should be randomized relatively rarely, roughly no more than a few times per day. It’s very possible that I’ve misunderstood that. As for type_t, noted. Thanks.
From my perspective, the advantage is flexibility. I think it’s pretty easy to imagine, for example, an application that could be generating keys in one thread and signing transactions in another. In that case, it would be advantageous to share a constants-only context but maintain per-thread blindings. They could then be rotated infrequently but still independently, without the risk of a collision.
It also solves @sipa’s problem above, so a create_static_context() could be created.
I know I mentioned this to you a while back and you weren’t in favor, I just wanted to put it into code to see what it might look like.
This vastly shrinks the size of the context required for signing on devices with
memory-mapped Flash.
Tables are generated by the new gen_context tool into a header.