surjection: Fix test condition failures in probabilistic tests - #355
surjection: Fix test condition failures in probabilistic tests#355mllwchrry wants to merge 1 commit into
Conversation
|
I can't remember why we have this randomized design where proof initialization does rejection sampling and can fail. It's explained here how it works: https://github.com/BlockstreamResearch/secp256k1-zkp/blob/master/src/modules/surjection/surjection.md#initialization But I don't see the point. Can you provide an intuition for this for context? I mean, one could simply put the input asset at a random position in the subset and then sample some other input assets to add to the subset. The probability that this looks random can be determined mathematically and doesn't need to be estimated "experimentally". I feel like I don't understand what's going on here. |
|
|
||
| if (n_inputs >= 3) { | ||
| /* succeed in 10*n_inputs tries (probability of failure e^-10) */ | ||
| /* succeed in 100*n_inputs tries (probability of failure e^-300) */ |
The point is that the surjection proof is only actually proving that the asset matches one of 3 (or 5 or something) inputs. If there are many inputs, we choose 3 uniformly at random, to avoid leaking any information about which one is the "real" one.
By the time we're calling into secp256k1-zkp the assets are all in a fixed position. The library has to make the best of whatever (potentially biased) input ordering the caller has provided. But yes, we could iterate through all the inputs, look at the one(s) that have the correct asset ID, and then pick one of those uniformly at random. And then pick the others uniformly at random...
...and then analytically compute how much we deviated from the distribution we'd have gotten if we just chose 3 inputs uniformly at random. |
|
I think it's definitely worth cleaning this up to be deterministic and nonfallible (unless the output ID never appears in the input, i.e. you're attempting to construct a false proof). It does seem like we were trying to be too clever here. In Elements we should also bump the number of inputs from 3 to 10 or 20 or something. |
Fixes two CI failures:
test_input_selectionwhere test condition failed:result < n_inputs * 10(see https://github.com/BlockstreamResearch/secp256k1-zkp/actions/runs/23255024904/job/67611676287). The test had assertions that were stricter than the actual iteration budget.test_input_selection_distribution_helperwhere test condition failed:result > 0(see https://github.com/mllwchrry/secp256k1-zkp/actions/runs/23445282634/job/68207165336). Maximum iterations (64) were insufficient: ~10^-8 failure rate per call * 10,000 calls = ~0.01% failure.