| 287 | } |
| 288 | |
| 289 | int BlindTransaction(std::vector<uint256 >& input_value_blinding_factors, const std::vector<uint256 >& input_asset_blinding_factors, const std::vector<CAsset >& input_assets, const std::vector<CAmount >& input_amounts, std::vector<uint256 >& out_val_blind_factors, std::vector<uint256 >& out_asset_blind_factors, const std::vector<CPubKey>& output_pubkeys, const std::vector<CKey>& issuance_blinding_privkey, const std::vector<CKey>& token_blinding_privkey, CMutableTransaction& tx, std::vector<std::vector<unsigned char> >* auxiliary_generators) |
| 290 | { |
| 291 | // Sanity check input data and output_pubkey size, clear other output data |
| 292 | assert(tx.vout.size() >= output_pubkeys.size()); |
| 293 | assert(tx.vin.size() >= issuance_blinding_privkey.size()); |
| 294 | assert(tx.vin.size() >= token_blinding_privkey.size()); |
| 295 | out_val_blind_factors.clear(); |
| 296 | out_val_blind_factors.resize(tx.vout.size()); |
| 297 | out_asset_blind_factors.clear(); |
| 298 | out_asset_blind_factors.resize(tx.vout.size()); |
| 299 | assert(tx.vin.size() == input_value_blinding_factors.size()); |
| 300 | assert(tx.vin.size() == input_asset_blinding_factors.size()); |
| 301 | assert(tx.vin.size() == input_assets.size()); |
| 302 | assert(tx.vin.size() == input_amounts.size()); |
| 303 | |
| 304 | std::vector<unsigned char*> value_blindptrs; |
| 305 | std::vector<const unsigned char*> asset_blindptrs; |
| 306 | std::vector<uint64_t> blinded_amounts; |
| 307 | value_blindptrs.reserve(tx.vout.size() + tx.vin.size()); |
| 308 | asset_blindptrs.reserve(tx.vout.size() + tx.vin.size()); |
| 309 | |
| 310 | int ret; |
| 311 | int num_blind_attempts = 0, num_issuance_blind_attempts = 0, num_blinded = 0; |
| 312 | |
| 313 | //Surjection proof prep |
| 314 | |
| 315 | // Needed to surj init, only matches to output asset matters, rest can be garbage |
| 316 | std::vector<secp256k1_fixed_asset_tag> surjection_targets; |
| 317 | |
| 318 | // Needed to construct the proof itself. Generators must match final transaction to be valid |
| 319 | std::vector<secp256k1_generator> target_asset_generators; |
| 320 | |
| 321 | // maxTargets is a strict upper-bound for the size of target vectors. |
| 322 | // The vectors will be shrunk later according to final count of totalTargets |
| 323 | size_t maxTargets = tx.vin.size()*3; |
| 324 | if (auxiliary_generators) { |
| 325 | assert(auxiliary_generators->size() >= tx.vin.size()); |
| 326 | maxTargets += auxiliary_generators->size() - tx.vin.size(); |
| 327 | } |
| 328 | surjection_targets.resize(maxTargets); |
| 329 | target_asset_generators.resize(maxTargets); |
| 330 | |
| 331 | // input_asset_blinding_factors is only for inputs, not for issuances(0 by def) |
| 332 | // but we need to create surjection proofs against this list so we copy and insert 0's |
| 333 | // where issuances occur. |
| 334 | std::vector<uint256> target_asset_blinders; |
| 335 | |
| 336 | size_t totalTargets = 0; |
| 337 | for (size_t i = 0; i < tx.vin.size(); i++) { |
| 338 | // For each input we either need the asset/blinds or the generator |
| 339 | if (input_assets[i].IsNull()) { |
| 340 | // If non-empty generator exists, parse |
| 341 | if (auxiliary_generators) { |
| 342 | // Parse generator here |
| 343 | ret = secp256k1_generator_parse(secp256k1_blind_context, &target_asset_generators[totalTargets], &(*auxiliary_generators)[i][0]); |
| 344 | if (ret != 1) { |
| 345 | return -1; |
| 346 | } |