diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index 930e8ff204..3bd0ff9fc8 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -1080,6 +1080,28 @@ bool CWallet::CreateTransactionInternal( // the blinding logic. coin_selection_params.tx_noinputs_size += 70 + 66 +(MAX_RANGEPROOF_SIZE + DEFAULT_SURJECTIONPROOF_SIZE + WITNESS_SCALE_FACTOR - 1)/WITNESS_SCALE_FACTOR; } + // If we are going to issue an asset, add the issuance data to the noinputs_size so that + // we allocate enough coins for them. + if (issuance_details) { + size_t issue_count = 0; + for (unsigned int i = 0; i < txNew.vout.size(); i++) { + if (txNew.vout[i].nAsset.IsExplicit() && txNew.vout[i].nAsset.GetAsset() == CAsset(uint256S("1"))) { + issue_count++; + } else if (txNew.vout[i].nAsset.IsExplicit() && txNew.vout[i].nAsset.GetAsset() == CAsset(uint256S("2"))) { + issue_count++; + } + } + if (issue_count > 0) { + // Allocate space for blinding nonce, entropy, and whichever of nAmount/nInflationKeys is null + coin_selection_params.tx_noinputs_size += 2 * 32 + 2 * (2 - issue_count); + } + // Allocate non-null nAmount/nInflationKeys and rangeproofs + if (issuance_details->blind_issuance) { + coin_selection_params.tx_noinputs_size += issue_count * (33 * WITNESS_SCALE_FACTOR + MAX_RANGEPROOF_SIZE + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR; + } else { + coin_selection_params.tx_noinputs_size += issue_count * 9; + } + } // Include the fees for things that aren't inputs, excluding the change output const CAmount not_input_fees = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.tx_noinputs_size); diff --git a/test/functional/wallet_elements_regression_1172.py b/test/functional/wallet_elements_regression_1172.py index e070a4b1e8..0c9afa6db9 100755 --- a/test/functional/wallet_elements_regression_1172.py +++ b/test/functional/wallet_elements_regression_1172.py @@ -91,6 +91,36 @@ class WalletCtTest(BitcoinTestFramework): amt = satoshi_round(Decimal(amt - Decimal(0.0005))) self.test_send(amt, 1, 2, True) + addresses = [ self.nodes[1].getnewaddress() for i in range(15) ] \ + + [ self.nodes[2].getnewaddress() for i in range(15) ] + txid = self.nodes[2].sendmany(amounts={address: satoshi_round(Decimal(0.00025)) for address in addresses}) + self.log.info(f"Sent many small UTXOs to nodes 1 and 2 in {txid}") + self.nodes[2].generate(2) + self.sync_all() + + self.log.info(f"Issuing some assets from node 1") + # Try issuing assets + amt = satoshi_round(Decimal(1)) + res1 = self.nodes[1].issueasset(amt, amt, True); + res2 = self.nodes[1].issueasset(amt, amt, False); + + assets = [ res1["asset"], res1["token"], res2["asset"], res2["token"] ] + addresses = [ self.nodes[2].getnewaddress() for i in range(len(assets)) ] + txid = self.nodes[1].sendmany( + amounts={address: amt for address in addresses}, + output_assets={addresses[i]: assets[i] for i in range(len(assets))}, + ) + self.log.info(f"Sent them to node 2 in {txid}") + self.nodes[1].generate(2) + self.sync_all() + # Send them back + addresses = [ self.nodes[1].getnewaddress() for i in range(len(assets)) ] + txid = self.nodes[2].sendmany( + amounts={address: amt for address in addresses}, + output_assets={addresses[i]: assets[i] for i in range(len(assets))}, + ) + self.log.info(f"Sent them back to node 1 in {txid}") + if __name__ == '__main__': WalletCtTest().main()