Appends a single issuance to the first input that doesn't have one, and includes a single output per asset type in shuffled positions. Requires at least one output to exist (the fee output, which must be last).
| 2884 | // a single output per asset type in shuffled positions. Requires at least one output |
| 2885 | // to exist (the fee output, which must be last). |
| 2886 | void issueasset_base(CMutableTransaction& mtx, RawIssuanceDetails& issuance_details, const CAmount asset_amount, const CAmount token_amount, const CTxDestination& asset_dest, const CTxDestination& token_dest, const bool blind_issuance, const uint256& contract_hash) |
| 2887 | { |
| 2888 | CHECK_NONFATAL(asset_amount > 0 || token_amount > 0); |
| 2889 | CHECK_NONFATAL(mtx.vout.size() > 0); |
| 2890 | |
| 2891 | CScript asset_script = GetScriptForDestination(asset_dest); |
| 2892 | CScript token_script = GetScriptForDestination(token_dest); |
| 2893 | |
| 2894 | // Find an input with no issuance field |
| 2895 | size_t issuance_input_index = 0; |
| 2896 | for (; issuance_input_index < mtx.vin.size(); issuance_input_index++) { |
| 2897 | if (mtx.vin[issuance_input_index].assetIssuance.IsNull()) { |
| 2898 | break; |
| 2899 | } |
| 2900 | } |
| 2901 | // Can't add another one, exit |
| 2902 | if (issuance_input_index == mtx.vin.size()) { |
| 2903 | issuance_details.input_index = -1; |
| 2904 | return; |
| 2905 | } |
| 2906 | |
| 2907 | uint256 entropy; |
| 2908 | CAsset asset; |
| 2909 | CAsset token; |
| 2910 | GenerateAssetEntropy(entropy, mtx.vin[issuance_input_index].prevout, contract_hash); |
| 2911 | CalculateAsset(asset, entropy); |
| 2912 | CalculateReissuanceToken(token, entropy, blind_issuance); |
| 2913 | |
| 2914 | issuance_details.input_index = issuance_input_index; |
| 2915 | issuance_details.entropy = entropy; |
| 2916 | issuance_details.asset = asset; |
| 2917 | issuance_details.token = token; |
| 2918 | |
| 2919 | mtx.vin[issuance_input_index].assetIssuance.assetEntropy = contract_hash; |
| 2920 | |
| 2921 | if (asset_amount > 0) { |
| 2922 | // Fee output is required to be last. We will insert _before_ the selected position, which preserves that. |
| 2923 | int asset_place = GetRandInt(mtx.vout.size()); |
| 2924 | |
| 2925 | CTxOut asset_out(asset, asset_amount, asset_script); |
| 2926 | // If blinded address, insert the pubkey into the nonce field for later substitution by blinding |
| 2927 | if (IsBlindDestination(asset_dest)) { |
| 2928 | CPubKey asset_blind = GetDestinationBlindingKey(asset_dest); |
| 2929 | asset_out.nNonce.vchCommitment = std::vector<unsigned char>(asset_blind.begin(), asset_blind.end()); |
| 2930 | } |
| 2931 | |
| 2932 | mtx.vout.insert(mtx.vout.begin()+asset_place, asset_out); |
| 2933 | } |
| 2934 | // Explicit 0 is represented by a null value, don't set to non-null in that case |
| 2935 | if (blind_issuance || asset_amount != 0) { |
| 2936 | mtx.vin[issuance_input_index].assetIssuance.nAmount = asset_amount; |
| 2937 | } |
| 2938 | |
| 2939 | if (token_amount > 0) { |
| 2940 | // Calculate this _after_ we conditionally insert the asset output, which changes mtx.vout.size(). |
| 2941 | int token_place = GetRandInt(mtx.vout.size()); |
| 2942 | |
| 2943 | CTxOut token_out(token, token_amount, token_script); |
no test coverage detected