mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-20 18:45:55 +00:00
* make account starting seq the parent close time to prevent replay attacks in reset networks * add tests for activation --------- Co-authored-by: Denis Angell <dangell@transia.co>
5581 lines
238 KiB
C++
5581 lines
238 KiB
C++
//------------------------------------------------------------------------------
|
|
/*
|
|
This file is part of rippled: https://github.com/ripple/rippled
|
|
Copyright (c) 2023 XRPL Labs
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
//==============================================================================
|
|
|
|
#include <ripple/app/ledger/LedgerMaster.h>
|
|
#include <ripple/app/misc/AmendmentTable.h>
|
|
#include <ripple/app/misc/HashRouter.h>
|
|
#include <ripple/app/tx/impl/Import.h>
|
|
#include <ripple/core/ConfigSections.h>
|
|
#include <ripple/json/json_reader.h>
|
|
#include <ripple/json/json_writer.h>
|
|
#include <ripple/ledger/Directory.h>
|
|
#include <ripple/protocol/Feature.h>
|
|
#include <ripple/protocol/Import.h>
|
|
#include <ripple/protocol/jss.h>
|
|
#include <test/app/Import_json.h>
|
|
#include <test/jtx.h>
|
|
|
|
#define BEAST_REQUIRE(x) \
|
|
{ \
|
|
BEAST_EXPECT(!!(x)); \
|
|
if (!(x)) \
|
|
return; \
|
|
}
|
|
#define M(m) memo(m, "", "")
|
|
|
|
namespace ripple {
|
|
namespace test {
|
|
|
|
class Import_test : public beast::unit_test::suite
|
|
{
|
|
std::vector<std::string> const keys = {
|
|
"ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1CDC1"};
|
|
|
|
std::unique_ptr<Config>
|
|
makeNetworkConfig(uint32_t networkID)
|
|
{
|
|
using namespace jtx;
|
|
return envconfig([&](std::unique_ptr<Config> cfg) {
|
|
cfg->NETWORK_ID = networkID;
|
|
Section config;
|
|
config.append(
|
|
{"reference_fee = 10",
|
|
"account_reserve = 1000000",
|
|
"owner_reserve = 200000"});
|
|
auto setup = setup_FeeVote(config);
|
|
cfg->FEES = setup;
|
|
return cfg;
|
|
});
|
|
}
|
|
|
|
std::unique_ptr<Config>
|
|
makeNetworkVLConfig(uint32_t networkID, std::vector<std::string> keys)
|
|
{
|
|
using namespace jtx;
|
|
return envconfig([&](std::unique_ptr<Config> cfg) {
|
|
cfg->NETWORK_ID = networkID;
|
|
Section config;
|
|
config.append(
|
|
{"reference_fee = 10",
|
|
"account_reserve = 1000000",
|
|
"owner_reserve = 200000"});
|
|
auto setup = setup_FeeVote(config);
|
|
cfg->FEES = setup;
|
|
|
|
for (auto const& strPk : keys)
|
|
{
|
|
auto pkHex = strUnHex(strPk);
|
|
if (!pkHex)
|
|
Throw<std::runtime_error>(
|
|
"Import VL Key '" + strPk + "' was not valid hex.");
|
|
|
|
auto const pkType = publicKeyType(makeSlice(*pkHex));
|
|
if (!pkType)
|
|
Throw<std::runtime_error>(
|
|
"Import VL Key '" + strPk +
|
|
"' was not a valid key type.");
|
|
|
|
cfg->IMPORT_VL_KEYS.emplace(strPk, makeSlice(*pkHex));
|
|
}
|
|
return cfg;
|
|
});
|
|
}
|
|
|
|
std::unique_ptr<Config>
|
|
makeMaxFeeConfig(uint32_t networkID, std::vector<std::string> keys)
|
|
{
|
|
using namespace jtx;
|
|
return envconfig([&](std::unique_ptr<Config> cfg) {
|
|
cfg->NETWORK_ID = networkID;
|
|
Section config;
|
|
config.append(
|
|
{"reference_fee = 50",
|
|
"account_reserve = 10000000",
|
|
"owner_reserve = 2000000"});
|
|
auto setup = setup_FeeVote(config);
|
|
cfg->FEES = setup;
|
|
|
|
for (auto const& strPk : keys)
|
|
{
|
|
auto pkHex = strUnHex(strPk);
|
|
if (!pkHex)
|
|
Throw<std::runtime_error>(
|
|
"Import VL Key '" + strPk + "' was not valid hex.");
|
|
|
|
auto const pkType = publicKeyType(makeSlice(*pkHex));
|
|
if (!pkType)
|
|
Throw<std::runtime_error>(
|
|
"Import VL Key '" + strPk +
|
|
"' was not a valid key type.");
|
|
|
|
cfg->IMPORT_VL_KEYS.emplace(strPk, makeSlice(*pkHex));
|
|
}
|
|
return cfg;
|
|
});
|
|
}
|
|
|
|
static Json::Value
|
|
import(jtx::Account const& account, Json::Value const& xpop)
|
|
{
|
|
using namespace jtx;
|
|
Json::Value jv;
|
|
std::string strJson = Json::FastWriter().write(xpop);
|
|
jv[jss::TransactionType] = jss::Import;
|
|
jv[jss::Account] = account.human();
|
|
jv[sfBlob.jsonName] = strHex(strJson);
|
|
return jv;
|
|
}
|
|
|
|
static std::pair<uint256, std::shared_ptr<SLE const>>
|
|
accountKeyAndSle(ReadView const& view, jtx::Account const& account)
|
|
{
|
|
auto const k = keylet::account(account);
|
|
return {k.key, view.read(k)};
|
|
}
|
|
|
|
static std::pair<uint256, std::shared_ptr<SLE const>>
|
|
feesKeyAndSle(ReadView const& view)
|
|
{
|
|
auto const k = keylet::fees();
|
|
return {k.key, view.read(k)};
|
|
}
|
|
|
|
static std::pair<uint256, std::shared_ptr<SLE const>>
|
|
signersKeyAndSle(ReadView const& view, jtx::Account const& account)
|
|
{
|
|
auto const k = keylet::signers(account);
|
|
return {k.key, view.read(k)};
|
|
}
|
|
|
|
static std::size_t
|
|
ownerDirCount(ReadView const& view, jtx::Account const& acct)
|
|
{
|
|
ripple::Dir const ownerDir(view, keylet::ownerDir(acct.id()));
|
|
return std::distance(ownerDir.begin(), ownerDir.end());
|
|
};
|
|
|
|
static Json::Value
|
|
loadXpop(std::string content)
|
|
{
|
|
// If the string is empty, return an empty Json::Value
|
|
if (content.empty())
|
|
{
|
|
std::cout << "JSON string was empty"
|
|
<< "\n";
|
|
return {};
|
|
}
|
|
|
|
Json::Value jsonValue;
|
|
Json::Reader reader;
|
|
reader.parse(content, jsonValue);
|
|
return jsonValue;
|
|
}
|
|
|
|
static std::uint32_t
|
|
importVLSequence(jtx::Env const& env, PublicKey const& pk)
|
|
{
|
|
auto const sle = env.le(keylet::import_vlseq(pk));
|
|
if (sle->isFieldPresent(sfImportSequence))
|
|
return (*sle)[sfImportSequence];
|
|
return 0;
|
|
}
|
|
|
|
STTx
|
|
createUNLReportTx(
|
|
LedgerIndex seq,
|
|
PublicKey const& importKey,
|
|
PublicKey const& valKey)
|
|
{
|
|
auto fill = [&](auto& obj) {
|
|
obj.setFieldU32(sfLedgerSequence, seq);
|
|
obj.set(([&]() {
|
|
auto inner = std::make_unique<STObject>(sfActiveValidator);
|
|
inner->setFieldVL(sfPublicKey, valKey);
|
|
return inner;
|
|
})());
|
|
obj.set(([&]() {
|
|
auto inner = std::make_unique<STObject>(sfImportVLKey);
|
|
inner->setFieldVL(sfPublicKey, importKey);
|
|
return inner;
|
|
})());
|
|
};
|
|
return STTx(ttUNL_REPORT, fill);
|
|
}
|
|
|
|
bool
|
|
hasUNLReport(jtx::Env const& env)
|
|
{
|
|
auto const slep = env.le(keylet::UNLReport());
|
|
return slep != nullptr;
|
|
}
|
|
|
|
void
|
|
incLgrSeqForAccDel(
|
|
jtx::Env& env,
|
|
jtx::Account const& acc,
|
|
std::uint32_t margin = 0)
|
|
{
|
|
int const delta = [&]() -> int {
|
|
if (env.seq(acc) + 255 > env.current()->seq())
|
|
return env.seq(acc) - env.current()->seq() + 255 - margin;
|
|
return 0;
|
|
}();
|
|
BEAST_EXPECT(margin == 0 || delta >= 0);
|
|
for (int i = 0; i < delta; ++i)
|
|
env.close();
|
|
BEAST_EXPECT(env.current()->seq() == env.seq(acc) + 255 - margin);
|
|
}
|
|
|
|
void
|
|
testComputeStartingBalance(FeatureBitset features)
|
|
{
|
|
testcase("import header - computeStartingBonus");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
// old fee
|
|
XRPAmount const value = Import::computeStartingBonus(*env.current());
|
|
BEAST_EXPECT(value == drops(2000000));
|
|
|
|
// todo: new fee
|
|
}
|
|
|
|
void
|
|
testIsHex(FeatureBitset features)
|
|
{
|
|
testcase("import utils - isHex");
|
|
bool const result = isHex("DEADBEEF");
|
|
BEAST_EXPECT(result == true);
|
|
bool const result1 = isHex("Hello world");
|
|
BEAST_EXPECT(result1 == false);
|
|
}
|
|
|
|
void
|
|
testIsBase58(FeatureBitset features)
|
|
{
|
|
testcase("import utils - isBase58");
|
|
bool const result = isBase58("hE45rTtDcGvFz");
|
|
BEAST_EXPECT(result == true);
|
|
bool const result1 = isBase58("Hello world");
|
|
BEAST_EXPECT(result1 == false);
|
|
}
|
|
|
|
void
|
|
testIsBase64(FeatureBitset features)
|
|
{
|
|
testcase("import utils - isBase64");
|
|
bool const result = isBase64("SGVsbG8gV29ybGQh");
|
|
BEAST_EXPECT(result == true);
|
|
bool const result1 = isBase64("Hello world");
|
|
BEAST_EXPECT(result1 == false);
|
|
}
|
|
|
|
void
|
|
testParseUint64(FeatureBitset features)
|
|
{
|
|
testcase("import utils - parseUint64");
|
|
std::optional<uint64_t> result1 = parse_uint64("1234");
|
|
BEAST_EXPECT(result1 == 1234);
|
|
|
|
// std::optional<uint64_t> result2 = parse_uint64("0xFFAABBCCDD22");
|
|
// std::cout << "RESULT: " << *result2 << "\n";
|
|
// BEAST_EXPECT(result2 == 0xFFAABBCCDD22);
|
|
|
|
std::optional<uint64_t> result3 = parse_uint64("2147483647");
|
|
BEAST_EXPECT(result3 == 2147483647);
|
|
|
|
std::optional<uint64_t> result4 = parse_uint64("18446744073709551615");
|
|
BEAST_EXPECT(result4 == 18446744073709551615ull);
|
|
}
|
|
|
|
void
|
|
testSyntaxCheckProofArray(FeatureBitset features)
|
|
{
|
|
}
|
|
|
|
void
|
|
testSyntaxCheckProofObject(FeatureBitset features)
|
|
{
|
|
testcase("import utils - syntaxCheckProof: is object");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const alice = Account("alice");
|
|
env.fund(XRP(1000), alice);
|
|
env.close();
|
|
|
|
std::string strJson = R"json({
|
|
"children": {
|
|
"3": {
|
|
"children": {},
|
|
"hash": "AA126BA0486ADAE575BBC5335E42E236275A452037CA9A876D1A8CDACA1AE542",
|
|
"key": "39D6F6AB7D0A827DD1502B7B9571626A2B601DBE5BC786EF8ADD00E0CB7FCEB3"
|
|
}
|
|
},
|
|
"hash": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
})json";
|
|
|
|
Json::Value proof;
|
|
Json::Reader reader;
|
|
reader.parse(strJson, proof);
|
|
|
|
// XPOP.transaction.proof list entry has wrong format
|
|
{
|
|
BEAST_EXPECT(syntaxCheckProof(proof, env.journal, 65) == false);
|
|
}
|
|
// XPOP.transaction.proof invalid branch size
|
|
{
|
|
Json::Value tmpProof = proof;
|
|
tmpProof[jss::children]["30"] = tmpProof[jss::children]["3"];
|
|
BEAST_EXPECT(syntaxCheckProof(tmpProof, env.journal) == false);
|
|
}
|
|
// XPOP.transaction.proof child node was not 0-F
|
|
{
|
|
Json::Value tmpProof = proof;
|
|
tmpProof[jss::children]["not a hex"] = tmpProof[jss::children]["3"];
|
|
BEAST_EXPECT(syntaxCheckProof(tmpProof, env.journal) == false);
|
|
}
|
|
// XPOP.transaction.proof tree node has wrong format
|
|
// invalid child (must be object)
|
|
{
|
|
Json::Value tmpProof = proof;
|
|
tmpProof[jss::children]["3"] = "not object";
|
|
BEAST_EXPECT(syntaxCheckProof(tmpProof, env.journal) == false);
|
|
}
|
|
// XPOP.transaction.proof tree node has wrong format
|
|
// invalid hash (must be string)
|
|
{
|
|
Json::Value tmpProof = proof;
|
|
tmpProof[jss::children]["3"][jss::hash] = 1234;
|
|
BEAST_EXPECT(syntaxCheckProof(tmpProof, env.journal) == false);
|
|
}
|
|
// XPOP.transaction.proof tree node has wrong format
|
|
// invalid hash size (must be 64)
|
|
{
|
|
Json::Value tmpProof = proof;
|
|
tmpProof[jss::children]["3"][jss::hash] =
|
|
"00000000000000000000000000000000000000000000000000000000000000"
|
|
"000";
|
|
BEAST_EXPECT(syntaxCheckProof(tmpProof, env.journal) == false);
|
|
}
|
|
// XPOP.transaction.proof tree node has wrong format
|
|
// invalid key (must be string)
|
|
{
|
|
Json::Value tmpProof = proof;
|
|
tmpProof[jss::children]["3"][jss::key] = 1234;
|
|
BEAST_EXPECT(syntaxCheckProof(tmpProof, env.journal) == false);
|
|
}
|
|
// XPOP.transaction.proof tree node has wrong format
|
|
// invalid key size (must be 64)
|
|
{
|
|
Json::Value tmpProof = proof;
|
|
tmpProof[jss::children]["3"][jss::key] =
|
|
"00000000000000000000000000000000000000000000000000000000000000"
|
|
"000";
|
|
BEAST_EXPECT(syntaxCheckProof(tmpProof, env.journal) == false);
|
|
}
|
|
// XPOP.transaction.proof tree node has wrong format
|
|
// invalid node children (must be object)
|
|
{
|
|
Json::Value tmpProof = proof;
|
|
tmpProof[jss::children]["3"][jss::children] = "bad object";
|
|
BEAST_EXPECT(syntaxCheckProof(tmpProof, env.journal) == false);
|
|
}
|
|
// XPOP.transaction.proof bad children format
|
|
// invalid node child children (must be hex)
|
|
{
|
|
Json::Value tmpProof = proof;
|
|
tmpProof[jss::children]["3"][jss::children] =
|
|
tmpProof[jss::children]["3"];
|
|
BEAST_EXPECT(syntaxCheckProof(tmpProof, env.journal) == false);
|
|
}
|
|
// success
|
|
{
|
|
BEAST_EXPECT(syntaxCheckProof(proof, env.journal) == true);
|
|
}
|
|
}
|
|
|
|
void
|
|
testSyntaxCheckXPOP(FeatureBitset features)
|
|
{
|
|
testcase("import utils - syntaxCheckXPOP");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
// blob empty
|
|
{
|
|
Blob raw{};
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// blob string empty
|
|
{
|
|
Blob raw{0};
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP failed to parse string json
|
|
{
|
|
Blob raw{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP is not a JSON object
|
|
{
|
|
std::string strJson = R"json([])json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP.ledger is not a JSON object
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": "not object"
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP.transaction is not a JSON object
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {},
|
|
"transaction": "not object"
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP.validation is not a JSON object
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {},
|
|
"transaction": {},
|
|
"validation": "not object"
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.LEDGER
|
|
|
|
// XPOP.ledger.acroot missing or wrong format
|
|
// invalid xpop.ledger.acroot (must be string)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": {}
|
|
},
|
|
"transaction": {},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP.ledger.acroot missing or wrong format
|
|
// invalid xpop.ledger.acroot (must be 64)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "00000000000000000000000000000000000000000000000000000000000000000"
|
|
},
|
|
"transaction": {},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP.ledger.acroot missing or wrong format
|
|
// invalid xpop.ledger.acroot (must be hex)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "this string will pass a length check but fail when checking hex."
|
|
},
|
|
"transaction": {},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP.ledger.txroot missing or wrong format
|
|
// invalid xpop.ledger.txroot (must be string)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": {}
|
|
},
|
|
"transaction": {},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP.ledger.txroot missing or wrong format
|
|
// invalid xpop.ledger.txroot (must be 64)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "00000000000000000000000000000000000000000000000000000000000000000"
|
|
},
|
|
"transaction": {},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP.ledger.txroot missing or wrong format
|
|
// invalid xpop.ledger.txroot (must be hex)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "this string will pass a length check but fail when checking hex."
|
|
},
|
|
"transaction": {},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP.ledger.phash missing or wrong format
|
|
// invalid xpop.ledger.phash (must be string)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": {}
|
|
},
|
|
"transaction": {},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP.ledger.phash missing or wrong format
|
|
// invalid xpop.ledger.phash (must be 64)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "00000000000000000000000000000000000000000000000000000000000000000"
|
|
},
|
|
"transaction": {},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP.ledger.phash missing or wrong format
|
|
// invalid xpop.ledger.phash (must be hex)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "this string will pass a length check but fail when checking hex."
|
|
},
|
|
"transaction": {},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP.ledger.close missing or wrong format
|
|
// invalid xpop.ledger.close (must be int)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": "738786851"
|
|
|
|
},
|
|
"transaction": {},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP.ledger.coins missing or wrong format
|
|
// invalid xpop.ledger.coins (must be int or string)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": {}
|
|
},
|
|
"transaction": {},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP.ledger.coins missing or wrong format
|
|
// invalid xpop.ledger.coins (must be int or string)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "not an int string"
|
|
},
|
|
"transaction": {},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP.ledger.cres missing or wrong format
|
|
// invalid xpop.ledger.cres (must be int)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": "not an int"
|
|
},
|
|
"transaction": {},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP.ledger.flags missing or wrong format
|
|
// invalid xpop.ledger.flags (must be int)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": "not an int"
|
|
},
|
|
"transaction": {},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
// XPOP.ledger.pclose missing or wrong format
|
|
// invalid xpop.ledger.pclose (must be int)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": "not an int"
|
|
},
|
|
"transaction": {},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.TRANSACTION
|
|
|
|
// XPOP.transaction.blob missing or wrong format
|
|
// invalid xpop.transaction.blob (must be hex string)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": {}
|
|
},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.transaction.blob missing or wrong format
|
|
// invalid xpop.transaction.blob (must be hex string)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "not a hex"
|
|
},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.transaction.meta missing or wrong format
|
|
// invalid xpop.transaction.meta (must be hex string)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": {}
|
|
},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.transaction.meta missing or wrong format
|
|
// invalid xpop.transaction.meta (must be hex string)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": "not a hex"
|
|
},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.transaction.proof failed syntax check
|
|
// invalid xpop.transaction.proof (must pass syntaxCheckProof)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": "201C00000000F8E51100612500000052553CEFE169D8DB251A7757C8A80214D7466E81FB2EF6A91E0970B428326B2134EB56A92E4B1340C656FE01A66D529BB7957EAD34D9E193D190EA62AAE4764B5B08C5E624000000026240000000773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481148EA87CA747AF74EE03A7E36C0F8EB1C1568D588AE1E1F1031000",
|
|
"proof": {}
|
|
},
|
|
"validation": {}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.validation.data missing or wrong format
|
|
// invalid xpop.validation.data (must be object)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": "201C00000000F8E51100612500000052553CEFE169D8DB251A7757C8A80214D7466E81FB2EF6A91E0970B428326B2134EB56A92E4B1340C656FE01A66D529BB7957EAD34D9E193D190EA62AAE4764B5B08C5E624000000026240000000773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481148EA87CA747AF74EE03A7E36C0F8EB1C1568D588AE1E1F1031000",
|
|
"proof": {
|
|
"children": {
|
|
"3": {
|
|
"children": {},
|
|
"hash": "AA126BA0486ADAE575BBC5335E42E236275A452037CA9A876D1A8CDACA1AE542",
|
|
"key": "39D6F6AB7D0A827DD1502B7B9571626A2B601DBE5BC786EF8ADD00E0CB7FCEB3"
|
|
}
|
|
},
|
|
"hash": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
}
|
|
},
|
|
"validation": {
|
|
"data": "not an object"
|
|
}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.validation.unl missing or wrong format
|
|
// invalid xpop.validation.unl (must be object)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": "201C00000000F8E51100612500000052553CEFE169D8DB251A7757C8A80214D7466E81FB2EF6A91E0970B428326B2134EB56A92E4B1340C656FE01A66D529BB7957EAD34D9E193D190EA62AAE4764B5B08C5E624000000026240000000773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481148EA87CA747AF74EE03A7E36C0F8EB1C1568D588AE1E1F1031000",
|
|
"proof": {
|
|
"children": {
|
|
"3": {
|
|
"children": {},
|
|
"hash": "AA126BA0486ADAE575BBC5335E42E236275A452037CA9A876D1A8CDACA1AE542",
|
|
"key": "39D6F6AB7D0A827DD1502B7B9571626A2B601DBE5BC786EF8ADD00E0CB7FCEB3"
|
|
}
|
|
},
|
|
"hash": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
}
|
|
},
|
|
"validation": {
|
|
"data": {
|
|
"n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN": "22800000012600000059292C08FE225149FB62BB67011E9C3F641848E32A209CEAD98BD4D73A78A11F2F92E4AFA65F6A50177BC1723CF6FEDBE539067FF3EA2CF5ADF8FD611DA22B682617DB782041BCA913732103D4A61C3C4E882313665E67471AE9DB28D6679823C760EBA1416B5389EB12A53B76473045022100E53006BDE6CB3ECB7FD08711B103DFD793438751DDFBED5DC421A3C7DE3545C4022045A2332222261A55153A338930545A5F463DAC2E1BF56C4CE5E02726E919A714"
|
|
},
|
|
"unl": "not an object"
|
|
}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.TRANSACTION.DATA
|
|
|
|
// XPOP.validation.data entry has wrong format
|
|
// invalid xpop.validation.data key/value (must be base58 hex string)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A"
|
|
"meta": "201C00000000F8E51100612500000052553CEFE169D8DB251A7757C8A80214D7466E81FB2EF6A91E0970B428326B2134EB56A92E4B1340C656FE01A66D529BB7957EAD34D9E193D190EA62AAE4764B5B08C5E624000000026240000000773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481148EA87CA747AF74EE03A7E36C0F8EB1C1568D588AE1E1F1031000",
|
|
"proof": {
|
|
"children": {
|
|
"3": {
|
|
"children": {},
|
|
"hash": "AA126BA0486ADAE575BBC5335E42E236275A452037CA9A876D1A8CDACA1AE542",
|
|
"key": "39D6F6AB7D0A827DD1502B7B9571626A2B601DBE5BC786EF8ADD00E0CB7FCEB3"
|
|
}
|
|
},
|
|
"hash": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
}
|
|
},
|
|
"validation": {
|
|
"data": {
|
|
"not base 58": "",
|
|
},
|
|
"unl": {}
|
|
}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.validation.unl.public_key missing or
|
|
// invalid xpop.validation.data key/value (must be base58 hex string)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": "201C00000000F8E51100612500000052553CEFE169D8DB251A7757C8A80214D7466E81FB2EF6A91E0970B428326B2134EB56A92E4B1340C656FE01A66D529BB7957EAD34D9E193D190EA62AAE4764B5B08C5E624000000026240000000773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481148EA87CA747AF74EE03A7E36C0F8EB1C1568D588AE1E1F1031000",
|
|
"proof": {
|
|
"children": {
|
|
"3": {
|
|
"children": {},
|
|
"hash": "AA126BA0486ADAE575BBC5335E42E236275A452037CA9A876D1A8CDACA1AE542",
|
|
"key": "39D6F6AB7D0A827DD1502B7B9571626A2B601DBE5BC786EF8ADD00E0CB7FCEB3"
|
|
}
|
|
},
|
|
"hash": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
}
|
|
},
|
|
"validation": {
|
|
"data": {
|
|
"n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN": 1,
|
|
},
|
|
"unl": {}
|
|
}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.validation.unl.public_key invalid key type.
|
|
// invalid xpop.validation.data key/value (must be base58 hex string)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": "201C00000000F8E51100612500000052553CEFE169D8DB251A7757C8A80214D7466E81FB2EF6A91E0970B428326B2134EB56A92E4B1340C656FE01A66D529BB7957EAD34D9E193D190EA62AAE4764B5B08C5E624000000026240000000773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481148EA87CA747AF74EE03A7E36C0F8EB1C1568D588AE1E1F1031000",
|
|
"proof": {
|
|
"children": {
|
|
"3": {
|
|
"children": {},
|
|
"hash": "AA126BA0486ADAE575BBC5335E42E236275A452037CA9A876D1A8CDACA1AE542",
|
|
"key": "39D6F6AB7D0A827DD1502B7B9571626A2B601DBE5BC786EF8ADD00E0CB7FCEB3"
|
|
}
|
|
},
|
|
"hash": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
}
|
|
},
|
|
"validation": {
|
|
"data": {
|
|
"n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN": "not a hex",
|
|
},
|
|
"unl": {}
|
|
}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.TRANSACTION.UNL
|
|
|
|
// XPOP.validation.unl.public_key missing or
|
|
// invalid xpop.validation.unl.public_key (must be hex string with valid
|
|
// key type)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": "201C00000000F8E51100612500000052553CEFE169D8DB251A7757C8A80214D7466E81FB2EF6A91E0970B428326B2134EB56A92E4B1340C656FE01A66D529BB7957EAD34D9E193D190EA62AAE4764B5B08C5E624000000026240000000773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481148EA87CA747AF74EE03A7E36C0F8EB1C1568D588AE1E1F1031000",
|
|
"proof": {
|
|
"children": {
|
|
"3": {
|
|
"children": {},
|
|
"hash": "AA126BA0486ADAE575BBC5335E42E236275A452037CA9A876D1A8CDACA1AE542",
|
|
"key": "39D6F6AB7D0A827DD1502B7B9571626A2B601DBE5BC786EF8ADD00E0CB7FCEB3"
|
|
}
|
|
},
|
|
"hash": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
}
|
|
},
|
|
"validation": {
|
|
"data": {
|
|
"n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN": "22800000012600000059292C08FE225149FB62BB67011E9C3F641848E32A209CEAD98BD4D73A78A11F2F92E4AFA65F6A50177BC1723CF6FEDBE539067FF3EA2CF5ADF8FD611DA22B682617DB782041BCA913732103D4A61C3C4E882313665E67471AE9DB28D6679823C760EBA1416B5389EB12A53B76473045022100E53006BDE6CB3ECB7FD08711B103DFD793438751DDFBED5DC421A3C7DE3545C4022045A2332222261A55153A338930545A5F463DAC2E1BF56C4CE5E02726E919A714"
|
|
},
|
|
"unl": {
|
|
"public_key": 1
|
|
}
|
|
}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.validation.unl.public_key missing or
|
|
// invalid xpop.validation.unl.public_key (must be hex string with valid
|
|
// key type)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": "201C00000000F8E51100612500000052553CEFE169D8DB251A7757C8A80214D7466E81FB2EF6A91E0970B428326B2134EB56A92E4B1340C656FE01A66D529BB7957EAD34D9E193D190EA62AAE4764B5B08C5E624000000026240000000773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481148EA87CA747AF74EE03A7E36C0F8EB1C1568D588AE1E1F1031000",
|
|
"proof": {
|
|
"children": {
|
|
"3": {
|
|
"children": {},
|
|
"hash": "AA126BA0486ADAE575BBC5335E42E236275A452037CA9A876D1A8CDACA1AE542",
|
|
"key": "39D6F6AB7D0A827DD1502B7B9571626A2B601DBE5BC786EF8ADD00E0CB7FCEB3"
|
|
}
|
|
},
|
|
"hash": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
}
|
|
},
|
|
"validation": {
|
|
"data": {
|
|
"n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN": "22800000012600000059292C08FE225149FB62BB67011E9C3F641848E32A209CEAD98BD4D73A78A11F2F92E4AFA65F6A50177BC1723CF6FEDBE539067FF3EA2CF5ADF8FD611DA22B682617DB782041BCA913732103D4A61C3C4E882313665E67471AE9DB28D6679823C760EBA1416B5389EB12A53B76473045022100E53006BDE6CB3ECB7FD08711B103DFD793438751DDFBED5DC421A3C7DE3545C4022045A2332222261A55153A338930545A5F463DAC2E1BF56C4CE5E02726E919A714"
|
|
},
|
|
"unl": {
|
|
"public_key": "not a hex"
|
|
}
|
|
}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.validation.unl.public_key missing or
|
|
// invalid xpop.validation.unl.public_key (must be hex string with valid
|
|
// key type)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": "201C00000000F8E51100612500000052553CEFE169D8DB251A7757C8A80214D7466E81FB2EF6A91E0970B428326B2134EB56A92E4B1340C656FE01A66D529BB7957EAD34D9E193D190EA62AAE4764B5B08C5E624000000026240000000773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481148EA87CA747AF74EE03A7E36C0F8EB1C1568D588AE1E1F1031000",
|
|
"proof": {
|
|
"children": {
|
|
"3": {
|
|
"children": {},
|
|
"hash": "AA126BA0486ADAE575BBC5335E42E236275A452037CA9A876D1A8CDACA1AE542",
|
|
"key": "39D6F6AB7D0A827DD1502B7B9571626A2B601DBE5BC786EF8ADD00E0CB7FCEB3"
|
|
}
|
|
},
|
|
"hash": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
}
|
|
},
|
|
"validation": {
|
|
"data": {
|
|
"n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN": "22800000012600000059292C08FE225149FB62BB67011E9C3F641848E32A209CEAD98BD4D73A78A11F2F92E4AFA65F6A50177BC1723CF6FEDBE539067FF3EA2CF5ADF8FD611DA22B682617DB782041BCA913732103D4A61C3C4E882313665E67471AE9DB28D6679823C760EBA1416B5389EB12A53B76473045022100E53006BDE6CB3ECB7FD08711B103DFD793438751DDFBED5DC421A3C7DE3545C4022045A2332222261A55153A338930545A5F463DAC2E1BF56C4CE5E02726E919A714"
|
|
},
|
|
"unl": {
|
|
"public_key": "0074D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1CDC1"
|
|
}
|
|
}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.validation.unl.manifest missing or wrong
|
|
// invalid xpop.validation.unl.manifest (must be string)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": "201C00000000F8E51100612500000052553CEFE169D8DB251A7757C8A80214D7466E81FB2EF6A91E0970B428326B2134EB56A92E4B1340C656FE01A66D529BB7957EAD34D9E193D190EA62AAE4764B5B08C5E624000000026240000000773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481148EA87CA747AF74EE03A7E36C0F8EB1C1568D588AE1E1F1031000",
|
|
"proof": {
|
|
"children": {
|
|
"3": {
|
|
"children": {},
|
|
"hash": "AA126BA0486ADAE575BBC5335E42E236275A452037CA9A876D1A8CDACA1AE542",
|
|
"key": "39D6F6AB7D0A827DD1502B7B9571626A2B601DBE5BC786EF8ADD00E0CB7FCEB3"
|
|
}
|
|
},
|
|
"hash": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
}
|
|
},
|
|
"validation": {
|
|
"data": {
|
|
"n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN": "22800000012600000059292C08FE225149FB62BB67011E9C3F641848E32A209CEAD98BD4D73A78A11F2F92E4AFA65F6A50177BC1723CF6FEDBE539067FF3EA2CF5ADF8FD611DA22B682617DB782041BCA913732103D4A61C3C4E882313665E67471AE9DB28D6679823C760EBA1416B5389EB12A53B76473045022100E53006BDE6CB3ECB7FD08711B103DFD793438751DDFBED5DC421A3C7DE3545C4022045A2332222261A55153A338930545A5F463DAC2E1BF56C4CE5E02726E919A714"
|
|
},
|
|
"unl": {
|
|
"public_key": "ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1CDC1",
|
|
"manifest": 1
|
|
}
|
|
}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.validation.unl.blob missing or wrong
|
|
// invalid xpop.validation.unl.blob (must be base 64 string)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": "201C00000000F8E51100612500000052553CEFE169D8DB251A7757C8A80214D7466E81FB2EF6A91E0970B428326B2134EB56A92E4B1340C656FE01A66D529BB7957EAD34D9E193D190EA62AAE4764B5B08C5E624000000026240000000773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481148EA87CA747AF74EE03A7E36C0F8EB1C1568D588AE1E1F1031000",
|
|
"proof": {
|
|
"children": {
|
|
"3": {
|
|
"children": {},
|
|
"hash": "AA126BA0486ADAE575BBC5335E42E236275A452037CA9A876D1A8CDACA1AE542",
|
|
"key": "39D6F6AB7D0A827DD1502B7B9571626A2B601DBE5BC786EF8ADD00E0CB7FCEB3"
|
|
}
|
|
},
|
|
"hash": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
}
|
|
},
|
|
"validation": {
|
|
"data": {
|
|
"n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN": "22800000012600000059292C08FE225149FB62BB67011E9C3F641848E32A209CEAD98BD4D73A78A11F2F92E4AFA65F6A50177BC1723CF6FEDBE539067FF3EA2CF5ADF8FD611DA22B682617DB782041BCA913732103D4A61C3C4E882313665E67471AE9DB28D6679823C760EBA1416B5389EB12A53B76473045022100E53006BDE6CB3ECB7FD08711B103DFD793438751DDFBED5DC421A3C7DE3545C4022045A2332222261A55153A338930545A5F463DAC2E1BF56C4CE5E02726E919A714"
|
|
},
|
|
"unl": {
|
|
"public_key": "ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1CDC1",
|
|
"manifest": "JAAAAAFxIe101ANsZZGkvfnFTO+jm5lqXc5fhtEf2hh0SBzp1aHNwXMh7TN9+b62cZqTngaFYU5tbGpYHC8oYuI3G3vwj9OW2Z9gdkAnUjfY5zOEkhq31tU4338jcyUpVA5/VTsANFce7unDo+JeVoEhfuOb/Y8WA3Diu9XzuOD4U/ikfgf9SZOlOGcBcBJAw44PLjH+HUtEnwX45lIRmo0x5aINFMvZsBpE9QteSDBXKwYzLdnSW4e1bs21o+IILJIiIKU/+1Uxx0FRpQbMDA==",
|
|
"blob": 1
|
|
}
|
|
}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.validation.unl.blob missing or wrong
|
|
// invalid xpop.validation.unl.blob (must be base 64 string)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": "201C00000000F8E51100612500000052553CEFE169D8DB251A7757C8A80214D7466E81FB2EF6A91E0970B428326B2134EB56A92E4B1340C656FE01A66D529BB7957EAD34D9E193D190EA62AAE4764B5B08C5E624000000026240000000773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481148EA87CA747AF74EE03A7E36C0F8EB1C1568D588AE1E1F1031000",
|
|
"proof": {
|
|
"children": {
|
|
"3": {
|
|
"children": {},
|
|
"hash": "AA126BA0486ADAE575BBC5335E42E236275A452037CA9A876D1A8CDACA1AE542",
|
|
"key": "39D6F6AB7D0A827DD1502B7B9571626A2B601DBE5BC786EF8ADD00E0CB7FCEB3"
|
|
}
|
|
},
|
|
"hash": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
}
|
|
},
|
|
"validation": {
|
|
"data": {
|
|
"n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN": "22800000012600000059292C08FE225149FB62BB67011E9C3F641848E32A209CEAD98BD4D73A78A11F2F92E4AFA65F6A50177BC1723CF6FEDBE539067FF3EA2CF5ADF8FD611DA22B682617DB782041BCA913732103D4A61C3C4E882313665E67471AE9DB28D6679823C760EBA1416B5389EB12A53B76473045022100E53006BDE6CB3ECB7FD08711B103DFD793438751DDFBED5DC421A3C7DE3545C4022045A2332222261A55153A338930545A5F463DAC2E1BF56C4CE5E02726E919A714"
|
|
},
|
|
"unl": {
|
|
"public_key": "ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1CDC1",
|
|
"manifest": "JAAAAAFxIe101ANsZZGkvfnFTO+jm5lqXc5fhtEf2hh0SBzp1aHNwXMh7TN9+b62cZqTngaFYU5tbGpYHC8oYuI3G3vwj9OW2Z9gdkAnUjfY5zOEkhq31tU4338jcyUpVA5/VTsANFce7unDo+JeVoEhfuOb/Y8WA3Diu9XzuOD4U/ikfgf9SZOlOGcBcBJAw44PLjH+HUtEnwX45lIRmo0x5aINFMvZsBpE9QteSDBXKwYzLdnSW4e1bs21o+IILJIiIKU/+1Uxx0FRpQbMDA==",
|
|
"blob": "not a base 64 string"
|
|
}
|
|
}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.validation.unl.signature missing or wrong
|
|
// invalid xpop.validation.unl.signature (must be hex string)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": "201C00000000F8E51100612500000052553CEFE169D8DB251A7757C8A80214D7466E81FB2EF6A91E0970B428326B2134EB56A92E4B1340C656FE01A66D529BB7957EAD34D9E193D190EA62AAE4764B5B08C5E624000000026240000000773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481148EA87CA747AF74EE03A7E36C0F8EB1C1568D588AE1E1F1031000",
|
|
"proof": {
|
|
"children": {
|
|
"3": {
|
|
"children": {},
|
|
"hash": "AA126BA0486ADAE575BBC5335E42E236275A452037CA9A876D1A8CDACA1AE542",
|
|
"key": "39D6F6AB7D0A827DD1502B7B9571626A2B601DBE5BC786EF8ADD00E0CB7FCEB3"
|
|
}
|
|
},
|
|
"hash": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
}
|
|
},
|
|
"validation": {
|
|
"data": {
|
|
"n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN": "22800000012600000059292C08FE225149FB62BB67011E9C3F641848E32A209CEAD98BD4D73A78A11F2F92E4AFA65F6A50177BC1723CF6FEDBE539067FF3EA2CF5ADF8FD611DA22B682617DB782041BCA913732103D4A61C3C4E882313665E67471AE9DB28D6679823C760EBA1416B5389EB12A53B76473045022100E53006BDE6CB3ECB7FD08711B103DFD793438751DDFBED5DC421A3C7DE3545C4022045A2332222261A55153A338930545A5F463DAC2E1BF56C4CE5E02726E919A714"
|
|
},
|
|
"unl": {
|
|
"public_key": "ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1CDC1",
|
|
"manifest": "JAAAAAFxIe101ANsZZGkvfnFTO+jm5lqXc5fhtEf2hh0SBzp1aHNwXMh7TN9+b62cZqTngaFYU5tbGpYHC8oYuI3G3vwj9OW2Z9gdkAnUjfY5zOEkhq31tU4338jcyUpVA5/VTsANFce7unDo+JeVoEhfuOb/Y8WA3Diu9XzuOD4U/ikfgf9SZOlOGcBcBJAw44PLjH+HUtEnwX45lIRmo0x5aINFMvZsBpE9QteSDBXKwYzLdnSW4e1bs21o+IILJIiIKU/+1Uxx0FRpQbMDA==",
|
|
"blob": "eyJzZXF1ZW5jZSI6MiwiZXhwaXJhdGlvbiI6NzQxMzk4NDAwLCJ2YWxpZGF0b3JzIjpbeyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDM4QkQ0NDVBRkQ2MjE1OTYyMENDMTk2QzI2NjhBMjZCNkZCQjM2QjA5OUVCNTVCMzhBNThDMTFDMTIwNERFNUMiLCJtYW5pZmVzdCI6IkpBQUFBQUp4SWUwNHZVUmEvV0lWbGlETUdXd21hS0pyYjdzMnNKbnJWYk9LV01FY0VnVGVYSE1oQW9HTU5jc2dVVU53S28raDd6aGFYS0YrSEd3NlhoRWpvREtyYWxrWW5Naktka2N3UlFJaEFKN2NONEo2TmRWZnBudkVJL1pldVdDVHZucGFKaXJLTkZjQzN6TU9qZ3dqQWlBYktJMGZiWGdTMVJMbG9OaHhkSGhWcTlvekVXVkU5Y0l3WEROM0F4cXlZM0FTUUN0MCt1L2lOU0RENmJYdlVUdGRtdDROcnRsYng0Vnp1bVRwZmpSWXA0bE1vSS9oNDNwVVRqcDdWRm9YYm5LV2pWaHFOYUdtNTc3SzZKNjk3WFo3VFFFPSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRURCRUUzMEZBRTkyRUVFODhFMUM0OTgwRDA5RUNGREU5OUExMTZEMDc4RUMyMTg1N0RCMUI0N0I0MjY0MThFNDI4IiwibWFuaWZlc3QiOiJKQUFBQUFKeEllMis0dyt1a3U3b2poeEpnTkNlejk2Wm9SYlFlT3doaFgyeHRIdENaQmprS0hNaEE5U21IRHhPaUNNVFpsNW5SeHJwMnlqV1o1Z2p4MkRyb1VGclU0bnJFcVU3ZGtjd1JRSWhBTGRFRmVqWStwVW5nbGk3c1R2aWIwQm1ESFA3TjZpa1ZFQkk2SDdJd1UxekFpQmRzeW9TcVBjQzJOTXFnQW5IWEhHZGtBSXdCUUQxQVVnOVg4WkpMeWZjd0hBU1FDdDFiS1Z6T014UlFtUjN3Tks0ZEtkb2ZJR3J4RTlTanVMUjZQYThCNW4wOFNZSjhLNjJnZSs5YTZCdFphbEVtL0hPZGN6ME5BRk9jeWNyRi9DdFNBND0ifV19",
|
|
"signature": 1
|
|
}
|
|
}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.validation.unl.signature missing or wrong
|
|
// invalid xpop.validation.unl.signature (must be hex string)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": "201C00000000F8E51100612500000052553CEFE169D8DB251A7757C8A80214D7466E81FB2EF6A91E0970B428326B2134EB56A92E4B1340C656FE01A66D529BB7957EAD34D9E193D190EA62AAE4764B5B08C5E624000000026240000000773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481148EA87CA747AF74EE03A7E36C0F8EB1C1568D588AE1E1F1031000",
|
|
"proof": {
|
|
"children": {
|
|
"3": {
|
|
"children": {},
|
|
"hash": "AA126BA0486ADAE575BBC5335E42E236275A452037CA9A876D1A8CDACA1AE542",
|
|
"key": "39D6F6AB7D0A827DD1502B7B9571626A2B601DBE5BC786EF8ADD00E0CB7FCEB3"
|
|
}
|
|
},
|
|
"hash": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
}
|
|
},
|
|
"validation": {
|
|
"data": {
|
|
"n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN": "22800000012600000059292C08FE225149FB62BB67011E9C3F641848E32A209CEAD98BD4D73A78A11F2F92E4AFA65F6A50177BC1723CF6FEDBE539067FF3EA2CF5ADF8FD611DA22B682617DB782041BCA913732103D4A61C3C4E882313665E67471AE9DB28D6679823C760EBA1416B5389EB12A53B76473045022100E53006BDE6CB3ECB7FD08711B103DFD793438751DDFBED5DC421A3C7DE3545C4022045A2332222261A55153A338930545A5F463DAC2E1BF56C4CE5E02726E919A714"
|
|
},
|
|
"unl": {
|
|
"public_key": "ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1CDC1",
|
|
"manifest": "JAAAAAFxIe101ANsZZGkvfnFTO+jm5lqXc5fhtEf2hh0SBzp1aHNwXMh7TN9+b62cZqTngaFYU5tbGpYHC8oYuI3G3vwj9OW2Z9gdkAnUjfY5zOEkhq31tU4338jcyUpVA5/VTsANFce7unDo+JeVoEhfuOb/Y8WA3Diu9XzuOD4U/ikfgf9SZOlOGcBcBJAw44PLjH+HUtEnwX45lIRmo0x5aINFMvZsBpE9QteSDBXKwYzLdnSW4e1bs21o+IILJIiIKU/+1Uxx0FRpQbMDA==",
|
|
"blob": "eyJzZXF1ZW5jZSI6MiwiZXhwaXJhdGlvbiI6NzQxMzk4NDAwLCJ2YWxpZGF0b3JzIjpbeyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDM4QkQ0NDVBRkQ2MjE1OTYyMENDMTk2QzI2NjhBMjZCNkZCQjM2QjA5OUVCNTVCMzhBNThDMTFDMTIwNERFNUMiLCJtYW5pZmVzdCI6IkpBQUFBQUp4SWUwNHZVUmEvV0lWbGlETUdXd21hS0pyYjdzMnNKbnJWYk9LV01FY0VnVGVYSE1oQW9HTU5jc2dVVU53S28raDd6aGFYS0YrSEd3NlhoRWpvREtyYWxrWW5Naktka2N3UlFJaEFKN2NONEo2TmRWZnBudkVJL1pldVdDVHZucGFKaXJLTkZjQzN6TU9qZ3dqQWlBYktJMGZiWGdTMVJMbG9OaHhkSGhWcTlvekVXVkU5Y0l3WEROM0F4cXlZM0FTUUN0MCt1L2lOU0RENmJYdlVUdGRtdDROcnRsYng0Vnp1bVRwZmpSWXA0bE1vSS9oNDNwVVRqcDdWRm9YYm5LV2pWaHFOYUdtNTc3SzZKNjk3WFo3VFFFPSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRURCRUUzMEZBRTkyRUVFODhFMUM0OTgwRDA5RUNGREU5OUExMTZEMDc4RUMyMTg1N0RCMUI0N0I0MjY0MThFNDI4IiwibWFuaWZlc3QiOiJKQUFBQUFKeEllMis0dyt1a3U3b2poeEpnTkNlejk2Wm9SYlFlT3doaFgyeHRIdENaQmprS0hNaEE5U21IRHhPaUNNVFpsNW5SeHJwMnlqV1o1Z2p4MkRyb1VGclU0bnJFcVU3ZGtjd1JRSWhBTGRFRmVqWStwVW5nbGk3c1R2aWIwQm1ESFA3TjZpa1ZFQkk2SDdJd1UxekFpQmRzeW9TcVBjQzJOTXFnQW5IWEhHZGtBSXdCUUQxQVVnOVg4WkpMeWZjd0hBU1FDdDFiS1Z6T014UlFtUjN3Tks0ZEtkb2ZJR3J4RTlTanVMUjZQYThCNW4wOFNZSjhLNjJnZSs5YTZCdFphbEVtL0hPZGN6ME5BRk9jeWNyRi9DdFNBND0ifV19",
|
|
"signature": "not a hex"
|
|
}
|
|
}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.validation.unl.version missing or
|
|
// invalid xpop.validation.unl.version (must be int)
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": "201C00000000F8E51100612500000052553CEFE169D8DB251A7757C8A80214D7466E81FB2EF6A91E0970B428326B2134EB56A92E4B1340C656FE01A66D529BB7957EAD34D9E193D190EA62AAE4764B5B08C5E624000000026240000000773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481148EA87CA747AF74EE03A7E36C0F8EB1C1568D588AE1E1F1031000",
|
|
"proof": {
|
|
"children": {
|
|
"3": {
|
|
"children": {},
|
|
"hash": "AA126BA0486ADAE575BBC5335E42E236275A452037CA9A876D1A8CDACA1AE542",
|
|
"key": "39D6F6AB7D0A827DD1502B7B9571626A2B601DBE5BC786EF8ADD00E0CB7FCEB3"
|
|
}
|
|
},
|
|
"hash": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
}
|
|
},
|
|
"validation": {
|
|
"data": {
|
|
"n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN": "22800000012600000059292C08FE225149FB62BB67011E9C3F641848E32A209CEAD98BD4D73A78A11F2F92E4AFA65F6A50177BC1723CF6FEDBE539067FF3EA2CF5ADF8FD611DA22B682617DB782041BCA913732103D4A61C3C4E882313665E67471AE9DB28D6679823C760EBA1416B5389EB12A53B76473045022100E53006BDE6CB3ECB7FD08711B103DFD793438751DDFBED5DC421A3C7DE3545C4022045A2332222261A55153A338930545A5F463DAC2E1BF56C4CE5E02726E919A714"
|
|
},
|
|
"unl": {
|
|
"public_key": "ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1CDC1",
|
|
"manifest": "JAAAAAFxIe101ANsZZGkvfnFTO+jm5lqXc5fhtEf2hh0SBzp1aHNwXMh7TN9+b62cZqTngaFYU5tbGpYHC8oYuI3G3vwj9OW2Z9gdkAnUjfY5zOEkhq31tU4338jcyUpVA5/VTsANFce7unDo+JeVoEhfuOb/Y8WA3Diu9XzuOD4U/ikfgf9SZOlOGcBcBJAw44PLjH+HUtEnwX45lIRmo0x5aINFMvZsBpE9QteSDBXKwYzLdnSW4e1bs21o+IILJIiIKU/+1Uxx0FRpQbMDA==",
|
|
"blob": "eyJzZXF1ZW5jZSI6MiwiZXhwaXJhdGlvbiI6NzQxMzk4NDAwLCJ2YWxpZGF0b3JzIjpbeyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDM4QkQ0NDVBRkQ2MjE1OTYyMENDMTk2QzI2NjhBMjZCNkZCQjM2QjA5OUVCNTVCMzhBNThDMTFDMTIwNERFNUMiLCJtYW5pZmVzdCI6IkpBQUFBQUp4SWUwNHZVUmEvV0lWbGlETUdXd21hS0pyYjdzMnNKbnJWYk9LV01FY0VnVGVYSE1oQW9HTU5jc2dVVU53S28raDd6aGFYS0YrSEd3NlhoRWpvREtyYWxrWW5Naktka2N3UlFJaEFKN2NONEo2TmRWZnBudkVJL1pldVdDVHZucGFKaXJLTkZjQzN6TU9qZ3dqQWlBYktJMGZiWGdTMVJMbG9OaHhkSGhWcTlvekVXVkU5Y0l3WEROM0F4cXlZM0FTUUN0MCt1L2lOU0RENmJYdlVUdGRtdDROcnRsYng0Vnp1bVRwZmpSWXA0bE1vSS9oNDNwVVRqcDdWRm9YYm5LV2pWaHFOYUdtNTc3SzZKNjk3WFo3VFFFPSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRURCRUUzMEZBRTkyRUVFODhFMUM0OTgwRDA5RUNGREU5OUExMTZEMDc4RUMyMTg1N0RCMUI0N0I0MjY0MThFNDI4IiwibWFuaWZlc3QiOiJKQUFBQUFKeEllMis0dyt1a3U3b2poeEpnTkNlejk2Wm9SYlFlT3doaFgyeHRIdENaQmprS0hNaEE5U21IRHhPaUNNVFpsNW5SeHJwMnlqV1o1Z2p4MkRyb1VGclU0bnJFcVU3ZGtjd1JRSWhBTGRFRmVqWStwVW5nbGk3c1R2aWIwQm1ESFA3TjZpa1ZFQkk2SDdJd1UxekFpQmRzeW9TcVBjQzJOTXFnQW5IWEhHZGtBSXdCUUQxQVVnOVg4WkpMeWZjd0hBU1FDdDFiS1Z6T014UlFtUjN3Tks0ZEtkb2ZJR3J4RTlTanVMUjZQYThCNW4wOFNZSjhLNjJnZSs5YTZCdFphbEVtL0hPZGN6ME5BRk9jeWNyRi9DdFNBND0ifV19",
|
|
"signature": "849F6B8DA6E11C213B561659C16F13D35385E8EA9E775483ADC84578F6D578943DE5EB681584B2C03EFFFDFD216F9E0B21576E482F941C7195893B72B5B1F70D",
|
|
"version": "not an int"
|
|
}
|
|
}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(
|
|
syntaxCheckXPOP(raw, env.journal).has_value() == false);
|
|
}
|
|
|
|
// XPOP.validation.unl entry has wrong format
|
|
|
|
// valid xpop
|
|
{
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": "201C00000000F8E51100612500000052553CEFE169D8DB251A7757C8A80214D7466E81FB2EF6A91E0970B428326B2134EB56A92E4B1340C656FE01A66D529BB7957EAD34D9E193D190EA62AAE4764B5B08C5E624000000026240000000773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481148EA87CA747AF74EE03A7E36C0F8EB1C1568D588AE1E1F1031000",
|
|
"proof": {
|
|
"children": {
|
|
"3": {
|
|
"children": {},
|
|
"hash": "AA126BA0486ADAE575BBC5335E42E236275A452037CA9A876D1A8CDACA1AE542",
|
|
"key": "39D6F6AB7D0A827DD1502B7B9571626A2B601DBE5BC786EF8ADD00E0CB7FCEB3"
|
|
}
|
|
},
|
|
"hash": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
}
|
|
},
|
|
"validation": {
|
|
"data": {
|
|
"n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN": "22800000012600000059292C08FE225149FB62BB67011E9C3F641848E32A209CEAD98BD4D73A78A11F2F92E4AFA65F6A50177BC1723CF6FEDBE539067FF3EA2CF5ADF8FD611DA22B682617DB782041BCA913732103D4A61C3C4E882313665E67471AE9DB28D6679823C760EBA1416B5389EB12A53B76473045022100E53006BDE6CB3ECB7FD08711B103DFD793438751DDFBED5DC421A3C7DE3545C4022045A2332222261A55153A338930545A5F463DAC2E1BF56C4CE5E02726E919A714"
|
|
},
|
|
"unl": {
|
|
"public_key": "ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1CDC1",
|
|
"manifest": "JAAAAAFxIe101ANsZZGkvfnFTO+jm5lqXc5fhtEf2hh0SBzp1aHNwXMh7TN9+b62cZqTngaFYU5tbGpYHC8oYuI3G3vwj9OW2Z9gdkAnUjfY5zOEkhq31tU4338jcyUpVA5/VTsANFce7unDo+JeVoEhfuOb/Y8WA3Diu9XzuOD4U/ikfgf9SZOlOGcBcBJAw44PLjH+HUtEnwX45lIRmo0x5aINFMvZsBpE9QteSDBXKwYzLdnSW4e1bs21o+IILJIiIKU/+1Uxx0FRpQbMDA==",
|
|
"blob": "eyJzZXF1ZW5jZSI6MiwiZXhwaXJhdGlvbiI6NzQxMzk4NDAwLCJ2YWxpZGF0b3JzIjpbeyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDM4QkQ0NDVBRkQ2MjE1OTYyMENDMTk2QzI2NjhBMjZCNkZCQjM2QjA5OUVCNTVCMzhBNThDMTFDMTIwNERFNUMiLCJtYW5pZmVzdCI6IkpBQUFBQUp4SWUwNHZVUmEvV0lWbGlETUdXd21hS0pyYjdzMnNKbnJWYk9LV01FY0VnVGVYSE1oQW9HTU5jc2dVVU53S28raDd6aGFYS0YrSEd3NlhoRWpvREtyYWxrWW5Naktka2N3UlFJaEFKN2NONEo2TmRWZnBudkVJL1pldVdDVHZucGFKaXJLTkZjQzN6TU9qZ3dqQWlBYktJMGZiWGdTMVJMbG9OaHhkSGhWcTlvekVXVkU5Y0l3WEROM0F4cXlZM0FTUUN0MCt1L2lOU0RENmJYdlVUdGRtdDROcnRsYng0Vnp1bVRwZmpSWXA0bE1vSS9oNDNwVVRqcDdWRm9YYm5LV2pWaHFOYUdtNTc3SzZKNjk3WFo3VFFFPSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRURCRUUzMEZBRTkyRUVFODhFMUM0OTgwRDA5RUNGREU5OUExMTZEMDc4RUMyMTg1N0RCMUI0N0I0MjY0MThFNDI4IiwibWFuaWZlc3QiOiJKQUFBQUFKeEllMis0dyt1a3U3b2poeEpnTkNlejk2Wm9SYlFlT3doaFgyeHRIdENaQmprS0hNaEE5U21IRHhPaUNNVFpsNW5SeHJwMnlqV1o1Z2p4MkRyb1VGclU0bnJFcVU3ZGtjd1JRSWhBTGRFRmVqWStwVW5nbGk3c1R2aWIwQm1ESFA3TjZpa1ZFQkk2SDdJd1UxekFpQmRzeW9TcVBjQzJOTXFnQW5IWEhHZGtBSXdCUUQxQVVnOVg4WkpMeWZjd0hBU1FDdDFiS1Z6T014UlFtUjN3Tks0ZEtkb2ZJR3J4RTlTanVMUjZQYThCNW4wOFNZSjhLNjJnZSs5YTZCdFphbEVtL0hPZGN6ME5BRk9jeWNyRi9DdFNBND0ifV19",
|
|
"signature": "849F6B8DA6E11C213B561659C16F13D35385E8EA9E775483ADC84578F6D578943DE5EB681584B2C03EFFFDFD216F9E0B21576E482F941C7195893B72B5B1F70D",
|
|
"version": 1
|
|
}
|
|
}
|
|
})json";
|
|
Blob raw = Blob(strJson.begin(), strJson.end());
|
|
BEAST_EXPECT(syntaxCheckXPOP(raw, env.journal).has_value() == true);
|
|
}
|
|
}
|
|
|
|
void
|
|
testGetVLInfo(FeatureBitset features)
|
|
{
|
|
testcase("import utils - getVLInfo");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
std::string strJson = R"json({
|
|
"ledger": {
|
|
"acroot": "DCE36DCACDCFCB3441866E09A183B7B8064B3F5E06593CD6AA8ACCC1B284B477",
|
|
"txroot": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"phash": "BAB19E13B25251A83493073F424FD986EA7BA49F9F4C83A061700131460D747D",
|
|
"close": 738786851,
|
|
"coins": "99999998999999868",
|
|
"cres": 10,
|
|
"flags": 10,
|
|
"pclose": 738786851
|
|
},
|
|
"transaction": {
|
|
"blob": "12000322000000002400000002201B0000006C201D0000535968400000003B9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519560F81148EA87CA747AF74EE03A7E36C0F8EB1C1568D588A",
|
|
"meta": "201C00000000F8E51100612500000052553CEFE169D8DB251A7757C8A80214D7466E81FB2EF6A91E0970B428326B2134EB56A92E4B1340C656FE01A66D529BB7957EAD34D9E193D190EA62AAE4764B5B08C5E624000000026240000000773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481148EA87CA747AF74EE03A7E36C0F8EB1C1568D588AE1E1F1031000",
|
|
"proof": {
|
|
"children": {
|
|
"3": {
|
|
"children": {},
|
|
"hash": "AA126BA0486ADAE575BBC5335E42E236275A452037CA9A876D1A8CDACA1AE542",
|
|
"key": "39D6F6AB7D0A827DD1502B7B9571626A2B601DBE5BC786EF8ADD00E0CB7FCEB3"
|
|
}
|
|
},
|
|
"hash": "409C8D073DDB5AB07FD2CD4F14467A8F3BC8FFBA16A0032D12D823D8511C12F4",
|
|
"key": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
}
|
|
},
|
|
"validation": {
|
|
"data": {
|
|
"n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN": "22800000012600000059292C08FE225149FB62BB67011E9C3F641848E32A209CEAD98BD4D73A78A11F2F92E4AFA65F6A50177BC1723CF6FEDBE539067FF3EA2CF5ADF8FD611DA22B682617DB782041BCA913732103D4A61C3C4E882313665E67471AE9DB28D6679823C760EBA1416B5389EB12A53B76473045022100E53006BDE6CB3ECB7FD08711B103DFD793438751DDFBED5DC421A3C7DE3545C4022045A2332222261A55153A338930545A5F463DAC2E1BF56C4CE5E02726E919A714"
|
|
},
|
|
"unl": {
|
|
"public_key": "ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1CDC1",
|
|
"manifest": "JAAAAAFxIe101ANsZZGkvfnFTO+jm5lqXc5fhtEf2hh0SBzp1aHNwXMh7TN9+b62cZqTngaFYU5tbGpYHC8oYuI3G3vwj9OW2Z9gdkAnUjfY5zOEkhq31tU4338jcyUpVA5/VTsANFce7unDo+JeVoEhfuOb/Y8WA3Diu9XzuOD4U/ikfgf9SZOlOGcBcBJAw44PLjH+HUtEnwX45lIRmo0x5aINFMvZsBpE9QteSDBXKwYzLdnSW4e1bs21o+IILJIiIKU/+1Uxx0FRpQbMDA==",
|
|
"blob": "eyJzZXF1ZW5jZSI6MiwiZXhwaXJhdGlvbiI6NzQxMzk4NDAwLCJ2YWxpZGF0b3JzIjpbeyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDM4QkQ0NDVBRkQ2MjE1OTYyMENDMTk2QzI2NjhBMjZCNkZCQjM2QjA5OUVCNTVCMzhBNThDMTFDMTIwNERFNUMiLCJtYW5pZmVzdCI6IkpBQUFBQUp4SWUwNHZVUmEvV0lWbGlETUdXd21hS0pyYjdzMnNKbnJWYk9LV01FY0VnVGVYSE1oQW9HTU5jc2dVVU53S28raDd6aGFYS0YrSEd3NlhoRWpvREtyYWxrWW5Naktka2N3UlFJaEFKN2NONEo2TmRWZnBudkVJL1pldVdDVHZucGFKaXJLTkZjQzN6TU9qZ3dqQWlBYktJMGZiWGdTMVJMbG9OaHhkSGhWcTlvekVXVkU5Y0l3WEROM0F4cXlZM0FTUUN0MCt1L2lOU0RENmJYdlVUdGRtdDROcnRsYng0Vnp1bVRwZmpSWXA0bE1vSS9oNDNwVVRqcDdWRm9YYm5LV2pWaHFOYUdtNTc3SzZKNjk3WFo3VFFFPSJ9LHsidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRURCRUUzMEZBRTkyRUVFODhFMUM0OTgwRDA5RUNGREU5OUExMTZEMDc4RUMyMTg1N0RCMUI0N0I0MjY0MThFNDI4IiwibWFuaWZlc3QiOiJKQUFBQUFKeEllMis0dyt1a3U3b2poeEpnTkNlejk2Wm9SYlFlT3doaFgyeHRIdENaQmprS0hNaEE5U21IRHhPaUNNVFpsNW5SeHJwMnlqV1o1Z2p4MkRyb1VGclU0bnJFcVU3ZGtjd1JRSWhBTGRFRmVqWStwVW5nbGk3c1R2aWIwQm1ESFA3TjZpa1ZFQkk2SDdJd1UxekFpQmRzeW9TcVBjQzJOTXFnQW5IWEhHZGtBSXdCUUQxQVVnOVg4WkpMeWZjd0hBU1FDdDFiS1Z6T014UlFtUjN3Tks0ZEtkb2ZJR3J4RTlTanVMUjZQYThCNW4wOFNZSjhLNjJnZSs5YTZCdFphbEVtL0hPZGN6ME5BRk9jeWNyRi9DdFNBND0ifV19",
|
|
"signature": "849F6B8DA6E11C213B561659C16F13D35385E8EA9E775483ADC84578F6D578943DE5EB681584B2C03EFFFDFD216F9E0B21576E482F941C7195893B72B5B1F70D",
|
|
"version": 1
|
|
}
|
|
}
|
|
})json";
|
|
|
|
Json::Value xpop;
|
|
Json::Reader reader;
|
|
reader.parse(strJson, xpop);
|
|
Json::FastWriter writer;
|
|
|
|
// Import: unl blob was not valid json (after base64 decoding)
|
|
{
|
|
Json::Value tmpXpop = xpop;
|
|
tmpXpop[jss::validation][jss::unl][jss::blob] = "YmFkSnNvbg==";
|
|
std::string strJson = writer.write(tmpXpop);
|
|
Blob raw(strJson.begin(), strJson.end());
|
|
auto const xpop = syntaxCheckXPOP(raw, env.journal);
|
|
BEAST_EXPECT(getVLInfo(*xpop, env.journal).has_value() == false);
|
|
}
|
|
|
|
// Import: failed to deserialize manifest
|
|
{
|
|
Json::Value tmpXpop = xpop;
|
|
tmpXpop[jss::validation][jss::unl][jss::manifest] = "YmFkSnNvbg==";
|
|
std::string strJson = writer.write(tmpXpop);
|
|
Blob raw(strJson.begin(), strJson.end());
|
|
auto const xpop = syntaxCheckXPOP(raw, env.journal);
|
|
BEAST_EXPECT(getVLInfo(*xpop, env.journal).has_value() == false);
|
|
}
|
|
|
|
// Import: valid unl blob
|
|
{
|
|
Json::Value tmpXpop = xpop;
|
|
std::string strJson = writer.write(tmpXpop);
|
|
Blob raw(strJson.begin(), strJson.end());
|
|
auto const xpop = syntaxCheckXPOP(raw, env.journal);
|
|
auto const [seq, masterKey] = *getVLInfo(*xpop, env.journal);
|
|
BEAST_EXPECT(std::to_string(seq) == "2");
|
|
BEAST_EXPECT(
|
|
strHex(masterKey) ==
|
|
"ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1"
|
|
"CDC1");
|
|
}
|
|
}
|
|
|
|
void
|
|
testEnabled(FeatureBitset features)
|
|
{
|
|
testcase("enabled");
|
|
using namespace jtx;
|
|
using namespace std::literals::chrono_literals;
|
|
|
|
for (bool const withImport : {false, true})
|
|
{
|
|
// If the Import amendment is not enabled, you should not be able
|
|
// to import.
|
|
auto const amend = withImport ? features : features - featureImport;
|
|
Env env{*this, makeNetworkVLConfig(21337, keys), amend};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// setup env
|
|
auto const alice = Account("alice");
|
|
env.fund(XRP(1000), alice);
|
|
env.close();
|
|
|
|
// burn 1000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(1'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
auto const txResult =
|
|
withImport ? ter(tesSUCCESS) : ter(temDISABLED);
|
|
|
|
// IMPORT - Account Set
|
|
env(import(alice, loadXpop(ImportTCAccountSet::w_seed)),
|
|
fee(feeDrops * 10),
|
|
txResult);
|
|
env.close();
|
|
}
|
|
}
|
|
|
|
void
|
|
testInvalidPreflight(FeatureBitset features)
|
|
{
|
|
testcase("import invalid preflight");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
//----------------------------------------------------------------------
|
|
// preflight
|
|
|
|
// temDISABLED - disabled
|
|
// !ctx.rules.enabled(featureImport)
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys), features - featureImport};
|
|
|
|
auto const alice = Account("alice");
|
|
env.fund(XRP(1000), alice);
|
|
env.close();
|
|
|
|
env(import(alice, loadXpop(ImportTCAccountSet::w_seed)), ter(temDISABLED));
|
|
}
|
|
|
|
// temDISABLED - disabled
|
|
// !ctx.rules.enabled(featureHooksUpdate1) &&
|
|
// ctx.tx.isFieldPresent(sfIssuer)
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys), features - featureHooksUpdate1};
|
|
|
|
auto const alice = Account("alice");
|
|
auto const issuer = Account("issuer");
|
|
env.fund(XRP(1000), alice, issuer);
|
|
env.close();
|
|
|
|
auto tx = import(alice, loadXpop(ImportTCAccountSet::w_seed));
|
|
tx[sfIssuer.jsonName] = issuer.human();
|
|
env(tx, ter(temDISABLED));
|
|
}
|
|
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
// burn 1000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(1'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
|
|
env.fund(XRP(1000), alice, bob);
|
|
env.close();
|
|
|
|
// temMALFORMED
|
|
// Issuer cannot be the source account.
|
|
{
|
|
auto tx = import(alice, loadXpop(ImportTCAccountSet::w_seed));
|
|
tx[sfIssuer.jsonName] = alice.human();
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// telINSUF_FEE_P - sfFee cannot be 0
|
|
{
|
|
Json::Value tx =
|
|
import(alice, loadXpop(ImportTCAccountSet::w_seed));
|
|
STAmount const& fee = XRP(0);
|
|
tx[jss::Fee] = fee.getJson(JsonOptions::none);
|
|
env(tx, ter(telINSUF_FEE_P));
|
|
}
|
|
|
|
// DA: blob.resize(513 * 1024); fails with Boost
|
|
// temMALFORMED
|
|
// blob was more than 512kib
|
|
// {
|
|
// ripple::Blob blob;
|
|
// blob.resize(513 * 1024);
|
|
// Json::Value tx = import(alice, loadXpop(ImportTCAccountSet::w_seed));
|
|
// tx[sfBlob.jsonName] = strHex(blob);
|
|
// env(tx, ter(temMALFORMED));
|
|
// }
|
|
|
|
// temMALFORMED - sfAmount field must be in drops
|
|
{
|
|
Json::Value tx =
|
|
import(alice, loadXpop(ImportTCAccountSet::w_seed));
|
|
STAmount const& amount = XRP(-1);
|
|
tx[jss::Amount] = amount.getJson(JsonOptions::none);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - !xpop | XPOP.validation is not a JSON object
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::validation] = {}; // one of many ways to throw error
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: validation.unl.public_key was not valid hex
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::validation][jss::unl][jss::public_key] = "not a hex";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: validation.unl.public_key was not a recognised
|
|
// public key type
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::validation][jss::unl][jss::public_key] =
|
|
"0084D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1"
|
|
"CDC1";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// getInnerTxn - !xpop
|
|
// DA: Duplicate -
|
|
|
|
// getInnerTxn - failed to deserialize tx blob inside xpop (invalid hex)
|
|
// DA: Duplicate - "XPOP.transaction.blob missing or wrong format"
|
|
|
|
// getInnerTxn - failed to deserialize tx meta inside xpop (invalid hex)
|
|
// DA: Duplicate - "XPOP.transaction.meta missing or wrong format"
|
|
|
|
// getInnerTxn - failed to deserialize tx blob/meta inside xpop
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::transaction][jss::blob] = "DEADBEEF";
|
|
tmpXpop[jss::transaction][jss::meta] = "DEADBEEF";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// // temMALFORMED - !stpTrans
|
|
// // DA: Duplicate - getInnerTxn (Any Failure)
|
|
|
|
// temMALFORMED - Import: attempted to import xpop containing an emitted
|
|
// or pseudo txn.
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::transaction][jss::blob] =
|
|
"12000322000000002400000002201B00000069201D0000535968400000003B"
|
|
"9ACA0073210388935426E0D08083314842EDFBB2D517BD47699F9A4527318A"
|
|
"8E10468C97C0527446304402200E40CA821A7BFE347448FFA6540F67C7FFBF"
|
|
"0287756D324DFBADCEDE2B23782C02207BE1B1294F1A1D5AC21990740B78F9"
|
|
"C0693431237D6E07FE84228082986E50FF8114AE123A8556F3CF9115471137"
|
|
"6AFB0F894F832B3DED202E000000013D00000000000000015B2200676F4B9B"
|
|
"45C5ADE9DE3C8CD01200CB12DFF8C792220DB088FE615BE5C2905C207064D8"
|
|
"1954F6A7225A8BAADF5A3042016BFB87355D1D0AFEDBAA8FB22F98355D745F"
|
|
"398EEE9E6B294BBE6A5681A31A6107243D19384E277B5A7B1F23B8C83DE78A"
|
|
"14AE123A8556F3CF91154711376AFB0F894F832B3DE1";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: inner txn lacked transaction result
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::transaction][jss::meta] =
|
|
"201C00000006F8E5110061250000005655463E39A6AFDDA77DBF3591BF3C2A"
|
|
"4BE9BB8D9113BF6D0797EB403C3D0D894FEF5692FA6A9FC8EA6018D5D16532"
|
|
"D7795C91BFB0831355BDFDA177E86C8BF997985FE624000000026240000000"
|
|
"773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481"
|
|
"14AE123A8556F3CF91154711376AFB0F894F832B3DE1E1F1";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: inner txn did not have a tesSUCCESS or tec
|
|
// result
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::transaction][jss::meta] =
|
|
"201C00000006F8E5110061250000005655463E39A6AFDDA77DBF3591BF3C2A"
|
|
"4BE9BB8D9113BF6D0797EB403C3D0D894FEF5692FA6A9FC8EA6018D5D16532"
|
|
"D7795C91BFB0831355BDFDA177E86C8BF997985FE624000000026240000000"
|
|
"773593F4E1E7220000000024000000032D0000000162400000003B9AC9F481"
|
|
"14AE123A8556F3CF91154711376AFB0F894F832B3DE1E1F103103C";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: import and txn inside xpop must be signed by
|
|
// the same account
|
|
{
|
|
Json::Value const tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value const tx = import(bob, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: attempted to import xpop containing a txn with
|
|
// a sfNetworkID field.
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::transaction][jss::blob] =
|
|
"120003210000535922000000002400000002201B00000069201D0000535968"
|
|
"400000003B9ACA0073210388935426E0D08083314842EDFBB2D517BD47699F"
|
|
"9A4527318A8E10468C97C0527446304402200E40CA821A7BFE347448FFA654"
|
|
"0F67C7FFBF0287756D324DFBADCEDE2B23782C02207BE1B1294F1A1D5AC219"
|
|
"90740B78F9C0693431237D6E07FE84228082986E50FF8114AE123A8556F3CF"
|
|
"91154711376AFB0F894F832B3D";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: OperationLimit missing from inner xpop txn.
|
|
// outer txid:
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::transaction][jss::blob] =
|
|
"12000322000000002400000002201B0000006C68400000003B9ACA007321ED"
|
|
"A8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C"
|
|
"747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F"
|
|
"232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C51"
|
|
"77C519560F8114AE123A8556F3CF91154711376AFB0F894F832B3D";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: Wrong network ID for OperationLimit in inner
|
|
// txn. outer txid:
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::transaction][jss::blob] =
|
|
"12000322000000002400000002201B0000006C201D0000535A68400000003B"
|
|
"9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62"
|
|
"ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593EC"
|
|
"C21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF"
|
|
"3EC206AD3C5177C519560F8114AE123A8556F3CF91154711376AFB0F894F83"
|
|
"2B3D";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(telWRONG_NETWORK));
|
|
}
|
|
|
|
// temMALFORMED - Import: inner txn must be an AccountSet, SetRegularKey
|
|
// or SignerListSet transaction.
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::transaction][jss::blob] =
|
|
"12006322000000002400000002201B0000006C201D0000535968400000003B"
|
|
"9ACA007321EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62"
|
|
"ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593EC"
|
|
"C21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF"
|
|
"3EC206AD3C5177C519560F8114AE123A8556F3CF91154711376AFB0F894F83"
|
|
"2B3D";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: outer and inner txns were (multi) signed with
|
|
// different keys.
|
|
|
|
// temMALFORMED - Import: outer and inner txns were signed with
|
|
// different keys.
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::transaction][jss::blob] =
|
|
"12000322000000002400000002201B0000006C201D0000535968400000003B"
|
|
"9ACA007321EBA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62"
|
|
"ECAD0AE4A96C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593EC"
|
|
"C21B3C79EF0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF"
|
|
"3EC206AD3C5177C519560F8114AE123A8556F3CF91154711376AFB0F894F83"
|
|
"2B3D";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: inner txn signature verify failed
|
|
// DA: TODO: ASK FOR HELP
|
|
|
|
// temMALFORMED - Import: failed to deserialize manifest on txid
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::validation][jss::unl][jss::manifest] = "YmFkSnNvbg==";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: manifest master key did not match top level
|
|
// master key in unl section of xpop
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::validation][jss::unl][jss::manifest] =
|
|
"JAAAAAFxIe2E1ANsZZGkvfnFTO+jm5lqXc5fhtEf2hh0SBzp1aHNwXMh7TN9+"
|
|
"b62cZqTngaFYU5tbGpYHC8oYuI3G3vwj9OW2Z9gdkAnUjfY5zOEkhq31tU4338"
|
|
"jcyUpVA5/VTsANFce7unDo+JeVoEhfuOb/Y8WA3Diu9XzuOD4U/"
|
|
"ikfgf9SZOlOGcBcBJAw44PLjH+"
|
|
"HUtEnwX45lIRmo0x5aINFMvZsBpE9QteSDBXKwYzLdnSW4e1bs21o+"
|
|
"IILJIiIKU/+1Uxx0FRpQbMDA==";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: manifest signature invalid
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::validation][jss::unl][jss::manifest] =
|
|
"JAAAAAFxIe101ANsZZGkvfnFTO+jm5lqXc5fhtEf2hh0SBzp1aHNwXMh7TN9+"
|
|
"b62cZqTngaFYU5tbGpYHC8oYuI3G3vwj9OW2Z9gdkA3UjfY5zOEkhq31tU4338"
|
|
"jcyUpVA5/VTsANFce7unDo+JeVoEhfuOb/Y8WA3Diu9XzuOD4U/"
|
|
"ikfgf9SZOlOGcBcBJAw34PLjH+"
|
|
"HUtEnwX45lIRmo0x5aINFMvZsBpE9QteSDBXKwYzLdnSW4e1bs21o+"
|
|
"IILJIiIKU/+1Uxx0FRpQbMDA==";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: unl blob not signed correctly
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::validation][jss::unl][jss::signature] =
|
|
"949F6B8DA6E11C213B561659C16F13D35385E8EA9E775483ADC84578F6D578"
|
|
"943DE5EB681584B2C03EFFFDFD216F9E0B21576E482F941C7195893B72B5B1"
|
|
"F70D";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: unl blob not signed correctly
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::validation][jss::unl][jss::signature] = "not a hex";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// DA: GOOD SIGNATURE NOT JSON
|
|
// temMALFORMED - Import: unl blob was not valid json (after base64
|
|
// decoding)
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::validation][jss::unl][jss::blob] = "YmFkSnNvbg==";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// DA: GOOD SIGNATURE GOOD JSON MISSING FIELDS
|
|
// temMALFORMED - Import: unl blob json (after base64 decoding) lacked
|
|
// required fields and/or types
|
|
|
|
// temMALFORMED - Import: unl blob validUntil <= validFrom
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::validation][jss::unl][jss::blob] =
|
|
"eyJzZXF1ZW5jZSI6MSwiZWZmZWN0aXZlIjowLCJleHBpcmF0aW9uIjowLCJ2YW"
|
|
"xpZGF0b3JzIjpbeyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDM4QkQ0NDVB"
|
|
"RkQ2MjE1OTYyMENDMTk2QzI2NjhBMjZCNkZCQjM2QjA5OUVCNTVCMzhBNThDMT"
|
|
"FDMTIwNERFNUMiLCJtYW5pZmVzdCI6IkpBQUFBQUp4SWUwNHZVUmEvV0lWbGlE"
|
|
"TUdXd21hS0pyYjdzMnNKbnJWYk9LV01FY0VnVGVYSE1oQW9HTU5jc2dVVU53S2"
|
|
"8raDd6aGFYS0YrSEd3NlhoRWpvREtyYWxrWW5Naktka2N3UlFJaEFKN2NONEo2"
|
|
"TmRWZnBudkVJL1pldVdDVHZucGFKaXJLTkZjQzN6TU9qZ3dqQWlBYktJMGZiWG"
|
|
"dTMVJMbG9OaHhkSGhWcTlvekVXVkU5Y0l3WEROM0F4cXlZM0FTUUN0MCt1L2lO"
|
|
"U0RENmJYdlVUdGRtdDROcnRsYng0Vnp1bVRwZmpSWXA0bE1vSS9oNDNwVVRqcD"
|
|
"dWRm9YYm5LV2pWaHFOYUdtNTc3SzZKNjk3WFo3VFFFPSJ9LHsidmFsaWRhdGlv"
|
|
"bl9wdWJsaWNfa2V5IjoiRURCRUUzMEZBRTkyRUVFODhFMUM0OTgwRDA5RUNGRE"
|
|
"U5OUExMTZEMDc4RUMyMTg1N0RCMUI0N0I0MjY0MThFNDI4IiwibWFuaWZlc3Qi"
|
|
"OiJKQUFBQUFKeEllMis0dyt1a3U3b2poeEpnTkNlejk2Wm9SYlFlT3doaFgyeH"
|
|
"RIdENaQmprS0hNaEE5U21IRHhPaUNNVFpsNW5SeHJwMnlqV1o1Z2p4MkRyb1VG"
|
|
"clU0bnJFcVU3ZGtjd1JRSWhBTGRFRmVqWStwVW5nbGk3c1R2aWIwQm1ESFA3Tj"
|
|
"Zpa1ZFQkk2SDdJd1UxekFpQmRzeW9TcVBjQzJOTXFnQW5IWEhHZGtBSXdCUUQx"
|
|
"QVVnOVg4WkpMeWZjd0hBU1FDdDFiS1Z6T014UlFtUjN3Tks0ZEtkb2ZJR3J4RT"
|
|
"lTanVMUjZQYThCNW4wOFNZSjhLNjJnZSs5YTZCdFphbEVtL0hPZGN6ME5BRk9j"
|
|
"eWNyRi9DdFNBND0ifV19";
|
|
tmpXpop[jss::validation][jss::unl][jss::signature] =
|
|
"2B3C0ECB63C82454522188337354C480693A9BCD64E776B4DBAD4C61B9E72D"
|
|
"D4CC1DC237B06891E57C623C38506FE8E01B1914C9413471BCC160111E2829"
|
|
"7606";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: unl blob expired
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::validation][jss::unl][jss::blob] =
|
|
"eyJzZXF1ZW5jZSI6MSwiZWZmZWN0aXZlIjowLCJleHBpcmF0aW9uIjoxLCJ2YW"
|
|
"xpZGF0b3JzIjpbeyJ2YWxpZGF0aW9uX3B1YmxpY19rZXkiOiJFRDM4QkQ0NDVB"
|
|
"RkQ2MjE1OTYyMENDMTk2QzI2NjhBMjZCNkZCQjM2QjA5OUVCNTVCMzhBNThDMT"
|
|
"FDMTIwNERFNUMiLCJtYW5pZmVzdCI6IkpBQUFBQUp4SWUwNHZVUmEvV0lWbGlE"
|
|
"TUdXd21hS0pyYjdzMnNKbnJWYk9LV01FY0VnVGVYSE1oQW9HTU5jc2dVVU53S2"
|
|
"8raDd6aGFYS0YrSEd3NlhoRWpvREtyYWxrWW5Naktka2N3UlFJaEFKN2NONEo2"
|
|
"TmRWZnBudkVJL1pldVdDVHZucGFKaXJLTkZjQzN6TU9qZ3dqQWlBYktJMGZiWG"
|
|
"dTMVJMbG9OaHhkSGhWcTlvekVXVkU5Y0l3WEROM0F4cXlZM0FTUUN0MCt1L2lO"
|
|
"U0RENmJYdlVUdGRtdDROcnRsYng0Vnp1bVRwZmpSWXA0bE1vSS9oNDNwVVRqcD"
|
|
"dWRm9YYm5LV2pWaHFOYUdtNTc3SzZKNjk3WFo3VFFFPSJ9LHsidmFsaWRhdGlv"
|
|
"bl9wdWJsaWNfa2V5IjoiRURCRUUzMEZBRTkyRUVFODhFMUM0OTgwRDA5RUNGRE"
|
|
"U5OUExMTZEMDc4RUMyMTg1N0RCMUI0N0I0MjY0MThFNDI4IiwibWFuaWZlc3Qi"
|
|
"OiJKQUFBQUFKeEllMis0dyt1a3U3b2poeEpnTkNlejk2Wm9SYlFlT3doaFgyeH"
|
|
"RIdENaQmprS0hNaEE5U21IRHhPaUNNVFpsNW5SeHJwMnlqV1o1Z2p4MkRyb1VG"
|
|
"clU0bnJFcVU3ZGtjd1JRSWhBTGRFRmVqWStwVW5nbGk3c1R2aWIwQm1ESFA3Tj"
|
|
"Zpa1ZFQkk2SDdJd1UxekFpQmRzeW9TcVBjQzJOTXFnQW5IWEhHZGtBSXdCUUQx"
|
|
"QVVnOVg4WkpMeWZjd0hBU1FDdDFiS1Z6T014UlFtUjN3Tks0ZEtkb2ZJR3J4RT"
|
|
"lTanVMUjZQYThCNW4wOFNZSjhLNjJnZSs5YTZCdFphbEVtL0hPZGN6ME5BRk9j"
|
|
"eWNyRi9DdFNBND0ifV19";
|
|
tmpXpop[jss::validation][jss::unl][jss::signature] =
|
|
"FA82662A23EC78E9644C65F752B7A58F61F35AC36C260F9E9D5CAC7D53D16D"
|
|
"5D615A02A6462F2618C162D089AD2E3BA7D656728392180517A81B4C47F86A"
|
|
"640D";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: unl blob not yet valid
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::validation][jss::unl][jss::blob] =
|
|
"eyJzZXF1ZW5jZSI6MSwiZWZmZWN0aXZlIjozNjAwLCJleHBpcmF0aW9uIjo4Nj"
|
|
"QwMCwidmFsaWRhdG9ycyI6W3sidmFsaWRhdGlvbl9wdWJsaWNfa2V5IjoiRUQz"
|
|
"OEJENDQ1QUZENjIxNTk2MjBDQzE5NkMyNjY4QTI2QjZGQkIzNkIwOTlFQjU1Qj"
|
|
"M4QTU4QzExQzEyMDRERTVDIiwibWFuaWZlc3QiOiJKQUFBQUFKeEllMDR2VVJh"
|
|
"L1dJVmxpRE1HV3dtYUtKcmI3czJzSm5yVmJPS1dNRWNFZ1RlWEhNaEFvR01OY3"
|
|
"NnVVVOd0tvK2g3emhhWEtGK0hHdzZYaEVqb0RLcmFsa1luTWpLZGtjd1JRSWhB"
|
|
"SjdjTjRKNk5kVmZwbnZFSS9aZXVXQ1R2bnBhSmlyS05GY0Mzek1Pamd3akFpQW"
|
|
"JLSTBmYlhnUzFSTGxvTmh4ZEhoVnE5b3pFV1ZFOWNJd1hETjNBeHF5WTNBU1FD"
|
|
"dDArdS9pTlNERDZiWHZVVHRkbXQ0TnJ0bGJ4NFZ6dW1UcGZqUllwNGxNb0kvaD"
|
|
"QzcFVUanA3VkZvWGJuS1dqVmhxTmFHbTU3N0s2SjY5N1haN1RRRT0ifSx7InZh"
|
|
"bGlkYXRpb25fcHVibGljX2tleSI6IkVEQkVFMzBGQUU5MkVFRTg4RTFDNDk4ME"
|
|
"QwOUVDRkRFOTlBMTE2RDA3OEVDMjE4NTdEQjFCNDdCNDI2NDE4RTQyOCIsIm1h"
|
|
"bmlmZXN0IjoiSkFBQUFBSnhJZTIrNHcrdWt1N29qaHhKZ05DZXo5NlpvUmJRZU"
|
|
"93aGhYMnh0SHRDWkJqa0tITWhBOVNtSER4T2lDTVRabDVuUnhycDJ5aldaNWdq"
|
|
"eDJEcm9VRnJVNG5yRXFVN2RrY3dSUUloQUxkRUZlalkrcFVuZ2xpN3NUdmliME"
|
|
"JtREhQN042aWtWRUJJNkg3SXdVMXpBaUJkc3lvU3FQY0MyTk1xZ0FuSFhIR2Rr"
|
|
"QUl3QlFEMUFVZzlYOFpKTHlmY3dIQVNRQ3QxYktWek9NeFJRbVIzd05LNGRLZG"
|
|
"9mSUdyeEU5U2p1TFI2UGE4QjVuMDhTWUo4SzYyZ2UrOWE2QnRaYWxFbS9IT2Rj"
|
|
"ejBOQUZPY3ljckYvQ3RTQTQ9In1dfQ";
|
|
tmpXpop[jss::validation][jss::unl][jss::signature] =
|
|
"9CCA07A3EDD1334D5ADCB3730D8F3F9BD1E0C338100384C7B15B6A910F96BE"
|
|
"4F46E3052B37E9FE2E7DC9918BD85B9E871923AE1BDD7144EE2A92F625064C"
|
|
"570C";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: depth > 32
|
|
// temMALFORMED - Import: !proof->isObject() && !proof->isArray()
|
|
// DA: Catchall Error
|
|
// temMALFORMED - Import: return false
|
|
|
|
// temMALFORMED - Import: xpop proof did not contain the specified txn
|
|
// hash
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::transaction][jss::proof][jss::children]["D"]
|
|
[jss::children]["7"][jss::hash] =
|
|
"12D47E7D543E15F1EDBA91CDF335722727851BDDA8C2FF8924772AD"
|
|
"C6B522A29";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// // temMALFORMED - Import: depth > 32
|
|
// // temMALFORMED - Import: !proof.isObject() && !proof.isArray()
|
|
// // DA: CatchAll Error
|
|
|
|
// temMALFORMED - Import: computed txroot does not match xpop txroot,
|
|
// invalid xpop.
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::transaction][jss::proof][jss::children]["3"]
|
|
[jss::hash] =
|
|
"22D47E7D543E15F1EDBA91CDF335722727851BDDA8C2FF8924772AD"
|
|
"C6B522A29";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: error parsing coins | phash | acroot in the
|
|
// ledger section of XPOP.
|
|
|
|
// temMALFORMED - Import: unl blob contained invalid validator entry,
|
|
// skipping
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::validation][jss::unl][jss::blob] =
|
|
"eyJzZXF1ZW5jZSI6MiwiZXhwaXJhdGlvbiI6NzQxMzk4NDAwLCJ2YWxpZGF0b3"
|
|
"JzIjpbeyJtYW5pZmVzdCI6IkpBQUFBQUp4SWUwNHZVUmEvV0lWbGlETUdXd21h"
|
|
"S0pyYjdzMnNKbnJWYk9LV01FY0VnVGVYSE1oQW9HTU5jc2dVVU53S28raDd6aG"
|
|
"FYS0YrSEd3NlhoRWpvREtyYWxrWW5Naktka2N3UlFJaEFKN2NONEo2TmRWZnBu"
|
|
"dkVJL1pldVdDVHZucGFKaXJLTkZjQzN6TU9qZ3dqQWlBYktJMGZiWGdTMVJMbG"
|
|
"9OaHhkSGhWcTlvekVXVkU5Y0l3WEROM0F4cXlZM0FTUUN0MCt1L2lOU0RENmJY"
|
|
"dlVUdGRtdDROcnRsYng0Vnp1bVRwZmpSWXA0bE1vSS9oNDNwVVRqcDdWRm9YYm"
|
|
"5LV2pWaHFOYUdtNTc3SzZKNjk3WFo3VFFFPSJ9LHsibWFuaWZlc3QiOiJKQUFB"
|
|
"QUFKeEllMis0dyt1a3U3b2poeEpnTkNlejk2Wm9SYlFlT3doaFgyeHRIdENaQm"
|
|
"prS0hNaEE5U21IRHhPaUNNVFpsNW5SeHJwMnlqV1o1Z2p4MkRyb1VGclU0bnJF"
|
|
"cVU3ZGtjd1JRSWhBTGRFRmVqWStwVW5nbGk3c1R2aWIwQm1ESFA3TjZpa1ZFQk"
|
|
"k2SDdJd1UxekFpQmRzeW9TcVBjQzJOTXFnQW5IWEhHZGtBSXdCUUQxQVVnOVg4"
|
|
"WkpMeWZjd0hBU1FDdDFiS1Z6T014UlFtUjN3Tks0ZEtkb2ZJR3J4RTlTanVMUj"
|
|
"ZQYThCNW4wOFNZSjhLNjJnZSs5YTZCdFphbEVtL0hPZGN6ME5BRk9jeWNyRi9D"
|
|
"dFNBND0ifV19=";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: unl blob contained an invalid validator key,
|
|
// skipping
|
|
// {
|
|
|
|
// }
|
|
// temMALFORMED - Import: unl blob contained an invalid manifest,
|
|
// skipping
|
|
// {
|
|
|
|
// }
|
|
// // temMALFORMED - Import: unl blob list entry manifest master key did
|
|
// // not match master key, skipping
|
|
// // temMALFORMED - Import: unl blob list entry manifest signature
|
|
// // invalid, skipping
|
|
// // temMALFORMED - Import: validator nodepub did not appear in
|
|
// validator
|
|
// // list but did appear
|
|
// // temMALFORMED - Import: validator nodepub key appears more than
|
|
// once
|
|
// // in data section
|
|
|
|
// temMALFORMED - Import: validation inside xpop was not valid hex
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value valData;
|
|
valData["n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN"] =
|
|
"not a hex";
|
|
tmpXpop[jss::validation][jss::data] = valData;
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: validation message was not for computed ledger
|
|
// hash
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value valData;
|
|
valData["n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN"] =
|
|
"22800000012600000056292C0D012051A0829745427488A59B6525231634DC"
|
|
"327F91589EB03F469ABF1C3CA32070625A501790AD68E9045001FDEED03F0A"
|
|
"C8277F11F6E46E0ABD2DC38B1F8240D56B22E4F2732103D4A61C3C4E882313"
|
|
"665E67471AE9DB28D6679823C760EBA1416B5389EB12A53B76463044022072"
|
|
"427336342AE80B7AAE407CEA611B0DA680426B3C5894E52EE2D23641D09A73"
|
|
"02203B131B68D3C5B6C5482312CC7D90D2CE131A9C46458967F2F98688B726"
|
|
"C16719";
|
|
tmpXpop[jss::validation][jss::data] = valData;
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
// temMALFORMED - Import: validation inside xpop was not signed with a
|
|
// signing key we recognise
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value valData;
|
|
valData["n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN"] =
|
|
"22800000012600000056292C0D012051B0829745427488A59B6525231634DC"
|
|
"327F91589EB03F469ABF1C3CA32070625A501790BD68E9045001FDEED03F0A"
|
|
"C8277F11F6E46E0ABD2DC38B1F8240D56B22E4F2732103E4A61C3C4E882313"
|
|
"665E67471AE9DB28D6679823C760EBA1416B5389EB12A53B76463054022072"
|
|
"427336342AE80B7AAE407CEA611B0DA680426B3C5894E52EE2D23641D09A73"
|
|
"02203B131B68D3C5B6C5482312CC7D90D2CE131A9C46458967F2F98688B726"
|
|
"C16719";
|
|
tmpXpop[jss::validation][jss::data] = valData;
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
// temMALFORMED - Import: validation inside xpop was not correctly
|
|
// signed
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value valData;
|
|
valData["n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN"] =
|
|
"22800000012600000056292C0D012051B0829745427488A59B6525231634DC"
|
|
"327F91589EB03F469ABF1C3CA32070625A501790BD68E9045001FDEED03F0A"
|
|
"C8277F11F6E46E0ABD2DC38B1F8240D56B22E4F2732103D4A61C3C4E882313"
|
|
"665E67471AE9DB28D6679823C760EBA1416B5389EB12A53B76463044022072"
|
|
"427336342AE80B7AAE407CEA611B0DA680426B3C5894E52EE2D23641D09A73"
|
|
"02203B131B68D3C5B6C5482312CC7D90D2CE131A9C46458967F2F98688B726"
|
|
"C16719";
|
|
tmpXpop[jss::validation][jss::data] = valData;
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: validation inside xpop was not able to be
|
|
// parsed DA: Unknown Catch All
|
|
|
|
// temMALFORMED - Import: xpop did not contain an 80% quorum for the txn
|
|
// it purports to prove.
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value valData;
|
|
valData["n94at1vSdHSBEun25yT4ZfgqD1tVQNsx1nqRZG3T6ygbuvwgcMZN"] =
|
|
"";
|
|
valData["n9KXYzdZD8YpsNiChtMjP6yhvQAhkkh5XeSTbvYyV1waF8wkNnBT"] =
|
|
"";
|
|
tmpXpop[jss::validation][jss::data] = valData;
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// temMALFORMED - Import: xpop inner txn did not contain a sequence
|
|
// number or fee No Sequence
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::transaction][jss::blob] =
|
|
"1200632200000000201B0000006C201D0000535968400000003B9ACA007321"
|
|
"EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A9"
|
|
"6C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF"
|
|
"0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C"
|
|
"5177C519560F8114AE123A8556F3CF91154711376AFB0F894F832B3D";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
// No Fee
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::transaction][jss::blob] =
|
|
"12006322000000002400000002201B0000006C201D000053597321EDA8D46E"
|
|
"11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A96C747440"
|
|
"549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF0F232EB4"
|
|
"375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C5177C519"
|
|
"560F8114AE123A8556F3CF91154711376AFB0F894F832B3D";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
// Bad Fee - TODO
|
|
}
|
|
|
|
void
|
|
testInvalidPreclaim(FeatureBitset features)
|
|
{
|
|
testcase("import invalid preclaim");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
// ----------------------------------------------------------------------
|
|
// preclaim
|
|
|
|
// temDISABLED
|
|
{
|
|
test::jtx::Env env{
|
|
*this,
|
|
makeNetworkVLConfig(21337, keys),
|
|
features - featureImport};
|
|
|
|
auto const alice = Account("alice");
|
|
env.fund(XRP(1000), alice);
|
|
env.close();
|
|
|
|
env(import(alice, loadXpop(ImportTCAccountSet::w_seed)),
|
|
ter(temDISABLED));
|
|
}
|
|
|
|
// tefINTERNAL
|
|
// during preclaim could not parse xpop, bailing.
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const alice = Account("alice");
|
|
env.fund(XRP(1000), alice);
|
|
env.close();
|
|
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::validation] = {};
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
// DA: Sanity Check - tefINTERNAL(preclaim)
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// tefINTERNAL
|
|
// during preclaim could not find importSequence, bailing.
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const alice = Account("alice");
|
|
env.fund(XRP(1000), alice);
|
|
env.close();
|
|
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::transaction][jss::blob] =
|
|
"1200632200000000201B0000006C201D0000535968400000003B9ACA007321"
|
|
"EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A9"
|
|
"6C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF"
|
|
"0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C"
|
|
"5177C519560F8114AE123A8556F3CF91154711376AFB0F894F832B3D";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
// DA: Sanity Check - tefINTERNAL(preclaim)
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// tefPAST_IMPORT_SEQ
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
auto const alice = Account("alice");
|
|
env.fund(XRP(1000), alice);
|
|
env.close();
|
|
|
|
env(import(alice, loadXpop(ImportTCAccountSet::w_seed)),
|
|
fee(feeDrops * 10),
|
|
ter(tesSUCCESS));
|
|
env(import(alice, loadXpop(ImportTCAccountSet::min)),
|
|
fee(feeDrops * 10),
|
|
ter(tefPAST_IMPORT_SEQ));
|
|
}
|
|
|
|
// temBAD_FEE
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const alice = Account("alice");
|
|
env.memoize(alice);
|
|
Json::Value tx =
|
|
import(alice, loadXpop(ImportTCAccountSet::w_seed));
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 10;
|
|
env(tx, ter(temBAD_FEE));
|
|
}
|
|
|
|
// tefINTERNAL
|
|
// during preclaim could not parse vlInfo, bailing.
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const alice = Account("alice");
|
|
env.fund(XRP(1000), alice);
|
|
env.close();
|
|
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::validation][jss::unl][jss::blob] = "YmFkSnNvbg==";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
// DA: Sanity Check - tefINTERNAL(preclaim)
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// tefPAST_IMPORT_VL_SEQ
|
|
// import vl sequence already used, bailing.
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
std::string const pkString =
|
|
"ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1"
|
|
"CDC1";
|
|
auto const pkHex = strUnHex(pkString);
|
|
PublicKey const pk{makeSlice(*pkHex)};
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
env.fund(XRP(1000), alice, bob);
|
|
env.close();
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
Json::Value const xpop1_1 =
|
|
loadXpop(ImportTCAccountSet::unl_seq_1_1);
|
|
Json::Value const tx_1_1 = import(alice, xpop1_1);
|
|
env(tx_1_1, fee(feeDrops * 10), ter(tesSUCCESS));
|
|
|
|
BEAST_EXPECT(importVLSequence(env, pk) == 1);
|
|
|
|
Json::Value const xpop2_1 =
|
|
loadXpop(ImportTCAccountSet::unl_seq_2_1);
|
|
Json::Value const tx_2_1 = import(bob, xpop2_1);
|
|
env(tx_2_1, fee(feeDrops * 10), ter(tesSUCCESS));
|
|
|
|
BEAST_EXPECT(importVLSequence(env, pk) == 2);
|
|
|
|
Json::Value const xpop1_2 =
|
|
loadXpop(ImportTCAccountSet::unl_seq_1_2);
|
|
Json::Value const tx_1_2 = import(alice, xpop1_2);
|
|
env(tx_1_2, fee(feeDrops * 10), ter(tefPAST_IMPORT_VL_SEQ));
|
|
}
|
|
|
|
// tesSUCCESS
|
|
// DA: testImportSequence
|
|
|
|
// tefINTERNAL
|
|
// DA: Impossible Test
|
|
|
|
// tefINTERNAL
|
|
// DA: Impossible Test
|
|
|
|
// tesSUCCESS
|
|
// DA: testImportSequence
|
|
|
|
// telIMPORT_VL_KEY_NOT_RECOGNISED
|
|
// import vl key not recognized, bailing.
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkConfig(21337)};
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
auto const alice = Account("alice");
|
|
env.fund(XRP(1000), alice);
|
|
env.close();
|
|
|
|
Json::Value const tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, fee(feeDrops * 10), ter(telIMPORT_VL_KEY_NOT_RECOGNISED));
|
|
}
|
|
}
|
|
|
|
void
|
|
testInvalidDoApply(FeatureBitset features)
|
|
{
|
|
testcase("import invalid doApply");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
|
|
env.fund(XRP(1000), alice, bob);
|
|
env.close();
|
|
|
|
// burn 1000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(1'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
//----------------------------------------------------------------------
|
|
// doApply
|
|
|
|
// temDISABLED
|
|
|
|
// tefINTERNAL/temMALFORMED - ctx_.tx.isFieldPresent(sfBlob)
|
|
{
|
|
Json::Value tx;
|
|
tx[jss::TransactionType] = jss::Import;
|
|
tx[jss::Account] = alice.human();
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// tefINTERNAL/temMALFORMED - !xpop
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::validation] = {}; // one of many ways to throw error
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// tefINTERNAL/temMALFORMED
|
|
// during apply could not find importSequence or fee, bailing.
|
|
// No Fee
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::transaction][jss::blob] =
|
|
"1200632200000000201B0000006C201D0000535968400000003B9ACA007321"
|
|
"EDA8D46E11FD5D2082A4E6FF3039EB6259FBC2334983D015FC62ECAD0AE4A9"
|
|
"6C747440549A370E68DBB1947419D4CCDF90CAE0BCA9121593ECC21B3C79EF"
|
|
"0F232EB4375F95F1EBCED78B94D09838B5E769D43F041019ADEF3EC206AD3C"
|
|
"5177C519560F8114AE123A8556F3CF91154711376AFB0F894F832B3D";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
// No Sequence
|
|
|
|
// tefINTERNAL
|
|
// initBal <= beast::zero
|
|
// Sanity Check
|
|
|
|
// tefINTERNAL
|
|
// ImportSequence passed
|
|
// Sanity Check (tefPAST_IMPORT_SEQ)
|
|
|
|
// tefINTERNAL/temMALFORMED
|
|
// !infoVL
|
|
{
|
|
Json::Value tmpXpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
tmpXpop[jss::validation][jss::unl][jss::blob] = "YmFkSnNvbg==";
|
|
Json::Value const tx = import(alice, tmpXpop);
|
|
env(tx, ter(temMALFORMED));
|
|
}
|
|
|
|
// tefINTERNAL
|
|
// current > infoVL->first
|
|
// Sanity Check (tefPAST_IMPORT_VL_SEQ)
|
|
}
|
|
|
|
void
|
|
testAccountSet(FeatureBitset features)
|
|
{
|
|
testcase("account set tx");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
// w/ seed -> dne (bad signer)
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
env.memoize(alice);
|
|
env.memoize(bob);
|
|
|
|
// confirm env
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == burnCoins);
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value tx = import(bob, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, bob, ter(temMALFORMED));
|
|
env.close();
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins);
|
|
|
|
// confirm account does not exist
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(acctSle == nullptr);
|
|
}
|
|
|
|
// w/ seed -> dne
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
env.memoize(alice);
|
|
env.memoize(bob);
|
|
|
|
// confirm env
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == burnCoins);
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
Json::Value tx =
|
|
import(alice, loadXpop(ImportTCAccountSet::w_seed));
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops - feeDrops
|
|
auto const totalBurn = XRP(1000) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm account exists
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(acctSle != nullptr);
|
|
env(noop(alice), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
|
|
// w/ regular key other -> dne (bad signer)
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
env.memoize(alice);
|
|
env.memoize(bob);
|
|
env.memoize(carol);
|
|
|
|
// confirm env
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == 99'999'990'000'000'000);
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx - wrong regular key
|
|
Json::Value txBad =
|
|
import(alice, loadXpop(ImportTCAccountSet::w_regular_key));
|
|
txBad[jss::Sequence] = 0;
|
|
txBad[jss::Fee] = 0;
|
|
env(txBad, alice, sig(carol), ter(temMALFORMED));
|
|
env.close();
|
|
|
|
// confirm fee was not minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice);
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins);
|
|
|
|
// confirm account does not exist
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(acctSle == nullptr);
|
|
}
|
|
|
|
// w/ regular key -> dne
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
env.memoize(alice);
|
|
env.memoize(bob);
|
|
|
|
// confirm env
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == 99'999'990'000'000'000);
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
Json::Value tx =
|
|
import(alice, loadXpop(ImportTCAccountSet::w_regular_key));
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, sig(bob), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops - feeDrops
|
|
auto const totalBurn = XRP(1000) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm account exists
|
|
auto const [acct, acctSle1] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(acctSle1 != nullptr);
|
|
// alice cannnot sign
|
|
env(noop(alice),
|
|
sig(alice),
|
|
fee(feeDrops),
|
|
ter(tefMASTER_DISABLED));
|
|
// bob cannot sign
|
|
env(noop(alice), sig(bob), fee(feeDrops), ter(tefBAD_AUTH));
|
|
}
|
|
|
|
// w/ signers list -> dne
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
env.memoize(alice);
|
|
env.memoize(bob);
|
|
env.memoize(carol);
|
|
|
|
// confirm env
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == burnCoins);
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::w_signers);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, msig(bob, carol), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops - feeDrops
|
|
auto const totalBurn = drops(48) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm signers not set
|
|
auto const k = keylet::signers(alice);
|
|
BEAST_EXPECT(env.current()->read(k) == nullptr);
|
|
env(noop(alice),
|
|
msig(bob, carol),
|
|
fee(3 * feeDrops),
|
|
ter(tefNOT_MULTI_SIGNING));
|
|
env.close();
|
|
|
|
// alice cannnot sign
|
|
env(noop(alice),
|
|
sig(alice),
|
|
fee(feeDrops),
|
|
ter(tefMASTER_DISABLED));
|
|
}
|
|
|
|
// w/ seed -> funded
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10,000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
env.fund(XRP(1000), alice);
|
|
env.close();
|
|
|
|
// confirm env
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == burnCoins - (2 * feeDrops));
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(1000));
|
|
|
|
// import tx
|
|
env(import(alice, loadXpop(ImportTCAccountSet::w_seed)),
|
|
fee(10 * 10),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops - feeDrops
|
|
auto const totalBurn = XRP(1000) - (feeDrops * 10);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm account exists
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(acctSle != nullptr);
|
|
env(noop(alice), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
|
|
// w/ regular key -> funded
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
env.fund(XRP(1000), alice, bob);
|
|
env.close();
|
|
|
|
// confirm env
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == burnCoins - (4 * feeDrops));
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(1000));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::w_regular_key);
|
|
Json::Value const tx = import(alice, xpopJson);
|
|
env(tx, alice, sig(bob), fee(10 * 10), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops - feeDrops
|
|
auto const totalBurn = XRP(1000) - (feeDrops * 10);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm account exists bob can sign
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(acctSle != nullptr);
|
|
BEAST_EXPECT(!acctSle->isFieldPresent(sfRegularKey));
|
|
env(noop(alice), sig(bob), fee(feeDrops), ter(tefBAD_AUTH));
|
|
env(noop(alice), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
|
|
// w/ signers -> funded
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
env.fund(XRP(1000), alice, bob, carol);
|
|
env.close();
|
|
|
|
// confirm env
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == burnCoins - (6 * feeDrops));
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(1000));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::w_signers);
|
|
Json::Value const tx = import(alice, xpopJson);
|
|
env(tx,
|
|
alice,
|
|
msig(bob, carol),
|
|
fee((3 * feeDrops) * 10),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops - feeDrops
|
|
auto const totalBurn = drops(48) - ((3 * feeDrops) * 10);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm signers not set
|
|
auto const k = keylet::signers(alice);
|
|
BEAST_EXPECT(env.current()->read(k) == nullptr);
|
|
env(noop(alice),
|
|
msig(bob, carol),
|
|
fee(3 * feeDrops),
|
|
ter(tefNOT_MULTI_SIGNING));
|
|
env.close();
|
|
|
|
// alice cannnot sign
|
|
env(noop(alice), sig(alice), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
}
|
|
|
|
void
|
|
testAccountSetFlags(FeatureBitset features)
|
|
{
|
|
testcase("account set flags");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
// account set flags not migrated
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
env.fund(XRP(1000), alice);
|
|
env.close();
|
|
|
|
// confirm env
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == burnCoins - (2 * feeDrops));
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(1000));
|
|
|
|
// import tx
|
|
env(import(alice, loadXpop(ImportTCAccountSet::w_flags)),
|
|
fee(feeDrops * 10),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops - fee drops
|
|
auto const totalBurn = drops(10) - (feeDrops * 10);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm account exists
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(acctSle != nullptr);
|
|
env(noop(alice), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
}
|
|
|
|
void
|
|
testSetRegularKey(FeatureBitset features)
|
|
{
|
|
testcase("set regular key tx");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
// w/ seed -> dne
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm env
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
env.memoize(alice);
|
|
env.memoize(bob);
|
|
|
|
// confirm env
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == burnCoins);
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCSetRegularKey::w_seed);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops + reward amount
|
|
auto const totalBurn = drops(12) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm regular key
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(acctSle->getAccountID(sfRegularKey) == bob.id());
|
|
env(noop(alice), sig(bob), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
|
|
// w/ regular key -> dne
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm env
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
env.memoize(alice);
|
|
env.memoize(bob);
|
|
env.memoize(carol);
|
|
|
|
// confirm env
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == burnCoins);
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson =
|
|
loadXpop(ImportTCSetRegularKey::w_regular_key);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, sig(bob), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops - initial value
|
|
auto const totalBurn = drops(12) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm regular key
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(acctSle->getAccountID(sfRegularKey) == carol.id());
|
|
env(noop(alice), sig(carol), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
|
|
// w/ signers -> dne
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm env
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
auto const dave = Account("dave");
|
|
env.memoize(alice);
|
|
env.memoize(bob);
|
|
env.memoize(carol);
|
|
env.memoize(dave);
|
|
|
|
// confirm env
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == burnCoins);
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCSetRegularKey::w_signers);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, msig(bob, carol), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops + reward amount
|
|
auto const totalBurn = drops(48) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm signers not set
|
|
auto const k = keylet::signers(alice);
|
|
BEAST_EXPECT(env.current()->read(k) == nullptr);
|
|
|
|
// confirm regular key
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(
|
|
acctSle && acctSle->isFieldPresent(sfRegularKey) &&
|
|
acctSle->getAccountID(sfRegularKey) == dave.id());
|
|
env(noop(alice), sig(dave), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
|
|
// w/ seed -> funded
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm env
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
env.fund(XRP(1000), alice, bob);
|
|
env.close();
|
|
|
|
// confirm env
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == burnCoins - (4 * feeDrops));
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(1000));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCSetRegularKey::w_seed);
|
|
env(import(alice, xpopJson), fee(feeDrops * 10), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops - feeDrops
|
|
auto const totalBurn = drops(12) - (feeDrops * 10);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm regular key
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(acctSle->getAccountID(sfRegularKey) == bob.id());
|
|
env(noop(alice), sig(bob), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
|
|
// w/ seed -> funded (update regular key)
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
env.fund(XRP(1000), alice, bob, carol);
|
|
env.close();
|
|
|
|
// confirm env
|
|
auto const envCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(envCoins == burnCoins - (6 * feeDrops));
|
|
auto const envAlice = env.balance(alice);
|
|
BEAST_EXPECT(envAlice == XRP(1000));
|
|
|
|
// set the regular key
|
|
env(regkey(alice, carol));
|
|
env(noop(alice), sig(carol), fee(feeDrops), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == envCoins - (2 * feeDrops));
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == envAlice - (2 * feeDrops));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCSetRegularKey::w_seed);
|
|
env(import(alice, xpopJson),
|
|
fee(feeDrops * 10),
|
|
sig(alice),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops - fee drops
|
|
auto const totalBurn = drops(12) - (feeDrops * 10);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm regular key set
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(acctSle->getAccountID(sfRegularKey) == bob.id());
|
|
env(noop(alice), sig(bob), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
|
|
// w/ regular key -> funded (update regular key)
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
auto const dave = Account("dave");
|
|
env.fund(XRP(1000), alice, bob, carol, dave);
|
|
env.close();
|
|
|
|
// confirm env
|
|
auto const envCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(envCoins == burnCoins - (8 * feeDrops));
|
|
auto const envAlice = env.balance(alice);
|
|
BEAST_EXPECT(envAlice == XRP(1000));
|
|
|
|
// set the regular key
|
|
env(regkey(alice, dave));
|
|
env(noop(alice), sig(dave), fee(feeDrops), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == envCoins - (2 * feeDrops));
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == envAlice - (2 * feeDrops));
|
|
|
|
// import tx
|
|
auto const xpopJson =
|
|
loadXpop(ImportTCSetRegularKey::w_regular_key);
|
|
env(import(alice, xpopJson),
|
|
fee(feeDrops * 10),
|
|
sig(bob),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops - fee drops
|
|
auto const totalBurn = drops(12) - (feeDrops * 10);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm regular key
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(acctSle->getAccountID(sfRegularKey) == carol.id());
|
|
env(noop(alice), sig(carol), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
|
|
// w/ signers list -> funded (update regular key)
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
auto const dave = Account("dave");
|
|
auto const elsa = Account("elsa");
|
|
env.fund(XRP(1000), alice, bob, carol, dave, elsa);
|
|
env.close();
|
|
|
|
// confirm env
|
|
auto const envCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(envCoins == burnCoins - (10 * feeDrops));
|
|
auto const envAlice = env.balance(alice);
|
|
BEAST_EXPECT(envAlice == XRP(1000));
|
|
|
|
// set the regular key
|
|
env(regkey(alice, elsa));
|
|
env(noop(alice), sig(elsa), fee(feeDrops), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == envCoins - (2 * feeDrops));
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == envAlice - (2 * feeDrops));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCSetRegularKey::w_signers);
|
|
env(import(alice, xpopJson),
|
|
msig(bob, carol),
|
|
fee((3 * feeDrops) * 10),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops - fee drops
|
|
auto const totalBurn = drops(48) - ((3 * feeDrops) * 10);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm regular key
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(acctSle->getAccountID(sfRegularKey) == dave.id());
|
|
env(noop(alice), sig(dave), fee(feeDrops), ter(tesSUCCESS));
|
|
|
|
// confirm signers list not set
|
|
auto const k = keylet::signers(alice);
|
|
BEAST_EXPECT(env.current()->read(k) == nullptr);
|
|
}
|
|
|
|
// seed -> funded (empty regular key)
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
env.fund(XRP(1000), alice, bob, carol);
|
|
env.close();
|
|
|
|
// confirm env
|
|
auto const envCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(envCoins == burnCoins - (6 * feeDrops));
|
|
auto const envAlice = env.balance(alice);
|
|
BEAST_EXPECT(envAlice == XRP(1000));
|
|
|
|
// set the regular key
|
|
env(regkey(alice, carol));
|
|
env(noop(alice), sig(carol), fee(feeDrops), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == envCoins - (2 * feeDrops));
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == envAlice - (2 * feeDrops));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCSetRegularKey::w_seed_empty);
|
|
env(import(alice, xpopJson),
|
|
fee(feeDrops * 10),
|
|
sig(alice),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops - fee drops
|
|
auto const totalBurn = drops(12) - (feeDrops * 10);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm regular key
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(!acctSle->isFieldPresent(sfRegularKey));
|
|
}
|
|
|
|
// w/ regular key -> funded (empty regular key)
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
env.fund(XRP(1000), alice, bob, carol);
|
|
env.close();
|
|
|
|
// confirm env
|
|
auto const envCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(envCoins == burnCoins - (6 * feeDrops));
|
|
auto const envAlice = env.balance(alice);
|
|
BEAST_EXPECT(envAlice == XRP(1000));
|
|
|
|
// set the regular key
|
|
env(regkey(alice, carol));
|
|
env(noop(alice), sig(carol), fee(feeDrops), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == envCoins - (2 * feeDrops));
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == envAlice - (2 * feeDrops));
|
|
|
|
// import tx
|
|
auto const xpopJson =
|
|
loadXpop(ImportTCSetRegularKey::w_regular_key_empty);
|
|
env(import(alice, xpopJson),
|
|
fee(feeDrops * 10),
|
|
sig(bob),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops - fee drops
|
|
auto const totalBurn = drops(12) - (feeDrops * 10);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm regular key
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(!acctSle->isFieldPresent(sfRegularKey));
|
|
env(noop(alice), sig(alice), fee(feeDrops), ter(tesSUCCESS));
|
|
env(noop(alice), sig(bob), fee(feeDrops), ter(tefBAD_AUTH));
|
|
env(noop(alice), sig(carol), fee(feeDrops), ter(tefBAD_AUTH));
|
|
}
|
|
|
|
// w/ signers -> funded (empty regular key)
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
auto const dave = Account("dave");
|
|
env.fund(XRP(1000), alice, bob, carol, dave);
|
|
env.close();
|
|
|
|
// confirm env
|
|
auto const envCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(envCoins == burnCoins - (8 * feeDrops));
|
|
auto const envAlice = env.balance(alice);
|
|
BEAST_EXPECT(envAlice == XRP(1000));
|
|
|
|
// set the regular key
|
|
env(regkey(alice, dave));
|
|
env(noop(alice), sig(dave), fee(feeDrops), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == envCoins - (2 * feeDrops));
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == envAlice - (2 * feeDrops));
|
|
|
|
// import tx
|
|
auto const xpopJson =
|
|
loadXpop(ImportTCSetRegularKey::w_signers_empty);
|
|
env(import(alice, xpopJson),
|
|
msig(bob, carol),
|
|
fee((3 * feeDrops) * 10),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops - fee drops
|
|
auto const totalBurn = drops(48) - ((3 * feeDrops) * 10);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm regular key
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(!acctSle->isFieldPresent(sfRegularKey));
|
|
env(noop(alice), sig(alice), fee(feeDrops), ter(tesSUCCESS));
|
|
env(noop(alice), sig(bob), fee(feeDrops), ter(tefBAD_AUTH));
|
|
env(noop(alice), sig(carol), fee(feeDrops), ter(tefBAD_AUTH));
|
|
env(noop(alice), sig(dave), fee(feeDrops), ter(tefBAD_AUTH));
|
|
}
|
|
}
|
|
|
|
void
|
|
testSetRegularKeyFlags(FeatureBitset features)
|
|
{
|
|
testcase("set regular key flags");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
// dne -> dont set flag
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
env.memoize(alice);
|
|
env.memoize(bob);
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCSetRegularKey::w_seed);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm lsfPasswordSpent is set
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(
|
|
(acctSle->getFieldU32(sfFlags) & lsfPasswordSpent) ==
|
|
lsfPasswordSpent);
|
|
}
|
|
|
|
// funded -> set flag
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
env.fund(XRP(1000), alice, bob);
|
|
env.close();
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCSetRegularKey::w_seed_zero);
|
|
env(import(alice, xpopJson), fee(feeDrops * 10), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm lsfPasswordSpent is not set
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(
|
|
(acctSle->getFieldU32(sfFlags) & lsfPasswordSpent) == 0);
|
|
}
|
|
}
|
|
|
|
void
|
|
testSignersListSet(FeatureBitset features)
|
|
{
|
|
testcase("signers list set tx");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
// w/ seed -> dne w/ seed (Bad Fee)
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
env.memoize(alice);
|
|
env.memoize(bob);
|
|
env.memoize(carol);
|
|
|
|
// confirm env
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == burnCoins);
|
|
|
|
// confirm total coins header
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson =
|
|
loadXpop(ImportTCSignersListSet::w_seed_bad_fee);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
// tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(temBAD_FEE));
|
|
env.close();
|
|
}
|
|
|
|
// w/ seed -> dne w/ seed
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
env.memoize(alice);
|
|
|
|
// confirm total coins header
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == burnCoins);
|
|
|
|
// confirm alice balance
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCSignersListSet::w_seed);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = (burn drops + burn fee drops) - reward
|
|
auto const totalBurn = XRP(2) + drops(12) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm fee was minted
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm signers set
|
|
auto const [signers, signersSle] =
|
|
signersKeyAndSle(*env.current(), alice);
|
|
auto const signerEntries =
|
|
signersSle->getFieldArray(sfSignerEntries);
|
|
BEAST_EXPECT(signerEntries.size() == 2);
|
|
BEAST_EXPECT(signerEntries[0u].getFieldU16(sfSignerWeight) == 1);
|
|
BEAST_EXPECT(
|
|
signerEntries[0u].getAccountID(sfAccount) == carol.id());
|
|
BEAST_EXPECT(signerEntries[1u].getFieldU16(sfSignerWeight) == 1);
|
|
BEAST_EXPECT(signerEntries[1u].getAccountID(sfAccount) == bob.id());
|
|
|
|
// confirm multisign tx
|
|
env.close();
|
|
auto const aliceSeq = env.seq(alice);
|
|
env(noop(alice),
|
|
msig(bob, carol),
|
|
fee(3 * feeDrops),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
|
|
|
|
// confirm noop master disabled
|
|
env(noop(alice), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
|
|
// w/ regular key -> dne
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
auto const dave = Account("dave");
|
|
env.memoize(alice);
|
|
|
|
// confirm total coins header
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == burnCoins);
|
|
|
|
// confirm alice balance
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const burnAmt = XRP(2);
|
|
auto const xpopJson =
|
|
loadXpop(ImportTCSignersListSet::w_regular_key);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, sig(bob), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = (burn drops + burn fee drops) - fee drops
|
|
auto const totalBurn = XRP(2) + drops(12) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm fee was minted
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm signers set
|
|
auto const [signers, signersSle] =
|
|
signersKeyAndSle(*env.current(), alice);
|
|
auto const signerEntries =
|
|
signersSle->getFieldArray(sfSignerEntries);
|
|
BEAST_EXPECT(signerEntries.size() == 2);
|
|
BEAST_EXPECT(signerEntries[0u].getFieldU16(sfSignerWeight) == 1);
|
|
BEAST_EXPECT(
|
|
signerEntries[0u].getAccountID(sfAccount) == dave.id());
|
|
BEAST_EXPECT(signerEntries[1u].getFieldU16(sfSignerWeight) == 1);
|
|
BEAST_EXPECT(
|
|
signerEntries[1u].getAccountID(sfAccount) == carol.id());
|
|
|
|
// confirm multisign tx
|
|
env.close();
|
|
auto const aliceSeq = env.seq(alice);
|
|
env(noop(alice),
|
|
msig(carol, dave),
|
|
fee(3 * feeDrops),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
|
|
|
|
// confirm regular key bad auth
|
|
env(noop(alice), sig(bob), fee(feeDrops), ter(tefBAD_AUTH));
|
|
|
|
// confirm noop master disabled
|
|
env(noop(alice), fee(feeDrops), ter(tefMASTER_DISABLED));
|
|
}
|
|
|
|
// w/ signers -> dne
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 100,000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
auto const dave = Account("dave");
|
|
auto const elsa = Account("elsa");
|
|
env.memoize(alice);
|
|
env.memoize(dave);
|
|
env.memoize(elsa);
|
|
|
|
// confirm total coins header
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == burnCoins);
|
|
|
|
// confirm alice balance
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCSignersListSet::w_signers);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, msig(bob, carol), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm signers set
|
|
auto const [signers, signersSle] =
|
|
signersKeyAndSle(*env.current(), alice);
|
|
auto const signerEntries =
|
|
signersSle->getFieldArray(sfSignerEntries);
|
|
BEAST_EXPECT(signerEntries.size() == 2);
|
|
BEAST_EXPECT(signerEntries[0u].getFieldU16(sfSignerWeight) == 1);
|
|
BEAST_EXPECT(
|
|
signerEntries[0u].getAccountID(sfAccount) == dave.id());
|
|
BEAST_EXPECT(signerEntries[1u].getFieldU16(sfSignerWeight) == 1);
|
|
BEAST_EXPECT(
|
|
signerEntries[1u].getAccountID(sfAccount) == elsa.id());
|
|
|
|
// confirm multisign tx
|
|
env.close();
|
|
auto const aliceSeq = env.seq(alice);
|
|
env(noop(alice),
|
|
msig(dave, elsa),
|
|
fee(3 * feeDrops),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
|
|
|
|
// confirm regular key bad auth
|
|
env(noop(alice), sig(bob), fee(feeDrops), ter(tefBAD_AUTH));
|
|
|
|
// confirm noop master disabled
|
|
env(noop(alice), fee(feeDrops), ter(tefMASTER_DISABLED));
|
|
}
|
|
|
|
// w/ seed -> funded
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
env.fund(XRP(1000), alice, bob, carol);
|
|
env.close();
|
|
|
|
// confirm env
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == burnCoins - (6 * feeDrops));
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(1000));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCSignersListSet::w_seed);
|
|
env(import(alice, xpopJson), fee(feeDrops * 10), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = (burn drops + burn fee drops) - fee drops
|
|
auto const totalBurn = XRP(2) + drops(12) - (feeDrops * 10);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm signers set
|
|
auto const [signers, signersSle] =
|
|
signersKeyAndSle(*env.current(), alice);
|
|
auto const signerEntries =
|
|
signersSle->getFieldArray(sfSignerEntries);
|
|
BEAST_EXPECT(signerEntries.size() == 2);
|
|
BEAST_EXPECT(signerEntries[0u].getFieldU16(sfSignerWeight) == 1);
|
|
BEAST_EXPECT(
|
|
signerEntries[0u].getAccountID(sfAccount) == carol.id());
|
|
BEAST_EXPECT(signerEntries[1u].getFieldU16(sfSignerWeight) == 1);
|
|
BEAST_EXPECT(signerEntries[1u].getAccountID(sfAccount) == bob.id());
|
|
|
|
// confirm multisign tx
|
|
env.close();
|
|
auto const aliceSeq = env.seq(alice);
|
|
env(noop(alice),
|
|
msig(bob, carol),
|
|
fee(3 * feeDrops),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
BEAST_EXPECT(env.seq(alice) == aliceSeq + 1);
|
|
|
|
// confirm noop alice tx
|
|
env(noop(alice), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
|
|
// w/ seed (empty) -> funded (has entries)
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
env.fund(XRP(1000), alice, bob, carol);
|
|
env.close();
|
|
|
|
// confirm env
|
|
auto const envCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(envCoins == burnCoins - (6 * feeDrops));
|
|
auto const envAlice = env.balance(alice);
|
|
BEAST_EXPECT(envAlice == XRP(1000));
|
|
|
|
// set the signers list
|
|
env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
|
|
env(noop(alice),
|
|
msig(bob, carol),
|
|
fee(3 * feeDrops),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == envCoins - (4 * feeDrops));
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == envAlice - (4 * feeDrops));
|
|
|
|
// import tx
|
|
auto const xpopJson =
|
|
loadXpop(ImportTCSignersListSet::w_seed_empty);
|
|
env(import(alice, xpopJson), fee(feeDrops * 10), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = (burn drops + burn fee drops) - fee drops
|
|
auto const totalBurn = XRP(2) + drops(12) - (feeDrops * 10);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm signers not set
|
|
auto const k = keylet::signers(alice);
|
|
BEAST_EXPECT(env.current()->read(k) == nullptr);
|
|
|
|
// confirm noop master success
|
|
env(noop(alice), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
|
|
// w/ regular key (empty) -> funded (has entries)
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
env.fund(XRP(1000), alice, bob, carol);
|
|
env.close();
|
|
|
|
// confirm env
|
|
auto const envCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(envCoins == burnCoins - (6 * feeDrops));
|
|
auto const envAlice = env.balance(alice);
|
|
BEAST_EXPECT(envAlice == XRP(1000));
|
|
|
|
// set the regular key
|
|
env(regkey(alice, bob));
|
|
env(noop(alice), sig(bob), fee(feeDrops), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// set the signers list
|
|
env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
|
|
env(noop(alice),
|
|
msig(bob, carol),
|
|
fee(3 * feeDrops),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == envCoins - (6 * feeDrops));
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == envAlice - (6 * feeDrops));
|
|
|
|
// import tx
|
|
auto const xpopJson =
|
|
loadXpop(ImportTCSignersListSet::w_regular_key_empty);
|
|
env(import(alice, xpopJson),
|
|
fee(feeDrops * 10),
|
|
sig(bob),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = (burn drops + burn fee drops) - fee drops
|
|
auto const totalBurn = XRP(2) + drops(12) - (feeDrops * 10);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm regular key
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(acctSle->getAccountID(sfRegularKey) == bob.id());
|
|
env(noop(alice), sig(bob), fee(feeDrops), ter(tesSUCCESS));
|
|
|
|
// confirm signers not set
|
|
auto const k = keylet::signers(alice);
|
|
BEAST_EXPECT(env.current()->read(k) == nullptr);
|
|
|
|
// confirm noop master success
|
|
env(noop(alice), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
|
|
// w/ signers (empty) -> funded (has entries)
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
env.fund(XRP(1000), alice, bob, carol);
|
|
env.close();
|
|
|
|
// confirm env
|
|
auto const envCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(envCoins == burnCoins - (6 * feeDrops));
|
|
auto const envAlice = env.balance(alice);
|
|
BEAST_EXPECT(envAlice == XRP(1000));
|
|
|
|
// set the signers list
|
|
env(signers(alice, 2, {{bob, 1}, {carol, 1}}));
|
|
env(noop(alice),
|
|
msig(bob, carol),
|
|
fee(3 * feeDrops),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == envCoins - (4 * feeDrops));
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == envAlice - (4 * feeDrops));
|
|
|
|
// import tx
|
|
auto const xpopJson =
|
|
loadXpop(ImportTCSignersListSet::w_signers_empty);
|
|
env(import(alice, xpopJson),
|
|
msig(bob, carol),
|
|
fee((3 * feeDrops) * 10),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = (burn drops + burn fee drops) - fee drops
|
|
auto const totalBurn = XRP(2) + drops(48) - ((3 * feeDrops) * 10);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm signers not set
|
|
auto const k = keylet::signers(alice);
|
|
BEAST_EXPECT(env.current()->read(k) == nullptr);
|
|
|
|
// confirm noop master success
|
|
env(noop(alice), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
}
|
|
|
|
void
|
|
testAccountIndex(FeatureBitset features)
|
|
{
|
|
testcase("account index");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
// Account Index from Import
|
|
{
|
|
for (std::uint32_t const withFeature : {0, 1, 2})
|
|
{
|
|
auto const amend = withFeature == 0 ? features
|
|
: withFeature == 1 ? features - featureXahauGenesis
|
|
: features - featureDeletableAccounts;
|
|
test::jtx::Env env{
|
|
*this, makeNetworkVLConfig(21337, keys), amend};
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
env.fund(XRP(1000), alice);
|
|
env.close();
|
|
|
|
env(import(alice, loadXpop(ImportTCAccountSet::w_seed)),
|
|
fee(feeDrops * 10),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm account index was set
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
|
|
std::cout << "withFeature: " << withFeature << "\n";
|
|
|
|
// confirm sequence
|
|
if (withFeature == 0)
|
|
{
|
|
BEAST_EXPECT((*acctSle)[sfAccountIndex] == 0);
|
|
}
|
|
std::uint64_t const seq = withFeature == 0 ? 12
|
|
: withFeature == 1 ? 6
|
|
: 12;
|
|
BEAST_EXPECT((*acctSle)[sfSequence] == seq);
|
|
|
|
// confirm account count was set
|
|
if (withFeature == 0)
|
|
{
|
|
auto const [fee, feeSle] = feesKeyAndSle(*env.current());
|
|
BEAST_EXPECT((*feeSle)[sfAccountCount] == 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Account Index from Payment
|
|
{
|
|
for (std::uint32_t const withFeature : {0, 1, 2})
|
|
{
|
|
auto const amend = withFeature == 0 ? features
|
|
: withFeature == 1 ? features - featureXahauGenesis
|
|
: features - featureDeletableAccounts;
|
|
test::jtx::Env env{
|
|
*this, makeNetworkVLConfig(21337, keys), amend};
|
|
auto const feeDrops = env.current()->fees().base;
|
|
env.close();
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
auto const carol = Account("carol");
|
|
env.fund(XRP(1000), alice, bob, carol);
|
|
env.close();
|
|
|
|
struct TestAccountData
|
|
{
|
|
Account acct;
|
|
std::uint32_t index;
|
|
std::uint64_t sequence;
|
|
};
|
|
|
|
std::uint64_t const seq = withFeature == 0 ? 11
|
|
: withFeature == 1 ? 5
|
|
: 11;
|
|
std::array<TestAccountData, 3> acctTests = {{
|
|
{alice, 0, seq},
|
|
{bob, 1, seq},
|
|
{carol, 2, seq},
|
|
}};
|
|
|
|
for (auto const& t : acctTests)
|
|
{
|
|
// confirm index was set
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), t.acct);
|
|
|
|
// confirm sequence
|
|
if (withFeature == 0)
|
|
{
|
|
BEAST_EXPECT((*acctSle)[sfAccountIndex] == t.index);
|
|
}
|
|
BEAST_EXPECT((*acctSle)[sfSequence] == t.sequence);
|
|
}
|
|
|
|
if (withFeature == 0)
|
|
{
|
|
// confirm count was updated
|
|
auto const [fee, feeSle] = feesKeyAndSle(*env.current());
|
|
BEAST_EXPECT((*feeSle)[sfAccountCount] == 3);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
testHookIssuer(FeatureBitset features)
|
|
{
|
|
testcase("hook issuer tx");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
// Test that hook can reject and does NOT mint the funds.
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
auto const issuer = Account("issuer");
|
|
env.fund(XRP(10000), alice, issuer);
|
|
env.close();
|
|
|
|
std::string const createCodeHex =
|
|
"0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F"
|
|
"017F60017F017E02250303656E76057472616365000003656E7608726F6C6C"
|
|
"6261636B000103656E76025F670002030201030503010002062B077F0141C0"
|
|
"88040B7F004180080B7F0041BE080B7F004180080B7F0041C088040B7F0041"
|
|
"000B7F0041010B07080104686F6F6B00030AC3800001BF800001017F230041"
|
|
"106B220124002001200036020C41940841154180084114410010001A41AA08"
|
|
"4114420A10011A41012200200010021A200141106A240042000B0B44010041"
|
|
"80080B3D526F6C6C6261636B2E633A2043616C6C65642E0022526F6C6C6261"
|
|
"636B2E633A2043616C6C65642E2200526F6C6C6261636B3A20526F6C6C6261"
|
|
"636B21";
|
|
std::string ns_str =
|
|
"CAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECAFECA"
|
|
"FE";
|
|
Json::Value jv =
|
|
ripple::test::jtx::hook(issuer, {{hso(createCodeHex)}}, 0);
|
|
jv[jss::Hooks][0U][jss::Hook][jss::HookNamespace] = ns_str;
|
|
jv[jss::Hooks][0U][jss::Hook][jss::HookOn] =
|
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFFFFFFBFFF"
|
|
"FF";
|
|
env(jv, fee(1'000'000));
|
|
env.close();
|
|
|
|
auto const preAlice = env.balance(alice);
|
|
auto const preCoins = env.current()->info().drops;
|
|
|
|
auto tx = import(alice, loadXpop(ImportTCAccountSet::w_seed));
|
|
tx[sfIssuer.jsonName] = issuer.human();
|
|
env(tx, fee(1'000'000), ter(tecHOOK_REJECTED));
|
|
env.close();
|
|
|
|
// confirm fee was burned but no mint
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice - XRP(1));
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins - XRP(1));
|
|
|
|
// resubmit import without issuer - no trigger hook
|
|
env(import(alice, loadXpop(ImportTCAccountSet::w_seed)),
|
|
fee(feeDrops * 10),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = (burn drops + burn fee drops) - fee drops
|
|
auto const totalBurn = XRP(1000) - (feeDrops * 10);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice2 = env.balance(alice);
|
|
BEAST_EXPECT(postAlice2 == postAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins2 = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins2 == postCoins + totalBurn);
|
|
|
|
env.close();
|
|
}
|
|
}
|
|
|
|
void
|
|
testAccountDelete(FeatureBitset features)
|
|
{
|
|
testcase("account delete");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
auto const alice = Account("alice");
|
|
auto const bob = Account("bob");
|
|
env.fund(XRP(1000), alice, bob);
|
|
env.close();
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
Json::Value const xpop = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value const tx = import(alice, xpop);
|
|
env(tx, fee(feeDrops * 10), ter(tesSUCCESS));
|
|
|
|
// Close enough ledgers to be able to delete alices's account.
|
|
incLgrSeqForAccDel(env, alice);
|
|
|
|
// alice cannot delete account after import
|
|
auto const acctDelFee{drops(env.current()->fees().increment)};
|
|
env(acctdelete(alice, bob),
|
|
fee(acctDelFee),
|
|
ter(tecHAS_OBLIGATIONS));
|
|
}
|
|
}
|
|
|
|
void
|
|
testImportSequence(FeatureBitset features)
|
|
{
|
|
testcase("import sequence");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
// test bad IMPORT_VL_KEYS no UNLReport
|
|
{
|
|
std::vector<std::string> const badVLKeys = {
|
|
"ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1"
|
|
"CDC2"};
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, badVLKeys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
env.fund(XRP(1000), alice);
|
|
env.close();
|
|
|
|
auto preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(1000));
|
|
env(import(alice, loadXpop(ImportTCAccountSet::w_seed)),
|
|
fee(feeDrops * 10),
|
|
ter(telIMPORT_VL_KEY_NOT_RECOGNISED));
|
|
env.close();
|
|
}
|
|
|
|
// test good IMPORT_VL_KEYS no UNLReport
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
env.fund(XRP(1000), alice);
|
|
env.close();
|
|
|
|
auto preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(1000));
|
|
env(import(alice, loadXpop(ImportTCAccountSet::w_seed)),
|
|
fee(feeDrops * 10),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
}
|
|
|
|
// test no IMPORT_VL_KEYS has UNLReport
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkConfig(21337)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const burnCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(burnCoins == initCoins - 10'000'000'000);
|
|
|
|
auto const alice = Account("alice");
|
|
env.fund(XRP(1000), alice);
|
|
env.close();
|
|
|
|
auto preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(1000));
|
|
|
|
// ADD UNL REPORT
|
|
std::vector<std::string> const _ivlKeys = {
|
|
"ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1"
|
|
"CDC1",
|
|
"ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1"
|
|
"CDC2",
|
|
};
|
|
|
|
std::vector<PublicKey> ivlKeys;
|
|
for (auto const& strPk : _ivlKeys)
|
|
{
|
|
auto pkHex = strUnHex(strPk);
|
|
ivlKeys.emplace_back(makeSlice(*pkHex));
|
|
}
|
|
|
|
std::vector<std::string> const _vlKeys = {
|
|
"ED8E43A943A174190BA2FAE91F44AC6E2D1D8202EFDCC2EA3DBB39814576D6"
|
|
"90F7",
|
|
"ED45D1840EE724BE327ABE9146503D5848EFD5F38B6D5FEDE71E80ACCE5E6E"
|
|
"738B"};
|
|
|
|
std::vector<PublicKey> vlKeys;
|
|
for (auto const& strPk : _vlKeys)
|
|
{
|
|
auto pkHex = strUnHex(strPk);
|
|
vlKeys.emplace_back(makeSlice(*pkHex));
|
|
}
|
|
|
|
// insert a ttUNL_REPORT pseudo into the open ledger
|
|
env.app().openLedger().modify(
|
|
[&](OpenView& view, beast::Journal j) -> bool {
|
|
STTx tx = createUNLReportTx(
|
|
env.current()->seq() + 1, ivlKeys[0], vlKeys[0]);
|
|
uint256 txID = tx.getTransactionID();
|
|
auto s = std::make_shared<ripple::Serializer>();
|
|
tx.add(*s);
|
|
env.app().getHashRouter().setFlags(txID, SF_PRIVATE2);
|
|
view.rawTxInsert(txID, std::move(s), nullptr);
|
|
return true;
|
|
});
|
|
|
|
// close the ledger
|
|
env.close();
|
|
|
|
BEAST_EXPECT(hasUNLReport(env) == true);
|
|
|
|
// Test Import
|
|
env(import(alice, loadXpop(ImportTCAccountSet::w_seed)),
|
|
fee(feeDrops * 10),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
}
|
|
}
|
|
|
|
void
|
|
testMaxSupply(FeatureBitset features)
|
|
{
|
|
testcase("max supply");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
// burn 100'000 coins
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const envCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(envCoins == 100'000'000'000'000'000);
|
|
// 100'000'000'000'000'000 - drops
|
|
// 100'000'000'000 - xrp
|
|
|
|
// burn 100,000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(100'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == envCoins - drops(100'000'000'000));
|
|
|
|
auto const alice = Account("alice");
|
|
env.memoize(alice);
|
|
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
STAmount burnFee = XRP(1000) + XRP(2);
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + burnFee);
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + burnFee);
|
|
}
|
|
|
|
// burn all coins
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const envCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(envCoins == 100'000'000'000'000'000);
|
|
|
|
// burn all but 1,000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master),
|
|
fee(envCoins - drops(1'000'000'000)),
|
|
ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == XRP(1000));
|
|
|
|
auto const alice = Account("alice");
|
|
env.memoize(alice);
|
|
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
STAmount burnFee = XRP(1000) + XRP(2);
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + burnFee);
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + burnFee);
|
|
}
|
|
|
|
// burn no coins
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const envCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(envCoins == 100'000'000'000'000'000);
|
|
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == XRP(100'000'000'000));
|
|
|
|
auto const alice = Account("alice");
|
|
env.memoize(alice);
|
|
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
STAmount burnFee = XRP(1000) + XRP(2);
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tefINTERNAL));
|
|
env.close();
|
|
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice);
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins);
|
|
}
|
|
}
|
|
|
|
void
|
|
testMinMax(FeatureBitset features)
|
|
{
|
|
testcase("min max");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
// w/ seed -> dne (min)
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == initCoins - 10'000'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
env.memoize(alice);
|
|
|
|
// confirm env
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::min);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops + reward amount
|
|
auto const totalBurn = drops(10) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm account exists
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(acctSle != nullptr);
|
|
env(noop(alice), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
|
|
// w/ seed -> dne (min) (Reserve/Reference/Fee)
|
|
// Owner Fee = 20 xrp
|
|
{
|
|
test::jtx::Env env{*this, makeMaxFeeConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 10'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == initCoins - 10'000'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
env.memoize(alice);
|
|
|
|
// confirm env
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::min);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops + reward amount
|
|
auto const totalBurn = drops(10) + XRP(20);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm account exists
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(acctSle != nullptr);
|
|
env(noop(alice), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
|
|
// w/ seed -> dne (max)
|
|
{
|
|
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)};
|
|
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 100'000'000'000'000'000);
|
|
|
|
// burn 99'999'998'000 xrp
|
|
auto const master = Account("masterpassphrase");
|
|
env(noop(master), fee(99'999'998'000'000'000), ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// confirm total coins header
|
|
auto const preCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(preCoins == initCoins - 99'999'998'000'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
env.memoize(alice);
|
|
|
|
// confirm env
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::max);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops + reward amount
|
|
auto const totalBurn = drops(99'999'939'799'000'000) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + totalBurn);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == preCoins + totalBurn);
|
|
|
|
// confirm account exists
|
|
auto const [acct, acctSle] =
|
|
accountKeyAndSle(*env.current(), alice);
|
|
BEAST_EXPECT(acctSle != nullptr);
|
|
env(noop(alice), fee(feeDrops), ter(tesSUCCESS));
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<Config>
|
|
makeGenesisConfig(
|
|
FeatureBitset features,
|
|
uint32_t networkID,
|
|
std::string fee,
|
|
std::string a_res,
|
|
std::string o_res,
|
|
uint32_t ledgerID)
|
|
{
|
|
using namespace jtx;
|
|
|
|
// IMPORT VL KEY
|
|
std::vector<std::string> const keys = {
|
|
"ED74D4036C6591A4BDF9C54CEFA39B996A"
|
|
"5DCE5F86D11FDA1874481CE9D5A1CDC1"};
|
|
|
|
Json::Value jsonValue;
|
|
Json::Reader reader;
|
|
reader.parse(ImportTCHalving::base_genesis, jsonValue);
|
|
|
|
foreachFeature(features, [&](uint256 const& feature) {
|
|
std::string featureName = featureToName(feature);
|
|
std::optional<uint256> featureHash =
|
|
getRegisteredFeature(featureName);
|
|
if (featureHash.has_value())
|
|
{
|
|
std::string hashString = to_string(featureHash.value());
|
|
jsonValue["ledger"]["accountState"][1]["Amendments"].append(
|
|
hashString);
|
|
}
|
|
});
|
|
|
|
jsonValue["ledger_current_index"] = ledgerID;
|
|
jsonValue["ledger"]["ledger_index"] = to_string(ledgerID);
|
|
jsonValue["ledger"]["seqNum"] = to_string(ledgerID);
|
|
|
|
return envconfig([&](std::unique_ptr<Config> cfg) {
|
|
cfg->NETWORK_ID = networkID;
|
|
cfg->START_LEDGER = jsonValue.toStyledString();
|
|
cfg->START_UP = Config::LOAD_JSON;
|
|
Section config;
|
|
config.append(
|
|
{"reference_fee = " + fee,
|
|
"account_reserve = " + a_res,
|
|
"owner_reserve = " + o_res});
|
|
auto setup = setup_FeeVote(config);
|
|
cfg->FEES = setup;
|
|
|
|
for (auto const& strPk : keys)
|
|
{
|
|
auto pkHex = strUnHex(strPk);
|
|
if (!pkHex)
|
|
Throw<std::runtime_error>(
|
|
"Import VL Key '" + strPk + "' was not valid hex.");
|
|
|
|
auto const pkType = publicKeyType(makeSlice(*pkHex));
|
|
if (!pkType)
|
|
Throw<std::runtime_error>(
|
|
"Import VL Key '" + strPk +
|
|
"' was not a valid key type.");
|
|
|
|
cfg->IMPORT_VL_KEYS.emplace(strPk, makeSlice(*pkHex));
|
|
}
|
|
return cfg;
|
|
});
|
|
}
|
|
|
|
void
|
|
testHalving(FeatureBitset features)
|
|
{
|
|
testcase("halving");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
// Halving @ ledger seq 1'999'999
|
|
{
|
|
test::jtx::Env env{
|
|
*this,
|
|
makeGenesisConfig(
|
|
features, 21337, "10", "1000000", "200000", 1999998),
|
|
features};
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 0);
|
|
auto const initSeq = env.current()->info().seq;
|
|
BEAST_EXPECT(initSeq == 1'999'999);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
env.memoize(alice);
|
|
|
|
// confirm env
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops + Init Reward
|
|
auto const creditDrops = XRP(1'000) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + creditDrops);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == initCoins + creditDrops);
|
|
}
|
|
|
|
// Halving @ ledger seq 2'000'000
|
|
{
|
|
test::jtx::Env env{
|
|
*this,
|
|
makeGenesisConfig(
|
|
features, 21337, "10", "1000000", "200000", 1999998),
|
|
features};
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 0);
|
|
env.close();
|
|
auto const initSeq = env.current()->info().seq;
|
|
BEAST_EXPECT(initSeq == 2'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
env.memoize(alice);
|
|
|
|
// confirm env
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops + Init Reward
|
|
auto const creditDrops = XRP(1'000) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + creditDrops);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == initCoins + creditDrops);
|
|
}
|
|
|
|
// Halving @ ledger seq 2'000'001
|
|
{
|
|
test::jtx::Env env{
|
|
*this,
|
|
makeGenesisConfig(
|
|
features, 21337, "10", "1000000", "200000", 1999998),
|
|
features};
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 0);
|
|
env.close();
|
|
env.close();
|
|
auto const initSeq = env.current()->info().seq;
|
|
BEAST_EXPECT(initSeq == 2'000'001);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
env.memoize(alice);
|
|
|
|
// confirm env
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops + Init Reward
|
|
auto const creditDrops = drops(999999964) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + creditDrops);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == initCoins + creditDrops);
|
|
}
|
|
|
|
// Halving @ ledger seq 5'000'000
|
|
{
|
|
test::jtx::Env env{
|
|
*this,
|
|
makeGenesisConfig(
|
|
features, 21337, "10", "1000000", "200000", 4999999),
|
|
features};
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 0);
|
|
auto const initSeq = env.current()->info().seq;
|
|
BEAST_EXPECT(initSeq == 5'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
env.memoize(alice);
|
|
|
|
// confirm env
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops + Init Reward
|
|
auto const creditDrops = drops(892857142) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + creditDrops);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == initCoins + creditDrops);
|
|
}
|
|
|
|
// Halving @ ledger seq 20'000'000
|
|
{
|
|
test::jtx::Env env{
|
|
*this,
|
|
makeGenesisConfig(
|
|
features, 21337, "10", "1000000", "200000", 19999999),
|
|
features};
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 0);
|
|
auto const initSeq = env.current()->info().seq;
|
|
BEAST_EXPECT(initSeq == 20'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
env.memoize(alice);
|
|
|
|
// confirm env
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops + Init Reward
|
|
auto const creditDrops = drops(357142857) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + creditDrops);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == initCoins + creditDrops);
|
|
}
|
|
|
|
// Halving @ ledger seq 29'999'998
|
|
{
|
|
test::jtx::Env env{
|
|
*this,
|
|
makeGenesisConfig(
|
|
features, 21337, "10", "1000000", "200000", 29999998),
|
|
features};
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 0);
|
|
auto const initSeq = env.current()->info().seq;
|
|
BEAST_EXPECT(initSeq == 29'999'999);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
env.memoize(alice);
|
|
|
|
// confirm env
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops + Init Reward
|
|
auto const creditDrops = drops(35) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + creditDrops);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == initCoins + creditDrops);
|
|
}
|
|
|
|
// Halving @ ledger seq 30'000'000
|
|
{
|
|
test::jtx::Env env{
|
|
*this,
|
|
makeGenesisConfig(
|
|
features, 21337, "10", "1000000", "200000", 29999998),
|
|
features};
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 0);
|
|
env.close();
|
|
auto const initSeq = env.current()->info().seq;
|
|
BEAST_EXPECT(initSeq == 30'000'000);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
env.memoize(alice);
|
|
|
|
// confirm env
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops + Init Reward
|
|
auto const creditDrops = drops(0) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + creditDrops);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == initCoins + creditDrops);
|
|
}
|
|
|
|
// Halving @ ledger seq 50'000'001
|
|
{
|
|
test::jtx::Env env{
|
|
*this,
|
|
makeGenesisConfig(
|
|
features, 21337, "10", "1000000", "200000", 50000000),
|
|
features};
|
|
|
|
// confirm total coins header
|
|
auto const initCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(initCoins == 0);
|
|
auto const initSeq = env.current()->info().seq;
|
|
BEAST_EXPECT(initSeq == 50'000'001);
|
|
|
|
// init env
|
|
auto const alice = Account("alice");
|
|
env.memoize(alice);
|
|
|
|
// confirm env
|
|
auto const preAlice = env.balance(alice);
|
|
BEAST_EXPECT(preAlice == XRP(0));
|
|
|
|
// import tx
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::w_seed);
|
|
Json::Value tx = import(alice, xpopJson);
|
|
tx[jss::Sequence] = 0;
|
|
tx[jss::Fee] = 0;
|
|
env(tx, alice, ter(tesSUCCESS));
|
|
env.close();
|
|
|
|
// total burn = burn drops + Init Reward
|
|
auto const creditDrops = drops(0) + XRP(2);
|
|
|
|
// confirm fee was minted
|
|
auto const postAlice = env.balance(alice);
|
|
BEAST_EXPECT(postAlice == preAlice + creditDrops);
|
|
|
|
// confirm total coins header
|
|
auto const postCoins = env.current()->info().drops;
|
|
BEAST_EXPECT(postCoins == initCoins + creditDrops);
|
|
}
|
|
}
|
|
|
|
void
|
|
testRPCFee(FeatureBitset features)
|
|
{
|
|
testcase("rpc fee");
|
|
|
|
using namespace test::jtx;
|
|
using namespace std::literals;
|
|
|
|
test::jtx::Env env{*this, makeNetworkConfig(21337)};
|
|
auto const feeDrops = env.current()->fees().base;
|
|
|
|
auto const alice = Account("alice");
|
|
env.fund(XRP(1000), alice);
|
|
env.close();
|
|
|
|
// build tx_blob
|
|
Json::Value params;
|
|
auto const xpopJson = loadXpop(ImportTCAccountSet::w_seed);
|
|
auto tx = env.jt(import(alice, xpopJson));
|
|
params[jss::tx_blob] = strHex(tx.stx->getSerializer().slice());
|
|
|
|
// fee request
|
|
auto const jrr = env.rpc("json", "fee", to_string(params));
|
|
|
|
// verify hooks fee
|
|
auto const hooksFee = jrr[jss::result][jss::fee_hooks_feeunits];
|
|
BEAST_EXPECT(hooksFee == to_string(feeDrops * 10));
|
|
|
|
// verify open ledger fee
|
|
auto const dropsJV = jrr[jss::result][jss::drops];
|
|
auto const openLedgerFee = dropsJV[jss::open_ledger_fee];
|
|
BEAST_EXPECT(openLedgerFee == to_string((feeDrops * 10) + feeDrops));
|
|
}
|
|
|
|
public:
|
|
void
|
|
run() override
|
|
{
|
|
using namespace test::jtx;
|
|
FeatureBitset const all{supported_amendments()};
|
|
testWithFeats(all);
|
|
}
|
|
|
|
void
|
|
testWithFeats(FeatureBitset features)
|
|
{
|
|
// testComputeStartingBalance(features);
|
|
// testIsHex(features);
|
|
// testIsBase58(features);
|
|
// testIsBase64(features);
|
|
// testParseUint64(features);
|
|
// testSyntaxCheckProofObject(features);
|
|
// testSyntaxCheckXPOP(features);
|
|
// testGetVLInfo(features);
|
|
// testEnabled(features);
|
|
// testInvalidPreflight(features);
|
|
// testInvalidPreclaim(features);
|
|
// testInvalidDoApply(features);
|
|
// testAccountSet(features);
|
|
// testAccountSetFlags(features);
|
|
// testSetRegularKey(features);
|
|
// testSetRegularKeyFlags(features);
|
|
// testSignersListSet(features);
|
|
testAccountIndex(features);
|
|
// testHookIssuer(features);
|
|
// testImportSequence(features);
|
|
// testAccountDelete(features);
|
|
// testMaxSupply(features);
|
|
// testMinMax(features);
|
|
// testHalving(features - featureOwnerPaysFee);
|
|
// testRPCFee(features);
|
|
}
|
|
};
|
|
|
|
BEAST_DEFINE_TESTSUITE(Import, app, ripple);
|
|
|
|
} // namespace test
|
|
} // namespace ripple
|