Auto merge of #2692 - bitcartel:2639_enable_z_shieldcoinbase, r=str4d
Closes #2639. z_shieldcoinbase is now supported, no longer experimental.
This reverts commit 5023af7bd5
.
This commit is contained in:
commit
3775ac5250
|
@ -72,7 +72,7 @@ Command | Parameters | Description
|
|||
--- | --- | ---
|
||||
z_listreceivedbyaddress<br> | zaddr [minconf=1] | Return a list of amounts received by a zaddr belonging to the node’s wallet.<br><br>Optionally set the minimum number of confirmations which a received amount must have in order to be included in the result. Use 0 to count unconfirmed transactions.<br><br>Output:<br>[{<br>“txid”: “4a0f…”,<br>“amount”: 0.54,<br>“memo”:”F0FF…”,}, {...}, {...}<br>]
|
||||
z_sendmany<br> | fromaddress amounts [minconf=1] [fee=0.0001] | _This is an Asynchronous RPC call_<br><br>Send funds from an address to multiple outputs. The address can be either a taddr or a zaddr.<br><br>Amounts is a list containing key/value pairs corresponding to the addresses and amount to pay. Each output address can be in taddr or zaddr format.<br><br>When sending to a zaddr, you also have the option of attaching a memo in hexadecimal format.<br><br>**NOTE:**When sending coinbase funds to a zaddr, the node's wallet does not allow any change. Put another way, spending a partial amount of a coinbase utxo is not allowed. This is not a consensus rule but a local wallet rule due to the current implementation of z_sendmany. In future, this rule may be removed.<br><br>Example of Outputs parameter:<br>[{“address”:”t123…”, “amount”:0.005},<br>,{“address”:”z010…”,”amount”:0.03, “memo”:”f508af…”}]<br><br>Optionally set the minimum number of confirmations which a private or transparent transaction must have in order to be used as an input. When sending from a zaddr, minconf must be greater than zero.<br><br>Optionally set a transaction fee, which by default is 0.0001 ZEC.<br><br>Any transparent change will be sent to a new transparent address. Any private change will be sent back to the zaddr being used as the source of funds.<br><br>Returns an operationid. You use the operationid value with z_getoperationstatus and z_getoperationresult to obtain the result of sending funds, which if successful, will be a txid.
|
||||
z_shieldcoinbase<br> | fromaddress toaddress [fee=0.0001] | _This is an Asynchronous RPC call_<br><br>Shield transparent coinbase funds by sending to a shielded z address. Utxos selected for shielding will be locked. If there is an error, they are unlocked. The RPC call `listlockunspent` can be used to return a list of locked utxos. The number of coinbase utxos selected for shielding is limited by both the -mempooltxinputlimit=xxx option and a consensus rule defining a maximum transaction size of 100000 bytes. <br><br>The from address is a taddr or "*" for all taddrs belonging to the wallet. The to address is a zaddr. The default fee is 0.0001.<br><br>Returns an object containing an operationid which can be used with z_getoperationstatus and z_getoperationresult, along with key-value pairs regarding how many utxos are being shielded in this trasaction and what remains to be shielded.
|
||||
z_shieldcoinbase<br> | fromaddress toaddress [fee=0.0001] [limit=50] | _This is an Asynchronous RPC call_<br><br>Shield transparent coinbase funds by sending to a shielded z address. Utxos selected for shielding will be locked. If there is an error, they are unlocked. The RPC call `listlockunspent` can be used to return a list of locked utxos.<br><br>The number of coinbase utxos selected for shielding can be set with the limit parameter, which has a default value of 50. If the parameter is set to 0, the number of utxos selected is limited by the `-mempooltxinputlimit` option. Any limit is constrained by a consensus rule defining a maximum transaction size of 100000 bytes. <br><br>The from address is a taddr or "*" for all taddrs belonging to the wallet. The to address is a zaddr. The default fee is 0.0001.<br><br>Returns an object containing an operationid which can be used with z_getoperationstatus and z_getoperationresult, along with key-value pairs regarding how many utxos are being shielded in this trasaction and what remains to be shielded.
|
||||
|
||||
### Operations
|
||||
|
||||
|
|
|
@ -18,11 +18,11 @@ class WalletShieldCoinbaseTest (BitcoinTestFramework):
|
|||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
|
||||
def setup_network(self, split=False):
|
||||
args = ['-regtestprotectcoinbase', '-debug=zrpcunsafe', '-experimentalfeatures', '-zshieldcoinbase']
|
||||
args = ['-regtestprotectcoinbase', '-debug=zrpcunsafe']
|
||||
self.nodes = []
|
||||
self.nodes.append(start_node(0, self.options.tmpdir, args))
|
||||
self.nodes.append(start_node(1, self.options.tmpdir, args))
|
||||
args2 = ['-regtestprotectcoinbase', '-debug=zrpcunsafe', '-experimentalfeatures', '-zshieldcoinbase', "-mempooltxinputlimit=7"]
|
||||
args2 = ['-regtestprotectcoinbase', '-debug=zrpcunsafe', "-mempooltxinputlimit=7"]
|
||||
self.nodes.append(start_node(2, self.options.tmpdir, args2))
|
||||
connect_nodes_bi(self.nodes,0,1)
|
||||
connect_nodes_bi(self.nodes,1,2)
|
||||
|
@ -114,6 +114,20 @@ class WalletShieldCoinbaseTest (BitcoinTestFramework):
|
|||
errorString = e.error['message']
|
||||
assert_equal("Insufficient coinbase funds" in errorString, True)
|
||||
|
||||
# Shielding will fail because limit parameter must be at least 0
|
||||
try:
|
||||
self.nodes[0].z_shieldcoinbase("*", myzaddr, Decimal('0.001'), -1)
|
||||
except JSONRPCException,e:
|
||||
errorString = e.error['message']
|
||||
assert_equal("Limit on maximum number of utxos cannot be negative" in errorString, True)
|
||||
|
||||
# Shielding will fail because limit parameter is absurdly large
|
||||
try:
|
||||
self.nodes[0].z_shieldcoinbase("*", myzaddr, Decimal('0.001'), 99999999999999)
|
||||
except JSONRPCException,e:
|
||||
errorString = e.error['message']
|
||||
assert_equal("JSON integer out of range" in errorString, True)
|
||||
|
||||
# Shield coinbase utxos from node 0 of value 40, standard fee of 0.00010000
|
||||
result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr)
|
||||
self.wait_and_assert_operationid_status(0, result['opid'])
|
||||
|
@ -151,14 +165,15 @@ class WalletShieldCoinbaseTest (BitcoinTestFramework):
|
|||
|
||||
# Shielding the 800 utxos will occur over two transactions, since max tx size is 100,000 bytes.
|
||||
# We don't verify shieldingValue as utxos are not selected in any specific order, so value can change on each test run.
|
||||
result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr, 0)
|
||||
# We set an unrealistically high limit parameter of 99999, to verify that max tx size will constrain the number of utxos.
|
||||
result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr, 0, 99999)
|
||||
assert_equal(result["shieldingUTXOs"], Decimal('662'))
|
||||
assert_equal(result["remainingUTXOs"], Decimal('138'))
|
||||
remainingValue = result["remainingValue"]
|
||||
opid1 = result['opid']
|
||||
|
||||
# Verify that utxos are locked (not available for selection) by queuing up another shielding operation
|
||||
result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr)
|
||||
result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr, 0, 0)
|
||||
assert_equal(result["shieldingValue"], Decimal(remainingValue))
|
||||
assert_equal(result["shieldingUTXOs"], Decimal('138'))
|
||||
assert_equal(result["remainingValue"], Decimal('0'))
|
||||
|
@ -176,8 +191,9 @@ class WalletShieldCoinbaseTest (BitcoinTestFramework):
|
|||
self.sync_all()
|
||||
|
||||
# Verify maximum number of utxos which node 2 can shield is limited by option -mempooltxinputlimit
|
||||
# This option is used when the limit parameter is set to 0.
|
||||
mytaddr = self.nodes[2].getnewaddress()
|
||||
result = self.nodes[2].z_shieldcoinbase(mytaddr, myzaddr, 0)
|
||||
result = self.nodes[2].z_shieldcoinbase(mytaddr, myzaddr, Decimal('0.0001'), 0)
|
||||
assert_equal(result["shieldingUTXOs"], Decimal('7'))
|
||||
assert_equal(result["remainingUTXOs"], Decimal('13'))
|
||||
self.wait_and_assert_operationid_status(2, result['opid'])
|
||||
|
@ -185,5 +201,23 @@ class WalletShieldCoinbaseTest (BitcoinTestFramework):
|
|||
self.nodes[1].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
# Verify maximum number of utxos which node 0 can shield is set by default limit parameter of 50
|
||||
self.nodes[0].generate(200)
|
||||
self.sync_all()
|
||||
mytaddr = self.nodes[0].getnewaddress()
|
||||
result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr, Decimal('0.0001'))
|
||||
assert_equal(result["shieldingUTXOs"], Decimal('50'))
|
||||
assert_equal(result["remainingUTXOs"], Decimal('50'))
|
||||
self.wait_and_assert_operationid_status(0, result['opid'])
|
||||
|
||||
# Verify maximum number of utxos which node 0 can shield can be set by the limit parameter
|
||||
result = self.nodes[0].z_shieldcoinbase(mytaddr, myzaddr, Decimal('0.0001'), 33)
|
||||
assert_equal(result["shieldingUTXOs"], Decimal('33'))
|
||||
assert_equal(result["remainingUTXOs"], Decimal('17'))
|
||||
self.wait_and_assert_operationid_status(0, result['opid'])
|
||||
sync_blocks(self.nodes) # don't sync on mempool as node 2 will reject thix tx due to its mempooltxinputlimit
|
||||
self.nodes[1].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
if __name__ == '__main__':
|
||||
WalletShieldCoinbaseTest().main()
|
||||
|
|
|
@ -790,8 +790,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||
if (!fExperimentalMode) {
|
||||
if (mapArgs.count("-developerencryptwallet")) {
|
||||
return InitError(_("Wallet encryption requires -experimentalfeatures."));
|
||||
} else if (mapArgs.count("-zshieldcoinbase")) {
|
||||
return InitError(_("RPC call z_shieldcoinbase requires -experimentalfeatures."));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||
{ "z_sendmany", 2},
|
||||
{ "z_sendmany", 3},
|
||||
{ "z_shieldcoinbase", 2},
|
||||
{ "z_shieldcoinbase", 3},
|
||||
{ "z_getoperationstatus", 0},
|
||||
{ "z_getoperationresult", 0},
|
||||
{ "z_importkey", 2 },
|
||||
|
|
|
@ -1251,7 +1251,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_shieldcoinbase_parameters)
|
|||
|
||||
BOOST_CHECK_THROW(CallRPC("z_shieldcoinbase"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("z_shieldcoinbase toofewargs"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("z_shieldcoinbase too many args here"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("z_shieldcoinbase too many args shown here"), runtime_error);
|
||||
|
||||
// bad from address
|
||||
BOOST_CHECK_THROW(CallRPC("z_shieldcoinbase "
|
||||
|
@ -1279,6 +1279,13 @@ BOOST_AUTO_TEST_CASE(rpc_z_shieldcoinbase_parameters)
|
|||
"21000001"
|
||||
), runtime_error);
|
||||
|
||||
// invalid limit, must be at least 0
|
||||
BOOST_CHECK_THROW(CallRPC("z_shieldcoinbase "
|
||||
"tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ "
|
||||
"tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB "
|
||||
"100 -1"
|
||||
), runtime_error);
|
||||
|
||||
// Test constructor of AsyncRPCOperation_sendmany
|
||||
std::string testnetzaddr = "ztjiDe569DPNbyTE6TSdJTaSDhoXEHLGvYoUnBU1wfVNU52TEyT6berYtySkd21njAeEoh8fFJUT42kua9r8EnhBaEKqCpP";
|
||||
std::string mainnetzaddr = "zcMuhvq8sEkHALuSU2i4NbNQxshSAYrpCExec45ZjtivYPbuiFPwk6WHy4SvsbeZ4siy1WheuRGjtaJmoD1J8bFqNXhsG6U";
|
||||
|
|
|
@ -3522,25 +3522,21 @@ When estimating the number of coinbase utxos we can shield in a single transacti
|
|||
*/
|
||||
#define CTXIN_SPEND_P2SH_SIZE 400
|
||||
|
||||
#define SHIELD_COINBASE_DEFAULT_LIMIT 50
|
||||
|
||||
UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
bool fEnableShieldCoinbase = fExperimentalMode && GetBoolArg("-zshieldcoinbase", false);
|
||||
std::string strDisabledMsg = "";
|
||||
if (!fEnableShieldCoinbase) {
|
||||
strDisabledMsg = "\nWARNING: z_shieldcoinbase is DISABLED but can be enabled as an experimental feature.\n";
|
||||
}
|
||||
|
||||
if (fHelp || params.size() < 2 || params.size() > 3)
|
||||
if (fHelp || params.size() < 2 || params.size() > 4)
|
||||
throw runtime_error(
|
||||
"z_shieldcoinbase \"fromaddress\" \"tozaddress\" ( fee )\n"
|
||||
+ strDisabledMsg +
|
||||
"z_shieldcoinbase \"fromaddress\" \"tozaddress\" ( fee ) ( limit )\n"
|
||||
"\nShield transparent coinbase funds by sending to a shielded zaddr. This is an asynchronous operation and utxos"
|
||||
"\nselected for shielding will be locked. If there is an error, they are unlocked. The RPC call `listlockunspent`"
|
||||
"\ncan be used to return a list of locked utxos. The number of coinbase utxos selected for shielding is limited by"
|
||||
"\nboth the -mempooltxinputlimit=xxx option and a consensus rule defining a maximum transaction size of "
|
||||
"\ncan be used to return a list of locked utxos. The number of coinbase utxos selected for shielding can be limited"
|
||||
"\nby the caller. If the limit parameter is set to zero, the -mempooltxinputlimit option will determine the number"
|
||||
"\nof uxtos. Any limit is constrained by the consensus rule defining a maximum transaction size of "
|
||||
+ strprintf("%d bytes.", MAX_TX_SIZE)
|
||||
+ HelpRequiringPassphrase() + "\n"
|
||||
"\nArguments:\n"
|
||||
|
@ -3548,6 +3544,8 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
|
|||
"2. \"toaddress\" (string, required) The address is a zaddr.\n"
|
||||
"3. fee (numeric, optional, default="
|
||||
+ strprintf("%s", FormatMoney(SHIELD_COINBASE_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
|
||||
"4. limit (numeric, optional, default="
|
||||
+ strprintf("%d", SHIELD_COINBASE_DEFAULT_LIMIT) + ") Limit on the maximum number of utxos to shield. Set to 0 to use node option -mempooltxinputlimit.\n"
|
||||
"\nResult:\n"
|
||||
"{\n"
|
||||
" \"operationid\": xxx (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
|
||||
|
@ -3558,10 +3556,6 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
|
|||
"}\n"
|
||||
);
|
||||
|
||||
if (!fEnableShieldCoinbase) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error: z_shieldcoinbase is disabled.");
|
||||
}
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
// Validate the from address
|
||||
|
@ -3594,6 +3588,14 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
|
|||
}
|
||||
}
|
||||
|
||||
int nLimit = SHIELD_COINBASE_DEFAULT_LIMIT;
|
||||
if (params.size() > 3) {
|
||||
nLimit = params[3].get_int();
|
||||
if (nLimit < 0) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of utxos cannot be negative");
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare to get coinbase utxos
|
||||
std::vector<ShieldCoinbaseUTXO> inputs;
|
||||
CAmount shieldedValue = 0;
|
||||
|
@ -3601,7 +3603,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
|
|||
size_t estimatedTxSize = 2000; // 1802 joinsplit description + tx overhead + wiggle room
|
||||
size_t utxoCounter = 0;
|
||||
bool maxedOutFlag = false;
|
||||
size_t mempoolLimit = (size_t)GetArg("-mempooltxinputlimit", 0);
|
||||
size_t mempoolLimit = (nLimit != 0) ? nLimit : (size_t)GetArg("-mempooltxinputlimit", 0);
|
||||
|
||||
// Set of addresses to filter utxos by
|
||||
set<CBitcoinAddress> setAddress = {};
|
||||
|
|
Loading…
Reference in New Issue