Skip to content

Commit

Permalink
Merge pull request #3567 from graydon/complex-wasm-test
Browse files Browse the repository at this point in the history
Bump env and add complex-wasm testcase.

Reviewed-by: MonsieurNicolas
  • Loading branch information
latobarita authored Oct 5, 2022
2 parents 5b37240 + 15baacf commit 4e813f2
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 137 deletions.
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
members = ["src/rust"]

[patch.crates-io]
stellar-xdr = { git = "https://github.com/stellar/rs-stellar-xdr", rev = "f87409c" }
stellar-xdr = { git = "https://github.com/stellar/rs-stellar-xdr", rev = "88ded341" }
wasmi = { package = "soroban-wasmi", git = "https://github.com/stellar/wasmi", rev = "a61b6df" }
soroban-env-common = { git = "https://github.com/stellar/rs-soroban-env", rev = "96d7a04" }
soroban-native-sdk-macros = { git = "https://github.com/stellar/rs-soroban-env", rev = "96d7a04" }
soroban-env-common = { git = "https://github.com/stellar/rs-soroban-env", rev = "17ada13" }
soroban-native-sdk-macros = { git = "https://github.com/stellar/rs-soroban-env", rev = "17ada13" }


4 changes: 2 additions & 2 deletions src/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ cxx = "1.0"
im-rc = "15.0.0"
base64 = "0.13.0"
rustc-simple-version = "0.1.0"
soroban-env-host = { git = "https://github.com/stellar/rs-soroban-env", rev = "96d7a04", features = [
soroban-env-host = { git = "https://github.com/stellar/rs-soroban-env", rev = "17ada13", features = [
"vm",
] }
soroban-test-wasms = { git = "https://github.com/stellar/rs-soroban-env", rev = "96d7a04" }
soroban-test-wasms = { git = "https://github.com/stellar/rs-soroban-env", rev = "17ada13" }
6 changes: 6 additions & 0 deletions src/rust/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,3 +480,9 @@ pub(crate) fn get_test_wasm_contract_data() -> Result<RustBuf, Box<dyn Error>> {
data: soroban_test_wasms::CONTRACT_DATA.iter().cloned().collect(),
})
}

pub(crate) fn get_test_wasm_complex() -> Result<RustBuf, Box<dyn Error>> {
Ok(RustBuf {
data: soroban_test_wasms::COMPLEX.iter().cloned().collect(),
})
}
2 changes: 2 additions & 0 deletions src/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ mod rust_bridge {
// Accessors for test wasms, compiled into soroban-test-wasms crate.
fn get_test_wasm_add_i32() -> Result<RustBuf>;
fn get_test_wasm_contract_data() -> Result<RustBuf>;
fn get_test_wasm_complex() -> Result<RustBuf>;

// Return the rustc version used to build this binary.
fn get_rustc_version() -> String;
Expand Down Expand Up @@ -131,6 +132,7 @@ use b64::{from_base64, to_base64};
mod contract;
use contract::get_test_wasm_add_i32;
use contract::get_test_wasm_contract_data;
use contract::get_test_wasm_complex;
use contract::get_xdr_hashes;
use contract::invoke_host_function;
use contract::preflight_host_function;
Expand Down
184 changes: 57 additions & 127 deletions src/transactions/test/InvokeHostFunctionTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "xdr/Stellar-transaction.h"
#include <iterator>
#include <stdexcept>
#ifdef ENABLE_NEXT_PROTOCOL_VERSION_UNSAFE_FOR_PRODUCTION

#include "crypto/SecretKey.h"
Expand All @@ -15,6 +16,7 @@
#include "test/TestUtils.h"
#include "test/TxTests.h"
#include "test/test.h"
#include "transactions/InvokeHostFunctionOpFrame.h"
#include "transactions/SignatureUtils.h"
#include "transactions/TransactionUtils.h"
#include "util/XDRCereal.h"
Expand Down Expand Up @@ -94,44 +96,6 @@ submitOpToCreateContract(Application& app, Operation const& op,
ltxe2.current().data.contractData().val == contractCodeObj));
}

static LedgerKey
createContractFromEd25519(Application& app, RustBuf const& contract,
uint256 const& salt, PublicKey const& pub,
Signature const& sig, bool expectSuccess,
bool expectEntry)
{
HashIDPreimage preImage;
preImage.type(ENVELOPE_TYPE_CONTRACT_ID_FROM_ED25519);
preImage.ed25519ContractID().ed25519 = pub.ed25519();
preImage.ed25519ContractID().salt = salt;
auto contractID = xdrSha256(preImage);

// Create operation
Operation op;
op.body.type(INVOKE_HOST_FUNCTION);
auto& ihf = op.body.invokeHostFunctionOp();
ihf.function = HOST_FN_CREATE_CONTRACT_WITH_ED25519;

auto contractBin = makeBinary(contract.data.begin(), contract.data.end());
ihf.parameters = {contractBin, makeBinary(salt.begin(), salt.end()),
makeBinary(pub.ed25519().begin(), pub.ed25519().end()),
makeBinary(sig.begin(), sig.end())};

SCVal wasmKey(SCValType::SCV_STATIC);
wasmKey.ic() = SCStatic::SCS_LEDGER_KEY_CONTRACT_CODE;

LedgerKey lk;
lk.type(CONTRACT_DATA);
lk.contractData().contractID = contractID;
lk.contractData().key = wasmKey;

ihf.footprint.readWrite = {lk};

submitOpToCreateContract(app, op, contract, contractID, wasmKey,
expectSuccess, expectEntry);
return lk;
}

static LedgerKey
createContractFromSource(Application& app, RustBuf const& contract,
uint256 const& salt, bool expectSuccess,
Expand Down Expand Up @@ -177,20 +141,8 @@ deployContract(Application& app, RustBuf const& contract, HostFunction fn,
{
case HostFunction::HOST_FN_CREATE_CONTRACT_WITH_ED25519:
{
auto key = SecretKey::fromSeed(sha256("a1"));

// create signature
auto const& separator =
"create_contract_from_ed25519(contract: Vec<u8>, "
"salt: u256, key: u256, sig: Vec<u8>)";
SHA256 hasher;
hasher.add(separator);
hasher.add(salt);
hasher.add(contract);

auto sig = SignatureUtils::sign(key, hasher.finish()).signature;
return createContractFromEd25519(app, contract, salt,
key.getPublicKey(), sig, true, true);
throw std::runtime_error(
"HOST_FN_CREATE_CONTRACT_WITH_ED25519 currently not supported");
}
case HostFunction::HOST_FN_CREATE_CONTRACT_WITH_SOURCE_ACCOUNT:
{
Expand Down Expand Up @@ -285,10 +237,6 @@ TEST_CASE("invoke host function", "[tx][contract]")
// Too many parameters for "add"
call({scContractID, scFunc, sc7, sc16, makeI32(0)}, false);
};
SECTION("create with ed25519 - add i32")
{
addI32(HostFunction::HOST_FN_CREATE_CONTRACT_WITH_ED25519);
}
SECTION("create with source - add i32")
{
addI32(HostFunction::HOST_FN_CREATE_CONTRACT_WITH_SOURCE_ACCOUNT);
Expand All @@ -297,9 +245,9 @@ TEST_CASE("invoke host function", "[tx][contract]")

SECTION("contract data")
{
auto contract =
deployContract(*app, contractDataWasm,
HostFunction::HOST_FN_CREATE_CONTRACT_WITH_ED25519);
auto contract = deployContract(
*app, contractDataWasm,
HostFunction::HOST_FN_CREATE_CONTRACT_WITH_SOURCE_ACCOUNT);
auto const& contractID = contract.contractData().contractID;

auto checkContractData = [&](SCVal const& key, SCVal const* val) {
Expand Down Expand Up @@ -419,80 +367,62 @@ TEST_CASE("invoke host function", "[tx][contract]")
del("key1");
del("key2");
}
}

SECTION("create contract failures")
{
// create signature
auto const& separator =
"create_contract_from_ed25519(contract: Vec<u8>, "
"salt: u256, key: u256, sig: Vec<u8>)";
uint256 salt = sha256("salt");
auto key = SecretKey::fromSeed(sha256("a1"));
TEST_CASE("complex contract with preflight", "[tx][contract]")
{
VirtualClock clock;
auto app = createTestApplication(clock, getTestConfig());
auto root = TestAccount::createRoot(*app);

{
SHA256 hasher;
hasher.add(separator);
hasher.add(salt);
hasher.add(addI32Wasm);
auto sig = SignatureUtils::sign(key, hasher.finish()).signature;

// public key is different than the one that created the signature
auto new_pub = SecretKey::fromSeed(sha256("a2"));
createContractFromEd25519(*app, addI32Wasm, salt,
new_pub.getPublicKey(), sig, false,
false);
}
auto const complexWasm = rust_bridge::get_test_wasm_complex();

{
// bad separator
SHA256 hasher;
hasher.add("bad_separator");
hasher.add(salt);
hasher.add(addI32Wasm);
auto sig = SignatureUtils::sign(key, hasher.finish()).signature;

createContractFromEd25519(*app, addI32Wasm, salt,
key.getPublicKey(), sig, false, false);
}
auto contract = deployContract(
*app, complexWasm,
HostFunction::HOST_FN_CREATE_CONTRACT_WITH_SOURCE_ACCOUNT);
auto const& contractID = contract.contractData().contractID;

{
// Incorrect salt was hashed
SHA256 hasher;
hasher.add(separator);
hasher.add(sha256("wrong_salt"));
hasher.add(addI32Wasm);
auto sig = SignatureUtils::sign(key, hasher.finish()).signature;

createContractFromEd25519(*app, addI32Wasm, salt,
key.getPublicKey(), sig, false, false);
}
auto scContractID = makeBinary(contractID.begin(), contractID.end());
auto scFunc = makeSymbol("go");

{
// Incorrect contract was hashed
SHA256 hasher;
hasher.add(separator);
hasher.add(salt);
hasher.add(contractDataWasm);
auto sig = SignatureUtils::sign(key, hasher.finish()).signature;

createContractFromEd25519(*app, addI32Wasm, salt,
key.getPublicKey(), sig, false, false);
}
Operation op;
op.body.type(INVOKE_HOST_FUNCTION);
auto& ihf = op.body.invokeHostFunctionOp();
ihf.function = HOST_FN_INVOKE_CONTRACT;
ihf.parameters = {scContractID, scFunc};

AccountID source;
auto res = InvokeHostFunctionOpFrame::preflight(*app, ihf, source);

// Contract reads just the WASM entry.
SCVal contractCodeKey(SCValType::SCV_STATIC);
contractCodeKey.ic() = SCStatic::SCS_LEDGER_KEY_CONTRACT_CODE;
LedgerKey wasmKey;
wasmKey.type(CONTRACT_DATA);
wasmKey.contractData().contractID = contractID;
wasmKey.contractData().key = contractCodeKey;

// Contract writes a single `data` CONTRACT_DATA entry.
LedgerKey dataKey(LedgerEntryType::CONTRACT_DATA);
dataKey.contractData().contractID = contractID;
dataKey.contractData().key = makeSymbol("data");

ihf.footprint.readOnly.emplace_back(wasmKey);
ihf.footprint.readWrite.emplace_back(dataKey);

auto tx = transactionFrameFromOps(app->getNetworkID(), root, {op}, {});
LedgerTxn ltx(app->getLedgerTxnRoot());
TransactionMetaFrame txm(ltx.loadHeader().current().ledgerVersion);
REQUIRE(tx->checkValid(ltx, 0, 0, 0));
REQUIRE(tx->apply(*app, ltx, txm));
ltx.commit();
txm.finalizeHashes();

{
// duplicate contract
SHA256 hasher;
hasher.add(separator);
hasher.add(salt);
hasher.add(addI32Wasm);

auto sig = SignatureUtils::sign(key, hasher.finish()).signature;
createContractFromEd25519(*app, addI32Wasm, salt,
key.getPublicKey(), sig, true, true);
createContractFromEd25519(*app, addI32Wasm, salt,
key.getPublicKey(), sig, false, true);
}
}
// Contract should have emitted a single event carrying a `Bytes` value.
REQUIRE(txm.getXDR().v3().events.size() == 1);
REQUIRE(txm.getXDR().v3().events.at(0).type == ContractEventType::CONTRACT);
REQUIRE(txm.getXDR().v3().events.at(0).body.v0().data.obj()->type() ==
SCO_BYTES);
}

#endif

0 comments on commit 4e813f2

Please sign in to comment.