<p><code>secp256k1_context</code> is an opaque data type. The <a href="https://github.com/bitcoin-core/secp256k1/blob/master/src/secp256k1.c#L47" rel="nofollow noreferrer"><code>secp256k1_context_struct</code></a> is defined in <a href="https://github.com/bitcoin-core/secp256k1/blob/master/src/secp256k1.c" rel="nofollow noreferrer"><code>secp256k1.c</code></a> (not in <a href="https://github.com/bitcoin-core/secp256k1/blob/master/include/secp256k1.h" rel="nofollow noreferrer"><code>secp256k1.h</code></a>) which results in hiding internal data members from the callers.  Therefore, the caller can't access the context's internal data members (by dereferencing).</p>
<p>This implementation design is not limited to libsecp256k1. For example, <a href="https://en.wikipedia.org/wiki/C_file_input/output#Example" rel="nofollow noreferrer">file input and output in C</a> uses the same method. <a href="https://interrupt.memfault.com/blog/opaque-pointers" rel="nofollow noreferrer">This article</a> will give a better understanding of implementing opaque objects in C.</p>

CC BY-SA 4.0
2022-02-28T17:41:04.327Z
2022-02-28T17:41:04.327Z
siv2r
<p>The reason for this error is that <code>secp256k1_context</code> is an opaque type. This means that you cannot create it on the stack; you need to create a heap-allocated version (and destroy it) using the functions from the API (specifically <code>secp256k1_context_create</code> and <code>secp256k1_context_destroy</code>, as Mark H mentioned in a comment). There is no way to access the internals.</p>
<p>You're right not to try to <code>#include &lt;secp256k1.c&gt;</code> ... aside from being unlikely to build and requiring you to bundle a copy of the whole library, it would expose internals of the library to your code which are not safe to use directly.</p>
<p>For what you are doing (replacing internal signing functionality with OCL-enabled versions) you are probably better off forking the library and directly editing the source. This isn't much more invasive than what you're trying to do, and it would let you use the existing unit tests and valgrind ctime tests to check your work.</p>

CC BY-SA 4.0
2021-02-18T03:15:31.387Z
first of all, Thank you all for the above comments and suggestions. I will add more into the original post.
LeonMSH
CC BY-SA 4.0
2021-02-10T15:24:33.147Z
2021-02-10T15:24:33.147Z
Andrew Poelstra
<p>I make a small test code (test.cpp), try to show the problem I meet:
to compile use</p>
<p>g++ -o test test.cpp -lsecp256k1</p>
<pre><code>#include &lt;stdio.h&gt;
#include &quot;secp256k1.h&quot;

static secp256k1_context_t *ctx = NULL;

int main(int argc, char **argv) {

ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);
printf(&quot;Context created!\n&quot;);
secp256k1_context_t *ctx_clone;
ctx_clone = secp256k1_context_clone(ctx);
printf(&quot;Context cloned!\n&quot;);

/* if enable below two lines of code the compliling error will happen */
// secp256k1_ecmult_context_t* clone_ecm_ctx;
// secp256k1_ecmult_context_clone(clone_ecm_ctx, &amp;ctx-&gt;ecmult_ctx);

secp256k1_context_destroy(ctx_clone);
secp256k1_context_destroy(ctx);
printf(&quot;Context destroyed!\n&quot;);

return 0;
}
</code></pre>
<p>Without the two comments out code I will not have issue.
If with two comments out code, the complier will report that:</p>
<pre><code>test.cpp:15:51: error: invalid use of incomplete type 'secp256k1_context_t {aka struct secp256k1_context_struct}'
 secp256k1_ecmult_context_clone(clone_ecm_ctx, &amp;ctx-&gt;ecmult_ctx);
                                                   ^~
In file included from test.cpp:2:0:
/usr/local/include/secp256k1.h:50:16: note: forward declaration of 'secp256k1_context_t {aka struct secp256k1_context_struct}'
 typedef struct secp256k1_context_struct secp256k1_context_t;
                ^~~~~~~~~~~~~~~~~~~~~~~~
</code></pre>
<p>That looks like I can not operate the context struct internal member (because of the opaque struct), however, my code indeed need to access the struct inside of the context struct, for exp, the below code will trig a similar compiling error:</p>
<p>secp256k1_ecdsa_sig_verify(&amp;ctx-&gt;ecmult_ctx, &amp;r1, &amp;s1, &amp;q, &amp;m)</p>
<p>is there any workaround there?</p>

CC BY-SA 4.0
2021-02-10T10:04:50.403Z
You use `secp256k1_context_create ()` to initialize the context. Usually you will pass the flags `SECP256K1_CONTEXT_SIGN` or `SECP256K1_CONTEXT_VERIFY`
Mark H
CC BY-SA 4.0
2021-02-10T14:17:00.203Z
Can you add this as the answer @MarkH? I haven't verified it personally but I've been told it is correct.
Michael Folkson
CC BY-SA 4.0
2021-02-10T17:08:54.110Z
There's an open PR to libsecp256k1 that adds example usage code https://github.com/bitcoin-core/secp256k1/pull/748 Perhaps that's helpful for you.
nickler
CC BY-SA 4.0
2021-02-18T03:59:33.270Z
@MarkH Thank you so much for your suggestion, I add more into the questions.
LeonMSH
CC BY-SA 4.0
2021-03-02T01:45:24.540Z
@MarkH So far I still have the problem, using the posted small code can reproduce the issue I have, would you please help to check? Thanks so much...
LeonMSH
CC BY-SA 4.0
2021-03-14T06:50:10.077Z
Just an update of one solution, for whoever meet such an issue, that one can copy the definition of the   secp256k1_context_struct into the test.h, include this test.h in test.cpp, then you don't meet such compiler complain any more..
LeonMSH
<ecdsa><secp256k1>
secp256k1 lib compiling issue "invalid use of incomplete type secp256k1_context"
LeonMSH
# secp256k1 lib compiling issue "invalid use of incomplete type secp256k1_context"

(Asked by: username_0 on 2021-02-10)

I make a small test code (test.cpp), try to show the problem I meet:
to compile use

g++ -o test test.cpp -lsecp256k1

```
#include <stdio.h>
#include "secp256k1.h"

static secp256k1_context_t *ctx = NULL;

int main(int argc, char **argv) {

ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);
printf("Context created!\n");
secp256k1_context_t *ctx_clone;
ctx_clone = secp256k1_context_clone(ctx);
printf("Context cloned!\n");

/* if enable below two lines of code the compliling error will happen */
// secp256k1_ecmult_context_t* clone_ecm_ctx;
// secp256k1_ecmult_context_clone(clone_ecm_ctx, &ctx->ecmult_ctx);

secp256k1_context_destroy(ctx_clone);
secp256k1_context_destroy(ctx);
printf("Context destroyed!\n");

return 0;
}

```

Without the two comments out code I will not have issue.
If with two comments out code, the complier will report that:

```
test.cpp:15:51: error: invalid use of incomplete type 'secp256k1_context_t {aka struct secp256k1_context_struct}'
 secp256k1_ecmult_context_clone(clone_ecm_ctx, &ctx->ecmult_ctx);
                                                   ^~
In file included from test.cpp:2:0:
/usr/local/include/secp256k1.h:50:16: note: forward declaration of 'secp256k1_context_t {aka struct secp256k1_context_struct}'
 typedef struct secp256k1_context_struct secp256k1_context_t;
                ^~~~~~~~~~~~~~~~~~~~~~~~

```

That looks like I can not operate the context struct internal member (because of the opaque struct), however, my code indeed need to access the struct inside of the context struct, for exp, the below code will trig a similar compiling error:

secp256k1\_ecdsa\_sig\_verify(&ctx->ecmult\_ctx, &r1, &s1, &q, &m)

is there any workaround there?

**Tags:** ecdsa, secp256k1

> **Comments:**
> **username_1**: You use `secp256k1_context_create ()` to initialize the context. Usually you will pass the flags `SECP256K1_CONTEXT_SIGN` or `SECP256K1_CONTEXT_VERIFY`  
> **username_2**: Can you add this as the answer @username_1? I haven't verified it personally but I've been told it is correct.  
> **username_3**: There's an open PR to libsecp256k1 that adds example usage code https://github.com/bitcoin-core/secp256k1/pull/748 Perhaps that's helpful for you.  
> **username_0**: @username_1 Thank you so much for your suggestion, I add more into the questions.  
> **username_0**: @username_1 So far I still have the problem, using the posted small code can reproduce the issue I have, would you please help to check? Thanks so much...  
> **username_0**: Just an update of one solution, for whoever meet such an issue, that one can copy the definition of the   secp256k1_context_struct into the test.h, include this test.h in test.cpp, then you don't meet such compiler complain any more..  

---

## 2 answers

### Answer by username_5 on 2021-02-10. Score: 4 | Accepted answer

The reason for this error is that `secp256k1_context` is an opaque type. This means that you cannot create it on the stack; you need to create a heap-allocated version (and destroy it) using the functions from the API (specifically `secp256k1_context_create` and `secp256k1_context_destroy`, as username_1 mentioned in a comment). There is no way to access the internals.

You're right not to try to `#include <secp256k1.c>` ... aside from being unlikely to build and requiring you to bundle a copy of the whole library, it would expose internals of the library to your code which are not safe to use directly.

For what you are doing (replacing internal signing functionality with OCL-enabled versions) you are probably better off forking the library and directly editing the source. This isn't much more invasive than what you're trying to do, and it would let you use the existing unit tests and valgrind ctime tests to check your work.

> **Comments:**
> **username_0**: first of all, Thank you all for the above comments and suggestions. I will add more into the original post.  

---

### Answer by username_4 on 2022-02-28. Score: 0

`secp256k1_context` is an opaque data type. The [`secp256k1_context_struct`](https://github.com/bitcoin-core/secp256k1/blob/master/src/secp256k1.c#L47) is defined in [`secp256k1.c`](https://github.com/bitcoin-core/secp256k1/blob/master/src/secp256k1.c) (not in [`secp256k1.h`](https://github.com/bitcoin-core/secp256k1/blob/master/include/secp256k1.h)) which results in hiding internal data members from the callers. Therefore, the caller can't access the context's internal data members (by dereferencing).

This implementation design is not limited to libsecp256k1. For example, [file input and output in C](https://en.wikipedia.org/wiki/C_file_input/output#Example) uses the same method. [This article](https://interrupt.memfault.com/blog/opaque-pointers) will give a better understanding of implementing opaque objects in C.


---

