Skip to content

Commit

Permalink
Merge pull request #3858 from sisuresh/invoke-tests
Browse files Browse the repository at this point in the history
More InvokeHostFunctionOp tests

Reviewed-by: dmkozh
  • Loading branch information
latobarita authored Aug 10, 2023
2 parents 35170ec + db589fb commit a5835ae
Show file tree
Hide file tree
Showing 2 changed files with 228 additions and 16 deletions.
149 changes: 133 additions & 16 deletions src/transactions/test/InvokeHostFunctionTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,24 @@ TEST_CASE("basic contract invocation", "[tx][soroban]")

auto contractKeys = deployContractWithSourceAccount(*app, addI32Wasm);
auto const& contractID = contractKeys[0].contractData().contract;
auto isValid = [&](SorobanResources const& resources,
SCAddress const& address, SCSymbol const& functionName,
std::vector<SCVal> const& args) -> bool {
Operation op;
op.body.type(INVOKE_HOST_FUNCTION);
auto& ihf = op.body.invokeHostFunctionOp().hostFunction;
ihf.type(HOST_FUNCTION_TYPE_INVOKE_CONTRACT);
ihf.invokeContract().contractAddress = address;
ihf.invokeContract().functionName = functionName;
ihf.invokeContract().args.assign(args.begin(), args.end());

auto tx = sorobanTransactionFrameFromOps(
app->getNetworkID(), root, {op}, {}, resources, 100'000, 1200);

LedgerTxn ltx(app->getLedgerTxnRoot());
return tx->checkValid(*app, ltx, 0, 0, 0);
};

auto call = [&](SorobanResources const& resources, SCAddress const& address,
SCSymbol const& functionName,
std::vector<SCVal> const& args, bool success) {
Expand Down Expand Up @@ -490,6 +508,81 @@ TEST_CASE("basic contract invocation", "[tx][soroban]")
resources.readBytes = 100;
call(resources, contractID, scFunc, {sc7, sc16}, false);
}

SECTION("invalid footprint keys")
{
auto invalidFootprint = [&](xdr::xvector<stellar::LedgerKey>&
footprint) {
auto acc = root.create(
"acc", app->getLedgerManager().getLastMinBalance(1));
SECTION("valid")
{
// add a valid trustline to the footprint to make sure the
// initial tx is valid.
footprint.emplace_back(
trustlineKey(root.getPublicKey(), makeAsset(acc, "USD")));
REQUIRE(isValid(resources, contractID, scFunc, {sc7, sc16}));
}
SECTION("native asset trustline")
{
footprint.emplace_back(
trustlineKey(root.getPublicKey(), makeNativeAsset()));
REQUIRE(!isValid(resources, contractID, scFunc, {sc7, sc16}));
}
SECTION("issuer trustline")
{
footprint.emplace_back(
trustlineKey(root.getPublicKey(), makeAsset(root, "USD")));
REQUIRE(!isValid(resources, contractID, scFunc, {sc7, sc16}));
}
auto invalidAssets = testutil::getInvalidAssets(root);
for (size_t i = 0; i < invalidAssets.size(); ++i)
{
auto key = trustlineKey(acc.getPublicKey(), invalidAssets[i]);
SECTION("invalid asset " + std::to_string(i))
{
footprint.emplace_back(key);
REQUIRE(
!isValid(resources, contractID, scFunc, {sc7, sc16}));
}
}
SECTION("offer")
{
footprint.emplace_back(offerKey(root, 1));
REQUIRE(!isValid(resources, contractID, scFunc, {sc7, sc16}));
}
SECTION("data")
{
footprint.emplace_back(dataKey(root, "name"));
REQUIRE(!isValid(resources, contractID, scFunc, {sc7, sc16}));
}
SECTION("claimable balance")
{
footprint.emplace_back(
claimableBalanceKey(ClaimableBalanceID{}));
REQUIRE(!isValid(resources, contractID, scFunc, {sc7, sc16}));
}
SECTION("liquidity pool")
{
footprint.emplace_back(liquidityPoolKey(PoolID{}));
REQUIRE(!isValid(resources, contractID, scFunc, {sc7, sc16}));
}
SECTION("config setting")
{
footprint.emplace_back(configSettingKey(ConfigSettingID{}));
REQUIRE(!isValid(resources, contractID, scFunc, {sc7, sc16}));
}
};

SECTION("readOnly")
{
invalidFootprint(resources.footprint.readOnly);
}
SECTION("readWrite")
{
invalidFootprint(resources.footprint.readWrite);
}
}
}

TEST_CASE("contract storage", "[tx][soroban]")
Expand Down Expand Up @@ -903,22 +996,6 @@ TEST_CASE("contract storage", "[tx][soroban]")
put("key1", 0, ContractDataDurability::PERSISTENT);
put("key2", 21, ContractDataDurability::PERSISTENT);

// Failure: contract data isn't in footprint
putWithFootprint("key1", 88, contractKeys, {}, 1000, false,
ContractDataDurability::PERSISTENT);
delWithFootprint("key1", contractKeys, {}, false,
ContractDataDurability::PERSISTENT);

// Failure: contract data is read only
auto readOnlyFootprint = contractKeys;
readOnlyFootprint.push_back(
contractDataKey(contractID, makeSymbolSCVal("key2"),
ContractDataDurability::PERSISTENT, DATA_ENTRY));
putWithFootprint("key2", 888888, readOnlyFootprint, {}, 1000, false,
ContractDataDurability::PERSISTENT);
delWithFootprint("key2", readOnlyFootprint, {}, false,
ContractDataDurability::PERSISTENT);

// Failure: insufficient write bytes
putWithFootprint(
"key2", 88888, contractKeys,
Expand Down Expand Up @@ -1368,6 +1445,46 @@ TEST_CASE("contract storage", "[tx][soroban]")
checkContractDataExpirationLedger(
"key2", ContractDataDurability::PERSISTENT, maxExpiration);
}
SECTION("footprint tests")
{
put("key1", 0, ContractDataDurability::PERSISTENT);
put("key2", 21, ContractDataDurability::PERSISTENT);
SECTION("unused readWrite key")
{
auto acc = root.create(
"acc", app->getLedgerManager().getLastMinBalance(1));

REQUIRE(doesAccountExist(*app, acc));

putWithFootprint(
"key1", 0, contractKeys,
{contractDataKey(contractID, makeSymbolSCVal("key1"),
ContractDataDurability::PERSISTENT,
DATA_ENTRY),
accountKey(acc)},
1000, true, ContractDataDurability::PERSISTENT);
// make sure account still exists and hasn't change
REQUIRE(doesAccountExist(*app, acc));
}
SECTION("incorrect footprint")
{
// Failure: contract data isn't in footprint
putWithFootprint("key1", 88, contractKeys, {}, 1000, false,
ContractDataDurability::PERSISTENT);
delWithFootprint("key1", contractKeys, {}, false,
ContractDataDurability::PERSISTENT);

// Failure: contract data is read only
auto readOnlyFootprint = contractKeys;
readOnlyFootprint.push_back(contractDataKey(
contractID, makeSymbolSCVal("key2"),
ContractDataDurability::PERSISTENT, DATA_ENTRY));
putWithFootprint("key2", 888888, readOnlyFootprint, {}, 1000, false,
ContractDataDurability::PERSISTENT);
delWithFootprint("key2", readOnlyFootprint, {}, false,
ContractDataDurability::PERSISTENT);
}
}
}

TEST_CASE("failed invocation with diagnostics", "[tx][soroban]")
Expand Down
95 changes: 95 additions & 0 deletions test-tx-meta-baseline-next/InvokeHostFunctionTests.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@

{
"!cfg protocol version" : 20,
"!rng seed" : 12345,
"!test all versions" : true,
"!versions to test" :
[
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20
],
"basic contract invocation|invalid footprint keys|readOnly" :
[
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU="
],
"basic contract invocation|invalid footprint keys|readWrite" :
[
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU=",
"3l7t9opHMbU="
],
"contract storage|footprint tests|unused readWrite key" : [ "PJ5bN6hAeFA=" ]
}

0 comments on commit a5835ae

Please sign in to comment.