diff --git a/include/xrpl/protocol/STObject.h b/include/xrpl/protocol/STObject.h index e65cc79c78..044e48ce62 100644 --- a/include/xrpl/protocol/STObject.h +++ b/include/xrpl/protocol/STObject.h @@ -217,6 +217,11 @@ public: [[nodiscard]] AccountID getAccountID(SField const& field) const; + /** The account responsible for the fee and authorization: the delegate when + sfDelegate is present, otherwise the account. */ + [[nodiscard]] AccountID + getFeePayer() const; + [[nodiscard]] Blob getFieldVL(SField const& field) const; [[nodiscard]] STAmount const& diff --git a/include/xrpl/protocol/STTx.h b/include/xrpl/protocol/STTx.h index 95f31cc711..e78fce27a1 100644 --- a/include/xrpl/protocol/STTx.h +++ b/include/xrpl/protocol/STTx.h @@ -84,9 +84,6 @@ public: [[nodiscard]] std::uint32_t getSeqValue() const; - [[nodiscard]] AccountID - getFeePayer() const; - [[nodiscard]] boost::container::flat_set getMentionedAccounts() const; diff --git a/include/xrpl/tx/transactors/system/Batch.h b/include/xrpl/tx/transactors/system/Batch.h index 85d28ab341..927a5b27cd 100644 --- a/include/xrpl/tx/transactors/system/Batch.h +++ b/include/xrpl/tx/transactors/system/Batch.h @@ -25,9 +25,6 @@ public: static NotTEC preflightSigValidated(PreflightContext const& ctx); - static NotTEC - checkBatchSign(PreclaimContext const& ctx); - static NotTEC checkSign(PreclaimContext const& ctx); @@ -62,6 +59,12 @@ public: ttLOAN_MANAGE, ttLOAN_PAY, }); + +private: + // Skips signature verification for inner txns, so keep it private: it must + // only be reached through Batch::checkSign. + static NotTEC + checkBatchSign(PreclaimContext const& ctx); }; } // namespace xrpl diff --git a/src/libxrpl/protocol/STObject.cpp b/src/libxrpl/protocol/STObject.cpp index e16cbc871f..445da16828 100644 --- a/src/libxrpl/protocol/STObject.cpp +++ b/src/libxrpl/protocol/STObject.cpp @@ -635,6 +635,20 @@ STObject::getAccountID(SField const& field) const return getFieldByValue(field); } +AccountID +STObject::getFeePayer() const +{ + // If sfDelegate is present, the delegate account is the payer + // note: if a delegate is specified, its authorization to act on behalf of the account is + // enforced in `Transactor::invokeCheckPermission` + // cryptographic signature validity is checked separately (e.g., in `Transactor::checkSign`) + if (isFieldPresent(sfDelegate)) + return getAccountID(sfDelegate); + + // Default payer + return getAccountID(sfAccount); +} + Blob STObject::getFieldVL(SField const& field) const { diff --git a/src/libxrpl/protocol/STTx.cpp b/src/libxrpl/protocol/STTx.cpp index f7b89942ef..cd2da12316 100644 --- a/src/libxrpl/protocol/STTx.cpp +++ b/src/libxrpl/protocol/STTx.cpp @@ -214,20 +214,6 @@ STTx::getSeqValue() const return getSeqProxy().value(); } -AccountID -STTx::getFeePayer() const -{ - // If sfDelegate is present, the delegate account is the payer - // note: if a delegate is specified, its authorization to act on behalf of the account is - // enforced in `Transactor::invokeCheckPermission` - // cryptographic signature validity is checked separately (e.g., in `Transactor::checkSign`) - if (isFieldPresent(sfDelegate)) - return getAccountID(sfDelegate); - - // Default payer - return getAccountID(sfAccount); -} - void STTx::sign( PublicKey const& publicKey, diff --git a/src/libxrpl/tx/transactors/system/Batch.cpp b/src/libxrpl/tx/transactors/system/Batch.cpp index e1cd323766..16d27f98d9 100644 --- a/src/libxrpl/tx/transactors/system/Batch.cpp +++ b/src/libxrpl/tx/transactors/system/Batch.cpp @@ -421,7 +421,7 @@ Batch::preflightSigValidated(PreflightContext const& ctx) { // A delegated inner is signed by the delegate, not the account holder, // so the delegate is the required signer when present. - AccountID const authorizer = rb[~sfDelegate].value_or(rb[sfAccount]); + AccountID const authorizer = rb.getFeePayer(); // The outer account signs the batch itself, so it is never added to the // required signers.