mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-28 06:55:50 +00:00
exitWith
This commit is contained in:
@@ -91,7 +91,6 @@ struct ContractHostFuncImpl_test : public beast::unit_test::suite
|
|||||||
.nextSequence = nextSequence,
|
.nextSequence = nextSequence,
|
||||||
.otxnAccount = otxn.id(),
|
.otxnAccount = otxn.id(),
|
||||||
.otxnId = txId,
|
.otxnId = txId,
|
||||||
.exitType = ripple::ExitType::ROLLBACK,
|
|
||||||
.exitCode = -1,
|
.exitCode = -1,
|
||||||
.dataMap = dataMap,
|
.dataMap = dataMap,
|
||||||
.eventMap = eventMap,
|
.eventMap = eventMap,
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ ContractCall::doApply()
|
|||||||
.nextSequence = caSle->getFieldU32(sfSequence),
|
.nextSequence = caSle->getFieldU32(sfSequence),
|
||||||
.otxnAccount = account_,
|
.otxnAccount = account_,
|
||||||
.otxnId = ctx_.tx.getTransactionID(),
|
.otxnId = ctx_.tx.getTransactionID(),
|
||||||
.exitType = ripple::ExitType::ROLLBACK,
|
.exitReason = "",
|
||||||
.exitCode = -1,
|
.exitCode = -1,
|
||||||
.dataMap = dataMap,
|
.dataMap = dataMap,
|
||||||
.eventMap = eventMap,
|
.eventMap = eventMap,
|
||||||
@@ -306,8 +306,9 @@ ContractCall::doApply()
|
|||||||
auto ret = re.value().result;
|
auto ret = re.value().result;
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
JLOG(j_.error()) << "Contract Failure: " << ret;
|
JLOG(j_.error()) << "WASM Execution Failed: " << contractCtx.result.exitReason;
|
||||||
ctx_.setWasmReturnCode(ret);
|
ctx_.setWasmReturnCode(ret);
|
||||||
|
// ctx_.setWasmReturnStr(contractCtx.result.exitReason);
|
||||||
return tecWASM_REJECTED;
|
return tecWASM_REJECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,6 +326,7 @@ ContractCall::doApply()
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx_.setWasmReturnCode(ret);
|
ctx_.setWasmReturnCode(ret);
|
||||||
|
// ctx_.setWasmReturnStr(contractCtx.result.exitReason);
|
||||||
ctx_.setEmittedTxns(contractCtx.result.emittedTxns);
|
ctx_.setEmittedTxns(contractCtx.result.emittedTxns);
|
||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
@@ -333,6 +335,7 @@ ContractCall::doApply()
|
|||||||
JLOG(j_.error()) << "WASM Failure: " + transHuman(re.error());
|
JLOG(j_.error()) << "WASM Failure: " + transHuman(re.error());
|
||||||
auto const errorCode = TERtoInt(re.error());
|
auto const errorCode = TERtoInt(re.error());
|
||||||
ctx_.setWasmReturnCode(errorCode);
|
ctx_.setWasmReturnCode(errorCode);
|
||||||
|
// ctx_.setWasmReturnStr(contractCtx.result.exitReason);
|
||||||
return re.error();
|
return re.error();
|
||||||
}
|
}
|
||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ struct ContractResult
|
|||||||
ripple::AccountID const
|
ripple::AccountID const
|
||||||
otxnAccount; // AccountID for the originating transaction
|
otxnAccount; // AccountID for the originating transaction
|
||||||
ripple::uint256 const otxnId; // ID for the originating transaction
|
ripple::uint256 const otxnId; // ID for the originating transaction
|
||||||
ripple::ExitType exitType = ripple::ExitType::ROLLBACK;
|
std::string exitReason{""};
|
||||||
int64_t exitCode{-1};
|
int64_t exitCode{-1};
|
||||||
ContractDataMap dataMap;
|
ContractDataMap dataMap;
|
||||||
ContractEventMap eventMap;
|
ContractEventMap eventMap;
|
||||||
|
|||||||
@@ -118,6 +118,9 @@ public:
|
|||||||
Expected<int32_t, HostFunctionError>
|
Expected<int32_t, HostFunctionError>
|
||||||
emitEvent(std::string_view const& eventName, STJson const& eventData)
|
emitEvent(std::string_view const& eventName, STJson const& eventData)
|
||||||
override;
|
override;
|
||||||
|
|
||||||
|
Expected<int32_t, HostFunctionError>
|
||||||
|
exitWith(int32_t code, std::string_view const& msg) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|||||||
@@ -643,6 +643,12 @@ struct HostFunctions
|
|||||||
return Unexpected(HostFunctionError::INTERNAL);
|
return Unexpected(HostFunctionError::INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual Expected<int32_t, HostFunctionError>
|
||||||
|
exitWith(int32_t code, std::string_view const& msg)
|
||||||
|
{
|
||||||
|
return Unexpected(HostFunctionError::INTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~HostFunctions() = default;
|
virtual ~HostFunctions() = default;
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -714,4 +714,12 @@ emitEvent_wrap(
|
|||||||
wasm_val_vec_t const* params,
|
wasm_val_vec_t const* params,
|
||||||
wasm_val_vec_t* results);
|
wasm_val_vec_t* results);
|
||||||
|
|
||||||
|
using exitWith_proto =
|
||||||
|
int32_t(int32_t, uint8_t const*, int32_t);
|
||||||
|
wasm_trap_t*
|
||||||
|
exitWith_wrap(
|
||||||
|
void* env,
|
||||||
|
wasm_val_vec_t const* params,
|
||||||
|
wasm_val_vec_t* results);
|
||||||
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|||||||
@@ -1102,4 +1102,14 @@ ContractHostFunctionsImpl::emitEvent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expected<int32_t, HostFunctionError>
|
||||||
|
ContractHostFunctionsImpl::exitWith(
|
||||||
|
int32_t code,
|
||||||
|
std::string_view const& msg)
|
||||||
|
{
|
||||||
|
contractCtx.result.exitReason = std::string(msg);
|
||||||
|
contractCtx.result.exitCode = code;
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|||||||
@@ -2562,6 +2562,38 @@ emitEvent_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results)
|
|||||||
rt, params, results, hf->emitEvent(*name, *parsed), index);
|
rt, params, results, hf->emitEvent(*name, *parsed), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wasm_trap_t*
|
||||||
|
exitWith_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results)
|
||||||
|
{
|
||||||
|
auto* hf = reinterpret_cast<HostFunctions*>(env);
|
||||||
|
auto const* rt = reinterpret_cast<InstanceWrapper const*>(hf->getRT());
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
auto const code = getDataInt32(rt, params, index);
|
||||||
|
if (!code)
|
||||||
|
{
|
||||||
|
return hfResult(results, code.error());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params->data[2].of.i32 > maxWasmDataLength)
|
||||||
|
{
|
||||||
|
return hfResult(results, HostFunctionError::DATA_FIELD_TOO_LARGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const msg = getDataString(rt, params, index);
|
||||||
|
if (!msg)
|
||||||
|
{
|
||||||
|
return hfResult(results, msg.error());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call exitWith to store the exit code and reason
|
||||||
|
[[maybe_unused]] auto result = hf->exitWith(*code, *msg);
|
||||||
|
|
||||||
|
// ALWAYS return a trap to halt execution
|
||||||
|
// This ensures WASM stops here
|
||||||
|
return static_cast<wasm_trap_t*>(WasmEngine::instance().newTrap(*msg));
|
||||||
|
}
|
||||||
|
|
||||||
// LCOV_EXCL_START
|
// LCOV_EXCL_START
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ setCommonHostFunctions(HostFunctions* hfs, std::vector<WasmImportFunc>& i)
|
|||||||
WASM_IMPORT_FUNC2(i, emitBuiltTxn, "emit_built_txn", hfs, 2'000);
|
WASM_IMPORT_FUNC2(i, emitBuiltTxn, "emit_built_txn", hfs, 2'000);
|
||||||
WASM_IMPORT_FUNC2(i, emitTxn, "emit_txn", hfs, 2'000);
|
WASM_IMPORT_FUNC2(i, emitTxn, "emit_txn", hfs, 2'000);
|
||||||
WASM_IMPORT_FUNC2(i, emitEvent, "emit_event", hfs, 70);
|
WASM_IMPORT_FUNC2(i, emitEvent, "emit_event", hfs, 70);
|
||||||
|
WASM_IMPORT_FUNC2(i, exitWith, "exit_with", hfs, 70);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user