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

rangeproof: add secp256k1_rangeproof_max_size function to estimate rangeproof size #201

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
36 changes: 36 additions & 0 deletions include/secp256k1_rangeproof.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ extern "C" {

#include <stdint.h>

/** Length of a message that can be embedded into a maximally-sized rangeproof
*
* It is not be possible to fit a message of this size into a non-maximally-sized
* rangeproof, but it is guaranteed that any embeddable message can fit into an
* array of this size. This constant is intended to be used for memory allocations
* and sanity checks.
*/
#define SECP256K1_RANGEPROOF_MAX_MESSAGE_LEN 3968

/** Opaque data structure that stores a Pedersen commitment
*
* The exact representation of data inside is implementation defined and not
Expand Down Expand Up @@ -287,6 +296,33 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_rangeproof_info(
size_t plen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);

/** Returns an upper bound on the size of a rangeproof with the given parameters
*
* An actual rangeproof may be smaller, for example if the actual value
* is less than both the provided `max_value` and 2^`min_bits`, or if
* the `exp` parameter to `secp256k1_rangeproof_sign` is set such that
* the proven range is compressed. In particular this function will always
* overestimate the size of single-value proofs. Also, if `min_value`
* is set to 0 in the proof, the result will usually, but not always,
* be 8 bytes smaller than if a nonzero value had been passed.
*
* The goal of this function is to provide a useful upper bound for
* memory allocation or fee estimation purposes, without requiring
* too many parameters be fixed in advance.
*
* To obtain the size of largest possible proof, set `max_value` to
* `UINT64_MAX` (and `min_bits` to any valid value such as 0).
*
* In: ctx: pointer to a context object
* max_value: the maximum value that might be passed for `value` for the proof.
* min_bits: the value that will be passed as `min_bits` for the proof.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT size_t secp256k1_rangeproof_max_size(
const secp256k1_context* ctx,
uint64_t max_value,
int min_bits
) SECP256K1_ARG_NONNULL(1);

# ifdef __cplusplus
}
# endif
Expand Down
12 changes: 12 additions & 0 deletions src/modules/rangeproof/main_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -304,4 +304,16 @@ int secp256k1_rangeproof_sign(const secp256k1_context* ctx, unsigned char *proof
proof, plen, min_value, &commitp, blind, nonce, exp, min_bits, value, message, msg_len, extra_commit, extra_commit_len, &genp);
}

size_t secp256k1_rangeproof_max_size(const secp256k1_context* ctx, uint64_t max_value, int min_bits) {
const int val_mantissa = max_value > 0 ? 64 - secp256k1_clz64_var(max_value) : 1;
const int mantissa = min_bits > val_mantissa ? min_bits : val_mantissa;
const size_t rings = (mantissa + 1) / 2;
const size_t npubs = rings * 4 - 2 * (mantissa % 2);

VERIFY_CHECK(ctx != NULL);
(void) ctx;

return 10 + 32 * (npubs + rings - 1) + 32 + ((rings - 1 + 7) / 8);
}

#endif