mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
fix fee rpc to allow tx_blob
This commit is contained in:
@@ -6,8 +6,8 @@ if (process.argv.length < 5)
|
|||||||
const secret = process.argv[2];
|
const secret = process.argv[2];
|
||||||
const amount = BigInt(process.argv[3]) * 1000000n
|
const amount = BigInt(process.argv[3]) * 1000000n
|
||||||
const dest = process.argv[4];
|
const dest = process.argv[4];
|
||||||
|
const server = 'ws://tn4:6005'
|
||||||
require('../utils-tests.js').TestRig('ws://localhost:6005').then(t=>
|
require('../utils-tests.js').TestRig(server).then(t=>
|
||||||
{
|
{
|
||||||
t.pay(secret, amount, dest).then(x=>
|
t.pay(secret, amount, dest).then(x=>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -48,6 +48,26 @@ module.exports = {
|
|||||||
console.log(acc)
|
console.log(acc)
|
||||||
return acc
|
return acc
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const pay = (seed, amt, dest) =>
|
||||||
|
{
|
||||||
|
return new Promise((resolve, reject) =>
|
||||||
|
{
|
||||||
|
let wal = xrpljs.Wallet.fromSeed(seed);
|
||||||
|
|
||||||
|
api.submit({
|
||||||
|
Account: wal.classicAddress,
|
||||||
|
TransactionType: "Payment",
|
||||||
|
Amount: ''+amt,
|
||||||
|
Destination: dest,
|
||||||
|
Fee: "10000"
|
||||||
|
}, {wallet: wal}).then(x=>
|
||||||
|
{
|
||||||
|
assertTxnSuccess(x);
|
||||||
|
resolve(x);
|
||||||
|
}).catch(err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const hookHash = fn =>
|
const hookHash = fn =>
|
||||||
{
|
{
|
||||||
@@ -93,7 +113,8 @@ module.exports = {
|
|||||||
hsfNSDELETE: 2,
|
hsfNSDELETE: 2,
|
||||||
hfsOVERRIDE: 1,
|
hfsOVERRIDE: 1,
|
||||||
hfsNSDELETE: 2,
|
hfsNSDELETE: 2,
|
||||||
hookHash: hookHash
|
hookHash: hookHash,
|
||||||
|
pay: pay
|
||||||
});
|
});
|
||||||
}).catch(err);
|
}).catch(err);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -358,7 +358,7 @@ public:
|
|||||||
@returns a `Json objectvalue`
|
@returns a `Json objectvalue`
|
||||||
*/
|
*/
|
||||||
Json::Value
|
Json::Value
|
||||||
doRPC(Application& app) const;
|
doRPC(Application& app, std::optional<FeeUnit64> hookFeeUnits = std::nullopt) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Implementation for nextQueuableSeq(). The passed lock must be held.
|
// Implementation for nextQueuableSeq(). The passed lock must be held.
|
||||||
|
|||||||
@@ -1914,7 +1914,7 @@ TxQ::getTxs(ReadView const& view) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
Json::Value
|
Json::Value
|
||||||
TxQ::doRPC(Application& app) const
|
TxQ::doRPC(Application& app, std::optional<FeeUnit64> hookFeeUnits) const
|
||||||
{
|
{
|
||||||
auto const view = app.openLedger().current();
|
auto const view = app.openLedger().current();
|
||||||
if (!view)
|
if (!view)
|
||||||
@@ -1941,7 +1941,7 @@ TxQ::doRPC(Application& app) const
|
|||||||
levels[jss::median_level] = to_string(metrics.medFeeLevel);
|
levels[jss::median_level] = to_string(metrics.medFeeLevel);
|
||||||
levels[jss::open_ledger_level] = to_string(metrics.openLedgerFeeLevel);
|
levels[jss::open_ledger_level] = to_string(metrics.openLedgerFeeLevel);
|
||||||
|
|
||||||
auto const baseFee = view->fees().base;
|
auto const baseFee = view->fees().base + (hookFeeUnits ? hookFeeUnits->fee() : 0);
|
||||||
auto& drops = ret[jss::drops] = Json::Value();
|
auto& drops = ret[jss::drops] = Json::Value();
|
||||||
|
|
||||||
drops[jss::base_fee] =
|
drops[jss::base_fee] =
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ namespace hook
|
|||||||
if (!tx.isFieldPresent(sfAccount))
|
if (!tx.isFieldPresent(sfAccount))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
std::optional<AccountID> destAcc = tx.at(sfDestination);
|
std::optional<AccountID> destAcc = tx.at(~sfDestination);
|
||||||
std::optional<AccountID> otxnAcc = tx.at(sfAccount);
|
std::optional<AccountID> otxnAcc = tx.at(~sfAccount);
|
||||||
|
|
||||||
if (!otxnAcc)
|
if (!otxnAcc)
|
||||||
return {};
|
return {};
|
||||||
@@ -183,7 +183,7 @@ namespace hook
|
|||||||
for (auto& [a, e] : tshEntries)
|
for (auto& [a, e] : tshEntries)
|
||||||
ret[e.first] = std::pair<AccountID, bool>{a, e.second};
|
ret[e.first] = std::pair<AccountID, bool>{a, e.second};
|
||||||
|
|
||||||
return std::move(ret);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,62 +27,73 @@
|
|||||||
#include <ripple/rpc/GRPCHandlers.h>
|
#include <ripple/rpc/GRPCHandlers.h>
|
||||||
#include <ripple/app/tx/applyHook.h>
|
#include <ripple/app/tx/applyHook.h>
|
||||||
#include <ripple/app/tx/impl/Transactor.h>
|
#include <ripple/app/tx/impl/Transactor.h>
|
||||||
|
#include <ripple/basics/FeeUnits.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
|
inline
|
||||||
|
std::optional<FeeUnit64>
|
||||||
|
getHookFees(RPC::JsonContext const& context)
|
||||||
|
{
|
||||||
|
auto const& params(context.params);
|
||||||
|
if (params.isMember(jss::tx_blob))
|
||||||
|
{
|
||||||
|
auto ret = strUnHex(context.params[jss::tx_blob].asString());
|
||||||
|
|
||||||
|
if (!ret || !ret->size())
|
||||||
|
throw std::invalid_argument("Invalid tx_blob");
|
||||||
|
|
||||||
|
SerialIter sitTrans(makeSlice(*ret));
|
||||||
|
|
||||||
|
std::unique_ptr<STTx const> stpTrans;
|
||||||
|
stpTrans = std::make_unique<STTx const>(std::ref(sitTrans));
|
||||||
|
|
||||||
|
if (!stpTrans->isFieldPresent(sfAccount))
|
||||||
|
throw std::invalid_argument("No sfAccount specified");
|
||||||
|
|
||||||
|
FeeUnit64 hookFees =
|
||||||
|
Transactor::calculateHookChainFee(*(context.app.openLedger().current()),
|
||||||
|
*stpTrans, keylet::hook(stpTrans->getAccountID(sfAccount)));
|
||||||
|
|
||||||
|
auto const view = context.app.openLedger().current();
|
||||||
|
|
||||||
|
std::vector<std::pair<AccountID, bool>> tsh =
|
||||||
|
hook::getTransactionalStakeHolders(*stpTrans, *view);
|
||||||
|
|
||||||
|
for (auto const& [tshAccount, canRollback] : tsh)
|
||||||
|
if (canRollback)
|
||||||
|
hookFees +=
|
||||||
|
Transactor::calculateHookChainFee(*view, *stpTrans, keylet::hook(tshAccount));
|
||||||
|
return hookFees;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
Json::Value
|
Json::Value
|
||||||
doFee(RPC::JsonContext& context)
|
doFee(RPC::JsonContext& context)
|
||||||
{
|
{
|
||||||
Json::Value jvResult = context.app.getTxQ().doRPC(context.app);
|
// get hook fees, if any
|
||||||
if (jvResult.type() == Json::objectValue)
|
std::optional<FeeUnit64> hookFees;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
auto const& params(context.params);
|
hookFees = getHookFees(context);
|
||||||
if (params.isMember(jss::tx_blob))
|
}
|
||||||
{
|
catch (std::exception& e)
|
||||||
auto ret = strUnHex(context.params[jss::tx_blob].asString());
|
{
|
||||||
|
Json::Value jvResult;
|
||||||
if (!ret || !ret->size())
|
jvResult[jss::error] = "invalidTransaction";
|
||||||
return rpcError(rpcINVALID_PARAMS);
|
jvResult[jss::error_exception] = e.what();
|
||||||
|
|
||||||
SerialIter sitTrans(makeSlice(*ret));
|
|
||||||
|
|
||||||
std::unique_ptr<STTx const> stpTrans;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
stpTrans = std::make_unique<STTx const>(std::ref(sitTrans));
|
|
||||||
}
|
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
jvResult[jss::error] = "invalidTransaction";
|
|
||||||
jvResult[jss::error_exception] = e.what();
|
|
||||||
return jvResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!stpTrans->isFieldPresent(sfAccount))
|
|
||||||
{
|
|
||||||
jvResult[jss::error] = "invalidTransaction";
|
|
||||||
jvResult[jss::error_exception] = "No sfAccount specified";
|
|
||||||
return jvResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
FeeUnit64 hookFees =
|
|
||||||
Transactor::calculateHookChainFee(*(context.app.openLedger().current()),
|
|
||||||
*stpTrans, keylet::hook(stpTrans->getAccountID(sfAccount)));
|
|
||||||
|
|
||||||
auto const view = context.app.openLedger().current();
|
|
||||||
|
|
||||||
std::vector<std::pair<AccountID, bool>> tsh =
|
|
||||||
hook::getTransactionalStakeHolders(*stpTrans, *view);
|
|
||||||
|
|
||||||
for (auto const& [tshAccount, canRollback] : tsh)
|
|
||||||
if (canRollback)
|
|
||||||
hookFees +=
|
|
||||||
Transactor::calculateHookChainFee(*view, *stpTrans, keylet::hook(tshAccount));
|
|
||||||
|
|
||||||
jvResult[jss::fee_hooks_feeunits] = to_string(hookFees.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
return jvResult;
|
return jvResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Json::Value jvResult = context.app.getTxQ().doRPC(context.app, hookFees);
|
||||||
|
if (jvResult.type() == Json::objectValue && hookFees)
|
||||||
|
{
|
||||||
|
jvResult[jss::fee_hooks_feeunits] = to_string(*hookFees);
|
||||||
|
return jvResult;
|
||||||
|
}
|
||||||
|
|
||||||
assert(false);
|
assert(false);
|
||||||
RPC::inject_error(rpcINTERNAL, context.params);
|
RPC::inject_error(rpcINTERNAL, context.params);
|
||||||
return context.params;
|
return context.params;
|
||||||
|
|||||||
Reference in New Issue
Block a user