Create surjection proof
| 192 | |
| 193 | // Create surjection proof |
| 194 | bool SurjectOutput(CTxOutWitness& txoutwit, const std::vector<secp256k1_fixed_asset_tag>& surjection_targets, const std::vector<secp256k1_generator>& target_asset_generators, const std::vector<uint256 >& target_asset_blinders, const std::vector<const unsigned char*> asset_blindptrs, const secp256k1_generator& output_asset_gen, const CAsset& asset) |
| 195 | { |
| 196 | int ret; |
| 197 | // 1 to 3 targets |
| 198 | size_t nInputsToSelect = std::min(MAX_SURJECTION_TARGETS, surjection_targets.size()); |
| 199 | unsigned char randseed[32]; |
| 200 | GetStrongRandBytes(randseed, 32); |
| 201 | size_t input_index; |
| 202 | secp256k1_surjectionproof proof; |
| 203 | secp256k1_fixed_asset_tag tag; |
| 204 | memcpy(&tag, asset.begin(), 32); |
| 205 | // FIXME [hardfork] Elements currently cannot handle surjection proofs on transactions |
| 206 | // with more than 256 inputs. The Elements verification code will always try to give |
| 207 | // secp-zkp the complete list of inputs, and if this exceeds 256 then surjectionproof_verify |
| 208 | // will always return false, so there is no way to work around this situation at signing time |
| 209 | if (surjection_targets.size() > SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS) { |
| 210 | // We must return false here to avoid triggering an assertion within |
| 211 | // secp256k1_surjectionproof_initialize on the next line. |
| 212 | return false; |
| 213 | } |
| 214 | // Find correlation between asset tag and listed input tags |
| 215 | if (secp256k1_surjectionproof_initialize(secp256k1_blind_context, &proof, &input_index, &surjection_targets[0], surjection_targets.size(), nInputsToSelect, &tag, 100, randseed) == 0) { |
| 216 | return false; |
| 217 | } |
| 218 | // Using the input chosen, build proof |
| 219 | ret = secp256k1_surjectionproof_generate(secp256k1_blind_context, &proof, target_asset_generators.data(), target_asset_generators.size(), &output_asset_gen, input_index, target_asset_blinders[input_index].begin(), asset_blindptrs[asset_blindptrs.size()-1]); |
| 220 | assert(ret == 1); |
| 221 | // Double-check answer |
| 222 | ret = secp256k1_surjectionproof_verify(secp256k1_blind_context, &proof, target_asset_generators.data(), target_asset_generators.size(), &output_asset_gen); |
| 223 | assert(ret != 0); |
| 224 | |
| 225 | // Serialize into output witness structure |
| 226 | size_t output_len = secp256k1_surjectionproof_serialized_size(secp256k1_blind_context, &proof); |
| 227 | txoutwit.vchSurjectionproof.resize(output_len); |
| 228 | secp256k1_surjectionproof_serialize(secp256k1_blind_context, &txoutwit.vchSurjectionproof[0], &output_len, &proof); |
| 229 | assert(output_len == txoutwit.vchSurjectionproof.size()); |
| 230 | return true; |
| 231 | } |
| 232 | |
| 233 | // Creates ECDH nonce commitment using ephemeral key and output_pubkey |
| 234 | uint256 GenerateOutputRangeproofNonce(CTxOut& out, const CPubKey output_pubkey) |
no test coverage detected