Skip to content

Commit

Permalink
Feature/decodecustomtx (#340)
Browse files Browse the repository at this point in the history
* Added GetBlockHash() function to retrieve the block hash given the transaction hash

* Added new RPC decodecustomtx

* Added tests for decodecustomtx RPC

* Added iswitness parameter to vRPCConvertParams in client.cpp

* Updated decodecustomtx RPC as per new requirements

* Updated decodecustomtx to use INT_MAX as default block height. Updated testing.

* Removed redundant code

* Added GetBlockHash() function to retrieve the block hash given the transaction hash

* Added new RPC decodecustomtx

* Added tests for decodecustomtx RPC

* Added iswitness parameter to vRPCConvertParams in client.cpp

* Updated decodecustomtx RPC as per new requirements

* Updated decodecustomtx to use INT_MAX as default block height. Updated testing.

* Removed redundant code

Co-authored-by: monstrobishi <[email protected]>
  • Loading branch information
surangap and monstrobishi authored Apr 29, 2021
1 parent 9248e09 commit 0eac646
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 5 deletions.
80 changes: 80 additions & 0 deletions src/masternodes/rpc_tokens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,85 @@ UniValue minttokens(const JSONRPCRequest& request) {
return signsend(rawTx, pwallet, optAuthTx)->GetHash().GetHex();
}

UniValue decodecustomtx(const JSONRPCRequest& request)
{
RPCHelpMan{"decodecustomtx",
"\nGet detailed information about a DeFiChain custom transaction.\n",
{
{"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction hex string"},
{"iswitness", RPCArg::Type::BOOL, /* default */ "depends on heuristic tests", "Whether the transaction hex is a serialized witness transaction.\n"
"If iswitness is not present, heuristic tests will be used in decoding.\n"
"If true, only witness deserialization will be tried.\n"
"If false, only non-witness deserialization will be tried.\n"
"This boolean should reflect whether the transaction has inputs\n"
"(e.g. fully valid, or on-chain transactions), if known by the caller."
},
},
RPCResult{
"{\n"
" \"txid\": (string) The transaction id.\n"
" \"type\": (string) The transaction type.\n"
" \"valid\" (bool) Whether the transaction was valid.\n"
" \"results\" (json object) Set of results related to the transaction type\n"
"}\n"
},
RPCExamples{
HelpExampleCli("decodecustomtx", "\"hexstring\"")
+ HelpExampleRpc("decodecustomtx", "\"hexstring\"")
},
}.Check(request);

RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL});

bool try_witness = request.params[1].isNull() ? true : request.params[1].get_bool();
bool try_no_witness = request.params[1].isNull() ? true : !request.params[1].get_bool();

CMutableTransaction mtx;
if (!DecodeHexTx(mtx, request.params[0].get_str(), try_no_witness, try_witness)) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
}

int nHeight{0};
CustomTxType guess;
UniValue txResults(UniValue::VOBJ);
Res res{};
CTransactionRef tx = MakeTransactionRef(std::move(mtx));
std::string warnings;

if (tx)
{
LOCK(cs_main);
// Default to INT_MAX
nHeight = std::numeric_limits<int>::max();

// Skip coinbase TXs except for genesis block
if ((tx->IsCoinBase() && nHeight > 0)) {
return "Coinbase transaction. Not a custom transaction.";
}
//get custom tx info. We pass nHeight INT_MAX,
//just to get over hardfork validations. txResults are based on transaction metadata.
res = RpcInfo(*tx, nHeight, guess, txResults);
if (guess == CustomTxType::None) {
return "Not a custom transaction";
}

UniValue result(UniValue::VOBJ);
result.pushKV("txid", tx->GetHash().GetHex());
result.pushKV("type", ToString(guess));
result.pushKV("valid", res.ok ? true : false); // no actual block height
if (!res.ok) {
result.pushKV("error", res.msg);
} else {
result.pushKV("results", txResults);
}

return result;
} else {
// Should not get here without prior failure.
return "Could not decode the input transaction hexstring.";
}
}

static const CRPCCommand commands[] =
{
// category name actor (function) params
Expand All @@ -745,6 +824,7 @@ static const CRPCCommand commands[] =
{"tokens", "gettoken", &gettoken, {"key" }},
{"tokens", "getcustomtx", &getcustomtx, {"txid", "blockhash"}},
{"tokens", "minttokens", &minttokens, {"amounts", "inputs"}},
{"tokens", "decodecustomtx", &decodecustomtx, {"hexstring", "iswitness"}},
};

void RegisterTokensRPCCommands(CRPCTable& tableRPC) {
Expand Down
1 change: 1 addition & 0 deletions src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ static const CRPCConvertParam vRPCConvertParams[] =

{ "spv_claimhtlc", 3, "feerate" },
{ "spv_refundhtlc", 2, "feerate" },
{ "decodecustomtx", 1, "iswitness" },
};
// clang-format on

Expand Down
24 changes: 24 additions & 0 deletions src/test/rpc_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,30 @@ BOOST_AUTO_TEST_CASE(rpc_rawparams)
BOOST_CHECK_THROW(CallRPC("sendrawtransaction null"), std::runtime_error);
BOOST_CHECK_THROW(CallRPC("sendrawtransaction DEADBEEF"), std::runtime_error);
BOOST_CHECK_THROW(CallRPC(std::string("sendrawtransaction ")+rawtx+" extra"), std::runtime_error);

// decodecustomtx
BOOST_CHECK_THROW(CallRPC("decodecustomtx"), std::runtime_error);
BOOST_CHECK_THROW(CallRPC("decodecustomtx null"), std::runtime_error);
BOOST_CHECK_THROW(CallRPC("decodecustomtx DEADBEEF"), std::runtime_error);
std::string txHexString = "02000000000102451e06ae0c9849f7e225cc5c955c40ac227e85e237f739c5b47edeae3cebed5f01000000171600142fb061e87e925d30269f47403567003470b52e90ffffffff451e06ae0c9849f7e225cc5c955c40ac227e85e237f739c5b47edeae3cebed5f020000001716001474a10535114fc2557fd1ed797763e51830e648c6ffffffff030000000000000000526a4c4f446654787317a914424695dc36783457935a11e35c3effab7bf8a838870000c2eb0b0000000017a914424695dc36783457935a11e35c3effab7bf8a8388701a933ddec00000000000000000000000020cbab2f0000000017a9140f86611d6aa52b91642e6e4f214a67370673a29087400d03000000000017a914424695dc36783457935a11e35c3effab7bf8a8388702473044022041b75640d5f2eaa68343499642365a1b60b78ed09fdc8e00daf6d3641374508e022028d6ebf96314f3faefc80a504ab2f62d973053d5c75957f4ee0c16e39d39d6fb0121025e2d64209d4152a105f54cf692b501a0f977902d865a9890181fa4f7e74da86e02483045022100d672be7e857101ef4e98e66e2005965e4e58fe769dc541e595efb355f8a4f8cf022027ac5214b5d78cc1a177b087c57699b89a8e83183f23fb457df19d18cce3b9700121023756485f970b02af74180fe132d3551b454578ce305c0d6d511ceb73f7d145e800000000";
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("decodecustomtx ")+txHexString));
// r should be {"txid":"cc0f352bc55c835892b22c670ead2a9082247e18ba3c258c6b4dc8f37cade693","type":"PoolSwap","valid":true,"results":{"fromAddress":"a914424695dc36783457935a11e35c3effab7bf8a83887","fromToken":"0","fromAmount":2.00000000,"toAddress":"a914424695dc36783457935a11e35c3effab7bf8a83887","toToken":"1","maxPrice":3973919657.00000000}}
//Check for the details
BOOST_CHECK_EQUAL(find_value(r.get_obj(), "txid").get_str(), "cc0f352bc55c835892b22c670ead2a9082247e18ba3c258c6b4dc8f37cade693");
BOOST_CHECK_EQUAL(find_value(r.get_obj(), "type").get_str(), "PoolSwap");
BOOST_CHECK_EQUAL(find_value(r.get_obj(), "valid").get_bool(), true);
UniValue resultsObj;
BOOST_CHECK_NO_THROW(resultsObj = find_value(r.get_obj(), "results").get_obj());
BOOST_CHECK_EQUAL(find_value(resultsObj, "fromAddress").get_str(), "a914424695dc36783457935a11e35c3effab7bf8a83887");
BOOST_CHECK_EQUAL(find_value(resultsObj, "fromToken").get_str(), "0");
BOOST_CHECK_EQUAL(find_value(resultsObj, "fromAmount").get_real(), 2.0);
BOOST_CHECK_EQUAL(find_value(resultsObj, "toAddress").get_str(), "a914424695dc36783457935a11e35c3effab7bf8a83887");
BOOST_CHECK_EQUAL(find_value(resultsObj, "toToken").get_str(), "1");
BOOST_CHECK_EQUAL(find_value(resultsObj, "maxPrice").get_real(), 3973919657.0);

BOOST_CHECK_NO_THROW(r = CallRPC(std::string("decodecustomtx ")+txHexString + " true"));
BOOST_CHECK_THROW(CallRPC(std::string("decodecustomtx ")+txHexString+" extra"), std::runtime_error);
BOOST_CHECK_THROW(CallRPC(std::string("decodecustomtx ")+txHexString+" true extra"), std::runtime_error);
}

BOOST_AUTO_TEST_CASE(rpc_togglenetwork)
Expand Down
5 changes: 0 additions & 5 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1009,11 +1009,6 @@ bool GetTransaction(const uint256& hash, CTransactionRef& txOut, const Consensus
return false;
}






//////////////////////////////////////////////////////////////////////////////
//
// CBlock and CBlockIndex
Expand Down

0 comments on commit 0eac646

Please sign in to comment.