Skip to content

Commit

Permalink
Merge pull request #3805 from sisuresh/key-validation
Browse files Browse the repository at this point in the history
Footprint validation

Reviewed-by: dmkozh
  • Loading branch information
latobarita authored Jun 30, 2023
2 parents 2109a16 + 3d206b5 commit 61ef37d
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 16 deletions.
12 changes: 6 additions & 6 deletions src/herder/test/HerderTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1619,15 +1619,15 @@ TEST_CASE("surge pricing", "[herder][txset]")
auto write = rand_uniform<uint32_t>(
0, std::min(conf.txMaxWriteLedgerEntries(),
(conf.txMaxReadLedgerEntries() - read)));
for (auto const& key : LedgerTestUtils::
generateValidLedgerEntryKeysWithExclusions(
{CONFIG_SETTING}, write))
for (auto const& key :
LedgerTestUtils::generateUniqueValidSorobanLedgerEntryKeys(
write))
{
res.footprint.readWrite.emplace_back(key);
}
for (auto const& key : LedgerTestUtils::
generateValidLedgerEntryKeysWithExclusions(
{CONFIG_SETTING}, read))
for (auto const& key :
LedgerTestUtils::generateUniqueValidSorobanLedgerEntryKeys(
read))
{
res.footprint.readOnly.emplace_back(key);
}
Expand Down
8 changes: 8 additions & 0 deletions src/ledger/test/LedgerTestUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,14 @@ generateValidLedgerEntryKeysWithExclusions(
}
return keys;
}
#ifdef ENABLE_NEXT_PROTOCOL_VERSION_UNSAFE_FOR_PRODUCTION
std::vector<LedgerKey>
generateUniqueValidSorobanLedgerEntryKeys(size_t n)
{
return LedgerTestUtils::generateValidUniqueLedgerEntryKeysWithExclusions(
{OFFER, DATA, CLAIMABLE_BALANCE, LIQUIDITY_POOL, CONFIG_SETTING}, n);
}
#endif

std::vector<LedgerKey>
generateValidUniqueLedgerEntryKeysWithExclusions(
Expand Down
4 changes: 4 additions & 0 deletions src/ledger/test/LedgerTestUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ std::vector<LedgerEntry> generateValidUniqueLedgerEntries(size_t n);
std::vector<LedgerKey> generateValidLedgerEntryKeysWithExclusions(
std::unordered_set<LedgerEntryType> const& excludedTypes, size_t n);

#ifdef ENABLE_NEXT_PROTOCOL_VERSION_UNSAFE_FOR_PRODUCTION
std::vector<LedgerKey> generateUniqueValidSorobanLedgerEntryKeys(size_t n);
#endif

std::vector<LedgerKey> generateValidUniqueLedgerEntryKeysWithExclusions(
std::unordered_set<LedgerEntryType> const& excludedTypes, size_t n);

Expand Down
9 changes: 9 additions & 0 deletions src/transactions/InvokeHostFunctionOpFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,15 @@ InvokeHostFunctionOpFrame::doCheckValid(SorobanNetworkConfig const& config,
{
return false;
}
if (hostFn.type() == HOST_FUNCTION_TYPE_CREATE_CONTRACT)
{
auto const& preimage = hostFn.createContract().contractIDPreimage;
if (preimage.type() == CONTRACT_ID_PREIMAGE_FROM_ASSET &&
!isAssetValid(preimage.fromAsset(), ledgerVersion))
{
return false;
}
}
return true;
}

Expand Down
3 changes: 2 additions & 1 deletion src/transactions/RevokeSponsorshipOpFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ getAccountID(LedgerEntry const& le)
case CLAIMABLE_BALANCE:
return *le.ext.v1().sponsoringID;
default:
abort();
throw std::runtime_error("Invalid key type");
}
}

Expand Down Expand Up @@ -434,6 +434,7 @@ RevokeSponsorshipOpFrame::doCheckValid(uint32_t ledgerVersion)
case LIQUIDITY_POOL:
#ifdef ENABLE_NEXT_PROTOCOL_VERSION_UNSAFE_FOR_PRODUCTION
case CONTRACT_DATA:
case CONTRACT_CODE:
case CONFIG_SETTING:
#endif
innerResult().code(REVOKE_SPONSORSHIP_MALFORMED);
Expand Down
2 changes: 2 additions & 0 deletions src/transactions/SponsorshipUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ computeMultiplier(LedgerEntry const& le)
#ifdef ENABLE_NEXT_PROTOCOL_VERSION_UNSAFE_FOR_PRODUCTION
case CONFIG_SETTING:
case CONTRACT_DATA:
case CONTRACT_CODE:
#endif
case LIQUIDITY_POOL:
throw std::runtime_error(
Expand All @@ -229,6 +230,7 @@ isSubentry(LedgerEntry const& le)
#ifdef ENABLE_NEXT_PROTOCOL_VERSION_UNSAFE_FOR_PRODUCTION
case CONTRACT_DATA:
case CONFIG_SETTING:
case CONTRACT_CODE:
#endif
case LIQUIDITY_POOL:
throw std::runtime_error(
Expand Down
50 changes: 45 additions & 5 deletions src/transactions/TransactionFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -586,8 +586,8 @@ TransactionFrame::validateSorobanOpsConsistency() const
}

bool
TransactionFrame::validateSorobanResources(
SorobanNetworkConfig const& config) const
TransactionFrame::validateSorobanResources(SorobanNetworkConfig const& config,
uint32_t protocolVersion) const
{
auto const& resources = sorobanResources();
auto const& readEntries = resources.footprint.readOnly;
Expand Down Expand Up @@ -615,16 +615,56 @@ TransactionFrame::validateSorobanResources(
{
return false;
}
auto footprintKeyIsValid = [&](LedgerKey const& key) -> bool {
if (isSorobanExtEntry(key))
{
return false;
}

switch (key.type())
{
case ACCOUNT:
case CONTRACT_DATA:
case CONTRACT_CODE:
break;
case TRUSTLINE:
{
auto const& tl = key.trustLine();
if (!isAssetValid(tl.asset, protocolVersion) ||
(tl.asset.type() == ASSET_TYPE_NATIVE) ||
isIssuer(tl.accountID, tl.asset))
{
return false;
}
break;
}
case OFFER:
case DATA:
case CLAIMABLE_BALANCE:
case LIQUIDITY_POOL:
case CONFIG_SETTING:
return false;
default:
throw std::runtime_error("unknown ledger key type");
}

if (xdr::xdr_size(key) > config.maxContractDataKeySizeBytes())
{
return false;
}

return true;
};
for (auto const& lk : readEntries)
{
if (xdr::xdr_size(lk) > config.maxContractDataKeySizeBytes())
if (!footprintKeyIsValid(lk))
{
return false;
}
}
for (auto const& lk : writeEntries)
{
if (xdr::xdr_size(lk) > config.maxContractDataKeySizeBytes())
if (!footprintKeyIsValid(lk))
{
return false;
}
Expand Down Expand Up @@ -923,7 +963,7 @@ TransactionFrame::commonValidPreSeqNum(Application& app, AbstractLedgerTxn& ltx,
}
auto const& sorobanConfig =
app.getLedgerManager().getSorobanNetworkConfig(ltx);
if (!validateSorobanResources(sorobanConfig))
if (!validateSorobanResources(sorobanConfig, ledgerVersion))
{
getResult().result.code(txSOROBAN_RESOURCE_LIMIT_EXCEEDED);
return false;
Expand Down
3 changes: 2 additions & 1 deletion src/transactions/TransactionFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ class TransactionFrame : public TransactionFrameBase

#ifdef ENABLE_NEXT_PROTOCOL_VERSION_UNSAFE_FOR_PRODUCTION
bool validateSorobanOpsConsistency() const;
bool validateSorobanResources(SorobanNetworkConfig const& config) const;
bool validateSorobanResources(SorobanNetworkConfig const& config,
uint32_t protocolVersion) const;
void refundSorobanFee(uint32_t protocolVersion,
SorobanNetworkConfig const& sorobanConfig,
Config const& cfg, AbstractLedgerTxn& ltx);
Expand Down
5 changes: 2 additions & 3 deletions src/transactions/test/TxEnvelopeTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2531,9 +2531,8 @@ TEST_CASE("soroban transaction validation", "[tx][envelope][soroban]")
resources.extendedMetaDataSizeBytes =
InitialSorobanNetworkConfig::TX_MAX_EXTENDED_META_DATA_SIZE_BYTES;

auto keys =
LedgerTestUtils::generateValidUniqueLedgerEntryKeysWithExclusions(
{}, InitialSorobanNetworkConfig::TX_MAX_READ_LEDGER_ENTRIES);
auto keys = LedgerTestUtils::generateUniqueValidSorobanLedgerEntryKeys(
InitialSorobanNetworkConfig::TX_MAX_READ_LEDGER_ENTRIES);

resources.footprint.readWrite.assign(
keys.begin(),
Expand Down

0 comments on commit 61ef37d

Please sign in to comment.