Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
SirTyson committed Jul 3, 2024
1 parent ff8ff27 commit 096f5b3
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 70 deletions.
24 changes: 19 additions & 5 deletions src/test/FuzzerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -924,10 +924,24 @@ class FuzzTransactionFrame : public TransactionFrame
ltx.loadHeader().current().ledgerVersion, getContentsHash(),
mEnvelope.v1().signatures};
// if any ill-formed Operations, do not attempt transaction application
auto isInvalidOperation = [&](auto const& op, auto& opResult) {
return !op->checkValid(app, signatureChecker, ltx, false, opResult,
mTxResult->getSorobanData());
};
auto isInvalidOperation =
[&](std::shared_ptr<OperationFrame const> const& op,
auto& opResult) {
std::optional<SorobanNetworkConfig> sorobanCfg{};
if (protocolVersionStartsFrom(
ltx.loadHeader().current().ledgerVersion,
SOROBAN_PROTOCOL_VERSION))
{
sorobanCfg =
app.getLedgerManager().getSorobanNetworkConfig();
}

auto ret = op->checkValid<AbstractLedgerTxn>(
ltx, app.getConfig(), sorobanCfg,
ltx.loadHeader().current(), signatureChecker, false,
opResult, mTxResult->getSorobanData());
return !ret;
};

auto const& ops = getOperations();
for (size_t i = 0; i < ops.size(); ++i)
Expand All @@ -944,7 +958,7 @@ class FuzzTransactionFrame : public TransactionFrame
// while the following method's result is not captured, regardless, for
// protocols < 8, this triggered buggy caching, and potentially may do
// so in the future
loadSourceAccount(ltx, ltx.loadHeader());
loadSourceAccount(ltx, ltx.loadHeader().current());
processSeqNum(ltx);
TransactionMetaFrame tm(2);
applyOperations(signatureChecker, app, ltx, tm, *mTxResult, Hash{});
Expand Down
2 changes: 1 addition & 1 deletion src/transactions/FeeBumpTransactionFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ FeeBumpTransactionFrame::checkValidInternal(

SignatureChecker signatureChecker{header.ledgerVersion, getContentsHash(),
mEnvelope.feeBump().signatures};
if (commonValid(signatureChecker, dbLoader, header, false, *txResult) !=
if (commonValid<T>(signatureChecker, dbLoader, header, false, *txResult) !=
ValidationType::kFullyValid)
{
return txResult;
Expand Down
100 changes: 73 additions & 27 deletions src/transactions/OperationFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ namespace stellar
using namespace std;

static int32_t
getNeededThreshold(LedgerTxnEntry const& account, ThresholdLevel const level)
getNeededThreshold(LedgerEntry const& account, ThresholdLevel const level)
{
auto const& acc = account.current().data.account();
auto const& acc = account.data.account();
switch (level)
{
case ThresholdLevel::LOW:
Expand Down Expand Up @@ -142,8 +142,22 @@ OperationFrame::apply(Application& app, SignatureChecker& signatureChecker,
{
ZoneScoped;
CLOG_TRACE(Tx, "{}", xdrToCerealString(mOperation, "Operation"));
bool applyRes =
checkValid(app, signatureChecker, ltx, true, res, sorobanData);
std::optional<SorobanNetworkConfig> sorobanCfg{};
if (protocolVersionStartsFrom(ltx.loadHeader().current().ledgerVersion,
SOROBAN_PROTOCOL_VERSION))
{
sorobanCfg = app.getLedgerManager().getSorobanNetworkConfig();
}

bool applyRes;
{
LedgerTxn checkValidLtx(ltx);
applyRes = checkValid<AbstractLedgerTxn>(
checkValidLtx, app.getConfig(), sorobanCfg,
checkValidLtx.loadHeader().current(), signatureChecker, true, res,
sorobanData);
}

if (applyRes)
{
if (isSoroban())
Expand Down Expand Up @@ -185,19 +199,19 @@ OperationFrame::isOpSupported(LedgerHeader const&) const
return true;
}

template <class T>
bool
OperationFrame::checkSignature(SignatureChecker& signatureChecker,
AbstractLedgerTxn& ltx, OperationResult& res,
bool forApply) const
OperationFrame::checkSignature(T& dbLoader, LedgerHeader const& header,
SignatureChecker& signatureChecker,
OperationResult& res, bool forApply) const
{
ZoneScoped;
auto header = ltx.loadHeader();
auto sourceAccount = loadSourceAccount(ltx, header);
auto sourceAccount = loadReadOnlySourceAccount(dbLoader, header);
if (sourceAccount)
{
auto neededThreshold =
getNeededThreshold(sourceAccount, getThresholdLevel());
if (!mParentTx.checkSignature(signatureChecker, sourceAccount.current(),
getNeededThreshold(*sourceAccount, getThresholdLevel());
if (!mParentTx.checkSignature(signatureChecker, *sourceAccount,
neededThreshold))
{
res.code(opBAD_AUTH);
Expand Down Expand Up @@ -234,26 +248,28 @@ OperationFrame::getSourceID() const
// called when determining if we should flood
// make sure sig is correct
// verifies that the operation is well formed (operation specific)
template <class T>
bool
OperationFrame::checkValid(Application& app, SignatureChecker& signatureChecker,
AbstractLedgerTxn& ltxOuter, bool forApply,
OperationResult& res,
std::shared_ptr<SorobanTxData> sorobanData) const
OperationFrame::checkValid(
T& dbLoader, Config const& cfg,
std::optional<SorobanNetworkConfig const> const& sorobanCfg,
LedgerHeader const& header, SignatureChecker& signatureChecker,
bool forApply, OperationResult& res,
std::shared_ptr<SorobanTxData> sorobanData) const
{
ZoneScoped;
// Note: ltx is always rolled back so checkValid never modifies the ledger
LedgerTxn ltx(ltxOuter);
if (!isOpSupported(ltx.loadHeader().current()))
if (!isOpSupported(header))
{
res.code(opNOT_SUPPORTED);
return false;
}

auto ledgerVersion = ltx.loadHeader().current().ledgerVersion;
auto ledgerVersion = header.ledgerVersion;
if (!forApply ||
protocolVersionIsBefore(ledgerVersion, ProtocolVersion::V_10))
{
if (!checkSignature(signatureChecker, ltx, res, forApply))
if (!checkSignature<T>(dbLoader, header, signatureChecker, res,
forApply))
{
return false;
}
Expand All @@ -262,7 +278,7 @@ OperationFrame::checkValid(Application& app, SignatureChecker& signatureChecker,
{
// for ledger versions >= 10 we need to load account here, as for
// previous versions it is done in checkSignature call
if (!loadSourceAccount(ltx, ltx.loadHeader()))
if (!loadReadOnlySourceAccount(dbLoader, header))
{
res.code(opNO_ACCOUNT);
return false;
Expand All @@ -275,18 +291,31 @@ OperationFrame::checkValid(Application& app, SignatureChecker& signatureChecker,
isSoroban())
{
releaseAssertOrThrow(sorobanData);
auto const& sorobanConfig =
app.getLedgerManager().getSorobanNetworkConfig();

return doCheckValidForSoroban(sorobanConfig, app.getConfig(),
ledgerVersion, res, *sorobanData);
releaseAssertOrThrow(sorobanCfg);
return doCheckValidForSoroban(*sorobanCfg, cfg, ledgerVersion, res,
*sorobanData);
}
else
{
return doCheckValid(ledgerVersion, res);
}
}

template bool OperationFrame::checkValid<AbstractLedgerTxn>(
AbstractLedgerTxn& dbLoader, Config const& cfg,
std::optional<SorobanNetworkConfig const> const& sorobanCfg,
LedgerHeader const& header, SignatureChecker& signatureChecker,
bool forApply, OperationResult& res,
std::shared_ptr<SorobanTxData> sorobanData) const;

template bool
OperationFrame::checkValid<std::shared_ptr<SearchableBucketListSnapshot>>(
std::shared_ptr<SearchableBucketListSnapshot>& dbLoader, Config const& cfg,
std::optional<SorobanNetworkConfig const> const& sorobanCfg,
LedgerHeader const& header, SignatureChecker& signatureChecker,
bool forApply, OperationResult& res,
std::shared_ptr<SorobanTxData> sorobanData) const;

bool
OperationFrame::doCheckValidForSoroban(SorobanNetworkConfig const& config,
Config const& appConfig,
Expand All @@ -302,7 +331,24 @@ OperationFrame::loadSourceAccount(AbstractLedgerTxn& ltx,
LedgerTxnHeader const& header) const
{
ZoneScoped;
return mParentTx.loadAccount(ltx, header, getSourceID());
return mParentTx.loadAccount(ltx, header.current(), getSourceID());
}

std::shared_ptr<LedgerEntry>
OperationFrame::loadReadOnlySourceAccount(
std::shared_ptr<SearchableBucketListSnapshot> bl,
LedgerHeader const& header) const
{
ZoneScoped;
return mParentTx.loadReadOnlySourceAccount(bl, header);
}

std::shared_ptr<LedgerEntry>
OperationFrame::loadReadOnlySourceAccount(AbstractLedgerTxn& ltx,
LedgerHeader const& header) const
{
ZoneScoped;
return mParentTx.loadReadOnlySourceAccount(ltx, header);
}

void
Expand Down
21 changes: 16 additions & 5 deletions src/transactions/OperationFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ class OperationFrame
LedgerTxnEntry loadSourceAccount(AbstractLedgerTxn& ltx,
LedgerTxnHeader const& header) const;

std::shared_ptr<LedgerEntry>
loadReadOnlySourceAccount(std::shared_ptr<SearchableBucketListSnapshot> bl,
LedgerHeader const& header) const;
std::shared_ptr<LedgerEntry>
loadReadOnlySourceAccount(AbstractLedgerTxn& ltx,
LedgerHeader const& header) const;

public:
static std::shared_ptr<OperationFrame>
makeHelper(Operation const& op, TransactionFrame const& parentTx,
Expand All @@ -79,14 +86,18 @@ class OperationFrame
// given an operation result, gives a default value representing "success"
void resetResultSuccess(OperationResult& res) const;

bool checkSignature(SignatureChecker& signatureChecker,
AbstractLedgerTxn& ltx, OperationResult& res,
bool forApply) const;
template <class T>
bool checkSignature(T& dbLoader, LedgerHeader const& header,
SignatureChecker& signatureChecker,
OperationResult& res, bool forApply) const;

AccountID getSourceID() const;

bool checkValid(Application& app, SignatureChecker& signatureChecker,
AbstractLedgerTxn& ltxOuter, bool forApply,
template <class T>
bool checkValid(T& dbLoader, Config const& cfg,
std::optional<SorobanNetworkConfig const> const& sorobanCfg,
LedgerHeader const& header,
SignatureChecker& signatureChecker, bool forApply,
OperationResult& res,
std::shared_ptr<SorobanTxData> sorobanData) const;

Expand Down
Loading

0 comments on commit 096f5b3

Please sign in to comment.