Skip to content

Commit a6f155c

Browse files
committed
Add a smoke test for CAP-85.
1 parent 6dbc76d commit a6f155c

3 files changed

Lines changed: 106 additions & 0 deletions

File tree

src/transactions/test/InvokeHostFunctionTests.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <xdrpp/printer.h>
1919

2020
#include "bucket/BucketManager.h"
21+
#include "bucket/test/BucketTestUtils.h"
2122
#include "crypto/Random.h"
2223
#include "crypto/SecretKey.h"
2324
#include "herder/Herder.h"
@@ -11088,3 +11089,99 @@ TEST_CASE_VERSIONS("classic phase bumps sequence of soroban source account",
1108811089
-refund, ledgerVersion, true);
1108911090
});
1109011091
}
11092+
11093+
#ifdef CAP_0085_EXECUTABLE_REF
11094+
TEST_CASE("create and invoke external ref contract", "[tx][soroban]")
11095+
{
11096+
VirtualClock clock;
11097+
auto cfg = getTestConfig();
11098+
auto app = createTestApplication<BucketTestUtils::BucketTestApplication>(
11099+
clock, cfg);
11100+
SorobanTest test(app);
11101+
releaseAssert(protocolVersionStartsFrom(
11102+
test.getLedgerVersion(), EXTERNAL_EXECUTABLE_REF_PROTOCOL_VERSION));
11103+
11104+
auto wasm = rust_bridge::get_test_wasm_add_i32();
11105+
SCBytes wasmBytes(wasm.data.begin(), wasm.data.end());
11106+
Hash wasmHash = sha256(wasmBytes);
11107+
auto wasmKey = contractCodeKey(wasmHash);
11108+
SorobanResources uploadResources =
11109+
defaultUploadWasmResourcesWithoutFootprint(wasm,
11110+
test.getLedgerVersion());
11111+
auto uploadTx = makeSorobanWasmUploadTx(test.getApp(), test.getRoot(), wasm,
11112+
uploadResources, 1000);
11113+
REQUIRE(isSuccessResult(test.invokeTx(uploadTx)));
11114+
11115+
SCAddress owner = makeContractAddress(sha256("external ref owner"));
11116+
SCString tag("exec ref");
11117+
SCVal tagKey(SCV_EXECUTABLE_TAG);
11118+
tagKey.executable_tag() = tag;
11119+
auto refKey =
11120+
contractDataKey(owner, tagKey, ContractDataDurability::PERSISTENT);
11121+
11122+
// Inject the reference entry (and its TTL) directly into the ledger, which
11123+
// works thanks to using BucketTestUtils::BucketTestApplication app.
11124+
// We currently don't have a test Wasm that creates executable references,
11125+
// if we add one, we should use it instead of injecting the entry directly.
11126+
{
11127+
auto ledgerSeq = test.getLCLSeq() + 1;
11128+
11129+
LedgerEntry refEntry;
11130+
refEntry.lastModifiedLedgerSeq = ledgerSeq;
11131+
refEntry.data.type(CONTRACT_DATA);
11132+
auto& cd = refEntry.data.contractData();
11133+
cd.contract = owner;
11134+
cd.key = tagKey;
11135+
cd.durability = ContractDataDurability::PERSISTENT;
11136+
cd.val = makeBytesSCVal(wasmHash);
11137+
11138+
LedgerEntry ttlEntry;
11139+
ttlEntry.lastModifiedLedgerSeq = ledgerSeq;
11140+
ttlEntry.data.type(TTL);
11141+
ttlEntry.data.ttl().keyHash = getTTLKey(refKey).ttl().keyHash;
11142+
ttlEntry.data.ttl().liveUntilLedgerSeq = ledgerSeq + 1'000'000;
11143+
11144+
app->getLedgerManager().setNextLedgerEntryBatchForBucketTesting(
11145+
{refEntry, ttlEntry}, {}, {}, /*alsoAddActualEntries=*/true);
11146+
closeLedger(test.getApp());
11147+
}
11148+
11149+
auto idPreimage =
11150+
makeContractIDPreimage(test.getRoot(), sha256("external ref salt"));
11151+
auto contractID = xdrSha256(
11152+
makeFullContractIdPreimage(test.getApp().getNetworkID(), idPreimage));
11153+
auto contractAddress = makeContractAddress(contractID);
11154+
auto contractInstanceKey = makeContractInstanceKey(contractAddress);
11155+
11156+
ContractExecutable executable(CONTRACT_EXECUTABLE_EXTERNAL_REF);
11157+
executable.external_ref().executable_owner = owner;
11158+
executable.external_ref().tag = tag;
11159+
11160+
SorobanResources createResources{};
11161+
createResources.instructions = 2'000'000;
11162+
createResources.writeBytes = 500;
11163+
createResources.footprint.readOnly = {refKey, wasmKey};
11164+
createResources.footprint.readWrite = {contractInstanceKey};
11165+
11166+
auto createTx =
11167+
makeSorobanCreateContractTx(test.getApp(), test.getRoot(), idPreimage,
11168+
executable, createResources, 1000);
11169+
REQUIRE(isSuccessResult(test.invokeTx(createTx)));
11170+
11171+
{
11172+
auto ledgerView =
11173+
test.getApp().getLedgerManager().copyImmutableLedgerView();
11174+
auto le = ledgerView.load(contractInstanceKey);
11175+
REQUIRE(le);
11176+
REQUIRE(le.current().data.contractData().val.instance().executable ==
11177+
executable);
11178+
}
11179+
TestContract contract(test, contractAddress,
11180+
{contractInstanceKey, refKey, wasmKey});
11181+
auto spec = SorobanInvocationSpec().setInstructions(1'000'000);
11182+
auto invocation =
11183+
contract.prepareInvocation("add", {makeI32(3), makeI32(4)}, spec);
11184+
REQUIRE(invocation.invoke());
11185+
REQUIRE(invocation.getReturnValue().i32() == 7);
11186+
}
11187+
#endif // CAP_0085_EXECUTABLE_REF

src/util/ProtocolVersion.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,12 @@ constexpr ProtocolVersion EMPTY_TX_SET_PROTOCOL_VERSION =
7575
constexpr ProtocolVersion INVOKE_HOST_FUNCTION_V2_PROTOCOL_VERSION =
7676
ProtocolVersion::V_28;
7777

78+
#ifdef CAP_0085_EXECUTABLE_REF
79+
constexpr ProtocolVersion EXTERNAL_EXECUTABLE_REF_PROTOCOL_VERSION =
80+
ProtocolVersion::V_28;
81+
#else
82+
constexpr ProtocolVersion EXTERNAL_EXECUTABLE_REF_PROTOCOL_VERSION =
83+
ProtocolVersion::V_UINT32_MAX;
84+
#endif
85+
7886
} // namespace stellar

test-tx-meta-baseline-next/InvokeHostFunctionTests.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2216,6 +2216,7 @@
22162216
"+cR3oq2qY0I="
22172217
],
22182218
"contract storage|protocol version 28|footprint|unused readWrite key" : [ "cPvvRUP0NPQ=" ],
2219+
"create and invoke external ref contract" : [ "+cR3oq2qY0I=" ],
22192220
"create in first stage delete in second stage" : [ "+cR3oq2qY0I=", "0hd/OzcsUOc=", "WlN4KxDWk6Q=" ],
22202221
"delete in first stage extend in second stage" : [ "+cR3oq2qY0I=", "0hd/OzcsUOc=", "WlN4KxDWk6Q=" ],
22212222
"delete non existent entry with parallel apply" : [ "+cR3oq2qY0I=", "MQWsAsiP/Lg=" ],

0 commit comments

Comments
 (0)