diff --git a/include/secp256k1_surjectionproof.h b/include/secp256k1_surjectionproof.h index d9a38e40..4f83458d 100644 --- a/include/secp256k1_surjectionproof.h +++ b/include/secp256k1_surjectionproof.h @@ -11,6 +11,9 @@ extern "C" { /** Maximum number of inputs that may be given in a surjection proof */ #define SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS 256 +/** Maximum number of inputs that may be used in a surjection proof */ +#define SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS 16 + /** Number of bytes a serialized surjection proof requires given the * number of inputs and the number of used inputs. */ @@ -19,7 +22,7 @@ extern "C" { /** Maximum number of bytes a serialized surjection proof requires. */ #define SECP256K1_SURJECTIONPROOF_SERIALIZATION_BYTES_MAX \ - SECP256K1_SURJECTIONPROOF_SERIALIZATION_BYTES(SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS, SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS) + SECP256K1_SURJECTIONPROOF_SERIALIZATION_BYTES(SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS, SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS) /** Opaque data structure that holds a parsed surjection proof * @@ -46,7 +49,7 @@ typedef struct { /** Bitmap of which input tags are used in the surjection proof */ unsigned char used_inputs[SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS / 8]; /** Borromean signature: e0, scalars */ - unsigned char data[32 * (1 + SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS)]; + unsigned char data[32 * (1 + SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS)]; } secp256k1_surjectionproof; /** Parse a surjection proof @@ -143,7 +146,8 @@ SECP256K1_API size_t secp256k1_surjectionproof_serialized_size( * e.g. in a coinjoin with others' inputs, an ephemeral tag can be given; * this won't match the output tag but might be used in the anonymity set.) * n_input_tags: the number of entries in the fixed_input_tags array - * n_input_tags_to_use: the number of inputs to select randomly to put in the anonymity set + * n_input_tags_to_use: the number of inputs to select randomly to put in the anonymity set + * Must be <= SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS * fixed_output_tag: fixed output tag * max_n_iterations: the maximum number of iterations to do before giving up. Because the * maximum number of inputs (SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS) is diff --git a/src/modules/surjection/main_impl.h b/src/modules/surjection/main_impl.h index d08712a0..832377bc 100644 --- a/src/modules/surjection/main_impl.h +++ b/src/modules/surjection/main_impl.h @@ -9,11 +9,12 @@ #include #include +#include "include/secp256k1_rangeproof.h" +#include "include/secp256k1_surjectionproof.h" + #include "modules/rangeproof/borromean.h" #include "modules/surjection/surjection_impl.h" #include "hash.h" -#include "include/secp256k1_rangeproof.h" -#include "include/secp256k1_surjectionproof.h" static size_t secp256k1_count_bits_set(const unsigned char* data, size_t count) { size_t ret = 0; @@ -270,8 +271,8 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s size_t n_total_pubkeys; size_t n_used_pubkeys; size_t ring_input_index = 0; - secp256k1_gej ring_pubkeys[SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS]; - secp256k1_scalar borromean_s[SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS]; + secp256k1_gej ring_pubkeys[SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS]; + secp256k1_scalar borromean_s[SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS]; unsigned char msg32[32]; VERIFY_CHECK(ctx != NULL); @@ -310,7 +311,9 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s return 0; } - secp256k1_surjection_compute_public_keys(ring_pubkeys, n_used_pubkeys, ephemeral_input_tags, n_total_pubkeys, proof->used_inputs, ephemeral_output_tag, input_index, &ring_input_index); + if (secp256k1_surjection_compute_public_keys(ring_pubkeys, n_used_pubkeys, ephemeral_input_tags, n_total_pubkeys, proof->used_inputs, ephemeral_output_tag, input_index, &ring_input_index) == 0) { + return 0; + } /* Produce signature */ rsizes[0] = (int) n_used_pubkeys; @@ -338,8 +341,8 @@ int secp256k1_surjectionproof_verify(const secp256k1_context* ctx, const secp256 size_t i; size_t n_total_pubkeys; size_t n_used_pubkeys; - secp256k1_gej ring_pubkeys[SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS]; - secp256k1_scalar borromean_s[SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS]; + secp256k1_gej ring_pubkeys[SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS]; + secp256k1_scalar borromean_s[SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS]; unsigned char msg32[32]; VERIFY_CHECK(ctx != NULL); diff --git a/src/modules/surjection/surjection_impl.h b/src/modules/surjection/surjection_impl.h index c90c5767..1a839ff8 100644 --- a/src/modules/surjection/surjection_impl.h +++ b/src/modules/surjection/surjection_impl.h @@ -77,7 +77,7 @@ SECP256K1_INLINE static int secp256k1_surjection_compute_public_keys(secp256k1_g *ring_input_index = j; } j++; - if (j > n_pubkeys) { + if (j > n_pubkeys || j > SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS) { return 0; } } diff --git a/src/modules/surjection/tests_impl.h b/src/modules/surjection/tests_impl.h index 49f36847..dbab9576 100644 --- a/src/modules/surjection/tests_impl.h +++ b/src/modules/surjection/tests_impl.h @@ -671,7 +671,7 @@ void run_surjection_tests(void) { test_input_selection_distribution(); test_gen_verify(10, 3); - test_gen_verify(SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS, SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS); + test_gen_verify(SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS, SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS); test_no_used_inputs_verify(); test_bad_serialize(); test_bad_parse();