Compare commits

...

9 Commits

Author SHA1 Message Date
Richard Holland
45411750cf cadastre preflight 2023-12-18 14:15:45 +00:00
Richard Holland
b42be37d78 move utf8 checking to header file 2023-12-18 13:57:06 +00:00
Richard Holland
9215b87511 . 2023-12-18 13:57:02 +00:00
Richard Holland
2817f848e8 . 2023-12-09 13:10:08 +00:00
Richard Holland
557ad3d18e cadastre txn types 2023-12-09 13:08:28 +00:00
Richard Holland
e05d7e783c initial cadastre fields 2023-12-07 15:01:18 +00:00
Richard Holland
49798b1792 make server_definitions caching thread_local 2023-12-05 13:47:54 +00:00
Denis Angell
27f43ba9ee TSH Tests (#222) 2023-12-03 10:13:05 +01:00
Wietse Wind
7881b7f69f Build on most cores (nproc / 3 » nproc / 1.337) (#226)
Use those resources! 🎉🚀
2023-12-01 12:47:50 +01:00
27 changed files with 5597 additions and 461 deletions

View File

@@ -461,6 +461,7 @@ target_sources (rippled PRIVATE
src/ripple/app/tx/impl/Taker.cpp
src/ripple/app/tx/impl/Transactor.cpp
src/ripple/app/tx/impl/URIToken.cpp
src/ripple/app/tx/impl/Cadastre.cpp
src/ripple/app/tx/impl/apply.cpp
src/ripple/app/tx/impl/applySteps.cpp
src/ripple/app/hook/impl/applyHook.cpp
@@ -755,6 +756,7 @@ if (tests)
src/test/app/ValidatorList_test.cpp
src/test/app/ValidatorSite_test.cpp
src/test/app/SetHook_test.cpp
src/test/app/SetHookTSH_test.cpp
src/test/app/Wildcard_test.cpp
src/test/app/XahauGenesis_test.cpp
src/test/app/tx/apply_test.cpp
@@ -896,6 +898,7 @@ if (tests)
src/test/jtx/impl/token.cpp
src/test/jtx/impl/trust.cpp
src/test/jtx/impl/txflags.cpp
src/test/jtx/impl/unl.cpp
src/test/jtx/impl/uritoken.cpp
src/test/jtx/impl/utility.cpp

View File

@@ -5,7 +5,7 @@ echo "START BUILDING (HOST)"
echo "Cleaning previously built binary"
rm -f release-build/xahaud
BUILD_CORES=$(echo "scale=0 ; `nproc` / 3" | bc)
BUILD_CORES=$(echo "scale=0 ; `nproc` / 1.337" | bc)
if [[ "$GITHUB_REPOSITORY" == "" ]]; then
#Default

View File

@@ -891,13 +891,19 @@ hook::removeHookNamespaceEntry(ripple::SLE& sleAccount, ripple::uint256 ns)
bool
hook::canHook(ripple::TxType txType, ripple::uint256 hookOn)
{
uint16_t tt = safe_cast<uint16_t>(txType);
// only the low order byte is used to determine HookOn
tt &= 0xFFU;
// invert ttHOOK_SET bit
hookOn ^= UINT256_BIT[ttHOOK_SET];
// invert entire field
hookOn = ~hookOn;
return (hookOn & UINT256_BIT[txType]) != beast::zero;
return (hookOn & UINT256_BIT[tt]) != beast::zero;
}
// Update HookState ledger objects for the hook... only called after accept()

View File

@@ -0,0 +1,207 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#include <ripple/app/tx/impl/Cadastre.h>
#include <ripple/basics/Log.h>
#include <ripple/ledger/View.h>
#include <ripple/protocol/Feature.h>
#include <ripple/protocol/Indexes.h>
#include <ripple/app/tx/impl/URIToken.h>
namespace ripple {
TxConsequences
Cadastre::makeTxConsequences(PreflightContext const& ctx)
{
return TxConsequences{ctx.tx, TxConsequences::normal};
}
/*
add(jss::Cadastre,
ltCADASTRE,
{
{sfOwner, soeREQUIRED},
{sfOwnerNode, soeREQUIRED},
{sfAssociation, soeOPTIONAL},
{sfAssociationNode, soeOPTIONAL},
{sfLocationX, soeREQUIRED},
{sfLocationY, soeREQUIRED},
{sfUniverse, soeREQUIRED},
{sfDisplayURI, soeOPTIONAL},
{sfBroadcastURI, soeOPTIONAL},
{sfCadastreCount, soeOPTIONAL}, // for 0x8000,0x8000 tile only
},
commonFields);
ttCADASTRE_MINT = 0x005D, // HookOn = 93
ttCADASTRE_BURN = 0x015D,
ttCADASTRE_CREATE_SELL_OFFER = 0x025D,
ttCADASTRE_CANCEL_SELL_OFFER = 0x035D,
ttCADASTRE_BUY = 0x045D,
ttCADASTRE_SET = 0x055D,
*/
NotTEC
Cadastre::preflight(PreflightContext const& ctx)
{
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;
auto& tx = ctx.tx;
// the validation for amount is the same regardless of which txn is appears
// on
if (ctx.tx.isFieldPresent(sfAmount))
{
auto amt = ctx.tx.getFieldAmount(sfAmount);
if (!isLegalNet(amt) || amt.signum() < 0)
{
JLOG(ctx.j.warn()) << "Malformed transaction. Negative or "
"invalid amount/currency specified.";
return temBAD_AMOUNT;
}
if (isBadCurrency(amt.getCurrency()))
{
JLOG(ctx.j.warn()) << "Malformed transaction. Bad currency.";
return temBAD_CURRENCY;
}
if (amt == beast::zero && !ctx.tx.isFieldPresent(sfDestination))
{
if (tt == ttCADASTRE_BUY)
{
// buy operation does not specify a destination, and can have a
// zero amount pass
}
else
{
JLOG(ctx.j.warn()) << "Malformed transaction. "
<< "If no sell-to destination is specified "
"then a non-zero price must be set.";
return temMALFORMED;
}
}
}
if (ctx.tx.isFieldPresent(sfDestination) &&
!ctx.tx.isFieldPresent(sfAmount))
return temMALFORMED;
auto checkURI = [&ctx](SField const& f) -> TER
{
if (ctx.tx.isFieldPresent(f))
{
auto const& vl = ctx.tx.getFieldVL(f);
if (vl.size() < 1 || vl.size() > 256)
{
JLOG(ctx.j.warn())
<< "Cadastre: Malformed transaction, "
<< f.getName()
<< " was invalid size (too big/small)";
return temMALFORMED;
}
if (!URIToken::validateUTF8(ctx.tx.getFieldVL(sfDisplayURI)))
{
JLOG(ctx.j.warn())
<< "Cadastre: Malformed transaction, "
<< f.getName()
<< " was not valid utf-8";
return temMALFORMED;
}
}
return tesSUCCESS;
};
checkURI(sfDisplayURI);
checkURI(sfBroadcastURI);
return preflight2(ctx);
}
TER
Cadastre::preclaim(PreclaimContext const& ctx)
{
if (!ctx.view.rules().enabled(featureHooks))
return temDISABLED;
auto const id = ctx.tx[sfAccount];
auto const sle = ctx.view.read(keylet::account(id));
if (!sle)
return terNO_ACCOUNT;
if (ctx.tx.isFieldPresent(sfDestination))
{
if (!ctx.view.exists(keylet::account(ctx.tx[sfDestination])))
return tecNO_TARGET;
}
auto const tt = tx.getTxnType();
switch(tt)
{
case ttCADASTRE_MINT:
case ttCADASTRE_SET:
{
break;
}
case ttCADASTRE_BURN:
{
break;
}
case ttCADASTRE_CREATE_SELL_OFFER:
{
break;
}
case ttCADASTRE_CANCEL_SELL_OFFER:
{
break;
}
case ttCADASTRE_BUY:
{
break;
}
}
return tesSUCCESS;
}
TER
Cadastre::doApply()
{
// everything happens in the hooks!
return tesSUCCESS;
}
XRPAmount
Cadastre::calculateBaseFee(ReadView const& view, STTx const& tx)
{
XRPAmount extraFee{0};
return Transactor::calculateBaseFee(view, tx) + extraFee;
}
} // namespace ripple

View File

@@ -0,0 +1,57 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2014 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_TX_CADASTRE_H_INCLUDED
#define RIPPLE_TX_CADASTRE_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/tx/impl/Transactor.h>
#include <ripple/basics/Log.h>
#include <ripple/protocol/Indexes.h>
namespace ripple {
class Cadastre : public Transactor
{
public:
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
explicit Cadastre(ApplyContext& ctx) : Transactor(ctx)
{
}
static XRPAmount
calculateBaseFee(ReadView const& view, STTx const& tx);
static TxConsequences
makeTxConsequences(PreflightContext const& ctx);
static NotTEC
preflight(PreflightContext const& ctx);
static TER
preclaim(PreclaimContext const& ctx);
TER
doApply() override;
};
} // namespace ripple
#endif

View File

@@ -492,6 +492,7 @@ LedgerEntryTypesMatch::visitEntry(
case ltURI_TOKEN:
case ltIMPORT_VLSEQ:
case ltUNL_REPORT:
case ltCADASTRE:
break;
default:
invalidTypeAdded_ = true;

View File

@@ -103,57 +103,7 @@ URIToken::preflight(PreflightContext const& ctx)
return temMALFORMED;
}
if (!([](std::vector<uint8_t> const& u) -> bool {
// this code is from
// https://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c
uint8_t const* s = (uint8_t const*)u.data();
uint8_t const* end = s + u.size();
while (s < end)
{
if (*s < 0x80)
/* 0xxxxxxx */
s++;
else if ((s[0] & 0xe0) == 0xc0)
{
/* 110XXXXx 10xxxxxx */
if ((s[1] & 0xc0) != 0x80 ||
(s[0] & 0xfe) == 0xc0) /* overlong? */
return false;
else
s += 2;
}
else if ((s[0] & 0xf0) == 0xe0)
{
/* 1110XXXX 10Xxxxxx 10xxxxxx */
if ((s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80 ||
(s[0] == 0xe0 &&
(s[1] & 0xe0) == 0x80) || /* overlong? */
(s[0] == 0xed &&
(s[1] & 0xe0) == 0xa0) || /* surrogate? */
(s[0] == 0xef && s[1] == 0xbf &&
(s[2] & 0xfe) == 0xbe)) /* U+FFFE or U+FFFF? */
return false;
else
s += 3;
}
else if ((s[0] & 0xf8) == 0xf0)
{
/* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */
if ((s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80 ||
(s[3] & 0xc0) != 0x80 ||
(s[0] == 0xf0 &&
(s[1] & 0xf0) == 0x80) || /* overlong? */
(s[0] == 0xf4 && s[1] > 0x8f) ||
s[0] > 0xf4) /* > U+10FFFF? */
return false;
else
s += 4;
}
else
return false;
}
return true;
})(uri))
if (!validateUTF8(uri))
{
JLOG(ctx.j.warn()) << "Malformed transaction. URI must be a "
"valid utf-8 string.";

View File

@@ -30,6 +30,56 @@ namespace ripple {
class URIToken : public Transactor
{
public:
bool inline static validateUTF8(std::vector<uint8_t> const& u)
{
// this code is from
// https://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c
uint8_t const* s = (uint8_t const*)u.data();
uint8_t const* end = s + u.size();
while (s < end)
{
if (*s < 0x80)
/* 0xxxxxxx */
s++;
else if ((s[0] & 0xe0) == 0xc0)
{
/* 110XXXXx 10xxxxxx */
if ((s[1] & 0xc0) != 0x80 ||
(s[0] & 0xfe) == 0xc0) /* overlong? */
return false;
else
s += 2;
}
else if ((s[0] & 0xf0) == 0xe0)
{
/* 1110XXXX 10Xxxxxx 10xxxxxx */
if ((s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80 ||
(s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) || /* overlong? */
(s[0] == 0xed && (s[1] & 0xe0) == 0xa0) || /* surrogate? */
(s[0] == 0xef && s[1] == 0xbf &&
(s[2] & 0xfe) == 0xbe)) /* U+FFFE or U+FFFF? */
return false;
else
s += 3;
}
else if ((s[0] & 0xf8) == 0xf0)
{
/* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */
if ((s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80 ||
(s[3] & 0xc0) != 0x80 ||
(s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) || /* overlong? */
(s[0] == 0xf4 && s[1] > 0x8f) ||
s[0] > 0xf4) /* > U+10FFFF? */
return false;
else
s += 4;
}
else
return false;
}
return true;
}
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
explicit URIToken(ApplyContext& ctx) : Transactor(ctx)

View File

@@ -45,6 +45,7 @@
#include <ripple/app/tx/impl/SetSignerList.h>
#include <ripple/app/tx/impl/SetTrust.h>
#include <ripple/app/tx/impl/URIToken.h>
#include <ripple/app/tx/impl/Cadastre.h>
namespace ripple {
@@ -170,6 +171,13 @@ invoke_preflight(PreflightContext const& ctx)
case ttURITOKEN_CREATE_SELL_OFFER:
case ttURITOKEN_CANCEL_SELL_OFFER:
return invoke_preflight_helper<URIToken>(ctx);
case ttCADASTRE_MINT:
case ttCADASTRE_BURN:
case ttCADASTRE_CREATE_SELL_OFFER:
case ttCADASTRE_CANCEL_SELL_OFFER:
case ttCADASTRE_BUY:
case ttCADASTRE_SET:
return invoke_preflight_helper<Cadastre>(ctx);
default:
assert(false);
return {temUNKNOWN, TxConsequences{temUNKNOWN}};
@@ -289,6 +297,13 @@ invoke_preclaim(PreclaimContext const& ctx)
case ttURITOKEN_CREATE_SELL_OFFER:
case ttURITOKEN_CANCEL_SELL_OFFER:
return invoke_preclaim<URIToken>(ctx);
case ttCADASTRE_MINT:
case ttCADASTRE_BURN:
case ttCADASTRE_CREATE_SELL_OFFER:
case ttCADASTRE_CANCEL_SELL_OFFER:
case ttCADASTRE_BUY:
case ttCADASTRE_SET:
return invoke_preclaim<Cadastre>(ctx);
default:
assert(false);
return temUNKNOWN;
@@ -370,6 +385,13 @@ invoke_calculateBaseFee(ReadView const& view, STTx const& tx)
case ttURITOKEN_CREATE_SELL_OFFER:
case ttURITOKEN_CANCEL_SELL_OFFER:
return URIToken::calculateBaseFee(view, tx);
case ttCADASTRE_MINT:
case ttCADASTRE_BURN:
case ttCADASTRE_CREATE_SELL_OFFER:
case ttCADASTRE_CANCEL_SELL_OFFER:
case ttCADASTRE_BUY:
case ttCADASTRE_SET:
return Cadastre::calculateBaseFee(view, tx);
default:
assert(false);
return XRPAmount{0};
@@ -552,6 +574,15 @@ invoke_apply(ApplyContext& ctx)
URIToken p(ctx);
return p();
}
case ttCADASTRE_MINT:
case ttCADASTRE_BURN:
case ttCADASTRE_CREATE_SELL_OFFER:
case ttCADASTRE_CANCEL_SELL_OFFER:
case ttCADASTRE_BUY:
case ttCADASTRE_SET: {
Cadastre p(ctx);
return p();
}
default:
assert(false);
return {temUNKNOWN, false};

View File

@@ -297,6 +297,10 @@ import_vlseq(PublicKey const& key) noexcept;
Keylet
uritoken(AccountID const& issuer, Blob const& uri);
Keylet
cadastre(uint256 const& universe, uint16_t locx, uint16_t locy);
} // namespace keylet
// Everything below is deprecated and should be removed in favor of keylets:

View File

@@ -179,6 +179,15 @@ enum LedgerEntryType : std::uint16_t
*/
ltUNL_REPORT = 0x0052,
/** A ledger object that contains cadastral information about a unit of virtual land
* in a given universe. The block at 0x8000, 0x8000 is the center of the universe
* and has special rights and privileges, namely it is the god block whose hooks are
* strongly executed whenever dealings with land in that universe occur.
*
* \sa keylet::cadastre
*/
ltCADASTRE = 0x004B,
//---------------------------------------------------------------------------
/** A special type, matching any ledger entry type.

View File

@@ -354,6 +354,8 @@ extern SF_UINT16 const sfHookStateChangeCount;
extern SF_UINT16 const sfHookEmitCount;
extern SF_UINT16 const sfHookExecutionIndex;
extern SF_UINT16 const sfHookApiVersion;
extern SF_UINT16 const sfLocationX;
extern SF_UINT16 const sfLocationY;
// 32-bit integers (common)
extern SF_UINT32 const sfNetworkID;
@@ -433,6 +435,8 @@ extern SF_UINT64 const sfReferenceCount;
extern SF_UINT64 const sfRewardAccumulator;
extern SF_UINT64 const sfAccountCount;
extern SF_UINT64 const sfAccountIndex;
extern SF_UINT64 const sfAssociationNode;
extern SF_UINT64 const sfCadastreCount;
// 128-bit
extern SF_UINT128 const sfEmailHash;
@@ -483,6 +487,7 @@ extern SF_UINT256 const sfURITokenID;
extern SF_UINT256 const sfGovernanceFlags;
extern SF_UINT256 const sfGovernanceMarks;
extern SF_UINT256 const sfEmittedTxnID;
extern SF_UINT256 const sfUniverse;
// currency amount (common)
extern SF_AMOUNT const sfAmount;
@@ -537,6 +542,8 @@ extern SF_VL const sfHookReturnString;
extern SF_VL const sfHookParameterName;
extern SF_VL const sfHookParameterValue;
extern SF_VL const sfBlob;
extern SF_VL const sfBroadcastURI;
extern SF_VL const sfDisplayURI;
// account
extern SF_ACCOUNT const sfAccount;
@@ -552,6 +559,7 @@ extern SF_ACCOUNT const sfEmitCallback;
// account (uncommon)
extern SF_ACCOUNT const sfHookAccount;
extern SF_ACCOUNT const sfNFTokenMinter;
extern SF_ACCOUNT const sfAssociation;
// path set
extern SField const sfPaths;

View File

@@ -146,6 +146,15 @@ enum TxType : std::uint16_t
ttURITOKEN_CREATE_SELL_OFFER = 48,
ttURITOKEN_CANCEL_SELL_OFFER = 49,
/* This transaction mints, burns or updates cadastral tiles. */
ttCADASTRE_MINT = 0x005D, // HookOn = 93
ttCADASTRE_BURN = 0x015D,
ttCADASTRE_CREATE_SELL_OFFER = 0x025D,
ttCADASTRE_CANCEL_SELL_OFFER = 0x035D,
ttCADASTRE_BUY = 0x045D,
ttCADASTRE_SET = 0x055D,
/** This transaction can only be used by the genesis account, which is controlled exclusively by
* rewards/governance hooks, to print new XRP to be delivered directly to an array of destinations,
* according to reward schedule */

View File

@@ -72,6 +72,7 @@ enum class LedgerNameSpace : std::uint16_t {
URI_TOKEN = 'U',
IMPORT_VLSEQ = 'I',
UNL_REPORT = 'R',
CADASTRE = 'K',
// No longer used or supported. Left here to reserve the space
// to avoid accidental reuse.
@@ -443,6 +444,15 @@ uritoken(AccountID const& issuer, Blob const& uri)
LedgerNameSpace::URI_TOKEN, issuer, Slice{uri.data(), uri.size()})};
}
Keylet
cadastre(uint256 const& universe, uint16_t locx, uint16_t locy)
{
return {
ltCADASTRE,
indexHash(
LedgerNameSpace::CADASTRE, universe, locx, locy)};
}
} // namespace keylet
} // namespace ripple

View File

@@ -363,6 +363,22 @@ LedgerFormats::LedgerFormats()
},
commonFields);
add(jss::Cadastre,
ltCADASTRE,
{
{sfOwner, soeREQUIRED},
{sfOwnerNode, soeREQUIRED},
{sfAssociation, soeOPTIONAL},
{sfAssociationNode, soeOPTIONAL},
{sfLocationX, soeREQUIRED},
{sfLocationY, soeREQUIRED},
{sfUniverse, soeREQUIRED},
{sfDisplayURI, soeOPTIONAL},
{sfBroadcastURI, soeOPTIONAL},
{sfCadastreCount, soeOPTIONAL}, // for 0x8000,0x8000 tile only
},
commonFields);
// clang-format on
}

View File

@@ -102,6 +102,8 @@ CONSTRUCT_TYPED_SFIELD(sfHookStateChangeCount, "HookStateChangeCount", UINT16,
CONSTRUCT_TYPED_SFIELD(sfHookEmitCount, "HookEmitCount", UINT16, 18);
CONSTRUCT_TYPED_SFIELD(sfHookExecutionIndex, "HookExecutionIndex", UINT16, 19);
CONSTRUCT_TYPED_SFIELD(sfHookApiVersion, "HookApiVersion", UINT16, 20);
CONSTRUCT_TYPED_SFIELD(sfLocationX, "LocationX", UINT16, 99);
CONSTRUCT_TYPED_SFIELD(sfLocationY, "LocationY", UINT16, 98);
// 32-bit integers (common)
CONSTRUCT_TYPED_SFIELD(sfNetworkID, "NetworkID", UINT32, 1);
@@ -183,6 +185,8 @@ CONSTRUCT_TYPED_SFIELD(sfEmitBurden, "EmitBurden", UINT64,
CONSTRUCT_TYPED_SFIELD(sfHookInstructionCount, "HookInstructionCount", UINT64, 17);
CONSTRUCT_TYPED_SFIELD(sfHookReturnCode, "HookReturnCode", UINT64, 18);
CONSTRUCT_TYPED_SFIELD(sfReferenceCount, "ReferenceCount", UINT64, 19);
CONSTRUCT_TYPED_SFIELD(sfCadastreCount, "CadastreCount", UINT64, 96);
CONSTRUCT_TYPED_SFIELD(sfAssociationNode, "AssociationNode", UINT64, 97);
CONSTRUCT_TYPED_SFIELD(sfAccountIndex, "AccountIndex", UINT64, 98);
CONSTRUCT_TYPED_SFIELD(sfAccountCount, "AccountCount", UINT64, 99);
CONSTRUCT_TYPED_SFIELD(sfRewardAccumulator, "RewardAccumulator", UINT64, 100);
@@ -236,6 +240,7 @@ CONSTRUCT_TYPED_SFIELD(sfURITokenID, "URITokenID", UINT256,
CONSTRUCT_TYPED_SFIELD(sfGovernanceFlags, "GovernanceFlags", UINT256, 99);
CONSTRUCT_TYPED_SFIELD(sfGovernanceMarks, "GovernanceMarks", UINT256, 98);
CONSTRUCT_TYPED_SFIELD(sfEmittedTxnID, "EmittedTxnID", UINT256, 97);
CONSTRUCT_TYPED_SFIELD(sfUniverse, "Universe", UINT256, 96);
// currency amount (common)
CONSTRUCT_TYPED_SFIELD(sfAmount, "Amount", AMOUNT, 1);
@@ -290,6 +295,8 @@ CONSTRUCT_TYPED_SFIELD(sfHookReturnString, "HookReturnString", VL,
CONSTRUCT_TYPED_SFIELD(sfHookParameterName, "HookParameterName", VL, 24);
CONSTRUCT_TYPED_SFIELD(sfHookParameterValue, "HookParameterValue", VL, 25);
CONSTRUCT_TYPED_SFIELD(sfBlob, "Blob", VL, 26);
CONSTRUCT_TYPED_SFIELD(sfBroadcastURI, "BroadcastURI", VL, 99);
CONSTRUCT_TYPED_SFIELD(sfDisplayURI, "DisplayURI", VL, 98);
// account
CONSTRUCT_TYPED_SFIELD(sfAccount, "Account", ACCOUNT, 1);
@@ -305,6 +312,7 @@ CONSTRUCT_TYPED_SFIELD(sfEmitCallback, "EmitCallback", ACCOUNT,
// account (uncommon)
CONSTRUCT_TYPED_SFIELD(sfHookAccount, "HookAccount", ACCOUNT, 16);
CONSTRUCT_TYPED_SFIELD(sfAssociation, "Association", ACCOUNT, 99);
// vector of 256-bit
CONSTRUCT_TYPED_SFIELD(sfIndexes, "Indexes", VECTOR256, 1, SField::sMD_Never);

View File

@@ -441,6 +441,71 @@ TxFormats::TxFormats()
{sfTicketSequence, soeOPTIONAL},
},
commonFields);
add(jss::CadastreMint,
ttCADASTRE_MINT,
{
{sfDestination, soeOPTIONAL},
{sfAmount, soeOPTIONAL},
{sfAssociation, soeOPTIONAL},
{sfBroadcastURI, soeOPTIONAL},
{sfDisplayURI, soeOPTIONAL},
{sfLocationX, soeREQUIRED},
{sfLocationY, soeREQUIRED},
{sfUniverse, soeREQUIRED},
},
commonFields);
add(jss::CadastreBurn,
ttCADASTRE_BURN,
{
{sfLocationX, soeREQUIRED},
{sfLocationY, soeREQUIRED},
{sfUniverse, soeREQUIRED},
},
commonFields);
add(jss::CadastreCreateSellOffer,
ttCADASTRE_CREATE_SELL_OFFER,
{
{sfDestination, soeOPTIONAL},
{sfAmount, soeREQUIRED},
{sfLocationX, soeREQUIRED},
{sfLocationY, soeREQUIRED},
{sfUniverse, soeREQUIRED},
},
commonFields);
add(jss::CadastreCancelSellOffer,
ttCADASTRE_CANCEL_SELL_OFFER,
{
{sfLocationX, soeREQUIRED},
{sfLocationY, soeREQUIRED},
{sfUniverse, soeREQUIRED},
},
commonFields);
add(jss::CadastreBuy,
ttCADASTRE_BUY,
{
{sfAmount, soeREQUIRED},
{sfLocationX, soeREQUIRED},
{sfLocationY, soeREQUIRED},
{sfUniverse, soeREQUIRED},
},
commonFields);
add(jss::CadastreSet,
ttCADASTRE_SET,
{
{sfAssociation, soeOPTIONAL},
{sfBroadcastURI, soeOPTIONAL},
{sfDisplayURI, soeOPTIONAL},
{sfLocationX, soeREQUIRED},
{sfLocationY, soeREQUIRED},
{sfUniverse, soeREQUIRED},
},
commonFields);
}
TxFormats const&

View File

@@ -51,6 +51,13 @@ JSS(Amendments); // ledger type.
JSS(Amount); // in: TransactionSign; field.
JSS(Authorize); // field
JSS(Blob);
JSS(Cadastre); // ledger type
JSS(CadastreMint); // txn type
JSS(CadastreBurn); // txn type
JSS(CadastreCreateSellOffer); // txn type
JSS(CadastreCancelSellOffer); // txn type
JSS(CadastreBuy); // txn type
JSS(CadastreSet); // txn type
JSS(Check); // ledger type.
JSS(CheckCancel); // transaction type.
JSS(CheckCash); // transaction type.

View File

@@ -422,11 +422,11 @@ doServerDefinitions(RPC::JsonContext& context)
uint32_t curLgrSeq = context.ledgerMaster.getValidatedLedger()->info().seq;
// static values used for cache
static uint32_t lastGenerated = 0; // last ledger seq it was generated
static Json::Value lastFeatures{
Json::objectValue}; // the actual features JSON last generated
static uint256 lastFeatureHash; // the hash of the features JSON last time
// it was generated
static thread_local uint32_t lastGenerated = 0; // last ledger seq it was generated
static thread_local Json::Value lastFeatures{
Json::objectValue}; // the actual features JSON last generated
static thread_local uint256 lastFeatureHash; // the hash of the features JSON last time
// it was generated
// if a flag ledger has passed since it was last generated, regenerate it,
// update the cache above

View File

@@ -5549,73 +5549,6 @@ class Import_test : public beast::unit_test::suite
}
}
// std::unique_ptr<Config>
// network::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)
{

File diff suppressed because it is too large Load Diff

View File

@@ -42,35 +42,6 @@ namespace test {
* are put in their existing unit test files.
*/
/**
* Test the size of the negative UNL in a ledger,
* also test if the ledger has ToDisalbe and/or ToReEnable
*
* @param l the ledger
* @param size the expected negative UNL size
* @param hasToDisable if expect ToDisable in ledger
* @param hasToReEnable if expect ToDisable in ledger
* @return true if meet all three expectation
*/
bool
negUnlSizeTest(
std::shared_ptr<Ledger const> const& l,
size_t size,
bool hasToDisable,
bool hasToReEnable);
/**
* Try to apply a ttUNL_MODIFY Tx, and test the apply result
*
* @param env the test environment
* @param view the OpenView of the ledger
* @param tx the ttUNL_MODIFY Tx
* @param pass if the Tx should be applied successfully
* @return true if meet the expectation of apply result
*/
bool
applyAndTestResult(jtx::Env& env, OpenView& view, STTx const& tx, bool pass);
/**
* Verify the content of negative UNL entries (public key and ledger sequence)
* of a ledger
@@ -85,15 +56,6 @@ VerifyPubKeyAndSeq(
std::shared_ptr<Ledger const> const& l,
hash_map<PublicKey, std::uint32_t> nUnlLedgerSeq);
/**
* Count the number of Tx in a TxSet
*
* @param txSet the TxSet
* @return the number of Tx
*/
std::size_t
countTx(std::shared_ptr<SHAMap> const& txSet);
/**
* Create fake public keys
*
@@ -103,17 +65,6 @@ countTx(std::shared_ptr<SHAMap> const& txSet);
std::vector<PublicKey>
createPublicKeys(std::size_t n);
/**
* Create ttUNL_MODIFY Tx
*
* @param disabling disabling or re-enabling a validator
* @param seq current ledger seq
* @param txKey the public key of the validator
* @return the ttUNL_MODIFY Tx
*/
STTx
createTx(bool disabling, LedgerIndex seq, PublicKey const& txKey);
class NegativeUNL_test : public beast::unit_test::suite
{
/**
@@ -245,14 +196,16 @@ class NegativeUNL_test : public beast::unit_test::suite
l = std::make_shared<Ledger>(
*l, env.app().timeKeeper().closeTime());
auto txDisable_0 = createTx(true, l->seq(), publicKeys[0]);
auto txReEnable_1 = createTx(false, l->seq(), publicKeys[1]);
auto txDisable_0 = unl::createTx(true, l->seq(), publicKeys[0]);
auto txReEnable_1 = unl::createTx(false, l->seq(), publicKeys[1]);
OpenView accum(&*l);
BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_0, false));
BEAST_EXPECT(applyAndTestResult(env, accum, txReEnable_1, false));
BEAST_EXPECT(
unl::applyAndTestResult(env, accum, txDisable_0, false));
BEAST_EXPECT(
unl::applyAndTestResult(env, accum, txReEnable_1, false));
accum.apply(*l);
BEAST_EXPECT(negUnlSizeTest(l, 0, false, false));
BEAST_EXPECT(unl::negUnlSizeTest(l, 0, false, false));
}
{
@@ -266,18 +219,21 @@ class NegativeUNL_test : public beast::unit_test::suite
BEAST_EXPECT(l->isFlagLedger());
l->updateNegativeUNL();
auto txDisable_0 = createTx(true, l->seq(), publicKeys[0]);
auto txDisable_1 = createTx(true, l->seq(), publicKeys[1]);
auto txReEnable_2 = createTx(false, l->seq(), publicKeys[2]);
auto txDisable_0 = unl::createTx(true, l->seq(), publicKeys[0]);
auto txDisable_1 = unl::createTx(true, l->seq(), publicKeys[1]);
auto txReEnable_2 = unl::createTx(false, l->seq(), publicKeys[2]);
// can apply 1 and only 1 ToDisable Tx,
// cannot apply ToReEnable Tx, since negative UNL is empty
OpenView accum(&*l);
BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_0, true));
BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_1, false));
BEAST_EXPECT(applyAndTestResult(env, accum, txReEnable_2, false));
BEAST_EXPECT(
unl::applyAndTestResult(env, accum, txDisable_0, true));
BEAST_EXPECT(
unl::applyAndTestResult(env, accum, txDisable_1, false));
BEAST_EXPECT(
unl::applyAndTestResult(env, accum, txReEnable_2, false));
accum.apply(*l);
auto good_size = negUnlSizeTest(l, 0, true, false);
auto good_size = unl::negUnlSizeTest(l, 0, true, false);
BEAST_EXPECT(good_size);
if (good_size)
{
@@ -292,7 +248,7 @@ class NegativeUNL_test : public beast::unit_test::suite
//(3) ledgers before the next flag ledger
for (auto i = 0; i < 256; ++i)
{
auto good_size = negUnlSizeTest(l, 0, true, false);
auto good_size = unl::negUnlSizeTest(l, 0, true, false);
BEAST_EXPECT(good_size);
if (good_size)
BEAST_EXPECT(l->validatorToDisable() == publicKeys[0]);
@@ -304,7 +260,7 @@ class NegativeUNL_test : public beast::unit_test::suite
//(4) next flag ledger
// test if the ledger updated correctly
auto good_size = negUnlSizeTest(l, 1, false, false);
auto good_size = unl::negUnlSizeTest(l, 1, false, false);
BEAST_EXPECT(good_size);
if (good_size)
{
@@ -312,20 +268,25 @@ class NegativeUNL_test : public beast::unit_test::suite
nUnlLedgerSeq.emplace(publicKeys[0], l->seq());
}
auto txDisable_0 = createTx(true, l->seq(), publicKeys[0]);
auto txDisable_1 = createTx(true, l->seq(), publicKeys[1]);
auto txReEnable_0 = createTx(false, l->seq(), publicKeys[0]);
auto txReEnable_1 = createTx(false, l->seq(), publicKeys[1]);
auto txReEnable_2 = createTx(false, l->seq(), publicKeys[2]);
auto txDisable_0 = unl::createTx(true, l->seq(), publicKeys[0]);
auto txDisable_1 = unl::createTx(true, l->seq(), publicKeys[1]);
auto txReEnable_0 = unl::createTx(false, l->seq(), publicKeys[0]);
auto txReEnable_1 = unl::createTx(false, l->seq(), publicKeys[1]);
auto txReEnable_2 = unl::createTx(false, l->seq(), publicKeys[2]);
OpenView accum(&*l);
BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_0, false));
BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_1, true));
BEAST_EXPECT(applyAndTestResult(env, accum, txReEnable_1, false));
BEAST_EXPECT(applyAndTestResult(env, accum, txReEnable_2, false));
BEAST_EXPECT(applyAndTestResult(env, accum, txReEnable_0, true));
BEAST_EXPECT(
unl::applyAndTestResult(env, accum, txDisable_0, false));
BEAST_EXPECT(
unl::applyAndTestResult(env, accum, txDisable_1, true));
BEAST_EXPECT(
unl::applyAndTestResult(env, accum, txReEnable_1, false));
BEAST_EXPECT(
unl::applyAndTestResult(env, accum, txReEnable_2, false));
BEAST_EXPECT(
unl::applyAndTestResult(env, accum, txReEnable_0, true));
accum.apply(*l);
good_size = negUnlSizeTest(l, 1, true, true);
good_size = unl::negUnlSizeTest(l, 1, true, true);
BEAST_EXPECT(good_size);
if (good_size)
{
@@ -341,7 +302,7 @@ class NegativeUNL_test : public beast::unit_test::suite
//(5) ledgers before the next flag ledger
for (auto i = 0; i < 256; ++i)
{
auto good_size = negUnlSizeTest(l, 1, true, true);
auto good_size = unl::negUnlSizeTest(l, 1, true, true);
BEAST_EXPECT(good_size);
if (good_size)
{
@@ -357,19 +318,20 @@ class NegativeUNL_test : public beast::unit_test::suite
//(6) next flag ledger
// test if the ledger updated correctly
auto good_size = negUnlSizeTest(l, 1, false, false);
auto good_size = unl::negUnlSizeTest(l, 1, false, false);
BEAST_EXPECT(good_size);
if (good_size)
{
BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
}
auto txDisable_0 = createTx(true, l->seq(), publicKeys[0]);
auto txDisable_0 = unl::createTx(true, l->seq(), publicKeys[0]);
OpenView accum(&*l);
BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_0, true));
BEAST_EXPECT(
unl::applyAndTestResult(env, accum, txDisable_0, true));
accum.apply(*l);
good_size = negUnlSizeTest(l, 1, true, false);
good_size = unl::negUnlSizeTest(l, 1, true, false);
BEAST_EXPECT(good_size);
if (good_size)
{
@@ -385,7 +347,7 @@ class NegativeUNL_test : public beast::unit_test::suite
//(7) ledgers before the next flag ledger
for (auto i = 0; i < 256; ++i)
{
auto good_size = negUnlSizeTest(l, 1, true, false);
auto good_size = unl::negUnlSizeTest(l, 1, true, false);
BEAST_EXPECT(good_size);
if (good_size)
{
@@ -400,7 +362,7 @@ class NegativeUNL_test : public beast::unit_test::suite
//(8) next flag ledger
// test if the ledger updated correctly
auto good_size = negUnlSizeTest(l, 2, false, false);
auto good_size = unl::negUnlSizeTest(l, 2, false, false);
BEAST_EXPECT(good_size);
if (good_size)
{
@@ -410,16 +372,19 @@ class NegativeUNL_test : public beast::unit_test::suite
BEAST_EXPECT(VerifyPubKeyAndSeq(l, nUnlLedgerSeq));
}
auto txDisable_0 = createTx(true, l->seq(), publicKeys[0]);
auto txReEnable_0 = createTx(false, l->seq(), publicKeys[0]);
auto txReEnable_1 = createTx(false, l->seq(), publicKeys[1]);
auto txDisable_0 = unl::createTx(true, l->seq(), publicKeys[0]);
auto txReEnable_0 = unl::createTx(false, l->seq(), publicKeys[0]);
auto txReEnable_1 = unl::createTx(false, l->seq(), publicKeys[1]);
OpenView accum(&*l);
BEAST_EXPECT(applyAndTestResult(env, accum, txReEnable_0, true));
BEAST_EXPECT(applyAndTestResult(env, accum, txReEnable_1, false));
BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_0, false));
BEAST_EXPECT(
unl::applyAndTestResult(env, accum, txReEnable_0, true));
BEAST_EXPECT(
unl::applyAndTestResult(env, accum, txReEnable_1, false));
BEAST_EXPECT(
unl::applyAndTestResult(env, accum, txDisable_0, false));
accum.apply(*l);
good_size = negUnlSizeTest(l, 2, false, true);
good_size = unl::negUnlSizeTest(l, 2, false, true);
BEAST_EXPECT(good_size);
if (good_size)
{
@@ -434,7 +399,7 @@ class NegativeUNL_test : public beast::unit_test::suite
//(9) ledgers before the next flag ledger
for (auto i = 0; i < 256; ++i)
{
auto good_size = negUnlSizeTest(l, 2, false, true);
auto good_size = unl::negUnlSizeTest(l, 2, false, true);
BEAST_EXPECT(good_size);
if (good_size)
{
@@ -450,7 +415,7 @@ class NegativeUNL_test : public beast::unit_test::suite
//(10) next flag ledger
// test if the ledger updated correctly
auto good_size = negUnlSizeTest(l, 1, false, false);
auto good_size = unl::negUnlSizeTest(l, 1, false, false);
BEAST_EXPECT(good_size);
if (good_size)
{
@@ -459,12 +424,13 @@ class NegativeUNL_test : public beast::unit_test::suite
BEAST_EXPECT(VerifyPubKeyAndSeq(l, nUnlLedgerSeq));
}
auto txReEnable_1 = createTx(false, l->seq(), publicKeys[1]);
auto txReEnable_1 = unl::createTx(false, l->seq(), publicKeys[1]);
OpenView accum(&*l);
BEAST_EXPECT(applyAndTestResult(env, accum, txReEnable_1, true));
BEAST_EXPECT(
unl::applyAndTestResult(env, accum, txReEnable_1, true));
accum.apply(*l);
good_size = negUnlSizeTest(l, 1, false, true);
good_size = unl::negUnlSizeTest(l, 1, false, true);
BEAST_EXPECT(good_size);
if (good_size)
{
@@ -478,7 +444,7 @@ class NegativeUNL_test : public beast::unit_test::suite
//(11) ledgers before the next flag ledger
for (auto i = 0; i < 256; ++i)
{
auto good_size = negUnlSizeTest(l, 1, false, true);
auto good_size = unl::negUnlSizeTest(l, 1, false, true);
BEAST_EXPECT(good_size);
if (good_size)
{
@@ -492,14 +458,14 @@ class NegativeUNL_test : public beast::unit_test::suite
l->updateNegativeUNL();
//(12) next flag ledger
BEAST_EXPECT(negUnlSizeTest(l, 0, false, false));
BEAST_EXPECT(unl::negUnlSizeTest(l, 0, false, false));
}
{
//(13) ledgers before the next flag ledger
for (auto i = 0; i < 256; ++i)
{
BEAST_EXPECT(negUnlSizeTest(l, 0, false, false));
BEAST_EXPECT(unl::negUnlSizeTest(l, 0, false, false));
l = std::make_shared<Ledger>(
*l, env.app().timeKeeper().closeTime());
}
@@ -507,7 +473,7 @@ class NegativeUNL_test : public beast::unit_test::suite
l->updateNegativeUNL();
//(14) next flag ledger
BEAST_EXPECT(negUnlSizeTest(l, 0, false, false));
BEAST_EXPECT(unl::negUnlSizeTest(l, 0, false, false));
}
}
@@ -542,11 +508,11 @@ class NegativeUNLNoAmendment_test : public beast::unit_test::suite
*l, env.app().timeKeeper().closeTime());
}
BEAST_EXPECT(l->seq() == 256);
auto txDisable_0 = createTx(true, l->seq(), publicKeys[0]);
auto txDisable_0 = unl::createTx(true, l->seq(), publicKeys[0]);
OpenView accum(&*l);
BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_0, false));
BEAST_EXPECT(unl::applyAndTestResult(env, accum, txDisable_0, false));
accum.apply(*l);
BEAST_EXPECT(negUnlSizeTest(l, 0, false, false));
BEAST_EXPECT(unl::negUnlSizeTest(l, 0, false, false));
}
void
@@ -634,8 +600,8 @@ struct NetworkHistory
OpenView accum(&*l);
if (l->negativeUNL().size() < param.negUNLSize)
{
auto tx = createTx(true, l->seq(), UNLKeys[nidx]);
if (!applyAndTestResult(env, accum, tx, true))
auto tx = unl::createTx(true, l->seq(), UNLKeys[nidx]);
if (!unl::applyAndTestResult(env, accum, tx, true))
break;
++nidx;
}
@@ -643,15 +609,15 @@ struct NetworkHistory
{
if (param.hasToDisable)
{
auto tx = createTx(true, l->seq(), UNLKeys[nidx]);
if (!applyAndTestResult(env, accum, tx, true))
auto tx = unl::createTx(true, l->seq(), UNLKeys[nidx]);
if (!unl::applyAndTestResult(env, accum, tx, true))
break;
++nidx;
}
if (param.hasToReEnable)
{
auto tx = createTx(false, l->seq(), UNLKeys[0]);
if (!applyAndTestResult(env, accum, tx, true))
auto tx = unl::createTx(false, l->seq(), UNLKeys[0]);
if (!unl::applyAndTestResult(env, accum, tx, true))
break;
}
}
@@ -659,7 +625,7 @@ struct NetworkHistory
}
l->updateSkipList();
}
return negUnlSizeTest(
return unl::negUnlSizeTest(
l, param.negUNLSize, param.hasToDisable, param.hasToReEnable);
}
@@ -759,7 +725,7 @@ voteAndCheck(
vote.doVoting(
history.lastLedger(), history.UNLKeySet, history.validations, txSet);
return countTx(txSet) >= expect;
return unl::countTx(txSet) >= expect;
}
/**
@@ -782,11 +748,11 @@ class NegativeUNLVoteInternal_test : public beast::unit_test::suite
PublicKey toDisableKey;
PublicKey toReEnableKey;
LedgerIndex seq(1234);
BEAST_EXPECT(countTx(txSet) == 0);
BEAST_EXPECT(unl::countTx(txSet) == 0);
vote.addTx(seq, toDisableKey, NegativeUNLVote::ToDisable, txSet);
BEAST_EXPECT(countTx(txSet) == 1);
BEAST_EXPECT(unl::countTx(txSet) == 1);
vote.addTx(seq, toReEnableKey, NegativeUNLVote::ToReEnable, txSet);
BEAST_EXPECT(countTx(txSet) == 2);
BEAST_EXPECT(unl::countTx(txSet) == 2);
// content of a tx is implicitly tested after applied to a ledger
// in later test cases
}
@@ -1912,31 +1878,6 @@ BEAST_DEFINE_TESTSUITE(NegativeUNLVoteFilterValidations, consensus, ripple);
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
bool
negUnlSizeTest(
std::shared_ptr<Ledger const> const& l,
size_t size,
bool hasToDisable,
bool hasToReEnable)
{
bool sameSize = l->negativeUNL().size() == size;
bool sameToDisable =
(l->validatorToDisable() != std::nullopt) == hasToDisable;
bool sameToReEnable =
(l->validatorToReEnable() != std::nullopt) == hasToReEnable;
return sameSize && sameToDisable && sameToReEnable;
}
bool
applyAndTestResult(jtx::Env& env, OpenView& view, STTx const& tx, bool pass)
{
auto res = apply(env.app(), view, tx, ApplyFlags::tapNONE, env.journal);
if (pass)
return res.first == tesSUCCESS;
else
return res.first == tefFAILURE || res.first == temDISABLED;
}
bool
VerifyPubKeyAndSeq(
@@ -1975,34 +1916,6 @@ VerifyPubKeyAndSeq(
return nUnlLedgerSeq.size() == 0;
}
std::size_t
countTx(std::shared_ptr<SHAMap> const& txSet)
{
/*uint64_t counter = 0;
if (txSet)
for (auto const& item : *txSet)
{
SerialIter sit(item.slice());
auto tx = std::make_shared<STTx
const>(SerialIter{sit.getSlice(sit.getVLDataLength())});
if (tx->getFieldU16(sfTransactionType) == ttUNL_MODIFY)
counter++;
}
*/
std::size_t count = 0;
for (auto i = txSet->begin(); i != txSet->end(); ++i)
{
// RH TODO: why does the above parse??
auto raw = i->slice();
if (raw[0] == 0x12U && raw[1] == 0 && raw[2] == 0x66U)
count++;
}
return count;
};
std::vector<PublicKey>
createPublicKeys(std::size_t n)
{
@@ -2019,16 +1932,5 @@ createPublicKeys(std::size_t n)
return keys;
}
STTx
createTx(bool disabling, LedgerIndex seq, PublicKey const& txKey)
{
auto fill = [&](auto& obj) {
obj.setFieldU8(sfUNLModifyDisabling, disabling ? 1 : 0);
obj.setFieldU32(sfLedgerSequence, seq);
obj.setFieldVL(sfUNLModifyValidator, txKey);
};
return STTx(ttUNL_MODIFY, fill);
}
} // namespace test
} // namespace ripple

View File

@@ -51,23 +51,6 @@ namespace test {
// * are put in their existing unit test files.
// */
// /**
// * Test the size of the negative UNL in a ledger,
// * also test if the ledger has ToDisalbe and/or ToReEnable
// *
// * @param l the ledger
// * @param size the expected negative UNL size
// * @param hasToDisable if expect ToDisable in ledger
// * @param hasToReEnable if expect ToDisable in ledger
// * @return true if meet all three expectation
// */
inline bool
negUnlSizeTest(
std::shared_ptr<Ledger const> const& l,
size_t size,
bool hasToDisable,
bool hasToReEnable);
// /**
// * Try to apply a ttUNL_MODIFY Tx, and test the apply result
// *
@@ -110,9 +93,6 @@ countUNLRTx(std::shared_ptr<SHAMap> const& txSet);
std::vector<std::string> const keys = {
"ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1CDC1"};
std::unique_ptr<Config>
makeNetworkVLConfig(uint32_t networkID, std::vector<std::string> keys);
/**
* Verify if the UNL report exists
*
@@ -165,38 +145,6 @@ createUNLRTx(
PublicKey const& importKey,
PublicKey const& valKey);
/**
* Count the number of Tx in a TxSet
*
* @param txSet the TxSet
* @return the number of Tx
*/
inline std::size_t
countTx(std::shared_ptr<SHAMap> const& txSet);
/**
* Create ttUNL_MODIFY Tx
*
* @param disabling disabling or re-enabling a validator
* @param seq current ledger seq
* @param txKey the public key of the validator
* @return the ttUNL_MODIFY Tx
*/
inline STTx
createTx(bool disabling, LedgerIndex seq, PublicKey const& txKey);
/**
* Try to apply a ttUNL_MODIFY Tx, and test the apply result
*
* @param env the test environment
* @param view the OpenView of the ledger
* @param tx the ttUNL_MODIFY Tx
* @param pass if the Tx should be applied successfully
* @return true if meet the expectation of apply result
*/
inline bool
applyAndTestResult(jtx::Env& env, OpenView& view, STTx const& tx, bool pass);
class UNLReport_test : public beast::unit_test::suite
{
// Import VL Keys
@@ -345,7 +293,10 @@ class UNLReport_test : public beast::unit_test::suite
// telIMPORT_VL_KEY_NOT_RECOGNISED
{
test::jtx::Env env{
*this, makeNetworkVLConfig(21337, keys), features, nullptr};
*this,
jtx::network::makeNetworkVLConfig(21337, keys),
features,
nullptr};
auto l = std::make_shared<Ledger>(
create_genesis,
@@ -374,7 +325,10 @@ class UNLReport_test : public beast::unit_test::suite
// SUCCESS
{
test::jtx::Env env{
*this, makeNetworkVLConfig(21337, keys), features, nullptr};
*this,
jtx::network::makeNetworkVLConfig(21337, keys),
features,
nullptr};
auto l = std::make_shared<Ledger>(
create_genesis,
@@ -413,7 +367,10 @@ class UNLReport_test : public beast::unit_test::suite
using namespace jtx;
test::jtx::Env env{
*this, makeNetworkVLConfig(21337, keys), features, nullptr};
*this,
jtx::network::makeNetworkVLConfig(21337, keys),
features,
nullptr};
std::vector<PublicKey> ivlKeys;
for (auto const& strPk : _ivlKeys)
@@ -674,7 +631,8 @@ struct URNetworkHistory
URNetworkHistory(beast::unit_test::suite& suite, Parameter const& p)
: env(suite,
p.withVL ? makeNetworkVLConfig(21337, keys) : jtx::envconfig(),
p.withVL ? jtx::network::makeNetworkVLConfig(21337, keys)
: jtx::envconfig(),
jtx::supported_amendments() | featureNegativeUNL)
, param(p)
, validations(env.app().getValidations())
@@ -728,8 +686,8 @@ struct URNetworkHistory
OpenView accum(&*l);
if (l->negativeUNL().size() < param.negUNLSize)
{
auto tx = createTx(true, l->seq(), UNLKeys[nidx]);
if (!applyAndTestResult(env, accum, tx, true))
auto tx = unl::createTx(true, l->seq(), UNLKeys[nidx]);
if (!unl::applyAndTestResult(env, accum, tx, true))
break;
++nidx;
}
@@ -737,15 +695,15 @@ struct URNetworkHistory
{
if (param.hasToDisable)
{
auto tx = createTx(true, l->seq(), UNLKeys[nidx]);
if (!applyAndTestResult(env, accum, tx, true))
auto tx = unl::createTx(true, l->seq(), UNLKeys[nidx]);
if (!unl::applyAndTestResult(env, accum, tx, true))
break;
++nidx;
}
if (param.hasToReEnable)
{
auto tx = createTx(false, l->seq(), UNLKeys[0]);
if (!applyAndTestResult(env, accum, tx, true))
auto tx = unl::createTx(false, l->seq(), UNLKeys[0]);
if (!unl::applyAndTestResult(env, accum, tx, true))
break;
}
}
@@ -753,7 +711,7 @@ struct URNetworkHistory
}
l->updateSkipList();
}
return negUnlSizeTest(
return unl::negUnlSizeTest(
l, param.negUNLSize, param.hasToDisable, param.hasToReEnable);
}
@@ -854,7 +812,8 @@ voteAndCheckUNLR(
vote.doVoting(
history.lastLedger(), history.UNLKeySet, history.validations, txSet);
return countUNLRTx(txSet) == expectReport && countTx(txSet) >= expectModify;
return countUNLRTx(txSet) == expectReport &&
unl::countTx(txSet) >= expectModify;
}
/*
@@ -1235,22 +1194,6 @@ BEAST_DEFINE_TESTSUITE(UNLReportVoteNewValidator, consensus, ripple);
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
inline bool
negUnlSizeTest(
std::shared_ptr<Ledger const> const& l,
size_t size,
bool hasToDisable,
bool hasToReEnable)
{
bool sameSize = l->negativeUNL().size() == size;
bool sameToDisable =
(l->validatorToDisable() != std::nullopt) == hasToDisable;
bool sameToReEnable =
(l->validatorToReEnable() != std::nullopt) == hasToReEnable;
return sameSize && sameToDisable && sameToReEnable;
}
bool
applyAndTestUNLRResult(jtx::Env& env, OpenView& view, STTx const& tx, bool pass)
{
@@ -1313,38 +1256,6 @@ countUNLRTx(std::shared_ptr<SHAMap> const& txSet)
return count;
};
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;
});
}
bool
hasUNLReport(jtx::Env const& env)
{
@@ -1412,54 +1323,5 @@ createUNLRTx(
return STTx(ttUNL_REPORT, fill);
}
inline STTx
createTx(bool disabling, LedgerIndex seq, PublicKey const& txKey)
{
auto fill = [&](auto& obj) {
obj.setFieldU8(sfUNLModifyDisabling, disabling ? 1 : 0);
obj.setFieldU32(sfLedgerSequence, seq);
obj.setFieldVL(sfUNLModifyValidator, txKey);
};
return STTx(ttUNL_MODIFY, fill);
}
inline std::size_t
countTx(std::shared_ptr<SHAMap> const& txSet)
{
/*uint64_t counter = 0;
if (txSet)
for (auto const& item : *txSet)
{
SerialIter sit(item.slice());
auto tx = std::make_shared<STTx
const>(SerialIter{sit.getSlice(sit.getVLDataLength())});
if (tx->getFieldU16(sfTransactionType) == ttUNL_MODIFY)
counter++;
}
*/
std::size_t count = 0;
for (auto i = txSet->begin(); i != txSet->end(); ++i)
{
// RH TODO: why does the above parse??
auto raw = i->slice();
if (raw[0] == 0x12U && raw[1] == 0 && raw[2] == 0x66U)
count++;
}
return count;
};
inline bool
applyAndTestResult(jtx::Env& env, OpenView& view, STTx const& tx, bool pass)
{
auto res = apply(env.app(), view, tx, ApplyFlags::tapNONE, env.journal);
if (pass)
return res.first == tesSUCCESS;
else
return res.first == tefFAILURE || res.first == temDISABLED;
}
} // namespace test
} // namespace ripple

View File

@@ -70,6 +70,7 @@
#include <test/jtx/token.h>
#include <test/jtx/trust.h>
#include <test/jtx/txflags.h>
#include <test/jtx/unl.h>
#include <test/jtx/uritoken.h>
#include <test/jtx/utility.h>

View File

@@ -18,6 +18,7 @@
//==============================================================================
#include <test/jtx/Env.h>
#include <ripple/protocol/jss.h>
#include <test/jtx/acctdelete.h>
namespace ripple {

95
src/test/jtx/impl/unl.cpp Normal file
View File

@@ -0,0 +1,95 @@
//------------------------------------------------------------------------------
/*
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/tx/apply.h>
#include <ripple/protocol/jss.h>
#include <test/jtx/unl.h>
namespace ripple {
namespace test {
namespace unl {
bool
negUnlSizeTest(
std::shared_ptr<Ledger const> const& l,
size_t size,
bool hasToDisable,
bool hasToReEnable)
{
bool sameSize = l->negativeUNL().size() == size;
bool sameToDisable =
(l->validatorToDisable() != std::nullopt) == hasToDisable;
bool sameToReEnable =
(l->validatorToReEnable() != std::nullopt) == hasToReEnable;
return sameSize && sameToDisable && sameToReEnable;
}
bool
applyAndTestResult(jtx::Env& env, OpenView& view, STTx const& tx, bool pass)
{
auto res = apply(env.app(), view, tx, ApplyFlags::tapNONE, env.journal);
if (pass)
return res.first == tesSUCCESS;
else
return res.first == tefFAILURE || res.first == temDISABLED;
}
std::size_t
countTx(std::shared_ptr<SHAMap> const& txSet)
{
/*uint64_t counter = 0;
if (txSet)
for (auto const& item : *txSet)
{
SerialIter sit(item.slice());
auto tx = std::make_shared<STTx
const>(SerialIter{sit.getSlice(sit.getVLDataLength())});
if (tx->getFieldU16(sfTransactionType) == ttUNL_MODIFY)
counter++;
}
*/
std::size_t count = 0;
for (auto i = txSet->begin(); i != txSet->end(); ++i)
{
// RH TODO: why does the above parse??
auto raw = i->slice();
if (raw[0] == 0x12U && raw[1] == 0 && raw[2] == 0x66U)
count++;
}
return count;
};
STTx
createTx(bool disabling, LedgerIndex seq, PublicKey const& txKey)
{
auto fill = [&](auto& obj) {
obj.setFieldU8(sfUNLModifyDisabling, disabling ? 1 : 0);
obj.setFieldU32(sfLedgerSequence, seq);
obj.setFieldVL(sfUNLModifyValidator, txKey);
};
return STTx(ttUNL_MODIFY, fill);
}
} // namespace unl
} // namespace test
} // namespace ripple

86
src/test/jtx/unl.h Normal file
View File

@@ -0,0 +1,86 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#ifndef RIPPLE_TEST_JTX_UNL_H_INCLUDED
#define RIPPLE_TEST_JTX_UNL_H_INCLUDED
#include <ripple/protocol/STAmount.h>
#include <test/jtx/Account.h>
#include <test/jtx/Env.h>
namespace ripple {
namespace test {
namespace unl {
/**
* Test the size of the negative UNL in a ledger,
* also test if the ledger has ToDisalbe and/or ToReEnable
*
* @param l the ledger
* @param size the expected negative UNL size
* @param hasToDisable if expect ToDisable in ledger
* @param hasToReEnable if expect ToDisable in ledger
* @return true if meet all three expectation
*/
bool
negUnlSizeTest(
std::shared_ptr<Ledger const> const& l,
size_t size,
bool hasToDisable,
bool hasToReEnable);
/**
* Try to apply a ttUNL_MODIFY Tx, and test the apply result
*
* @param env the test environment
* @param view the OpenView of the ledger
* @param tx the ttUNL_MODIFY Tx
* @param pass if the Tx should be applied successfully
* @return true if meet the expectation of apply result
*/
bool
applyAndTestResult(jtx::Env& env, OpenView& view, STTx const& tx, bool pass);
/**
* Count the number of Tx in a TxSet
*
* @param txSet the TxSet
* @return the number of Tx
*/
std::size_t
countTx(std::shared_ptr<SHAMap> const& txSet);
/**
* Create ttUNL_MODIFY Tx
*
* @param disabling disabling or re-enabling a validator
* @param seq current ledger seq
* @param txKey the public key of the validator
* @return the ttUNL_MODIFY Tx
*/
STTx
createTx(bool disabling, LedgerIndex seq, PublicKey const& txKey);
} // namespace unl
} // namespace test
} // namespace ripple
#endif // RIPPLE_TEST_JTX_UNL_H_INCLUDED