Merge branch 'develop' into mvadari/constant-field-invariant

This commit is contained in:
Mayukha Vadari
2026-05-20 17:16:01 -04:00
committed by GitHub
24 changed files with 223 additions and 71 deletions

View File

@@ -365,8 +365,8 @@ using SF_XCHAIN_BRIDGE = TypedField<STXChainBridge>;
#define UNTYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) extern SField const sfName;
#define TYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) extern SF_##stiSuffix const sfName;
extern SField const kSfInvalid;
extern SField const kSfGeneric;
extern SField const sfInvalid; // NOLINT(readability-identifier-naming)
extern SField const sfGeneric; // NOLINT(readability-identifier-naming)
#include <xrpl/protocol/detail/sfields.macro>

View File

@@ -24,7 +24,7 @@ public:
STBlob(SField const& f, void const* data, std::size_t size);
STBlob(SField const& f, Buffer&& b);
STBlob(SField const& n);
STBlob(SerialIter&, SField const& name = kSfGeneric);
STBlob(SerialIter&, SField const& name = sfGeneric);
[[nodiscard]] std::size_t
size() const;

View File

@@ -53,8 +53,8 @@ TypedField<T>::TypedField(PrivateAccessTagT pat, Args&&... args)
##__VA_ARGS__);
// SFields which, for historical reasons, do not follow naming conventions.
SField const kSfInvalid(access, -1, "");
SField const kSfGeneric(access, 0, "Generic");
SField const sfInvalid(access, -1, "");
SField const sfGeneric(access, 0, "Generic");
// The following two fields aren't used anywhere, but they break tests/have
// downstream effects.
SField const kSfHash(access, STI_UINT256, 257, "hash");
@@ -121,7 +121,7 @@ SField::getField(int code)
{
return *(it->second);
}
return kSfInvalid;
return sfInvalid;
}
int
@@ -149,7 +149,7 @@ SField::getField(std::string const& fieldName)
{
return *(it->second);
}
return kSfInvalid;
return sfInvalid;
}
} // namespace xrpl

View File

@@ -1151,7 +1151,7 @@ amountFromJsonNoThrow(STAmount& result, json::Value const& jvSource)
{
try
{
result = amountFromJson(kSfGeneric, jvSource);
result = amountFromJson(sfGeneric, jvSource);
return true;
}
catch (std::exception const& e)

View File

@@ -12,7 +12,7 @@
namespace xrpl {
STBase::STBase() : fName_(&kSfGeneric)
STBase::STBase() : fName_(&sfGeneric)
{
}

View File

@@ -258,7 +258,7 @@ parseUInt16(
safeCast<typename STResult::value_type>(static_cast<Integer>(
TxFormats::getInstance().findTypeByName(strValue))));
if (*name == kSfGeneric)
if (*name == sfGeneric)
name = &sfTransaction;
}
else if (field == sfLedgerEntryType)
@@ -268,7 +268,7 @@ parseUInt16(
safeCast<typename STResult::value_type>(static_cast<Integer>(
LedgerFormats::getInstance().findTypeByName(strValue))));
if (*name == kSfGeneric)
if (*name == sfGeneric)
name = &sfLedgerEntry;
}
else
@@ -361,7 +361,7 @@ parseLeaf(
auto const& field = SField::getField(fieldName);
// checked in parseObject
if (field == kSfInvalid)
if (field == sfInvalid)
{
// LCOV_EXCL_START
error = unknownField(jsonName, fieldName);
@@ -1013,7 +1013,7 @@ parseObject(
json::Value const& value = json[fieldName];
auto const& field = SField::getField(fieldName);
if (field == kSfInvalid)
if (field == sfInvalid)
{
error = unknownField(jsonName, fieldName);
return std::nullopt;
@@ -1144,7 +1144,7 @@ parseArray(
std::string const memberName(json[i].getMemberNames()[0]);
auto const& nameField(SField::getField(memberName));
if (nameField == kSfInvalid)
if (nameField == sfInvalid)
{
error = unknownField(jsonName, memberName);
return std::nullopt;
@@ -1189,7 +1189,7 @@ parseArray(
STParsedJSONObject::STParsedJSONObject(std::string const& name, json::Value const& json)
{
using namespace STParsedJSONDetail;
object = parseObject(name, json, kSfGeneric, 0, error);
object = parseObject(name, json, sfGeneric, 0, error);
}
} // namespace xrpl

View File

@@ -535,8 +535,10 @@ STTx::checkMultiSign(Rules const& rules, STObject const& sigObject) const
{
// Used inside the loop in multiSignHelper to enforce that
// the account owner may not multisign for themselves.
// For delegated transactions sfDelegate is the account whose signer list is checked,
// the delegate account itself can not be among the signers.
auto const txnAccountID =
&sigObject != this ? std::nullopt : std::optional<AccountID>(getAccountID(sfAccount));
&sigObject != this ? std::nullopt : std::optional<AccountID>(getFeePayer());
// We can ease the computational load inside the loop a bit by
// pre-constructing part of the data that we hash. Fill a Serializer

View File

@@ -195,7 +195,7 @@ AttestationClaim::message(
std::uint64_t claimID,
std::optional<AccountID> const& dst)
{
STObject o{kSfGeneric};
STObject o{sfGeneric};
// Serialize in SField order to make python serializers easier to write
o[sfXChainClaimID] = claimID;
o[sfAmount] = sendingAmount;
@@ -332,7 +332,7 @@ AttestationCreateAccount::message(
std::uint64_t createCount,
AccountID const& dst)
{
STObject o{kSfGeneric};
STObject o{sfGeneric};
// Serialize in SField order to make python serializers easier to write
o[sfXChainAccountCreateCount] = createCount;
o[sfAmount] = sendingAmount;

View File

@@ -90,7 +90,7 @@ deserializeManifest(Slice s, beast::Journal journal)
try
{
SerialIter sit{s};
STObject st{sit, kSfGeneric};
STObject st{sit, sfGeneric};
st.applyTemplate(kManifestFormat);
@@ -193,7 +193,7 @@ logMftAct(
bool
Manifest::verify() const
{
STObject st(kSfGeneric);
STObject st(sfGeneric);
SerialIter sit(serialized.data(), serialized.size());
st.set(sit);
@@ -213,7 +213,7 @@ Manifest::verify() const
uint256
Manifest::hash() const
{
STObject st(kSfGeneric);
STObject st(sfGeneric);
SerialIter sit(serialized.data(), serialized.size());
st.set(sit);
return st.getHash(HashPrefix::Manifest);
@@ -240,7 +240,7 @@ Manifest::revoked(std::uint32_t sequence)
std::optional<Blob>
Manifest::getSignature() const
{
STObject st(kSfGeneric);
STObject st(sfGeneric);
SerialIter sit(serialized.data(), serialized.size());
st.set(sit);
if (!get(st, sfSignature))
@@ -251,7 +251,7 @@ Manifest::getSignature() const
Blob
Manifest::getMasterSignature() const
{
STObject st(kSfGeneric);
STObject st(sfGeneric);
SerialIter sit(serialized.data(), serialized.size());
st.set(sit);
return st.getFieldVL(sfMasterSignature);

View File

@@ -28,6 +28,7 @@
#include <xrpl/basics/strHex.h>
#include <xrpl/beast/unit_test/suite.h>
#include <xrpl/json/json_value.h>
#include <xrpl/json/to_string.h>
#include <xrpl/ledger/Dir.h>
#include <xrpl/ledger/helpers/DelegateHelpers.h>
#include <xrpl/protocol/Feature.h>
@@ -1879,6 +1880,149 @@ class Delegate_test : public beast::unit_test::Suite
BEAST_EXPECT(env.balance(edward) == edwardBalance);
}
void
testMultiSignDelegatorAsSigner()
{
// checkMultiSign disallows the owner of the account to
// be part of the multisigner list. When it is a delegated transaction,
// the delegate account should not be part of the multisigner list.
testcase("test delegator as multisigner in delegate's signer list");
using namespace jtx;
Env env(*this);
Account const alice{"alice"};
Account const bob{"bob"};
Account const carol{"carol"};
Account const daria{"daria"};
env.fund(XRP(100000), alice, bob, carol, daria);
env.close();
env(delegate::set(alice, bob, {"Payment"}));
env.close();
// bob's signer list includes the delegator alice and daria
env(signers(bob, 2, {{alice, 1}, {daria, 1}}));
env.close();
auto aliceBalance = env.balance(alice);
auto bobBalance = env.balance(bob);
auto carolBalance = env.balance(carol);
auto const amt = 100;
// alice can sign as a multisigner for bob
env(pay(alice, carol, XRP(100)), Fee(XRP(10)), delegate::As(bob), Msig(alice, daria));
env.close();
BEAST_EXPECT(env.balance(alice) == aliceBalance - XRP(amt));
BEAST_EXPECT(env.balance(bob) == bobBalance - XRP(10));
BEAST_EXPECT(env.balance(carol) == carolBalance + XRP(amt));
// alice can not sign as a multisigner if she sent the transaction by herself.
env(pay(alice, carol, XRP(100)), Fee(XRP(10)), Msig(alice, daria), Ter(telENV_RPC_FAILED));
env.close();
// Get new balances
aliceBalance = env.balance(alice);
bobBalance = env.balance(bob);
carolBalance = env.balance(carol);
// bob (the delegate) should not appear as a multisigner in his transaction sent on behalf
// of alice. STTx::checkMultiSign catches this at the local-check stage, so the jtx
// framework returns telENV_RPC_FAILED.
env(pay(alice, carol, XRP(50)),
Fee(XRP(10)),
delegate::As(bob),
Msig(alice, bob),
Ter(telENV_RPC_FAILED));
env.close();
BEAST_EXPECT(env.balance(alice) == aliceBalance);
BEAST_EXPECT(env.balance(bob) == bobBalance);
BEAST_EXPECT(env.balance(carol) == carolBalance);
}
void
testSignForDelegated()
{
// In sortAndValidateSigners, if it is a delegated transaction, the delegate account is
// the forbidden account from appearing in its own Signers array.
testcase("test sign_for with delegated transaction");
using namespace jtx;
Env env(*this);
Account const alice{"alice"};
Account const bob{"bob"};
Account const carol{"carol"};
Account const daria{"daria"};
env.fund(XRP(100000), alice, bob, carol, daria);
env.close();
env(delegate::set(alice, bob, {"Payment"}));
env.close();
// bob's signer list includes the delegator alice and daria
env(signers(bob, 2, {{alice, 1}, {daria, 1}}));
env.close();
auto const baseFee = env.current()->fees().base;
auto const sendAmt = 1'000'000;
auto makeDelegateTx = [&]() -> json::Value {
json::Value jv;
jv[jss::tx_json][jss::Account] = alice.human();
jv[jss::tx_json][sfDelegate.jsonName] = bob.human();
jv[jss::tx_json][jss::TransactionType] = jss::Payment;
jv[jss::tx_json][jss::Destination] = carol.human();
jv[jss::tx_json][jss::Amount] = sendAmt;
jv[jss::tx_json][jss::Fee] = std::to_string((10 * baseFee).drops());
jv[jss::tx_json][jss::Sequence] = env.seq(alice);
jv[jss::tx_json][jss::SigningPubKey] = "";
return jv;
};
// The delegator alice and daria both sign via sign_for, which is valid
{
auto const aliceBalance = env.balance(alice);
auto const bobBalance = env.balance(bob);
auto const dariaBalance = env.balance(daria);
auto const carolBalance = env.balance(carol);
json::Value jv = makeDelegateTx();
jv[jss::account] = alice.human();
jv[jss::secret] = alice.name();
auto jrr = env.rpc("json", "sign_for", to_string(jv))[jss::result];
BEAST_EXPECT(jrr[jss::status] == "success");
json::Value jv2;
jv2[jss::tx_json] = jrr[jss::tx_json];
jv2[jss::account] = daria.human();
jv2[jss::secret] = daria.name();
jrr = env.rpc("json", "sign_for", to_string(jv2))[jss::result];
BEAST_EXPECT(jrr[jss::status] == "success");
json::Value jvSubmit;
jvSubmit[jss::tx_json] = jrr[jss::tx_json];
jrr = env.rpc("json", "submit_multisigned", to_string(jvSubmit))[jss::result];
BEAST_EXPECT(jrr[jss::status] == "success");
env.close();
BEAST_EXPECT(env.balance(alice) == aliceBalance - XRPAmount(sendAmt));
BEAST_EXPECT(env.balance(bob) == bobBalance - (10 * baseFee));
BEAST_EXPECT(env.balance(daria) == dariaBalance);
BEAST_EXPECT(env.balance(carol) == carolBalance + XRPAmount(sendAmt));
}
// The delegated account bob attempts sign_for, will be rejected.
{
json::Value jv = makeDelegateTx();
jv[jss::account] = bob.human();
jv[jss::secret] = bob.name();
auto jrr = env.rpc("json", "sign_for", to_string(jv))[jss::result];
BEAST_EXPECT(jrr[jss::status] == "error");
BEAST_EXPECT(
jrr[jss::error_message].asString().find(
"A Signer may not be the transaction's Account") != std::string::npos);
}
}
void
testPermissionValue(FeatureBitset features)
{
@@ -2086,6 +2230,8 @@ class Delegate_test : public beast::unit_test::Suite
testSingleSignBadSecret();
testMultiSign();
testMultiSignQuorumNotMet();
testMultiSignDelegatorAsSigner();
testSignForDelegated();
testPermissionValue(all);
testTxRequireFeatures(all);
testTxDelegableCount();

View File

@@ -115,7 +115,7 @@ public:
SecretKey const& ssk,
int seq)
{
STObject st(kSfGeneric);
STObject st(sfGeneric);
st[sfSequence] = seq;
st[sfPublicKey] = pk;
st[sfSigningPubKey] = spk;
@@ -137,7 +137,7 @@ public:
{
auto const pk = derivePublicKey(type, sk);
STObject st(kSfGeneric);
STObject st(sfGeneric);
st[sfSequence] = std::numeric_limits<std::uint32_t>::max();
st[sfPublicKey] = pk;
@@ -156,7 +156,7 @@ public:
{
auto const pk = derivePublicKey(type, sk);
STObject st(kSfGeneric);
STObject st(sfGeneric);
st[sfSequence] = std::numeric_limits<std::uint32_t>::max();
st[sfPublicKey] = pk;
@@ -186,7 +186,7 @@ public:
auto const pk = derivePublicKey(type, sk);
auto const spk = derivePublicKey(stype, ssk);
STObject st(kSfGeneric);
STObject st(sfGeneric);
st[sfSequence] = seq;
st[sfPublicKey] = pk;
st[sfSigningPubKey] = spk;
@@ -363,7 +363,7 @@ public:
auto const kp = randomKeyPair(KeyType::Secp256k1);
auto const m = makeManifest(sk, KeyType::Ed25519, kp.second, KeyType::Secp256k1, 0);
STObject st(kSfGeneric);
STObject st(sfGeneric);
st[sfSequence] = 0;
st[sfPublicKey] = pk;
st[sfSigningPubKey] = kp.first;
@@ -495,7 +495,7 @@ public:
auto const spk = derivePublicKey(KeyType::Secp256k1, ssk);
auto buildManifestObject = [&](std::uint16_t version) {
STObject st(kSfGeneric);
STObject st(sfGeneric);
st[sfSequence] = 3;
st[sfPublicKey] = pk;
st[sfSigningPubKey] = spk;
@@ -573,7 +573,7 @@ public:
std::optional<std::string> domain,
bool noSigningPublic = false,
bool noSignature = false) {
STObject st(kSfGeneric);
STObject st(sfGeneric);
st[sfSequence] = seq;
st[sfPublicKey] = pk;
@@ -724,7 +724,7 @@ public:
}
{
// reject matching master & ephemeral keys
STObject st(kSfGeneric);
STObject st(sfGeneric);
st[sfSequence] = 314159;
st[sfPublicKey] = pk;
st[sfSigningPubKey] = pk;
@@ -797,7 +797,7 @@ public:
auto const pk2 = derivePublicKey(KeyType::Secp256k1, sk2);
auto test = [&](std::string domain) {
STObject st(kSfGeneric);
STObject st(sfGeneric);
st[sfSequence] = 7;
st[sfPublicKey] = pk1;
st[sfDomain] = makeSlice(domain);

View File

@@ -216,7 +216,7 @@ public:
STAmount da;
if (result.isMember(jss::destination_amount))
da = amountFromJson(kSfGeneric, result[jss::destination_amount]);
da = amountFromJson(sfGeneric, result[jss::destination_amount]);
STAmount sa;
STPathSet paths;
@@ -228,10 +228,10 @@ public:
auto const& path = alts[0u];
if (path.isMember(jss::source_amount))
sa = amountFromJson(kSfGeneric, path[jss::source_amount]);
sa = amountFromJson(sfGeneric, path[jss::source_amount]);
if (path.isMember(jss::destination_amount))
da = amountFromJson(kSfGeneric, path[jss::destination_amount]);
da = amountFromJson(sfGeneric, path[jss::destination_amount]);
if (path.isMember(jss::paths_computed))
{

View File

@@ -81,7 +81,7 @@ private:
SecretKey const& ssk,
int seq)
{
STObject st(kSfGeneric);
STObject st(sfGeneric);
st[sfSequence] = seq;
st[sfPublicKey] = pk;
@@ -104,7 +104,7 @@ private:
static std::string
makeRevocationString(PublicKey const& pk, SecretKey const& sk)
{
STObject st(kSfGeneric);
STObject st(sfGeneric);
st[sfSequence] = std::numeric_limits<std::uint32_t>::max();
st[sfPublicKey] = pk;

View File

@@ -101,7 +101,7 @@ public:
SecretKey const& ssk,
int seq)
{
STObject st(kSfGeneric);
STObject st(sfGeneric);
st[sfSequence] = seq;
st[sfPublicKey] = pk;
st[sfSigningPubKey] = spk;

View File

@@ -262,7 +262,7 @@ findPaths(
STAmount da;
if (result.isMember(jss::destination_amount))
da = amountFromJson(kSfGeneric, result[jss::destination_amount]);
da = amountFromJson(sfGeneric, result[jss::destination_amount]);
STAmount sa;
STPathSet paths;
@@ -274,10 +274,10 @@ findPaths(
auto const& path = alts[0u];
if (path.isMember(jss::source_amount))
sa = amountFromJson(kSfGeneric, path[jss::source_amount]);
sa = amountFromJson(sfGeneric, path[jss::source_amount]);
if (path.isMember(jss::destination_amount))
da = amountFromJson(kSfGeneric, path[jss::destination_amount]);
da = amountFromJson(sfGeneric, path[jss::destination_amount]);
if (path.isMember(jss::paths_computed))
{

View File

@@ -142,7 +142,7 @@ public:
{
auto master = randomKeyPair(KeyType::Ed25519);
auto signing = randomKeyPair(KeyType::Ed25519);
STObject st(kSfGeneric);
STObject st(sfGeneric);
st[sfSequence] = i;
st[sfPublicKey] = std::get<0>(master);
st[sfSigningPubKey] = std::get<0>(signing);
@@ -299,7 +299,7 @@ public:
auto master = randomKeyPair(KeyType::Ed25519);
auto signing = randomKeyPair(KeyType::Ed25519);
STObject st(kSfGeneric);
STObject st(sfGeneric);
st[sfSequence] = 0;
st[sfPublicKey] = std::get<0>(master);
st[sfSigningPubKey] = std::get<0>(signing);
@@ -326,7 +326,7 @@ public:
auto master = randomKeyPair(KeyType::Ed25519);
auto signing = randomKeyPair(KeyType::Ed25519);
STObject st(kSfGeneric);
STObject st(sfGeneric);
st[sfSequence] = 0;
st[sfPublicKey] = std::get<0>(master);
st[sfSigningPubKey] = std::get<0>(signing);

View File

@@ -73,7 +73,7 @@ class Hooks_test : public beast::unit_test::Suite
{
SField const& f = rf.get();
STObject dummy{kSfGeneric};
STObject dummy{sfGeneric};
BEAST_EXPECT(!dummy.isFieldPresent(f));
@@ -161,8 +161,8 @@ class Hooks_test : public beast::unit_test::Suite
case STI_ARRAY: {
STArray dummy2{f, 2};
dummy2.pushBack(STObject{kSfGeneric});
dummy2.pushBack(STObject{kSfGeneric});
dummy2.pushBack(STObject{sfGeneric});
dummy2.pushBack(STObject{sfGeneric});
dummy.setFieldArray(f, dummy2);
BEAST_EXPECT(dummy.getFieldArray(f) == dummy2);
BEAST_EXPECT(dummy.isFieldPresent(f));

View File

@@ -37,7 +37,7 @@ public:
s.add(ser);
SerialIter sit(ser.slice());
return STAmount(sit, kSfGeneric);
return STAmount(sit, sfGeneric);
}
//--------------------------------------------------------------------------

View File

@@ -36,19 +36,19 @@ public:
{
testcase("serialization");
unexpected(kSfGeneric.isUseful(), "sfGeneric must not be useful");
unexpected(sfGeneric.isUseful(), "sfGeneric must not be useful");
{
// Try to put sfGeneric in an SOTemplate.
except<std::runtime_error>(
[&]() { SOTemplate const elements{{kSfGeneric, SoeRequired}}; });
[&]() { SOTemplate const elements{{sfGeneric, SoeRequired}}; });
}
unexpected(kSfInvalid.isUseful(), "sfInvalid must not be useful");
unexpected(sfInvalid.isUseful(), "sfInvalid must not be useful");
{
// Test return of sfInvalid.
auto testInvalid = [this](SerializedTypeID tid, int fv) {
SField const& shouldBeInvalid{SField::getField(tid, fv)};
BEAST_EXPECT(shouldBeInvalid == kSfInvalid);
BEAST_EXPECT(shouldBeInvalid == sfInvalid);
};
testInvalid(STI_VL, 255);
testInvalid(STI_UINT256, 255);
@@ -59,7 +59,7 @@ public:
{
// Try to put sfInvalid in an SOTemplate.
except<std::runtime_error>(
[&]() { SOTemplate const elements{{kSfInvalid, SoeRequired}}; });
[&]() { SOTemplate const elements{{sfInvalid, SoeRequired}}; });
}
{
// Try to put the same SField into an SOTemplate twice.
@@ -188,7 +188,7 @@ public:
{
auto const st = [&]() {
STObject s(kSfGeneric);
STObject s(sfGeneric);
s.setFieldU32(sf1Outer, 1);
s.setFieldU32(sf2Outer, 2);
return s;
@@ -219,7 +219,7 @@ public:
{
auto const st = [&]() {
STObject s(sotOuter, kSfGeneric);
STObject s(sotOuter, sfGeneric);
s.setFieldU32(sf1Outer, 1);
s.setFieldU32(sf2Outer, 2);
return s;
@@ -239,7 +239,7 @@ public:
// write free object
{
STObject st(kSfGeneric);
STObject st(sfGeneric);
unexcept([&]() { st[sf1Outer]; });
except([&]() { return st[sf1Outer] == 0; });
BEAST_EXPECT(st[~sf1Outer] == std::nullopt);
@@ -295,7 +295,7 @@ public:
// Write templated object
{
STObject st(sotOuter, kSfGeneric);
STObject st(sotOuter, sfGeneric);
BEAST_EXPECT(!!st[~sf1Outer]);
BEAST_EXPECT(st[~sf1Outer] != std::nullopt);
BEAST_EXPECT(st[sf1Outer] == 0);
@@ -353,7 +353,7 @@ public:
// coercion operator to std::optional
{
STObject st(kSfGeneric);
STObject st(sfGeneric);
auto const v = ~st[~sf1Outer];
static_assert(
std::is_same_v<std::decay_t<decltype(v)>, std::optional<std::uint32_t>>, "");
@@ -362,7 +362,7 @@ public:
// UDT scalar fields
{
STObject st(kSfGeneric);
STObject st(sfGeneric);
st[sfAmount] = STAmount{};
st[sfAccount] = AccountID{};
st[sfDigest] = uint256{};
@@ -375,7 +375,7 @@ public:
{
{
STObject st(kSfGeneric);
STObject st(sfGeneric);
Buffer b(1);
BEAST_EXPECT(!b.empty());
st[sf4] = std::move(b);
@@ -392,7 +392,7 @@ public:
BEAST_EXPECT(Slice(st[sf5]).size() == 2);
}
{
STObject st(sotOuter, kSfGeneric);
STObject st(sotOuter, sfGeneric);
BEAST_EXPECT(st[sf5] == Slice{});
BEAST_EXPECT(!!st[~sf5]);
BEAST_EXPECT(!!~st[~sf5]);
@@ -408,7 +408,7 @@ public:
// UDT blobs
{
STObject st(kSfGeneric);
STObject st(sfGeneric);
BEAST_EXPECT(!st[~sf5]);
auto const kp = generateKeyPair(KeyType::Secp256k1, generateSeed("masterpassphrase"));
st[sf5] = kp.first;
@@ -419,7 +419,7 @@ public:
{
auto const& sf = sfIndexes;
STObject st(kSfGeneric);
STObject st(sfGeneric);
std::vector<uint256> v;
v.emplace_back(1);
v.emplace_back(2);
@@ -446,7 +446,7 @@ public:
{sf3, SoeDefault},
};
STObject st(sot, kSfGeneric);
STObject st(sot, sfGeneric);
auto const& cst(st);
BEAST_EXPECT(cst[sf1].empty());
BEAST_EXPECT(!cst[~sf2]);

View File

@@ -1390,7 +1390,7 @@ public:
// Lambda that returns a Payment STObject.
auto getPayment = [kp1, id1, id2]() {
// Account id1 pays account id2 10,000 XRP.
STObject payment(kSfGeneric);
STObject payment(sfGeneric);
payment.setFieldU16(sfTransactionType, ttPAYMENT);
payment.setAccountID(sfAccount, id1);
payment.setAccountID(sfDestination, id2);

View File

@@ -66,7 +66,7 @@ class Simulate_test : public beast::unit_test::Suite
{
auto const unHexed = strUnHex(result[jss::tx_blob].asString());
SerialIter sitTrans(makeSlice(*unHexed)); // NOLINT(bugprone-unchecked-optional-access)
txJson = STObject(std::ref(sitTrans), kSfGeneric).getJson(JsonOptions::Values::None);
txJson = STObject(std::ref(sitTrans), sfGeneric).getJson(JsonOptions::Values::None);
}
BEAST_EXPECT(txJson[jss::TransactionType] == tx[jss::TransactionType]);
BEAST_EXPECT(txJson[jss::Account] == tx[jss::Account]);
@@ -162,7 +162,7 @@ class Simulate_test : public beast::unit_test::Suite
{
auto unHexed = strUnHex(txResult[jss::meta_blob].asString());
SerialIter sitTrans(makeSlice(*unHexed)); // NOLINT(bugprone-unchecked-optional-access)
return STObject(std::ref(sitTrans), kSfGeneric).getJson(JsonOptions::Values::None);
return STObject(std::ref(sitTrans), sfGeneric).getJson(JsonOptions::Values::None);
}
return txResult[jss::meta];

View File

@@ -159,7 +159,7 @@ canonical_ARRAY()
inline STObject
canonical_OBJECT()
{
return STObject{kSfGeneric};
return STObject{sfGeneric};
}
inline STPathSet

View File

@@ -1255,7 +1255,9 @@ transactionSignFor(
signers.emplaceBack(std::move(signer));
// The array must be sorted and validated.
auto err = sortAndValidateSigners(signers, (*sttx)[sfAccount]);
// For delegated transactions, the delegate account is
// the one forbidden from appearing in its own Signers array.
auto err = sortAndValidateSigners(signers, sttx->getFeePayer());
if (RPC::containsError(err))
return err;
}
@@ -1422,7 +1424,9 @@ transactionSubmitMultiSigned(
}
// The array must be sorted and validated.
auto err = sortAndValidateSigners(signers, srcAddressID);
// For delegated transactions, getFeePayer() returns sfDelegate,
// that account is the one forbidden from appearing in its own Signers array.
auto err = sortAndValidateSigners(signers, stTx->getFeePayer());
if (RPC::containsError(err))
return err;

View File

@@ -194,7 +194,7 @@ getTxJsonFromParams(json::Value const& params)
try
{
SerialIter sitTrans(makeSlice(*unHexed));
txJson = STObject(std::ref(sitTrans), kSfGeneric).getJson(JsonOptions::Values::None);
txJson = STObject(std::ref(sitTrans), sfGeneric).getJson(JsonOptions::Values::None);
}
catch (std::runtime_error const&)
{