1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
//! Raw native functions for services to use
//!
//! This is the set of raw native functions (wasm imports). They are
//! available for services to use directly, but we recommend using
//! the [Wrapped Native Functions](crate::native) instead.
use crate::DbId;
#[derive(Debug, Clone, Copy)]
#[repr(transparent)]
pub struct KvHandle(pub(crate) u32);
impl KvHandle {
pub const INVALID: KvHandle = KvHandle(u32::MAX);
}
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum KvMode {
None = 0,
Read = 1,
Write = 2,
ReadWrite = 3,
}
extern "C" {
/// Copy `min(dest_size, resultSize - offset)` bytes from
/// `result + offset` into `dest` and return `resultSize`
///
/// If `offset >= resultSize`, then skip the copy.
///
/// Other functions set or clear result. `getResult`, [getKey], and
/// [writeConsole] are the only raw functions which leave the current
/// result and key intact.
pub fn getResult(dest: *mut u8, dest_size: u32, offset: u32) -> u32;
/// Copy `min(dest_size, key_size)` bytes of the most-recent key into
/// dest and return `key_size`
///
/// Other functions set or clear the key. [getResult], `getKey`, and
/// [writeConsole] are the only raw functions which leave the current
/// result and key intact.
pub fn getKey(dest: *mut u8, dest_size: u32) -> u32;
/// Write `message` to console
///
/// Message should be UTF8.
pub fn writeConsole(message: *const u8, len: u32);
/// Abort with `message`
///
/// Message should be UTF8.
pub fn abortMessage(message: *const u8, len: u32) -> !;
/// Store the currently-executing action into result and return the result size
///
/// The result contains a fracpacked [crate::Action]; use [getResult] to get it.
///
/// If the service, while handling action A, calls itself with action B:
/// * Before the call to B, `getCurrentAction()` returns A.
/// * After the call to B, `getCurrentAction()` returns B.
/// * After B returns, `getCurrentAction()` returns A.
///
/// Note: The above only applies if the service uses [call].
pub fn getCurrentAction() -> u32;
/// Call a service, store the return value into result, and return the result size
///
/// `action` must contain a fracpacked [crate::Action].
///
/// Use [getResult] to get result.
pub fn call(action: *const u8, len: u32, flags: u64) -> u32;
/// Set the currently-executing action's return value
pub fn setRetval(retval: *const u8, len: u32);
/// Opens a key-value database
///
/// The prefix will be added automatically to all accesses using the handle.
///
/// Access control is checked at open:
/// - Native databases can only be opened by privileged services
/// - For regular databases, the first 8 bytes of the prefix must be the
/// caller service (big endian)
/// - Some databases forbid reading or writing depending on the run mode
///
/// The maximum number of handles that a service can have open
/// simultaneously is `WasmConfigRow::maxHandles`. If the limit
/// is exceeded, this function will abort.
///
/// The handle is only usable by the current service. Use `exportHandles`
/// to pass it to another service.
pub fn kvOpen(db: DbId, prefix: *const u8, len: u32, mode: KvMode) -> KvHandle;
/// Opens a subtree of a key-value database
///
/// - The prefix will be appended to any prefix that the source has
/// - The mode must be at least as restrictive as the source mode
///
/// The maximum number of handles that a service can have open
/// simultaneously is `WasmConfigRow::maxHandles`. If the limit
/// is exceeded, this function will abort.
pub fn kvOpenAt(db: KvHandle, prefix: *const u8, len: u32, mode: KvMode) -> KvHandle;
/// Closes a key-value database
///
/// If the handle was exported, all copies are unaffected and
/// will remain usable until they are also closed.
pub fn kvClose(handle: KvHandle);
pub fn exportHandles(data: *const u8, len: u32);
pub fn importHandles() -> u32;
/// Set a key-value pair
///
/// If key already exists, then replace the existing value.
pub fn kvPut(db: KvHandle, key: *const u8, key_len: u32, value: *const u8, value_len: u32);
/// Add a sequentially-numbered record
///
/// Returns the id.
pub fn putSequential(db: crate::DbId, value: *const u8, value_len: u32) -> u64;
/// Remove a key-value pair if it exists
pub fn kvRemove(db: KvHandle, key: *const u8, key_len: u32);
/// Get a key-value pair, if any
///
/// If key exists, then sets result to value and returns size. If key does not
/// exist, returns `u32::MAX` and clears result. Use [getResult] to get result.
pub fn kvGet(db: KvHandle, key: *const u8, key_len: u32) -> u32;
/// Get a sequentially-numbered record
///
/// If `id` is available, then sets result to value and returns size. If id does
/// not exist, returns `u32::MAX` and clears result.
pub fn getSequential(db: crate::DbId, id: u64) -> u32;
/// Get the first key-value pair which is greater than or equal to the provided
/// key
///
/// If one is found, and the first `match_key_size` bytes of the found key
/// matches the provided key, then sets result to value and returns size. Also
/// sets key. Otherwise returns `u32::MAX` and clears result. Use [getResult] to get
/// result and [getKey] to get found key.
pub fn kvGreaterEqual(db: KvHandle, key: *const u8, key_len: u32, match_key_size: u32) -> u32;
/// Get the key-value pair immediately-before provided key
///
/// If one is found, and the first `match_key_size` bytes of the found key
/// matches the provided key, then sets result to value and returns size.
/// Also sets key. Otherwise returns `u32::MAX` and clears result. Use [getResult]
/// to get result and [getKey] to get found key.
pub fn kvLessThan(db: KvHandle, key: *const u8, key_len: u32, match_key_size: u32) -> u32;
/// Get the maximum key-value pair which has key as a prefix
///
/// If one is found, then sets result to value and returns size. Also sets key.
/// Otherwise returns `u32::MAX` and clears result. Use [getResult] to get result
/// and [getKey] to get found key.
pub fn kvMax(db: KvHandle, key: *const u8, key_len: u32) -> u32;
/// Gets the current value of a clock in nanoseconds.
///
/// This function is non-deterministic and is only available in subjective services.
///
/// The following clocks are supported
/// - `__WASI_CLOCKID_REALTIME` returns wall-clock time since the unix epoch.
/// - `__WASI_CLOCKID_MONOTONIC` returns monotonic time since an unspecified epoch.
/// All uses of CLOCK_MONOTONIC within the same block use the same epoch.
/// - `__WASI_CLOCKID_PROCESS_CPUTIME_ID` measures CPU time spent executing the
/// current transaction.
///
/// Returns 0 on success or an error code on failure.
///
/// Errors:
/// - `EINVAL`: the clock id is not supported
pub fn clockTimeGet(id: u32, time: *mut u64) -> i32;
/// Fills a buffer with random bytes
///
/// This function is non-deterministic and is only available in subjective services.
pub fn getRandom(buf: *mut u8, len: usize);
/// Sets the CPU timer to expire after the current transaction/query/callback
/// context has run for a given number of nanoseconds. When the timer
/// expires, the current context will be terminated. Setting the timeout
/// replaces any previous timeout.
pub fn setMaxCpuTime(ns: u64);
pub fn checkoutSubjective();
pub fn commitSubjective() -> bool;
pub fn abortSubjective();
/// Starts a new HTTP request
///
/// Returns a socket on success or a negative error code on failure
///
/// Errors:
/// - `ENOSYS`: the host does not support sockets
pub fn socketOpen(data: *const u8, len: usize) -> i32;
/// Send a message to a socket
///
/// Returns 0 on success or an error code on failure
///
/// Errors:
/// - `EBADF`: fd is not a valid file descriptor
/// - `ENOTSOCK`: fd is not a socket
pub fn socketSend(fd: i32, data: *const u8, len: usize) -> i32;
/// Change flags on a socket. The mask determines which flags are set.
///
/// If this function is called within a subjectiveCheckout, it will only take
/// effect if the top-level commit succeeds. If another context changes the
/// flags, subjectiveCommit may fail.
///
/// Returns 0 on success or an error code on failure.
///
/// Errors:
/// - `EBADF`: fd is not a valid file descriptor
/// - `ENOTSUP`: The socket does not support the requested flags
/// - `ENOTSOCK`: fd is not a socket
/// - `EACCES`: The socket is owned by another context
pub fn socketSetFlags(fd: i32, mask: u32, value: u32) -> i32;
}