mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-16 00:25:49 +00:00
setup import test
This commit is contained in:
@@ -703,6 +703,7 @@ if (tests)
|
||||
src/test/app/Flow_test.cpp
|
||||
src/test/app/Freeze_test.cpp
|
||||
src/test/app/HashRouter_test.cpp
|
||||
src/test/app/Import_test.cpp
|
||||
src/test/app/LedgerHistory_test.cpp
|
||||
src/test/app/LedgerLoad_test.cpp
|
||||
src/test/app/LedgerMaster_test.cpp
|
||||
|
||||
@@ -838,7 +838,7 @@ Import::preflight(PreflightContext const& ctx)
|
||||
if (!([](Json::Value const& proof, std::string hash) -> bool
|
||||
{
|
||||
auto const proofContains =
|
||||
[](Json::Value const* proof, std::string hash, int depth = 0, auto proofContains) -> bool
|
||||
[](Json::Value const* proof, std::string hash, int depth = 0, auto proofContains = nullptr) -> bool
|
||||
{
|
||||
if (depth > 32)
|
||||
return false;
|
||||
@@ -885,7 +885,7 @@ Import::preflight(PreflightContext const& ctx)
|
||||
([](Json::Value const& proof) -> uint256
|
||||
{
|
||||
auto hashProof =
|
||||
[](Json::Value const& proof, int depth = 0, auto const& hashProof) -> uint256
|
||||
[](Json::Value const& proof, int depth = 0, auto const& hashProof = nullptr) -> uint256
|
||||
{
|
||||
const uint256 nullhash;
|
||||
|
||||
@@ -918,6 +918,7 @@ Import::preflight(PreflightContext const& ctx)
|
||||
|
||||
for (int x = 0; x < 16; ++x)
|
||||
{
|
||||
// Duplicate / Sanity
|
||||
std::string const nibble (1, "0123456789ABCDEF"[x]);
|
||||
if (!proof[jss::children].isMember(nibble))
|
||||
hash_append(h, nullhash);
|
||||
@@ -948,6 +949,7 @@ Import::preflight(PreflightContext const& ctx)
|
||||
auto coins = parse_uint64(lgr[jss::coins].asString());
|
||||
uint256 phash, acroot;
|
||||
|
||||
// Duplicate / Sanity - syntaxCheckXPOP
|
||||
if (!coins ||
|
||||
!phash.parseHex(lgr[jss::phash].asString()) ||
|
||||
!acroot.parseHex(lgr[jss::acroot].asString()))
|
||||
@@ -1044,10 +1046,18 @@ Import::preflight(PreflightContext const& ctx)
|
||||
validatorsMaster[nodemaster] = nodepub;
|
||||
}
|
||||
|
||||
JLOG(ctx.j.trace())
|
||||
<< "totalValidatorCount: " << totalValidatorCount;
|
||||
|
||||
uint64_t quorum = totalValidatorCount * 0.8;
|
||||
|
||||
if (quorum == 0)
|
||||
{
|
||||
JLOG(ctx.j.warn())
|
||||
<< "Import: resetting quorum to 1. "
|
||||
<< tx.getTransactionID();
|
||||
quorum = 1;
|
||||
}
|
||||
|
||||
|
||||
// count how many validations this ledger hash has
|
||||
@@ -1185,7 +1195,7 @@ Import::preflight(PreflightContext const& ctx)
|
||||
// if it is less than the Account Sequence in the xpop then mint and
|
||||
// update sfImportSequence
|
||||
|
||||
|
||||
// Duplicate / Sanity
|
||||
if (!stpTrans->isFieldPresent(sfSequence) ||
|
||||
!stpTrans->isFieldPresent(sfFee) ||
|
||||
!isXRP(stpTrans->getFieldAmount(sfFee)))
|
||||
@@ -1238,14 +1248,14 @@ Import::preclaim(PreclaimContext const& ctx)
|
||||
return tefPAST_IMPORT_SEQ;
|
||||
}
|
||||
|
||||
auto const vl = getVLInfo(*xpop, ctx.j);
|
||||
auto const vlInfo = getVLInfo(*xpop, ctx.j);
|
||||
|
||||
if (!vl)
|
||||
if (!vlInfo)
|
||||
return tefINTERNAL;
|
||||
|
||||
auto const& sleVL = ctx.view.read(keylet::import_vlseq(vl->second));
|
||||
auto const& sleVL = ctx.view.read(keylet::import_vlseq(vlInfo->second));
|
||||
|
||||
if (sleVL && sleVL->getFieldU32(sfImportSequence) > vl->first)
|
||||
if (sleVL && sleVL->getFieldU32(sfImportSequence) > vlInfo->first)
|
||||
return tefPAST_IMPORT_VL_SEQ;
|
||||
|
||||
return tesSUCCESS;
|
||||
@@ -1298,11 +1308,13 @@ Import::doApply()
|
||||
{
|
||||
if (tt == ttSIGNER_LIST_SET)
|
||||
{
|
||||
JLOG(ctx_.journal.warn()) << "SingerListSet";
|
||||
// key import: signer list
|
||||
setSignerEntries = stpTrans->getFieldArray(sfSignerEntries);
|
||||
}
|
||||
else if (tt == ttREGULAR_KEY_SET)
|
||||
{
|
||||
JLOG(ctx_.journal.warn()) << "SetRegularKey";
|
||||
// key import: regular key
|
||||
setRegularKey = stpTrans->getAccountID(sfRegularKey);
|
||||
}
|
||||
@@ -1310,9 +1322,10 @@ Import::doApply()
|
||||
|
||||
bool const create = !sle;
|
||||
|
||||
if (!sle)
|
||||
if (create)
|
||||
{
|
||||
// Create the account.
|
||||
JLOG(ctx_.journal.warn()) << "create - create account";
|
||||
std::uint32_t const seqno{
|
||||
view().rules().enabled(featureDeletableAccounts) ? view().seq()
|
||||
: 1};
|
||||
@@ -1343,16 +1356,23 @@ Import::doApply()
|
||||
return tefINTERNAL;
|
||||
}
|
||||
|
||||
if (setSignerEntries)
|
||||
if (setSignerEntries) {
|
||||
JLOG(ctx_.journal.warn()) << "signer list set";
|
||||
sle->setFieldArray(sfSignerEntries, *setSignerEntries);
|
||||
}
|
||||
else if (setRegularKey)
|
||||
{
|
||||
JLOG(ctx_.journal.warn()) << "set regular key";
|
||||
sle->setAccountID(sfRegularKey, *setRegularKey);
|
||||
}
|
||||
|
||||
if (create)
|
||||
{
|
||||
JLOG(ctx_.journal.warn()) << "create";
|
||||
if (!signedWithMaster)
|
||||
{
|
||||
// disable master if the account is created using non-master key
|
||||
JLOG(ctx_.journal.warn()) << "create - disable master";
|
||||
sle->setAccountID(sfRegularKey, noAccount());
|
||||
sle->setFieldU32(sfFlags, lsfDisableMaster);
|
||||
}
|
||||
@@ -1361,11 +1381,13 @@ Import::doApply()
|
||||
else
|
||||
{
|
||||
// account already exists
|
||||
JLOG(ctx_.journal.warn()) << "update - import sequence";
|
||||
sle->setFieldU32(sfImportSequence, importSequence);
|
||||
|
||||
// credit the PoB
|
||||
if (burn > beast::zero)
|
||||
{
|
||||
JLOG(ctx_.journal.warn()) << "update - credit burn";
|
||||
STAmount startBal = sle->getFieldAmount(sfBalance);
|
||||
STAmount finalBal = startBal + burn;
|
||||
if (finalBal > startBal)
|
||||
@@ -1388,6 +1410,7 @@ Import::doApply()
|
||||
if (!sleVL)
|
||||
{
|
||||
// create VL import seq counter
|
||||
JLOG(ctx_.journal.warn()) << "create vl - insert import sequence + public key";
|
||||
sleVL = std::make_shared<SLE>(keyletVL);
|
||||
sleVL->setFieldU32(sfImportSequence, infoVL->first);
|
||||
sleVL->setFieldVL(sfPublicKey, infoVL->second.slice());
|
||||
@@ -1395,6 +1418,7 @@ Import::doApply()
|
||||
}
|
||||
else
|
||||
{
|
||||
JLOG(ctx_.journal.warn()) << "update vl - insert import sequence";
|
||||
uint32_t current = sleVL->getFieldU32(sfImportSequence);
|
||||
|
||||
if (current > infoVL->first)
|
||||
|
||||
438
src/ripple/protocol/Import.h
Normal file
438
src/ripple/protocol/Import.h
Normal file
@@ -0,0 +1,438 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_PROTOCOL_IMPORT_H_INCLUDED
|
||||
#define RIPPLE_PROTOCOL_IMPORT_H_INCLUDED
|
||||
|
||||
// #include <ripple/basics/Log.h>
|
||||
#include <charconv>
|
||||
#include <ripple/app/misc/Manifest.h>
|
||||
#include <ripple/basics/StringUtilities.h>
|
||||
#include <ripple/basics/base64.h>
|
||||
#include <ripple/json/json_reader.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
inline bool
|
||||
isHex(std::string const& str)
|
||||
{
|
||||
return str.find_first_not_of("0123456789abcdefABCDEF") == std::string::npos;
|
||||
}
|
||||
|
||||
inline bool
|
||||
isBase58(std::string const& str)
|
||||
{
|
||||
return str.find_first_not_of(
|
||||
"rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz") ==
|
||||
std::string::npos;
|
||||
}
|
||||
|
||||
inline bool
|
||||
isBase64(std::string const& str)
|
||||
{
|
||||
return str.find_first_not_of(
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+"
|
||||
"/=") == std::string::npos;
|
||||
}
|
||||
|
||||
inline std::optional<uint64_t>
|
||||
parse_uint64(std::string const& str)
|
||||
{
|
||||
uint64_t result;
|
||||
auto [ptr, ec] =
|
||||
std::from_chars(str.data(), str.data() + str.size(), result);
|
||||
|
||||
if (ec == std::errc())
|
||||
return result;
|
||||
return {};
|
||||
}
|
||||
|
||||
inline bool
|
||||
syntaxCheckProof(Json::Value const& proof, beast::Journal const& j, int depth = 0)
|
||||
{
|
||||
if (depth > 64) {
|
||||
JLOG(j.warn()) << "XPOP.transaction.proof list should be less than 64 entries";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (proof.isArray())
|
||||
{
|
||||
// List form
|
||||
if (proof.size() != 16)
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.transaction.proof list should be exactly 16 entries";
|
||||
return false;
|
||||
}
|
||||
for (const auto& entry : proof)
|
||||
{
|
||||
if (entry.isString())
|
||||
{
|
||||
if (!isHex(entry.asString()) || entry.asString().size() != 64)
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.transaction.proof list entry missing "
|
||||
"or wrong format "
|
||||
<< "(should be hex string with 64 characters)";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (entry.isArray())
|
||||
{
|
||||
if (!syntaxCheckProof(entry, j, depth + 1))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
JLOG(j.warn())
|
||||
<< "XPOP.transaction.proof list entry has wrong format";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (proof.isObject())
|
||||
{
|
||||
// Tree form
|
||||
if (depth == 0) // root is special case
|
||||
{
|
||||
if (!proof["hash"].isString() ||
|
||||
proof["hash"].asString().size() != 64 ||
|
||||
!proof["key"].isString() ||
|
||||
proof["key"].asString().size() != 64 ||
|
||||
!proof["children"].isObject())
|
||||
{
|
||||
JLOG(j.warn())
|
||||
<< "XPOP.transaction.proof tree node has wrong format (root)";
|
||||
return false;
|
||||
}
|
||||
|
||||
return syntaxCheckProof(proof["children"], j, depth + 1);
|
||||
}
|
||||
|
||||
for (const auto& branch : proof.getMemberNames())
|
||||
{
|
||||
if (branch.size() != 1 || !isHex(branch))
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.transaction.proof child node was not 0-F "
|
||||
"hex nibble";
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& node = proof[branch];
|
||||
if (!node.isObject() || !node["hash"].isString() ||
|
||||
node["hash"].asString().size() != 64 ||
|
||||
!node["key"].isString() ||
|
||||
node["key"].asString().size() != 64 ||
|
||||
!node["children"].isObject())
|
||||
{
|
||||
JLOG(j.warn())
|
||||
<< "XPOP.transaction.proof tree node has wrong format";
|
||||
return false;
|
||||
}
|
||||
if (!syntaxCheckProof(node["children"], j, depth + 1)) {
|
||||
JLOG(j.warn())
|
||||
<< "XPOP.transaction.proof bad children format";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.transaction.proof has wrong format (should be "
|
||||
"array or object)";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// does not check signature etc
|
||||
inline
|
||||
std::optional<Json::Value>
|
||||
syntaxCheckXPOP(Blob const& blob, beast::Journal const& j)
|
||||
{
|
||||
if (blob.empty())
|
||||
return {};
|
||||
|
||||
std::string strJson(blob.begin(), blob.end());
|
||||
if (strJson.empty())
|
||||
return {};
|
||||
|
||||
try
|
||||
{
|
||||
Json::Value xpop;
|
||||
Json::Reader reader;
|
||||
|
||||
if (!reader.parse(strJson, xpop))
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP failed to parse string json";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!xpop.isObject())
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP is not a JSON object";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!xpop["ledger"].isObject())
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.ledger is not a JSON object";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!xpop["transaction"].isObject())
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.transaction is not a JSON object";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!xpop["validation"].isObject())
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.validation is not a JSON object";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!xpop["ledger"]["acroot"].isString() ||
|
||||
xpop["ledger"]["acroot"].asString().size() != 64 ||
|
||||
!isHex(xpop["ledger"]["acroot"].asString()))
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.ledger.acroot missing or wrong format (should "
|
||||
"be hex string)";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!xpop["ledger"]["txroot"].isString() ||
|
||||
xpop["ledger"]["txroot"].asString().size() != 64 ||
|
||||
!isHex(xpop["ledger"]["txroot"].asString()))
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.ledger.txroot missing or wrong format "
|
||||
"(should be hex string)";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!xpop["ledger"]["phash"].isString() ||
|
||||
xpop["ledger"]["phash"].asString().size() != 64 ||
|
||||
!isHex(xpop["ledger"]["phash"].asString()))
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.ledger.phash missing or wrong format "
|
||||
"(should be hex string)";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!xpop["ledger"]["close"].isInt())
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.ledger.close missing or wrong format "
|
||||
"(should be int)";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (xpop["ledger"]["coins"].isInt())
|
||||
{
|
||||
// pass
|
||||
}
|
||||
else if (xpop["ledger"]["coins"].isString())
|
||||
{
|
||||
if (!parse_uint64(xpop["ledger"]["coins"].asString()))
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.ledger.coins missing or wrong format "
|
||||
"(should be int or string)";
|
||||
return {};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.ledger.coins missing or wrong format "
|
||||
"(should be int or string)";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!xpop["ledger"]["cres"].isInt())
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.ledger.cres missing or wrong format "
|
||||
"(should be int)";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!xpop["ledger"]["flags"].isInt())
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.ledger.flags missing or wrong format "
|
||||
"(should be int)";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!xpop["ledger"]["pclose"].isInt())
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.ledger.pclose missing or wrong format "
|
||||
"(should be int)";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!xpop["transaction"]["blob"].isString() ||
|
||||
!isHex(xpop["transaction"]["blob"].asString()))
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.transaction.blob missing or wrong format "
|
||||
"(should be hex string)";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!xpop["transaction"]["meta"].isString() ||
|
||||
!isHex(xpop["transaction"]["meta"].asString()))
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.transaction.meta missing or wrong format "
|
||||
"(should be hex string)";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!syntaxCheckProof(xpop["transaction"]["proof"], j))
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.transaction.proof failed syntax check "
|
||||
"(tree/list form)";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!xpop["validation"]["data"].isObject())
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.validation.data missing or wrong format "
|
||||
"(should be JSON object)";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!xpop["validation"]["unl"].isObject())
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.validation.unl missing or wrong format "
|
||||
"(should be JSON object)";
|
||||
return {};
|
||||
}
|
||||
|
||||
for (const auto& key : xpop["validation"]["data"].getMemberNames())
|
||||
{
|
||||
const auto& value = xpop["validation"]["data"][key];
|
||||
if (!isBase58(key) || !value.isString() || !isHex(value.asString()))
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.validation.data entry has wrong format "
|
||||
<< "(key should be base58 string and value "
|
||||
"should be hex string)";
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& key : xpop["validation"]["unl"].getMemberNames())
|
||||
{
|
||||
const auto& value = xpop["validation"]["unl"][key];
|
||||
if (key == "public_key")
|
||||
{
|
||||
if (!value.isString() || !isHex(value.asString()))
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.validation.unl.public_key missing or "
|
||||
"wrong format (should be hex string)";
|
||||
return {};
|
||||
}
|
||||
|
||||
auto pk = strUnHex(value.asString());
|
||||
|
||||
if (!publicKeyType(makeSlice(*pk)))
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.validation.unl.public_key invalid key type.";
|
||||
return {};
|
||||
}
|
||||
}
|
||||
else if (key == "manifest")
|
||||
{
|
||||
if (!value.isString())
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.validation.unl.manifest missing or "
|
||||
"wrong format (should be string)";
|
||||
return {};
|
||||
}
|
||||
}
|
||||
else if (key == "blob")
|
||||
{
|
||||
if (!value.isString() || !isBase64(value.asString()))
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.validation.unl.blob missing or wrong "
|
||||
"format (should be base64 string)";
|
||||
return {};
|
||||
}
|
||||
}
|
||||
else if (key == "signature")
|
||||
{
|
||||
if (!value.isString() || !isHex(value.asString()))
|
||||
{
|
||||
JLOG(j.warn())
|
||||
<< "XPOP.validation.unl.signature missing or wrong "
|
||||
"format (should be hex string)";
|
||||
return {};
|
||||
}
|
||||
}
|
||||
else if (key == "version")
|
||||
{
|
||||
if (!value.isInt())
|
||||
{
|
||||
JLOG(j.warn()) << "XPOP.validation.unl.version missing or "
|
||||
"wrong format (should be int)";
|
||||
return {};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!value.isObject() && !value.isString())
|
||||
{
|
||||
JLOG(j.warn())
|
||||
<< "XPOP.validation.unl entry has wrong format";
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
return xpop;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
JLOG(j.warn()) << "An exception occurred during XPOP validation";
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// <sequence, master key>
|
||||
inline
|
||||
std::optional<std::pair< uint32_t, PublicKey>>
|
||||
getVLInfo(Json::Value const& xpop, beast::Journal const& j)
|
||||
{
|
||||
auto const data = base64_decode(xpop[jss::validation][jss::unl][jss::blob].asString());
|
||||
Json::Reader r;
|
||||
Json::Value list;
|
||||
if (!r.parse(data, list))
|
||||
{
|
||||
JLOG(j.warn()) << "Import: unl blob was not valid json (after base64 decoding)";
|
||||
std::cout << "Import: unl blob was not valid json (after base64 decoding)" << "\n";
|
||||
return {};
|
||||
}
|
||||
auto const sequence = list[jss::sequence].asUInt();
|
||||
auto const m = deserializeManifest(base64_decode(xpop[jss::validation][jss::unl][jss::manifest].asString()));
|
||||
if (!m)
|
||||
{
|
||||
JLOG(j.warn()) << "Import: failed to deserialize manifest";
|
||||
std::cout << "Import: failed to deserialize manifest" << "\n";
|
||||
return {};
|
||||
}
|
||||
return { {sequence, m->masterKey} };
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
@@ -131,6 +131,7 @@ transResults()
|
||||
MAKE_ERROR(telREQUIRES_NETWORK_ID, "Transactions submitted to this node/network must include a correct NetworkID field."),
|
||||
MAKE_ERROR(telNETWORK_ID_MAKES_TX_NON_CANONICAL, "Transactions submitted to this node/network must NOT include a NetworkID field."),
|
||||
MAKE_ERROR(telNON_LOCAL_EMITTED_TXN, "Emitted transaction cannot be applied because it was not generated locally."),
|
||||
MAKE_ERROR(telIMPORT_VL_KEY_NOT_RECOGNISED, "Import vl key was not recognized."),
|
||||
MAKE_ERROR(telCAN_NOT_QUEUE_IMPORT, "Import transaction was not able to be directly applied and cannot be queued."),
|
||||
|
||||
MAKE_ERROR(temMALFORMED, "Malformed transaction."),
|
||||
|
||||
2366
src/test/app/Import_test.cpp
Normal file
2366
src/test/app/Import_test.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user