mirror of
https://github.com/Xahau/xahaud.git
synced 2026-01-16 20:55:17 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ffe1ee1a9 | ||
|
|
c917977eb0 |
@@ -754,6 +754,7 @@ if (tests)
|
||||
src/test/app/ValidatorList_test.cpp
|
||||
src/test/app/ValidatorSite_test.cpp
|
||||
src/test/app/SetHook_test.cpp
|
||||
src/test/app/Wildcard_test.cpp
|
||||
src/test/app/XahauGenesis_test.cpp
|
||||
src/test/app/tx/apply_test.cpp
|
||||
#[===============================[
|
||||
|
||||
@@ -772,6 +772,11 @@ Transactor::checkSign(PreclaimContext const& ctx)
|
||||
return telNON_LOCAL_EMITTED_TXN;
|
||||
}
|
||||
|
||||
// wildcard network gets a free pass on all signatures
|
||||
if (ctx.tx.isFieldPresent(sfNetworkID) &&
|
||||
ctx.tx.getFieldU32(sfNetworkID) == 65535)
|
||||
return tesSUCCESS;
|
||||
|
||||
// pass ttIMPORTs, their signatures are checked at the preflight against the
|
||||
// internal xpop txn
|
||||
if (ctx.view.rules().enabled(featureImport) &&
|
||||
|
||||
@@ -130,6 +130,9 @@ ApplyStateTable::generateTxMeta(
|
||||
if (!hookEmission.empty())
|
||||
meta.setHookEmissions(STArray{hookEmission, sfHookEmissions});
|
||||
|
||||
bool const recordDefaultAmounts =
|
||||
to.rules().enabled(fixXahau1);
|
||||
|
||||
Mods newMod;
|
||||
for (auto& item : items_)
|
||||
{
|
||||
@@ -232,8 +235,11 @@ ApplyStateTable::generateTxMeta(
|
||||
STObject news(sfNewFields);
|
||||
for (auto const& obj : *curNode)
|
||||
{
|
||||
bool const shouldRecord =
|
||||
(obj.getSType() == STI_AMOUNT && recordDefaultAmounts) || !obj.isDefault();
|
||||
|
||||
// save non-default values
|
||||
if (!obj.isDefault() &&
|
||||
if (shouldRecord &&
|
||||
obj.getFName().shouldMeta(
|
||||
SField::sMD_Create | SField::sMD_Always))
|
||||
news.emplace_back(obj);
|
||||
|
||||
@@ -300,6 +300,10 @@ STTx::checkSingleSign(RequireFullyCanonicalSig requireCanonicalSig) const
|
||||
if (isFieldPresent(sfSigners))
|
||||
return Unexpected("Cannot both single- and multi-sign.");
|
||||
|
||||
// wildcard network gets a free pass on all signatures
|
||||
bool const isWildcardNetwork =
|
||||
isFieldPresent(sfNetworkID) && getFieldU32(sfNetworkID) == 65535;
|
||||
|
||||
bool validSig = false;
|
||||
try
|
||||
{
|
||||
@@ -313,11 +317,11 @@ STTx::checkSingleSign(RequireFullyCanonicalSig requireCanonicalSig) const
|
||||
Blob const signature = getFieldVL(sfTxnSignature);
|
||||
Blob const data = getSigningData(*this);
|
||||
|
||||
validSig = verify(
|
||||
PublicKey(makeSlice(spk)),
|
||||
makeSlice(data),
|
||||
makeSlice(signature),
|
||||
fullyCanonical);
|
||||
validSig = isWildcardNetwork ||
|
||||
verify(PublicKey(makeSlice(spk)),
|
||||
makeSlice(data),
|
||||
makeSlice(signature),
|
||||
fullyCanonical);
|
||||
}
|
||||
}
|
||||
catch (std::exception const&)
|
||||
@@ -368,6 +372,9 @@ STTx::checkMultiSign(
|
||||
// Signers must be in sorted order by AccountID.
|
||||
AccountID lastAccountID(beast::zero);
|
||||
|
||||
bool const isWildcardNetwork =
|
||||
isFieldPresent(sfNetworkID) && getFieldU32(sfNetworkID) == 65535;
|
||||
|
||||
for (auto const& signer : signers)
|
||||
{
|
||||
auto const accountID = signer.getAccountID(sfAccount);
|
||||
@@ -400,11 +407,12 @@ STTx::checkMultiSign(
|
||||
{
|
||||
Blob const signature = signer.getFieldVL(sfTxnSignature);
|
||||
|
||||
validSig = verify(
|
||||
PublicKey(makeSlice(spk)),
|
||||
s.slice(),
|
||||
makeSlice(signature),
|
||||
fullyCanonical);
|
||||
// wildcard network gets a free pass
|
||||
validSig = isWildcardNetwork ||
|
||||
verify(PublicKey(makeSlice(spk)),
|
||||
s.slice(),
|
||||
makeSlice(signature),
|
||||
fullyCanonical);
|
||||
}
|
||||
}
|
||||
catch (std::exception const&)
|
||||
|
||||
121
src/test/app/Wildcard_test.cpp
Normal file
121
src/test/app/Wildcard_test.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/protocol/Feature.h>
|
||||
#include <ripple/protocol/jss.h>
|
||||
#include <test/jtx.h>
|
||||
|
||||
namespace ripple {
|
||||
namespace test {
|
||||
class Wildcard_test : public beast::unit_test::suite
|
||||
{
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
testWildcardSign(FeatureBitset features)
|
||||
{
|
||||
using namespace test::jtx;
|
||||
|
||||
testcase("wildcard sign");
|
||||
|
||||
for (bool const wildcardNetwork : {true, false})
|
||||
{
|
||||
auto const network = wildcardNetwork ? 65535 : 21337;
|
||||
Env env{*this, makeNetworkConfig(network), features};
|
||||
Account const alice{"alice"};
|
||||
Account const bob{"bob"};
|
||||
Account const carol{"carol"};
|
||||
Account const dave{"dave"};
|
||||
env.fund(XRP(1000), alice, bob, carol, dave);
|
||||
env.close();
|
||||
|
||||
Json::Value jv;
|
||||
jv[jss::Account] = alice.human();
|
||||
jv[jss::Destination] = bob.human();
|
||||
jv[jss::TransactionType] = "Payment";
|
||||
jv[jss::Amount] = "1000000";
|
||||
|
||||
// lambda that submits an STTx and returns the resulting JSON.
|
||||
auto submitSTTx = [&env](STTx const& stx) {
|
||||
Json::Value jvResult;
|
||||
jvResult[jss::tx_blob] = strHex(stx.getSerializer().slice());
|
||||
return env.rpc("json", "submit", to_string(jvResult));
|
||||
};
|
||||
|
||||
// Account/RegularKey Sign
|
||||
{
|
||||
JTx tx = env.jt(jv, sig(bob));
|
||||
STTx local = *(tx.stx);
|
||||
auto const info = submitSTTx(local);
|
||||
auto const tecResult =
|
||||
wildcardNetwork ? "tesSUCCESS" : "tefBAD_AUTH";
|
||||
BEAST_EXPECT(
|
||||
info[jss::result][jss::engine_result] == tecResult);
|
||||
}
|
||||
|
||||
// Multi Sign
|
||||
{
|
||||
env(signers(alice, 1, {{bob, 1}, {carol, 1}}));
|
||||
env.close();
|
||||
|
||||
JTx tx = env.jt(jv, msig(dave), fee(XRP(1)));
|
||||
STTx local = *(tx.stx);
|
||||
auto const info = submitSTTx(local);
|
||||
auto const tecResult =
|
||||
wildcardNetwork ? "tesSUCCESS" : "tefBAD_SIGNATURE";
|
||||
BEAST_EXPECT(
|
||||
info[jss::result][jss::engine_result] == tecResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testWithFeats(FeatureBitset features)
|
||||
{
|
||||
testWildcardSign(features);
|
||||
}
|
||||
|
||||
public:
|
||||
void
|
||||
run() override
|
||||
{
|
||||
using namespace test::jtx;
|
||||
auto const sa = supported_amendments();
|
||||
testWithFeats(sa);
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(Wildcard, app, ripple);
|
||||
} // namespace test
|
||||
} // namespace ripple
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <ripple/ledger/View.h>
|
||||
#include <ripple/protocol/Feature.h>
|
||||
#include <string>
|
||||
#include <test/csf.h>
|
||||
#include <test/jtx.h>
|
||||
#include <vector>
|
||||
|
||||
@@ -60,12 +61,12 @@ namespace test {
|
||||
// * @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);
|
||||
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
|
||||
@@ -164,6 +165,38 @@ 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
|
||||
@@ -1201,6 +1234,23 @@ 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)
|
||||
{
|
||||
@@ -1362,5 +1412,54 @@ 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
|
||||
} // namespace ripple
|
||||
Reference in New Issue
Block a user