Skip to content

Commit 250ebb3

Browse files
dgpvapoelstra
authored andcommitted
work in progress: add _allocate_initialized/destroy funcs
1 parent 4a77633 commit 250ebb3

File tree

3 files changed

+118
-0
lines changed

3 files changed

+118
-0
lines changed

include/secp256k1_surjectionproof.h

+46
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ SECP256K1_API size_t secp256k1_surjectionproof_serialized_size(
134134
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
135135

136136
/** Surjection proof initialization function; decides on inputs to use
137+
* To be used to initialize stack-allocated secp256k1_surjectionproof struct
137138
* Returns 0: inputs could not be selected
138139
* n: inputs were selected after n iterations of random selection
139140
*
@@ -166,6 +167,51 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_surjectionproof_initial
166167
const unsigned char *random_seed32
167168
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(7);
168169

170+
171+
/** Surjection proof allocation and initialization function; decides on inputs to use
172+
* Returns 0: inputs could not be selected, or malloc failure
173+
* n: inputs were selected after n iterations of random selection
174+
*
175+
* In: ctx: pointer to a context object
176+
* proof_out_p: a pointer to a pointer to `secp256k1_surjectionproof*`.
177+
* the newly-allocated struct pointer will be saved here.
178+
* fixed_input_tags: fixed input tags `A_i` for all inputs. (If the fixed tag is not known,
179+
* e.g. in a coinjoin with others' inputs, an ephemeral tag can be given;
180+
* this won't match the output tag but might be used in the anonymity set.)
181+
* n_input_tags: the number of entries in the fixed_input_tags array
182+
* n_input_tags_to_use: the number of inputs to select randomly to put in the anonymity set
183+
* fixed_output_tag: fixed output tag
184+
* max_n_iterations: the maximum number of iterations to do before giving up. Because the
185+
* maximum number of inputs (SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS) is
186+
* limited to 256 the probability of giving up is smaller than
187+
* (255/256)^(n_input_tags_to_use*max_n_iterations).
188+
*
189+
* random_seed32: a random seed to be used for input selection
190+
* Out: proof_out_p: The pointer to newly-allocated proof whose bitvector will be initialized.
191+
* In case of failure, the pointer will be NULL.
192+
* input_index: The index of the actual input that is secretly mapped to the output
193+
*/
194+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_surjectionproof_allocate_initialized(
195+
const secp256k1_context* ctx,
196+
secp256k1_surjectionproof** proof_out_p,
197+
size_t *input_index,
198+
const secp256k1_fixed_asset_tag* fixed_input_tags,
199+
const size_t n_input_tags,
200+
const size_t n_input_tags_to_use,
201+
const secp256k1_fixed_asset_tag* fixed_output_tag,
202+
const size_t n_max_iterations,
203+
const unsigned char *random_seed32
204+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(7);
205+
206+
/** Surjection proof destroy function
207+
* deallocates the struct that was allocated with secp256k1_surjectionproof_allocate_initialized
208+
*
209+
* In: proof: pointer to secp256k1_surjectionproof struct
210+
*/
211+
SECP256K1_API void secp256k1_surjectionproof_destroy(
212+
secp256k1_surjectionproof* proof
213+
) SECP256K1_ARG_NONNULL(1);
214+
169215
/** Surjection proof generation function
170216
* Returns 0: proof could not be created
171217
* 1: proof was successfully created

src/modules/surjection/main_impl.h

+31
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,37 @@ static size_t secp256k1_surjectionproof_csprng_next(secp256k1_surjectionproof_cs
151151
}
152152
}
153153

154+
/* XXX secp256k1_surjectionproof_create is not a good name, because it can be confused with secp256k1_surjectionproof_generate */
155+
int secp256k1_surjectionproof_allocate_initialized(const secp256k1_context* ctx, secp256k1_surjectionproof** proof_out_p, size_t *input_index, const secp256k1_fixed_asset_tag* fixed_input_tags, const size_t n_input_tags, const size_t n_input_tags_to_use, const secp256k1_fixed_asset_tag* fixed_output_tag, const size_t n_max_iterations, const unsigned char *random_seed32) {
156+
int ret = 0;
157+
secp256k1_surjectionproof* proof;
158+
159+
VERIFY_CHECK(ctx != NULL);
160+
161+
ARG_CHECK(proof_out_p != NULL);
162+
*proof_out_p = 0;
163+
164+
proof = (secp256k1_surjectionproof*)checked_malloc(&ctx->error_callback, sizeof(secp256k1_surjectionproof));
165+
if (proof != NULL) {
166+
ret = secp256k1_surjectionproof_initialize(ctx, proof, input_index, fixed_input_tags, n_input_tags, n_input_tags_to_use, fixed_output_tag, n_max_iterations, random_seed32);
167+
if (ret) {
168+
*proof_out_p = proof;
169+
}
170+
else {
171+
free(proof);
172+
}
173+
}
174+
return ret;
175+
}
176+
177+
/* XXX add checks to prevent destroy of stack-allocated struct ? */
178+
void secp256k1_surjectionproof_destroy(secp256k1_surjectionproof* proof) {
179+
if (proof != NULL) {
180+
VERIFY_CHECK(proof->n_inputs <= SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS);
181+
free(proof);
182+
}
183+
}
184+
154185
int secp256k1_surjectionproof_initialize(const secp256k1_context* ctx, secp256k1_surjectionproof* proof, size_t *input_index, const secp256k1_fixed_asset_tag* fixed_input_tags, const size_t n_input_tags, const size_t n_input_tags_to_use, const secp256k1_fixed_asset_tag* fixed_output_tag, const size_t n_max_iterations, const unsigned char *random_seed32) {
155186
secp256k1_surjectionproof_csprng csprng;
156187
size_t n_iterations = 0;

src/modules/surjection/tests_impl.h

+41
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ static void test_surjectionproof_api(void) {
2828
unsigned char serialized_proof[SECP256K1_SURJECTIONPROOF_SERIALIZATION_BYTES_MAX];
2929
size_t serialized_len;
3030
secp256k1_surjectionproof proof;
31+
secp256k1_surjectionproof* proof_on_heap;
3132
size_t n_inputs = sizeof(fixed_input_tags) / sizeof(fixed_input_tags[0]);
3233
size_t input_index;
3334
int32_t ecount = 0;
@@ -52,6 +53,46 @@ static void test_surjectionproof_api(void) {
5253
memcpy(&fixed_output_tag, &fixed_input_tags[0], sizeof(fixed_input_tags[0]));
5354
CHECK(secp256k1_generator_generate_blinded(ctx, &ephemeral_output_tag, fixed_output_tag.data, output_blinding_key));
5455

56+
/* check allocate_initialized */
57+
CHECK(secp256k1_surjectionproof_allocate_initialized(none, &proof_on_heap, &input_index, fixed_input_tags, n_inputs, 0, &fixed_input_tags[0], 100, seed) == 0);
58+
CHECK(proof_on_heap == 0);
59+
CHECK(ecount == 0);
60+
CHECK(secp256k1_surjectionproof_allocate_initialized(none, &proof_on_heap, &input_index, fixed_input_tags, n_inputs, 3, &fixed_input_tags[0], 100, seed) != 0);
61+
CHECK(proof_on_heap != 0);
62+
secp256k1_surjectionproof_destroy(proof_on_heap);
63+
CHECK(ecount == 0);
64+
CHECK(secp256k1_surjectionproof_allocate_initialized(none, NULL, &input_index, fixed_input_tags, n_inputs, 3, &fixed_input_tags[0], 100, seed) == 0);
65+
CHECK(ecount == 1);
66+
CHECK(secp256k1_surjectionproof_allocate_initialized(none, &proof_on_heap, NULL, fixed_input_tags, n_inputs, 3, &fixed_input_tags[0], 100, seed) == 0);
67+
CHECK(proof_on_heap == 0);
68+
CHECK(ecount == 2);
69+
CHECK(secp256k1_surjectionproof_allocate_initialized(none, &proof_on_heap, &input_index, NULL, n_inputs, 3, &fixed_input_tags[0], 100, seed) == 0);
70+
CHECK(proof_on_heap == 0);
71+
CHECK(ecount == 3);
72+
CHECK(secp256k1_surjectionproof_allocate_initialized(none, &proof_on_heap, &input_index, fixed_input_tags, SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS + 1, 3, &fixed_input_tags[0], 100, seed) == 0);
73+
CHECK(proof_on_heap == 0);
74+
CHECK(ecount == 4);
75+
CHECK(secp256k1_surjectionproof_allocate_initialized(none, &proof_on_heap, &input_index, fixed_input_tags, n_inputs, n_inputs, &fixed_input_tags[0], 100, seed) != 0);
76+
CHECK(proof_on_heap != 0);
77+
secp256k1_surjectionproof_destroy(proof_on_heap);
78+
CHECK(ecount == 4);
79+
CHECK(secp256k1_surjectionproof_allocate_initialized(none, &proof_on_heap, &input_index, fixed_input_tags, n_inputs, n_inputs + 1, &fixed_input_tags[0], 100, seed) == 0);
80+
CHECK(proof_on_heap == 0);
81+
CHECK(ecount == 5);
82+
CHECK(secp256k1_surjectionproof_allocate_initialized(none, &proof_on_heap, &input_index, fixed_input_tags, n_inputs, 3, NULL, 100, seed) == 0);
83+
CHECK(proof_on_heap == 0);
84+
CHECK(ecount == 6);
85+
CHECK((secp256k1_surjectionproof_allocate_initialized(none, &proof_on_heap, &input_index, fixed_input_tags, n_inputs, 0, &fixed_input_tags[0], 0, seed) & 1) == 0);
86+
CHECK(proof_on_heap == 0);
87+
CHECK(ecount == 6);
88+
CHECK(secp256k1_surjectionproof_allocate_initialized(none, &proof_on_heap, &input_index, fixed_input_tags, n_inputs, 0, &fixed_input_tags[0], 100, NULL) == 0);
89+
CHECK(proof_on_heap == 0);
90+
CHECK(ecount == 7);
91+
92+
/* we are now going to test essentially the same functions, just without heap allocation.
93+
* reset ecount. */
94+
ecount = 0;
95+
5596
/* check initialize */
5697
CHECK(secp256k1_surjectionproof_initialize(none, &proof, &input_index, fixed_input_tags, n_inputs, 0, &fixed_input_tags[0], 100, seed) == 0);
5798
CHECK(ecount == 0);

0 commit comments

Comments
 (0)