Merge #6336: fix: rpc getblock and getblockstats for blocks with withdrawal transactions (asset unlock)

b9a46f6d2c refactor: use IsPlatformTransfer in core_write and rpc/blockchain (Konstantin Akimov)
f6169fade4 fix: make composite rpc 'masternode payments' to work with withdrawals (Konstantin Akimov)
e498378eb7 feat: add test for fee in getmempoolentry (Konstantin Akimov)
b0d06f0b5f feat: add regression test for `getblock` and `getblockstats` for withdrawal fee calculation failure (Konstantin Akimov)
ab7172bc8f fix: getblockstats rpc to work with withdrawal transactions (Konstantin Akimov)
96c9b469ca fix: getblock for withdrawal transaction if verbosity level is 2 (Konstantin Akimov)

Pull request description:

  ## Issue being fixed or feature implemented
  https://github.com/dashpay/dash/issues/6335

  ## What was done?
  Applied fixes for `getblock` rpc and `getblockstats` rpc to make them work with withdrawal transactions (asset unlock).

  ## How Has This Been Tested?
  Run updated functional test `feature_asset_locks.py` without the fix causes a failure:
  ```
  2024-10-22T12:01:35.902000Z TestFramework (ERROR): JSONRPC error
  Traceback (most recent call last):
    File "/home/knst/projects/dash-reviews/test/functional/test_framework/test_framework.py", line 160, in main
      self.run_test()
    File "/home/knst/projects/dash-reviews/test/functional/feature_asset_locks.py", line 273, in run_test
      self.test_asset_unlocks(node_wallet, node, pubkey)
    File "/home/knst/projects/dash-reviews/test/functional/feature_asset_locks.py", line 410, in test_asset_unlocks
      self.log.info(f"block info: {node.getblock(block_asset_unlock, 2)}")
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/home/knst/projects/dash-reviews/test/functional/test_framework/coverage.py", line 49, in __call__
      return_val = self.auth_service_proxy_instance.__call__(*args, **kwargs)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/home/knst/projects/dash-reviews/test/functional/test_framework/authproxy.py", line 148, in __call__
      raise JSONRPCException(response['error'], status)
  test_framework.authproxy.JSONRPCException: Internal bug detected: "MoneyRange(fee)"
  core_write.cpp:338 (TxToUniv)
  Please report this issue here: https://github.com/dashpay/dash/issues
   (-1)
  ```

  With patch functional test `feature_asset_locks.py` succeed.

  ## Breaking Changes
  N/A

  ## Checklist:
  - [x] I have performed a self-review of my own code
  - [x] I have commented my code, particularly in hard-to-understand areas
  - [x] I have added or updated relevant unit/integration/functional/e2e tests
  - [x] I have made corresponding changes to the documentation
  - [x] I have assigned this pull request to a milestone

ACKs for top commit:
  PastaPastaPasta:
    utACK b9a46f6d2c
  kwvg:
    utACK b9a46f6d2c
  UdjinM6:
    utACK b9a46f6d2c
  ogabrielides:
    utACK b9a46f6d2c

Tree-SHA512: e49cf73bff5fabc9463ae538c6c556d02b3f9e396e0353f5ea0661afa015259409cdada406d05b77bf0414761c76a013cd428ffc283cbdefbefe3384c9d6ccc5
This commit is contained in:
pasta 2024-10-22 10:08:02 -05:00
commit 51ecd2ed48
No known key found for this signature in database
GPG Key ID: E2F3D7916E722D38
4 changed files with 20 additions and 1 deletions

View File

@ -334,7 +334,10 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, bool include_add
} }
if (calculate_fee) { if (calculate_fee) {
const CAmount fee = amt_total_in - amt_total_out; CAmount fee = amt_total_in - amt_total_out;
if (tx.IsPlatformTransfer()) {
fee = CHECK_NONFATAL(GetTxPayload<CAssetUnlockPayload>(tx))->getFee();
}
CHECK_NONFATAL(MoneyRange(fee)); CHECK_NONFATAL(MoneyRange(fee));
entry.pushKV("fee", ValueFromAmount(fee)); entry.pushKV("fee", ValueFromAmount(fee));
} }

View File

@ -49,6 +49,7 @@
#include <versionbits.h> #include <versionbits.h>
#include <warnings.h> #include <warnings.h>
#include <evo/assetlocktx.h>
#include <evo/cbtx.h> #include <evo/cbtx.h>
#include <evo/evodb.h> #include <evo/evodb.h>
#include <evo/mnhftx.h> #include <evo/mnhftx.h>
@ -2450,6 +2451,11 @@ static RPCHelpMan getblockstats()
} }
CAmount txfee = tx_total_in - tx_total_out; CAmount txfee = tx_total_in - tx_total_out;
if (tx->IsPlatformTransfer()) {
txfee = CHECK_NONFATAL(GetTxPayload<CAssetUnlockPayload>(*tx))->getFee();
}
CHECK_NONFATAL(MoneyRange(txfee)); CHECK_NONFATAL(MoneyRange(txfee));
if (do_medianfee) { if (do_medianfee) {
fee_array.push_back(txfee); fee_array.push_back(txfee);

View File

@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chainparams.h> #include <chainparams.h>
#include <evo/assetlocktx.h>
#include <evo/chainhelper.h> #include <evo/chainhelper.h>
#include <evo/deterministicmns.h> #include <evo/deterministicmns.h>
#include <governance/classes.h> #include <governance/classes.h>
@ -406,6 +407,11 @@ static RPCHelpMan masternode_payments()
if (tx->IsCoinBase()) { if (tx->IsCoinBase()) {
continue; continue;
} }
if (tx->IsPlatformTransfer()) {
nBlockFees += CHECK_NONFATAL(GetTxPayload<CAssetUnlockPayload>(*tx))->getFee();
continue;
}
CAmount nValueIn{0}; CAmount nValueIn{0};
for (const auto& txin : tx->vin) { for (const auto& txin : tx->vin) {
uint256 blockHashTmp; uint256 blockHashTmp;

View File

@ -370,6 +370,7 @@ class AssetLocksTest(DashTestFramework):
self.wait_for_sporks_same() self.wait_for_sporks_same()
txid = self.send_tx(asset_unlock_tx) txid = self.send_tx(asset_unlock_tx)
assert_equal(node.getmempoolentry(txid)['fee'], Decimal("0.0007"))
is_id = node_wallet.sendtoaddress(node_wallet.getnewaddress(), 1) is_id = node_wallet.sendtoaddress(node_wallet.getnewaddress(), 1)
for node in self.nodes: for node in self.nodes:
self.wait_for_instantlock(is_id, node) self.wait_for_instantlock(is_id, node)
@ -407,6 +408,9 @@ class AssetLocksTest(DashTestFramework):
self.mempool_size -= 2 self.mempool_size -= 2
self.check_mempool_size() self.check_mempool_size()
block_asset_unlock = node.getrawtransaction(asset_unlock_tx.rehash(), 1)['blockhash'] block_asset_unlock = node.getrawtransaction(asset_unlock_tx.rehash(), 1)['blockhash']
self.log.info("Checking rpc `getblock` and `getblockstats` succeeds as they use own fee calculation mechanism")
assert_equal(node.getblockstats(node.getblockcount())['maxfee'], tiny_amount)
node.getblock(block_asset_unlock, 2)
self.send_tx(asset_unlock_tx, self.send_tx(asset_unlock_tx,
expected_error = "Transaction already in block chain", expected_error = "Transaction already in block chain",