mirror of
https://github.com/XRPLF/rippled.git
synced 2026-09-28 07:48:01 +00:00
Note the escrow and contract host functions are not isolated
The two groups share one flat ABI table in one `host_lib` namespace, and the only thing separating them is that the escrow host leaves the contract methods at their `Unimplemented` default. That separates them too late, and in one direction only. An escrow whose bytecode imports `emit_built_txn` passes screening, so `EscrowCreate` stores it and the escrow fails at finish with `tecINTERNAL`, because `Unimplemented` is a fatal fault rather than a code a contract reads. A contract calling `set_data` does not fail at all: the method is inherited, only `EscrowFinish::doApply` drains it, so the write returns a byte count and is discarded. Both need screening to know which subset of the ABI the host being built for actually serves. `docs/wasm-amendment-gating.md` already designs that transport for amendments; this wants the same one keyed on which host is running.
This commit is contained in:
@@ -22,6 +22,10 @@ public:
|
||||
// getFieldBytesFromSTData(xrpl::STData const& funcParam, std::uint32_t
|
||||
// stTypeId);
|
||||
|
||||
// TODO: `updateData` is inherited from the escrow host and is not refused here, so a
|
||||
// contract calling `set_data` is told how many bytes it stored and then has them
|
||||
// dropped: `ContractCall::doApply` never drains `getData()`. Refusing it needs an error
|
||||
// a contract can read, which `Unimplemented` is not — see the note in HostFunc.h.
|
||||
std::expected<Bytes, HostFunctionError>
|
||||
instanceParam(std::uint32_t index, std::uint32_t stTypeId) override;
|
||||
|
||||
|
||||
@@ -479,6 +479,25 @@ public:
|
||||
return std::unexpected(HostFunctionError::Unimplemented);
|
||||
}
|
||||
|
||||
// Smart-contract host functions. `WasmHostFunctionsImpl`, the escrow host, leaves every
|
||||
// one of them at the `Unimplemented` default below, and `ContractHostFunctionsImpl`
|
||||
// overrides them.
|
||||
//
|
||||
// TODO: that default is the only thing separating the two groups, and it separates them
|
||||
// too late and in one direction only. The ABI is one flat table in one `host_lib`
|
||||
// namespace, so screening accepts an escrow whose bytecode imports `emit_built_txn`:
|
||||
// `EscrowCreate` stores it, and the escrow fails at finish with `tecINTERNAL`, because
|
||||
// `Unimplemented` is a fatal fault rather than a code a contract reads. The other
|
||||
// direction does not fail at all — `ContractHostFunctionsImpl` inherits `updateData`,
|
||||
// and only `EscrowFinish::doApply` ever drains it, so a contract's write returns a byte
|
||||
// count and is discarded.
|
||||
//
|
||||
// Both want the same thing: screening has to know which subset of
|
||||
// `HostFunctionSpec::ALL` the host being built for actually serves, so a module
|
||||
// importing the wrong group is refused at create with `temINVALID_BYTECODE`.
|
||||
// `docs/wasm-amendment-gating.md` designs that transport for amendments (a gate
|
||||
// bitfield threaded into `check()` and `register_host_functions`); this needs the same
|
||||
// transport keyed on which host is running.
|
||||
virtual std::expected<Bytes, HostFunctionError>
|
||||
instanceParam(std::uint32_t index, std::uint32_t stTypeId)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user