mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Refactor 4: Transactor extra signing support
This commit is contained in:
committed by
Bronek Kozicki
parent
4fe3ec8a08
commit
fb5d94bbef
@@ -149,8 +149,8 @@ public:
|
|||||||
sMD_ChangeNew = 0x02, // new value when it changes
|
sMD_ChangeNew = 0x02, // new value when it changes
|
||||||
sMD_DeleteFinal = 0x04, // final value when it is deleted
|
sMD_DeleteFinal = 0x04, // final value when it is deleted
|
||||||
sMD_Create = 0x08, // value when it's created
|
sMD_Create = 0x08, // value when it's created
|
||||||
sMD_Always = 0x10, // value when node containing it is affected at all
|
sMD_Always = 0x10, // value when node containing it is affected at all
|
||||||
sMD_BaseTen = 0x20, // value is treated as base 10, overriding behavior
|
sMD_BaseTen = 0x20, // value is treated as base 10, overriding behavior
|
||||||
sMD_PseudoAccount = 0x40, // if this field is set in an ACCOUNT_ROOT
|
sMD_PseudoAccount = 0x40, // if this field is set in an ACCOUNT_ROOT
|
||||||
// _only_, then it is a pseudo-account
|
// _only_, then it is a pseudo-account
|
||||||
sMD_Default =
|
sMD_Default =
|
||||||
|
|||||||
@@ -74,6 +74,10 @@ public:
|
|||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
/** Create an amount from an account ID. Should only be used when the secret
|
||||||
|
* key is unavailable, such as for pseudo-accounts. */
|
||||||
|
explicit Account(std::string name, AccountID const& id);
|
||||||
|
|
||||||
enum AcctStringType { base58Seed, other };
|
enum AcctStringType { base58Seed, other };
|
||||||
/** Create an account from a base58 seed string. Throws on invalid seed. */
|
/** Create an account from a base58 seed string. Throws on invalid seed. */
|
||||||
Account(AcctStringType stringType, std::string base58SeedStr);
|
Account(AcctStringType stringType, std::string base58SeedStr);
|
||||||
|
|||||||
@@ -86,6 +86,14 @@ Account::Account(AcctStringType stringType, std::string base58SeedStr)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Account::Account(std::string name, AccountID const& id)
|
||||||
|
: Account(name, randomKeyPair(KeyType::secp256k1), privateCtorTag{})
|
||||||
|
{
|
||||||
|
// override the randomly generated values
|
||||||
|
id_ = id;
|
||||||
|
human_ = toBase58(id_);
|
||||||
|
}
|
||||||
|
|
||||||
IOU
|
IOU
|
||||||
Account::operator[](std::string const& s) const
|
Account::operator[](std::string const& s) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -160,26 +160,28 @@ preflight1(PreflightContext const& ctx, std::uint32_t flagMask)
|
|||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Checks whether the signature appears valid */
|
std::optional<NotTEC>
|
||||||
NotTEC
|
preflightCheckSimulateKeys(
|
||||||
preflight2(PreflightContext const& ctx)
|
ApplyFlags flags,
|
||||||
|
STObject const& sigObject,
|
||||||
|
beast::Journal j)
|
||||||
{
|
{
|
||||||
if (ctx.flags & tapDRY_RUN) // simulation
|
if (flags & tapDRY_RUN) // simulation
|
||||||
{
|
{
|
||||||
if (!ctx.tx.getSignature().empty())
|
if (!sigObject.getFieldVL(sfTxnSignature).empty())
|
||||||
{
|
{
|
||||||
// NOTE: This code should never be hit because it's checked in the
|
// NOTE: This code should never be hit because it's checked in the
|
||||||
// `simulate` RPC
|
// `simulate` RPC
|
||||||
return temINVALID; // LCOV_EXCL_LINE
|
return temINVALID; // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctx.tx.isFieldPresent(sfSigners))
|
if (!sigObject.isFieldPresent(sfSigners))
|
||||||
{
|
{
|
||||||
// no signers, no signature - a valid simulation
|
// no signers, no signature - a valid simulation
|
||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const& signer : ctx.tx.getFieldArray(sfSigners))
|
for (auto const& signer : sigObject.getFieldArray(sfSigners))
|
||||||
{
|
{
|
||||||
if (signer.isFieldPresent(sfTxnSignature) &&
|
if (signer.isFieldPresent(sfTxnSignature) &&
|
||||||
!signer[sfTxnSignature].empty())
|
!signer[sfTxnSignature].empty())
|
||||||
@@ -191,6 +193,17 @@ preflight2(PreflightContext const& ctx)
|
|||||||
}
|
}
|
||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks whether the signature appears valid */
|
||||||
|
NotTEC
|
||||||
|
preflight2(PreflightContext const& ctx)
|
||||||
|
{
|
||||||
|
if (auto const ret = preflightCheckSimulateKeys(ctx.flags, ctx.tx, ctx.j))
|
||||||
|
// Skips following checks if the transaction is being simulated,
|
||||||
|
// regardless of success or failure
|
||||||
|
return *ret;
|
||||||
|
|
||||||
auto const sigValid = checkValidity(
|
auto const sigValid = checkValidity(
|
||||||
ctx.app.getHashRouter(), ctx.tx, ctx.rules, ctx.app.config());
|
ctx.app.getHashRouter(), ctx.tx, ctx.rules, ctx.app.config());
|
||||||
@@ -609,28 +622,44 @@ Transactor::apply()
|
|||||||
}
|
}
|
||||||
|
|
||||||
NotTEC
|
NotTEC
|
||||||
Transactor::checkSign(PreclaimContext const& ctx)
|
Transactor::checkSign(
|
||||||
|
PreclaimContext const& ctx,
|
||||||
|
AccountID const& id,
|
||||||
|
STObject const& sigObject)
|
||||||
{
|
{
|
||||||
if (ctx.flags & tapDRY_RUN)
|
if (ctx.flags & tapDRY_RUN)
|
||||||
{
|
{
|
||||||
// This code must be different for `simulate`
|
// This code must be different for `simulate`
|
||||||
// Since the public key may be empty even for single signing
|
// Since the public key may be empty even for single signing
|
||||||
if (ctx.tx.isFieldPresent(sfSigners))
|
if (sigObject.isFieldPresent(sfSigners))
|
||||||
return checkMultiSign(ctx);
|
return checkMultiSign(ctx, id, sigObject);
|
||||||
return checkSingleSign(ctx);
|
return checkSingleSign(ctx, id, sigObject);
|
||||||
}
|
}
|
||||||
// If the pk is empty, then we must be multi-signing.
|
// If the pk is empty, then we must be multi-signing.
|
||||||
if (ctx.tx.getSigningPubKey().empty())
|
if (sigObject.getFieldVL(sfSigningPubKey).empty())
|
||||||
return checkMultiSign(ctx);
|
return checkMultiSign(ctx, id, sigObject);
|
||||||
|
|
||||||
return checkSingleSign(ctx);
|
return checkSingleSign(ctx, id, sigObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
NotTEC
|
NotTEC
|
||||||
Transactor::checkSingleSign(PreclaimContext const& ctx)
|
Transactor::checkSign(PreclaimContext const& ctx)
|
||||||
|
{
|
||||||
|
auto const idAccount = ctx.tx.isFieldPresent(sfDelegate)
|
||||||
|
? ctx.tx.getAccountID(sfDelegate)
|
||||||
|
: ctx.tx.getAccountID(sfAccount);
|
||||||
|
return checkSign(ctx, idAccount, ctx.tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO generalize
|
||||||
|
NotTEC
|
||||||
|
Transactor::checkSingleSign(
|
||||||
|
PreclaimContext const& ctx,
|
||||||
|
AccountID const& idAccount,
|
||||||
|
STObject const& sigObject)
|
||||||
{
|
{
|
||||||
// Check that the value in the signing key slot is a public key.
|
// Check that the value in the signing key slot is a public key.
|
||||||
auto const pkSigner = ctx.tx.getSigningPubKey();
|
auto const pkSigner = sigObject.getFieldVL(sfSigningPubKey);
|
||||||
if (!(ctx.flags & tapDRY_RUN) && !publicKeyType(makeSlice(pkSigner)))
|
if (!(ctx.flags & tapDRY_RUN) && !publicKeyType(makeSlice(pkSigner)))
|
||||||
{
|
{
|
||||||
JLOG(ctx.j.trace())
|
JLOG(ctx.j.trace())
|
||||||
@@ -639,9 +668,6 @@ Transactor::checkSingleSign(PreclaimContext const& ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Look up the account.
|
// Look up the account.
|
||||||
auto const idAccount = ctx.tx.isFieldPresent(sfDelegate)
|
|
||||||
? ctx.tx.getAccountID(sfDelegate)
|
|
||||||
: ctx.tx.getAccountID(sfAccount);
|
|
||||||
auto const sleAccount = ctx.view.read(keylet::account(idAccount));
|
auto const sleAccount = ctx.view.read(keylet::account(idAccount));
|
||||||
if (!sleAccount)
|
if (!sleAccount)
|
||||||
return terNO_ACCOUNT;
|
return terNO_ACCOUNT;
|
||||||
@@ -708,13 +734,14 @@ Transactor::checkSingleSign(PreclaimContext const& ctx)
|
|||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO generalize
|
||||||
NotTEC
|
NotTEC
|
||||||
Transactor::checkMultiSign(PreclaimContext const& ctx)
|
Transactor::checkMultiSign(
|
||||||
|
PreclaimContext const& ctx,
|
||||||
|
AccountID const& id,
|
||||||
|
STObject const& sigObject)
|
||||||
{
|
{
|
||||||
auto const id = ctx.tx.isFieldPresent(sfDelegate)
|
// Get id's SignerList and Quorum.
|
||||||
? ctx.tx.getAccountID(sfDelegate)
|
|
||||||
: ctx.tx.getAccountID(sfAccount);
|
|
||||||
// Get mTxnAccountID's SignerList and Quorum.
|
|
||||||
std::shared_ptr<STLedgerEntry const> sleAccountSigners =
|
std::shared_ptr<STLedgerEntry const> sleAccountSigners =
|
||||||
ctx.view.read(keylet::signers(id));
|
ctx.view.read(keylet::signers(id));
|
||||||
// If the signer list doesn't exist the account is not multi-signing.
|
// If the signer list doesn't exist the account is not multi-signing.
|
||||||
@@ -740,7 +767,7 @@ Transactor::checkMultiSign(PreclaimContext const& ctx)
|
|||||||
return accountSigners.error();
|
return accountSigners.error();
|
||||||
|
|
||||||
// Get the array of transaction signers.
|
// Get the array of transaction signers.
|
||||||
STArray const& txSigners(ctx.tx.getFieldArray(sfSigners));
|
STArray const& txSigners(sigObject.getFieldArray(sfSigners));
|
||||||
|
|
||||||
// Walk the accountSigners performing a variety of checks and see if
|
// Walk the accountSigners performing a variety of checks and see if
|
||||||
// the quorum is met.
|
// the quorum is met.
|
||||||
|
|||||||
@@ -217,6 +217,12 @@ protected:
|
|||||||
static XRPAmount
|
static XRPAmount
|
||||||
calculateOwnerReserveFee(ReadView const& view, STTx const& tx);
|
calculateOwnerReserveFee(ReadView const& view, STTx const& tx);
|
||||||
|
|
||||||
|
static NotTEC
|
||||||
|
checkSign(
|
||||||
|
PreclaimContext const& ctx,
|
||||||
|
AccountID const& id,
|
||||||
|
STObject const& sigObject);
|
||||||
|
|
||||||
// Base class always returns true
|
// Base class always returns true
|
||||||
static bool
|
static bool
|
||||||
isEnabled(PreflightContext const& ctx);
|
isEnabled(PreflightContext const& ctx);
|
||||||
@@ -248,9 +254,15 @@ private:
|
|||||||
TER
|
TER
|
||||||
payFee();
|
payFee();
|
||||||
static NotTEC
|
static NotTEC
|
||||||
checkSingleSign(PreclaimContext const& ctx);
|
checkSingleSign(
|
||||||
|
PreclaimContext const& ctx,
|
||||||
|
AccountID const& id,
|
||||||
|
STObject const& sigObject);
|
||||||
static NotTEC
|
static NotTEC
|
||||||
checkMultiSign(PreclaimContext const& ctx);
|
checkMultiSign(
|
||||||
|
PreclaimContext const& ctx,
|
||||||
|
AccountID const& id,
|
||||||
|
STObject const& sigObject);
|
||||||
|
|
||||||
void trapTransaction(uint256) const;
|
void trapTransaction(uint256) const;
|
||||||
};
|
};
|
||||||
@@ -281,6 +293,16 @@ preflightCheckSigningKey(STObject const& sigObject, beast::Journal j);
|
|||||||
NotTEC
|
NotTEC
|
||||||
preflight1(PreflightContext const& ctx, std::uint32_t flagMask);
|
preflight1(PreflightContext const& ctx, std::uint32_t flagMask);
|
||||||
|
|
||||||
|
/** Checks the special signing key state needed for simulation
|
||||||
|
*
|
||||||
|
* Normally called from preflight2 with ctx.tx.
|
||||||
|
*/
|
||||||
|
std::optional<NotTEC>
|
||||||
|
preflightCheckSimulateKeys(
|
||||||
|
ApplyFlags flags,
|
||||||
|
STObject const& sigObject,
|
||||||
|
beast::Journal j);
|
||||||
|
|
||||||
/** Checks whether the signature appears valid */
|
/** Checks whether the signature appears valid */
|
||||||
NotTEC
|
NotTEC
|
||||||
preflight2(PreflightContext const& ctx);
|
preflight2(PreflightContext const& ctx);
|
||||||
|
|||||||
Reference in New Issue
Block a user