mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
ledger and account rpc tests (#62)
This commit is contained in:
@@ -32,6 +32,7 @@
|
|||||||
#include <boost/logic/tribool.hpp>
|
#include <boost/logic/tribool.hpp>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
|
|||||||
@@ -121,8 +121,10 @@ JSS(SetFlag); // field.
|
|||||||
JSS(SetRegularKey); // transaction type.
|
JSS(SetRegularKey); // transaction type.
|
||||||
JSS(SetHook); // transaction type.
|
JSS(SetHook); // transaction type.
|
||||||
JSS(Hook); // ledger type.
|
JSS(Hook); // ledger type.
|
||||||
|
JSS(HookDefinition); // ledger type.
|
||||||
JSS(HookState); // ledger type.
|
JSS(HookState); // ledger type.
|
||||||
JSS(HookDefinition);
|
JSS(HookStateData); // field.
|
||||||
|
JSS(HookStateKey); // field.
|
||||||
JSS(EmittedTxn); // ledger type.
|
JSS(EmittedTxn); // ledger type.
|
||||||
JSS(SignerList); // ledger type.
|
JSS(SignerList); // ledger type.
|
||||||
JSS(SignerListSet); // transaction type.
|
JSS(SignerListSet); // transaction type.
|
||||||
@@ -283,6 +285,7 @@ JSS(error_code); // out: error
|
|||||||
JSS(error_exception); // out: Submit
|
JSS(error_exception); // out: Submit
|
||||||
JSS(error_message); // out: error
|
JSS(error_message); // out: error
|
||||||
JSS(escrow); // in: LedgerEntry
|
JSS(escrow); // in: LedgerEntry
|
||||||
|
JSS(emitted_txn); // in: LedgerEntry
|
||||||
JSS(expand); // in: handler/Ledger
|
JSS(expand); // in: handler/Ledger
|
||||||
JSS(expected_date); // out: any (warnings)
|
JSS(expected_date); // out: any (warnings)
|
||||||
JSS(expected_date_UTC); // out: any (warnings)
|
JSS(expected_date_UTC); // out: any (warnings)
|
||||||
@@ -326,7 +329,9 @@ JSS(high); // out: BookChanges
|
|||||||
JSS(highest_sequence); // out: AccountInfo
|
JSS(highest_sequence); // out: AccountInfo
|
||||||
JSS(highest_ticket); // out: AccountInfo
|
JSS(highest_ticket); // out: AccountInfo
|
||||||
JSS(historical_perminute); // historical_perminute.
|
JSS(historical_perminute); // historical_perminute.
|
||||||
JSS(hook_hash); // in: LedgerEntry
|
JSS(hook); // in: LedgerEntry
|
||||||
|
JSS(hook_definition); // in: LedgerEntry
|
||||||
|
JSS(hook_state); // in: LedgerEntry
|
||||||
JSS(hostid); // out: NetworkOPs
|
JSS(hostid); // out: NetworkOPs
|
||||||
JSS(hotwallet); // in: GatewayBalances
|
JSS(hotwallet); // in: GatewayBalances
|
||||||
JSS(id); // websocket.
|
JSS(id); // websocket.
|
||||||
|
|||||||
@@ -217,6 +217,19 @@ doLedgerEntry(RPC::JsonContext& context)
|
|||||||
.key;
|
.key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (context.params.isMember(jss::emitted_txn))
|
||||||
|
{
|
||||||
|
expectedType = ltEMITTED_TXN;
|
||||||
|
if (!context.params[jss::emitted_txn].isObject())
|
||||||
|
{
|
||||||
|
if (!uNodeIndex.parseHex(context.params[jss::emitted_txn].asString()))
|
||||||
|
{
|
||||||
|
uNodeIndex = beast::zero;
|
||||||
|
jvResult[jss::error] = "malformedRequest";
|
||||||
|
}
|
||||||
|
uNodeIndex = keylet::emittedTxn(uNodeIndex).key;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (context.params.isMember(jss::offer))
|
else if (context.params.isMember(jss::offer))
|
||||||
{
|
{
|
||||||
expectedType = ltOFFER;
|
expectedType = ltOFFER;
|
||||||
@@ -337,11 +350,37 @@ doLedgerEntry(RPC::JsonContext& context)
|
|||||||
*id, context.params[jss::ticket][jss::ticket_seq].asUInt());
|
*id, context.params[jss::ticket][jss::ticket_seq].asUInt());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (context.params.isMember(jss::hook_hash))
|
else if (context.params.isMember(jss::hook))
|
||||||
|
{
|
||||||
|
expectedType = ltHOOK;
|
||||||
|
if (!context.params[jss::hook].isObject())
|
||||||
|
{
|
||||||
|
if (!uNodeIndex.parseHex(context.params[jss::hook].asString()))
|
||||||
|
{
|
||||||
|
uNodeIndex = beast::zero;
|
||||||
|
jvResult[jss::error] = "malformedRequest";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
!context.params[jss::hook].isMember(jss::account))
|
||||||
|
{
|
||||||
|
jvResult[jss::error] = "malformedRequest";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto const id = parseBase58<AccountID>(
|
||||||
|
context.params[jss::hook][jss::account].asString());
|
||||||
|
if (!id)
|
||||||
|
jvResult[jss::error] = "malformedAddress";
|
||||||
|
else
|
||||||
|
uNodeIndex = keylet::hook(*id).key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (context.params.isMember(jss::hook_definition))
|
||||||
{
|
{
|
||||||
expectedType = ltHOOK_DEFINITION;
|
expectedType = ltHOOK_DEFINITION;
|
||||||
if (context.params[jss::hook_hash].isObject() ||
|
if (context.params[jss::hook_definition].isObject() ||
|
||||||
(!uNodeIndex.parseHex(context.params[jss::hook_hash].asString())))
|
(!uNodeIndex.parseHex(context.params[jss::hook_definition].asString())))
|
||||||
{
|
{
|
||||||
uNodeIndex = beast::zero;
|
uNodeIndex = beast::zero;
|
||||||
jvResult[jss::error] = "malformedRequest";
|
jvResult[jss::error] = "malformedRequest";
|
||||||
@@ -351,6 +390,45 @@ doLedgerEntry(RPC::JsonContext& context)
|
|||||||
uNodeIndex = keylet::hookDefinition(uNodeIndex).key;
|
uNodeIndex = keylet::hookDefinition(uNodeIndex).key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (context.params.isMember(jss::hook_state))
|
||||||
|
{
|
||||||
|
expectedType = ltHOOK_STATE;
|
||||||
|
uint256 uNodeKey;
|
||||||
|
uint256 uNameSpace;
|
||||||
|
Json::Value jvHookState = context.params[jss::hook_state];
|
||||||
|
|
||||||
|
if (!jvHookState.isObject() ||
|
||||||
|
!jvHookState.isMember(jss::account) ||
|
||||||
|
!jvHookState.isMember(jss::key) ||
|
||||||
|
!jvHookState.isMember(jss::namespace_id) ||
|
||||||
|
!jvHookState[jss::account].isString() ||
|
||||||
|
!jvHookState[jss::key].isString() ||
|
||||||
|
!jvHookState[jss::namespace_id].isString())
|
||||||
|
{
|
||||||
|
uNodeIndex = beast::zero;
|
||||||
|
jvResult[jss::error] = "malformedRequest";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto const account = parseBase58<AccountID>(jvHookState[jss::account].asString());
|
||||||
|
if (!account)
|
||||||
|
{
|
||||||
|
jvResult[jss::error] = "malformedAddress";
|
||||||
|
}
|
||||||
|
else if (!uNodeKey.parseHex(jvHookState[jss::key].asString()))
|
||||||
|
{
|
||||||
|
jvResult[jss::error] = "malformedRequest";
|
||||||
|
}
|
||||||
|
else if (!uNameSpace.parseHex(jvHookState[jss::namespace_id].asString()))
|
||||||
|
{
|
||||||
|
jvResult[jss::error] = "malformedRequest";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uNodeIndex = keylet::hookState(*account, uNodeKey, uNameSpace).key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (context.params.isMember(jss::nft_page))
|
else if (context.params.isMember(jss::nft_page))
|
||||||
{
|
{
|
||||||
expectedType = ltNFTOKEN_PAGE;
|
expectedType = ltNFTOKEN_PAGE;
|
||||||
|
|||||||
@@ -1067,7 +1067,7 @@ chooseLedgerEntryType(Json::Value const& params)
|
|||||||
std::pair<RPC::Status, LedgerEntryType> result{RPC::Status::OK, ltANY};
|
std::pair<RPC::Status, LedgerEntryType> result{RPC::Status::OK, ltANY};
|
||||||
if (params.isMember(jss::type))
|
if (params.isMember(jss::type))
|
||||||
{
|
{
|
||||||
static constexpr std::array<std::pair<char const*, LedgerEntryType>, 15>
|
static constexpr std::array<std::pair<char const*, LedgerEntryType>, 17>
|
||||||
types{
|
types{
|
||||||
{{jss::account, ltACCOUNT_ROOT},
|
{{jss::account, ltACCOUNT_ROOT},
|
||||||
{jss::amendments, ltAMENDMENTS},
|
{jss::amendments, ltAMENDMENTS},
|
||||||
@@ -1075,6 +1075,9 @@ chooseLedgerEntryType(Json::Value const& params)
|
|||||||
{jss::deposit_preauth, ltDEPOSIT_PREAUTH},
|
{jss::deposit_preauth, ltDEPOSIT_PREAUTH},
|
||||||
{jss::directory, ltDIR_NODE},
|
{jss::directory, ltDIR_NODE},
|
||||||
{jss::escrow, ltESCROW},
|
{jss::escrow, ltESCROW},
|
||||||
|
{jss::hook, ltHOOK},
|
||||||
|
{jss::hook_definition, ltHOOK_DEFINITION},
|
||||||
|
{jss::hook_state, ltHOOK_STATE},
|
||||||
{jss::fee, ltFEE_SETTINGS},
|
{jss::fee, ltFEE_SETTINGS},
|
||||||
{jss::hashes, ltLEDGER_HASHES},
|
{jss::hashes, ltLEDGER_HASHES},
|
||||||
{jss::offer, ltOFFER},
|
{jss::offer, ltOFFER},
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ hook(Account const& account, std::optional<std::vector<Json::Value>> hooks, std:
|
|||||||
Json::Value
|
Json::Value
|
||||||
hso(std::vector<uint8_t> const& wasmBytes, void (*f)(Json::Value& jv) = 0);
|
hso(std::vector<uint8_t> const& wasmBytes, void (*f)(Json::Value& jv) = 0);
|
||||||
|
|
||||||
|
Json::Value
|
||||||
|
hso(std::string const& wasmHex, void (*f)(Json::Value& jv) = 0);
|
||||||
|
|
||||||
Json::Value
|
Json::Value
|
||||||
hso_delete(void (*f)(Json::Value& jv) = 0);
|
hso_delete(void (*f)(Json::Value& jv) = 0);
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,28 @@ hso(std::vector<uint8_t> const& wasmBytes, void (*f)(Json::Value& jv))
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Json::Value
|
||||||
|
hso(std::string const& wasmHex, void (*f)(Json::Value& jv))
|
||||||
|
{
|
||||||
|
|
||||||
|
if (wasmHex.size() == 0)
|
||||||
|
throw std::runtime_error("empty hook wasm passed to hso()");
|
||||||
|
|
||||||
|
Json::Value jv;
|
||||||
|
jv[jss::CreateCode] = wasmHex;
|
||||||
|
{
|
||||||
|
jv[jss::HookOn] = "0000000000000000000000000000000000000000000000000000000000000000";
|
||||||
|
jv[jss::HookNamespace] = to_string(uint256{beast::zero});
|
||||||
|
jv[jss::HookApiVersion] = Json::Value{0};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f)
|
||||||
|
f(jv);
|
||||||
|
|
||||||
|
return jv;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace jtx
|
} // namespace jtx
|
||||||
} // namespace test
|
} // namespace test
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
|
#include <ripple/app/hook/Enum.h>
|
||||||
#include <ripple/json/json_reader.h>
|
#include <ripple/json/json_reader.h>
|
||||||
#include <ripple/json/json_value.h>
|
#include <ripple/json/json_value.h>
|
||||||
#include <ripple/json/to_string.h>
|
#include <ripple/json/to_string.h>
|
||||||
@@ -111,6 +112,7 @@ static char const* bobs_account_objects[] = {
|
|||||||
class AccountObjects_test : public beast::unit_test::suite
|
class AccountObjects_test : public beast::unit_test::suite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
#define HSFEE fee(100'000'000)
|
||||||
void
|
void
|
||||||
testErrors()
|
testErrors()
|
||||||
{
|
{
|
||||||
@@ -586,6 +588,7 @@ public:
|
|||||||
BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::state), 0));
|
BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::state), 0));
|
||||||
BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::ticket), 0));
|
BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::ticket), 0));
|
||||||
BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::uri_token), 0));
|
BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::uri_token), 0));
|
||||||
|
BEAST_EXPECT(acct_objs_is_size(acct_objs(gw, jss::hook), 0));
|
||||||
|
|
||||||
// gw mints an NFT so we can find it.
|
// gw mints an NFT so we can find it.
|
||||||
uint256 const nftID{token::getNextID(env, gw, 0u, tfTransferable)};
|
uint256 const nftID{token::getNextID(env, gw, 0u, tfTransferable)};
|
||||||
@@ -755,6 +758,23 @@ public:
|
|||||||
BEAST_EXPECT(uritoken[sfIssuer.jsonName] == gw.human());
|
BEAST_EXPECT(uritoken[sfIssuer.jsonName] == gw.human());
|
||||||
BEAST_EXPECT(uritoken[sfURI.jsonName] == strHex(uri));
|
BEAST_EXPECT(uritoken[sfURI.jsonName] == strHex(uri));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
// Create hook
|
||||||
|
auto setHook = [](test::jtx::Account const& account) {
|
||||||
|
std::string const createCodeHex = "0061736D0100000001130360037F7F7E017E60027F7F017F60017F017E02170203656E7606616363657074000003656E76025F670001030201020503010002062B077F01418088040B7F004180080B7F004180080B7F004180080B7F00418088040B7F0041000B7F0041010B07080104686F6F6B00020AB5800001B1800001017F230041106B220124002001200036020C410022002000420010001A41012200200010011A200141106A240042000B";
|
||||||
|
Json::Value jv = ripple::test::jtx::hook(account, {{hso(createCodeHex)}}, 0);
|
||||||
|
return jv;
|
||||||
|
};
|
||||||
|
env(setHook(gw), HSFEE);
|
||||||
|
env.close();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Find the hook.
|
||||||
|
Json::Value const resp = acct_objs(gw, jss::hook);
|
||||||
|
BEAST_EXPECT(acct_objs_is_size(resp, 1));
|
||||||
|
auto const& hook = resp[jss::result][jss::account_objects][0u];
|
||||||
|
BEAST_EXPECT(hook[sfAccount.jsonName] == gw.human());
|
||||||
|
}
|
||||||
{
|
{
|
||||||
// See how "deletion_blockers_only" handles gw's directory.
|
// See how "deletion_blockers_only" handles gw's directory.
|
||||||
Json::Value params;
|
Json::Value params;
|
||||||
@@ -765,6 +785,7 @@ public:
|
|||||||
std::vector<std::string> const expectedLedgerTypes = [] {
|
std::vector<std::string> const expectedLedgerTypes = [] {
|
||||||
std::vector<std::string> v{
|
std::vector<std::string> v{
|
||||||
jss::Escrow.c_str(),
|
jss::Escrow.c_str(),
|
||||||
|
jss::Hook.c_str(),
|
||||||
jss::Check.c_str(),
|
jss::Check.c_str(),
|
||||||
jss::NFTokenPage.c_str(),
|
jss::NFTokenPage.c_str(),
|
||||||
jss::RippleState.c_str(),
|
jss::RippleState.c_str(),
|
||||||
@@ -811,7 +832,7 @@ public:
|
|||||||
// directory nodes.
|
// directory nodes.
|
||||||
for (int d = 1'000'032; d >= 1'000'000; --d)
|
for (int d = 1'000'032; d >= 1'000'000; --d)
|
||||||
{
|
{
|
||||||
env(offer(gw, USD(1), drops(d)));
|
env(offer(gw, USD(1), drops(d)), HSFEE);
|
||||||
env.close();
|
env.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,9 +18,11 @@
|
|||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <ripple/beast/unit_test.h>
|
#include <ripple/beast/unit_test.h>
|
||||||
|
#include <ripple/app/misc/TxQ.h>
|
||||||
#include <ripple/protocol/ErrorCodes.h>
|
#include <ripple/protocol/ErrorCodes.h>
|
||||||
#include <ripple/protocol/jss.h>
|
|
||||||
#include <ripple/rpc/impl/RPCHelpers.h>
|
#include <ripple/rpc/impl/RPCHelpers.h>
|
||||||
|
#include <ripple/app/hook/Enum.h>
|
||||||
|
#include <ripple/protocol/jss.h>
|
||||||
#include <test/jtx.h>
|
#include <test/jtx.h>
|
||||||
|
|
||||||
#include <boost/container/flat_set.hpp>
|
#include <boost/container/flat_set.hpp>
|
||||||
@@ -31,6 +33,8 @@ namespace test {
|
|||||||
|
|
||||||
class AccountTx_test : public beast::unit_test::suite
|
class AccountTx_test : public beast::unit_test::suite
|
||||||
{
|
{
|
||||||
|
#define HSFEE fee(100'000'000)
|
||||||
|
|
||||||
// A data structure used to describe the basic structure of a
|
// A data structure used to describe the basic structure of a
|
||||||
// transactions array node as returned by the account_tx RPC command.
|
// transactions array node as returned by the account_tx RPC command.
|
||||||
struct NodeSanity
|
struct NodeSanity
|
||||||
@@ -101,7 +105,6 @@ class AccountTx_test : public beast::unit_test::suite
|
|||||||
__FILE__,
|
__FILE__,
|
||||||
__LINE__);
|
__LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
BEAST_EXPECT(createdNodes == sane.created);
|
BEAST_EXPECT(createdNodes == sane.created);
|
||||||
BEAST_EXPECT(deletedNodes == sane.deleted);
|
BEAST_EXPECT(deletedNodes == sane.deleted);
|
||||||
BEAST_EXPECT(modifiedNodes == sane.modified);
|
BEAST_EXPECT(modifiedNodes == sane.modified);
|
||||||
@@ -393,6 +396,8 @@ class AccountTx_test : public beast::unit_test::suite
|
|||||||
env(check::cancel(alice, aliceCheckId), sig(alie));
|
env(check::cancel(alice, aliceCheckId), sig(alie));
|
||||||
env.close();
|
env.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ticket
|
||||||
{
|
{
|
||||||
// Deposit preauthorization with a Ticket.
|
// Deposit preauthorization with a Ticket.
|
||||||
std::uint32_t const tktSeq{env.seq(alice) + 1};
|
std::uint32_t const tktSeq{env.seq(alice) + 1};
|
||||||
@@ -403,7 +408,138 @@ class AccountTx_test : public beast::unit_test::suite
|
|||||||
env.close();
|
env.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup is done. Look at the transactions returned by account_tx.
|
// URIToken
|
||||||
|
{
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
std::string const uri(maxTokenURILength, '?');
|
||||||
|
|
||||||
|
// Mint URIToken
|
||||||
|
auto mintURI = [](test::jtx::Account const& account, std::string const& uri) {
|
||||||
|
Json::Value jv;
|
||||||
|
jv[jss::TransactionType] = jss::URITokenMint;
|
||||||
|
jv[jss::Flags] = tfBurnable;
|
||||||
|
jv[jss::Account] = account.human();
|
||||||
|
jv[sfURI.jsonName] = strHex(uri);
|
||||||
|
return jv;
|
||||||
|
};
|
||||||
|
env(mintURI(alice, uri), sig(alie));
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
auto tokenid = [](jtx::Account const& account, std::string const& uri) {
|
||||||
|
auto const k = keylet::uritoken(account, Blob(uri.begin(), uri.end()));
|
||||||
|
return k.key;
|
||||||
|
};
|
||||||
|
auto const tid = tokenid(alice, uri);
|
||||||
|
std::string const hexid{strHex(tid)};
|
||||||
|
|
||||||
|
// Sell URIToken
|
||||||
|
auto sellURI = [](test::jtx::Account const& account, std::string const& id, STAmount const& amount) {
|
||||||
|
Json::Value jv;
|
||||||
|
jv[jss::TransactionType] = jss::URITokenCreateSellOffer;
|
||||||
|
jv[jss::Account] = account.human();
|
||||||
|
jv[jss::Amount] = amount.getJson(JsonOptions::none);
|
||||||
|
jv[sfURITokenID.jsonName] = id;
|
||||||
|
return jv;
|
||||||
|
};
|
||||||
|
env(sellURI(alice, hexid, XRP(10)), sig(alie));
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
// Buy URIToken
|
||||||
|
auto buyURI = [](test::jtx::Account const& account, std::string const& id, STAmount const& amount) {
|
||||||
|
Json::Value jv;
|
||||||
|
jv[jss::TransactionType] = jss::URITokenBuy;
|
||||||
|
jv[jss::Account] = account.human();
|
||||||
|
jv[jss::Amount] = amount.getJson(JsonOptions::none);
|
||||||
|
jv[sfURITokenID.jsonName] = id;
|
||||||
|
return jv;
|
||||||
|
};
|
||||||
|
env(buyURI(gw, hexid, XRP(10)));
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
// Sell URIToken
|
||||||
|
env(sellURI(gw, hexid, XRP(10)));
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
// Clear URIToken
|
||||||
|
auto cancelURI = [](test::jtx::Account const& account, std::string const& id) {
|
||||||
|
Json::Value jv;
|
||||||
|
jv[jss::TransactionType] = jss::URITokenCancelSellOffer;
|
||||||
|
jv[jss::Account] = account.human();
|
||||||
|
jv[sfURITokenID.jsonName] = id;
|
||||||
|
return jv;
|
||||||
|
};
|
||||||
|
env(cancelURI(gw, hexid));
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
// Burn URIToken
|
||||||
|
auto burnURI = [](test::jtx::Account const& account, std::string const& id) {
|
||||||
|
Json::Value jv;
|
||||||
|
jv[jss::TransactionType] = jss::URITokenBurn;
|
||||||
|
jv[jss::Account] = account.human();
|
||||||
|
jv[sfURITokenID.jsonName] = id;
|
||||||
|
return jv;
|
||||||
|
};
|
||||||
|
env(burnURI(gw, hexid));
|
||||||
|
env.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hook
|
||||||
|
{
|
||||||
|
|
||||||
|
// Create Hook
|
||||||
|
auto createHook = [](test::jtx::Account const& account) {
|
||||||
|
std::string const createHookHex = "0061736D0100000001130360037F7F7E017E60027F7F017F60017F017E02170203656E7606616363657074000003656E76025F670001030201020503010002062B077F01418088040B7F004180080B7F004180080B7F004180080B7F00418088040B7F0041000B7F0041010B07080104686F6F6B00020AB5800001B1800001017F230041106B220124002001200036020C410022002000420010001A41012200200010011A200141106A240042000B";
|
||||||
|
Json::Value jv = ripple::test::jtx::hook(account, {{hso(createHookHex)}}, 0);
|
||||||
|
return jv;
|
||||||
|
};
|
||||||
|
env(createHook(alice), HSFEE, sig(alie));
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
// Update Hook - Binary
|
||||||
|
auto updateHook = [](test::jtx::Account const& account) {
|
||||||
|
std::string const updateHookHex = "0061736D0100000001130360037F7F7E017E60027F7F017F60017F017E02170203656E7606616363657074000003656E76025F670001030201020503010002062B077F01418088040B7F004180080B7F004180080B7F004180080B7F00418088040B7F0041000B7F0041010B07080104686F6F6B00020AB5800001B1800001017F230041106B220124002001200036020C410022002000420010001A41012200200010011A200141106A240042000B";
|
||||||
|
Json::Value jhv = hso(updateHookHex);
|
||||||
|
jhv[jss::Flags] = hsfOVERRIDE;
|
||||||
|
Json::Value jv = ripple::test::jtx::hook(account, {{jhv}}, hsfOVERRIDE);
|
||||||
|
return jv;
|
||||||
|
};
|
||||||
|
env(updateHook(alice), HSFEE, sig(alie));
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
// Install Hook - Hash
|
||||||
|
auto hh = [&](jtx::Env const& env, jtx::Account const& account) -> uint256 {
|
||||||
|
auto const hook = env.le(keylet::hook(account.id()));
|
||||||
|
if (hook) {
|
||||||
|
auto const& hooks = hook->getFieldArray(sfHooks);
|
||||||
|
if (hooks.size() > 0) {
|
||||||
|
return hooks[0].getFieldH256(sfHookHash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uint256{beast::zero};
|
||||||
|
};
|
||||||
|
auto installHook = [](test::jtx::Account const& account, uint256 const& hookHash) {
|
||||||
|
Json::Value jhv;
|
||||||
|
jhv[jss::Flags] = hsfOVERRIDE;
|
||||||
|
jhv[jss::HookOn] = "0000000000000000000000000000000000000000000000000000000000000000";
|
||||||
|
jhv[jss::HookNamespace] = to_string(uint256{beast::zero});
|
||||||
|
jhv[jss::HookHash] = to_string(hookHash);
|
||||||
|
Json::Value jv = ripple::test::jtx::hook(account, {{jhv}}, hsfOVERRIDE);
|
||||||
|
return jv;
|
||||||
|
};
|
||||||
|
uint256 const hid = hh(env, alice);
|
||||||
|
env(installHook(alice, hid), HSFEE, sig(alie));
|
||||||
|
env.close();
|
||||||
|
|
||||||
|
// Delete Hook
|
||||||
|
auto deleteHook = [](test::jtx::Account const& account) {
|
||||||
|
Json::Value jv = ripple::test::jtx::hook(account, {{hso_delete()}}, hsfOVERRIDE);
|
||||||
|
return jv;
|
||||||
|
};
|
||||||
|
env(deleteHook(alice), HSFEE, sig(alie));
|
||||||
|
env.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup is done. Look at the transactions returned by account_tx.
|
||||||
Json::Value params;
|
Json::Value params;
|
||||||
params[jss::account] = alice.human();
|
params[jss::account] = alice.human();
|
||||||
params[jss::ledger_index_min] = -1;
|
params[jss::ledger_index_min] = -1;
|
||||||
@@ -421,29 +557,39 @@ class AccountTx_test : public beast::unit_test::suite
|
|||||||
// Do a sanity check on each returned transaction. They should
|
// Do a sanity check on each returned transaction. They should
|
||||||
// be returned in the reverse order of application to the ledger.
|
// be returned in the reverse order of application to the ledger.
|
||||||
static const NodeSanity sanity[]{
|
static const NodeSanity sanity[]{
|
||||||
// txType, created, deleted, modified
|
// txType, created, deleted, modified
|
||||||
{0, jss::DepositPreauth, {jss::DepositPreauth}, {jss::Ticket}, {jss::AccountRoot, jss::DirectoryNode}},
|
{0, jss::SetHook, {}, {jss::Hook, jss::HookDefinition}, {jss::AccountRoot, jss::DirectoryNode}},
|
||||||
{1, jss::TicketCreate, {jss::Ticket}, {}, {jss::AccountRoot, jss::DirectoryNode}},
|
{1, jss::SetHook, {}, {}, {jss::AccountRoot, jss::Hook}},
|
||||||
{2, jss::CheckCancel, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
|
{2, jss::SetHook, {}, {}, {jss::AccountRoot, jss::Hook}},
|
||||||
{3, jss::CheckCash, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
|
{3, jss::SetHook, {jss::Hook, jss::HookDefinition}, {}, {jss::AccountRoot, jss::DirectoryNode}},
|
||||||
{4, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
|
{4, jss::URITokenBurn, {}, {jss::URIToken}, {jss::AccountRoot, jss::DirectoryNode}},
|
||||||
{5, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
|
{5, jss::URITokenCancelSellOffer, {}, {}, {jss::AccountRoot, jss::URIToken}},
|
||||||
{6, jss::PaymentChannelClaim, {}, {jss::PayChannel}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
|
{6, jss::URITokenCreateSellOffer, {}, {}, {jss::AccountRoot, jss::URIToken}},
|
||||||
{7, jss::PaymentChannelFund, {}, {}, {jss::AccountRoot, jss::PayChannel}},
|
{7, jss::URITokenBuy, {}, {}, {jss::AccountRoot, jss::DirectoryNode, jss::URIToken}},
|
||||||
{8, jss::PaymentChannelCreate, {jss::PayChannel}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
|
{8, jss::URITokenCreateSellOffer, {}, {}, {jss::AccountRoot, jss::URIToken}},
|
||||||
{9, jss::EscrowCancel, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}},
|
{9, jss::URITokenMint, {jss::URIToken}, {}, {jss::AccountRoot, jss::DirectoryNode}},
|
||||||
{10, jss::EscrowFinish, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}},
|
{10, jss::DepositPreauth, {jss::DepositPreauth}, {jss::Ticket}, {jss::AccountRoot, jss::DirectoryNode}},
|
||||||
{11, jss::EscrowCreate, {jss::Escrow}, {}, {jss::AccountRoot, jss::DirectoryNode}},
|
{11, jss::TicketCreate, {jss::Ticket}, {}, {jss::AccountRoot, jss::DirectoryNode}},
|
||||||
{12, jss::EscrowCreate, {jss::Escrow}, {}, {jss::AccountRoot, jss::DirectoryNode}},
|
{12, jss::CheckCancel, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
|
||||||
{13, jss::SignerListSet, {jss::SignerList}, {}, {jss::AccountRoot, jss::DirectoryNode}},
|
{13, jss::CheckCash, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
|
||||||
{14, jss::OfferCancel, {}, {jss::Offer, jss::DirectoryNode}, {jss::AccountRoot, jss::DirectoryNode}},
|
{14, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
|
||||||
{15, jss::OfferCreate, {jss::Offer, jss::DirectoryNode}, {}, {jss::AccountRoot, jss::DirectoryNode}},
|
{15, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
|
||||||
{16, jss::TrustSet, {jss::RippleState, jss::DirectoryNode, jss::DirectoryNode}, {}, {jss::AccountRoot, jss::AccountRoot}},
|
{16, jss::PaymentChannelClaim, {}, {jss::PayChannel}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
|
||||||
{17, jss::SetRegularKey, {}, {}, {jss::AccountRoot}},
|
{17, jss::PaymentChannelFund, {}, {}, {jss::AccountRoot, jss::PayChannel}},
|
||||||
{18, jss::Payment, {}, {}, {jss::AccountRoot, jss::AccountRoot}},
|
{18, jss::PaymentChannelCreate, {jss::PayChannel}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
|
||||||
{19, jss::AccountSet, {}, {}, {jss::AccountRoot}},
|
{19, jss::EscrowCancel, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}},
|
||||||
{20, jss::AccountSet, {}, {}, {jss::AccountRoot}},
|
{20, jss::EscrowFinish, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}},
|
||||||
{21, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}},
|
{21, jss::EscrowCreate, {jss::Escrow}, {}, {jss::AccountRoot, jss::DirectoryNode}},
|
||||||
|
{22, jss::EscrowCreate, {jss::Escrow}, {}, {jss::AccountRoot, jss::DirectoryNode}},
|
||||||
|
{23, jss::SignerListSet, {jss::SignerList}, {}, {jss::AccountRoot, jss::DirectoryNode}},
|
||||||
|
{24, jss::OfferCancel, {}, {jss::Offer, jss::DirectoryNode}, {jss::AccountRoot, jss::DirectoryNode}},
|
||||||
|
{25, jss::OfferCreate, {jss::Offer, jss::DirectoryNode}, {}, {jss::AccountRoot, jss::DirectoryNode}},
|
||||||
|
{26, jss::TrustSet, {jss::RippleState, jss::DirectoryNode, jss::DirectoryNode}, {}, {jss::AccountRoot, jss::AccountRoot}},
|
||||||
|
{27, jss::SetRegularKey, {}, {}, {jss::AccountRoot}},
|
||||||
|
{28, jss::Payment, {}, {}, {jss::AccountRoot, jss::AccountRoot}},
|
||||||
|
{29, jss::AccountSet, {}, {}, {jss::AccountRoot}},
|
||||||
|
{30, jss::AccountSet, {}, {}, {jss::AccountRoot}},
|
||||||
|
{31, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}},
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
|||||||
@@ -376,6 +376,17 @@ public:
|
|||||||
env(jv);
|
env(jv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::string const createCodeHex = "0061736D01000000011B0460027F7F017F60047F7F7F7F017E60037F7F7E017E60017F017E02270303656E76025F67000003656E760973746174655F736574000103656E76066163636570740002030201030503010002062B077F01419088040B7F004180080B7F00418A080B7F004180080B7F00419088040B7F0041000B7F0041010B07080104686F6F6B00030AE7800001E3800002017F017E230041106B220124002001200036020C41012200200010001A2001418008280000360208200141046A410022002F0088083B010020012000280084083602004100200020014106200141086A4104100110022102200141106A240020020B0B1001004180080B096B65790076616C7565";
|
||||||
|
std::string ns_str = "CAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFE";
|
||||||
|
Json::Value jv = ripple::test::jtx::hook(Account{"bob3"}, {{hso(createCodeHex)}}, 0);
|
||||||
|
jv[jss::Hooks][0U][jss::Hook][jss::HookNamespace] = ns_str;
|
||||||
|
env(jv, fee(100'000'000));
|
||||||
|
env.close();
|
||||||
|
env(pay(Account{"bob2"}, Account{"bob3"}, XRP(1)), fee(XRP(1)));
|
||||||
|
env.close();
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Json::Value jv;
|
Json::Value jv;
|
||||||
jv[jss::TransactionType] = jss::PaymentChannelCreate;
|
jv[jss::TransactionType] = jss::PaymentChannelCreate;
|
||||||
@@ -423,7 +434,7 @@ public:
|
|||||||
|
|
||||||
{ // jvParams[jss::type] = "directory";
|
{ // jvParams[jss::type] = "directory";
|
||||||
auto const jrr = makeRequest(jss::directory);
|
auto const jrr = makeRequest(jss::directory);
|
||||||
BEAST_EXPECT(checkArraySize(jrr[jss::state], 9));
|
BEAST_EXPECT(checkArraySize(jrr[jss::state], 10));
|
||||||
for (auto const& j : jrr[jss::state])
|
for (auto const& j : jrr[jss::state])
|
||||||
BEAST_EXPECT(j["LedgerEntryType"] == jss::DirectoryNode);
|
BEAST_EXPECT(j["LedgerEntryType"] == jss::DirectoryNode);
|
||||||
}
|
}
|
||||||
@@ -477,6 +488,27 @@ public:
|
|||||||
BEAST_EXPECT(j["LedgerEntryType"] == jss::Escrow);
|
BEAST_EXPECT(j["LedgerEntryType"] == jss::Escrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ // jvParams[jss::type] = "hook";
|
||||||
|
auto const jrr = makeRequest(jss::hook);
|
||||||
|
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
|
||||||
|
for (auto const& j : jrr[jss::state])
|
||||||
|
BEAST_EXPECT(j["LedgerEntryType"] == jss::Hook);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // jvParams[jss::type] = "hook_definition";
|
||||||
|
auto const jrr = makeRequest(jss::hook_definition);
|
||||||
|
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
|
||||||
|
for (auto const& j : jrr[jss::state])
|
||||||
|
BEAST_EXPECT(j["LedgerEntryType"] == jss::HookDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // jvParams[jss::type] = "hook_state";
|
||||||
|
auto const jrr = makeRequest(jss::hook_state);
|
||||||
|
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
|
||||||
|
for (auto const& j : jrr[jss::state])
|
||||||
|
BEAST_EXPECT(j["LedgerEntryType"] == jss::HookState);
|
||||||
|
}
|
||||||
|
|
||||||
{ // jvParams[jss::type] = "payment_channel";
|
{ // jvParams[jss::type] = "payment_channel";
|
||||||
auto const jrr = makeRequest(jss::payment_channel);
|
auto const jrr = makeRequest(jss::payment_channel);
|
||||||
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
|
BEAST_EXPECT(checkArraySize(jrr[jss::state], 1));
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user