@deroll/cmio 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AUTHORS +1 -0
- package/LICENSE +202 -0
- package/README.md +122 -0
- package/binding.gyp +53 -0
- package/deps/machine-guest-tools/AUTHORS +7 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/abi.h +589 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/buf.h +82 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/io.h +168 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/keccak.h +131 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/merkle.h +118 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/rollup.h +260 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/util.h +34 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/src/abi.c +315 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/src/buf.c +121 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/src/io-mock.c +319 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/src/io.c +164 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/src/keccak.c +156 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/src/merkle.c +202 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/src/rollup.c +455 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/src/util.c +52 -0
- package/lib/index.d.mts +18 -0
- package/lib/index.d.ts +162 -0
- package/lib/index.js +230 -0
- package/lib/index.mjs +19 -0
- package/package.json +70 -0
- package/prebuilds/darwin-arm64/@deroll+cmio.node +0 -0
- package/src/addon.cc +411 -0
|
@@ -0,0 +1,589 @@
|
|
|
1
|
+
/* Copyright Cartesi and individual authors (see AUTHORS)
|
|
2
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
/** @file
|
|
17
|
+
* @defgroup libcmt_abi abi
|
|
18
|
+
*
|
|
19
|
+
* This is a C library to encode and decode Ethereum Virtual Machine (EVM)
|
|
20
|
+
* calldata. This format is used to interacts with contracts in the Ethereum
|
|
21
|
+
* ecosystem.
|
|
22
|
+
*
|
|
23
|
+
* We will cover the basic concepts required to use the API we provide, but for
|
|
24
|
+
* a complete reference consult the solidity specification, it can be found
|
|
25
|
+
* here: https://docs.soliditylang.org/en/latest/abi-spec.html
|
|
26
|
+
*
|
|
27
|
+
* ## Function Selector {#funsel}
|
|
28
|
+
*
|
|
29
|
+
* 4 bytes that identify the function name and parameter types. This is used to
|
|
30
|
+
* distinguish between different formats. To compute it, take the four first
|
|
31
|
+
* bytes of the `keccak` digest of the solidity function declaration. It should
|
|
32
|
+
* respect a canonical format and such as having no the variable names, check
|
|
33
|
+
* docs for details. For reference, for a hypotetical "FunctionName" function,
|
|
34
|
+
* it should look something like this:
|
|
35
|
+
* `keccak("FunctionName(type1,type2,...,typeN)");`
|
|
36
|
+
*
|
|
37
|
+
* ## Data Sections {#sections}
|
|
38
|
+
*
|
|
39
|
+
* After the function selector, we can start encoding the function parameters.
|
|
40
|
+
* One by one, left to right in two sections. `Static` for fixed sized values.
|
|
41
|
+
* Think ints, bools, addresses, offsets, etc. Then `Dynamic` for variable
|
|
42
|
+
* sized data such as the contents of @b bytes. Values that need a dynamic
|
|
43
|
+
* section will also have an entry in the static section.
|
|
44
|
+
*
|
|
45
|
+
* ### Static Section {#static-section}
|
|
46
|
+
*
|
|
47
|
+
* [uint](@ref cmt_abi_put_uint), [bool](@ref cmt_abi_put_bool) and
|
|
48
|
+
* [address](@ref cmt_abi_put_address) values are encoded directly in the
|
|
49
|
+
* static section. In addition to those, @b bytes gets an entry in both
|
|
50
|
+
* sections. The static part is done with [this](@ref cmt_abi_put_bytes_s) call.
|
|
51
|
+
*
|
|
52
|
+
* ### Dynamic Section {#dynamic-section}
|
|
53
|
+
*
|
|
54
|
+
* The Dynamic section encodes the contents of variable sized types. Every entry
|
|
55
|
+
* in this section requires a corresponding entry in the static section as well.
|
|
56
|
+
*
|
|
57
|
+
* So types with variable size are encoded in both sections.
|
|
58
|
+
*
|
|
59
|
+
* - `static` section gets some kind of reference / offset to the dynamic section.
|
|
60
|
+
* - `dynamic` section gets the actual contents
|
|
61
|
+
*
|
|
62
|
+
* In more concrete terms, the @b bytes type is encoded first with a call to @ref
|
|
63
|
+
* cmt_abi_put_bytes_s for its `static` section part and then with a call to
|
|
64
|
+
* @ref cmt_abi_put_bytes_d for its `dynamic` section part.
|
|
65
|
+
*
|
|
66
|
+
* ## Encoder
|
|
67
|
+
*
|
|
68
|
+
* Lets look at some code starting with a simple case. A function that encodes
|
|
69
|
+
* the function selector and a single @b address value into the buffer:
|
|
70
|
+
*
|
|
71
|
+
* @includelineno "examples/abi_encode_000.c"
|
|
72
|
+
*
|
|
73
|
+
* For @b bytes, we need both sections. static and dynamic.
|
|
74
|
+
*
|
|
75
|
+
* @includelineno "examples/abi_encode_001.c"
|
|
76
|
+
*
|
|
77
|
+
* For multiple values in the dynamic section, do them in order.
|
|
78
|
+
*
|
|
79
|
+
* @includelineno "examples/abi_encode_002.c"
|
|
80
|
+
*
|
|
81
|
+
* ## Decoder
|
|
82
|
+
*
|
|
83
|
+
* Lets look at code that decodes the examples above. We'll _check_ instead of
|
|
84
|
+
* _put_ for funsel. And _get_ instead _put_ for most of everything else.
|
|
85
|
+
*
|
|
86
|
+
* @includelineno "examples/abi_decode_000.c"
|
|
87
|
+
*
|
|
88
|
+
* Retrieving @b bytes is a bit different since the API doesn't do dynamic
|
|
89
|
+
* memory allocation. @b data points inside the @p rd buffer itself, into its
|
|
90
|
+
* dynamic section. This makes the API very lightweight and fast but requires
|
|
91
|
+
* care in its usage. If @p rd gets free'd or reused while there is still a
|
|
92
|
+
* reference to @p data, we'll get memory corruption. If in doublt create a
|
|
93
|
+
* copy of @p data and use it instead.
|
|
94
|
+
*
|
|
95
|
+
* @includelineno "examples/abi_decode_001.c"
|
|
96
|
+
*
|
|
97
|
+
* ## Complete
|
|
98
|
+
*
|
|
99
|
+
* Lets look at some code on how to tie everything together. We'll build a @b
|
|
100
|
+
* echo of sorts that decodes the contents of @p rd and re-encodes it into @p
|
|
101
|
+
* wr. We'll use previous examples as a starting point to implement encode_echo
|
|
102
|
+
* and decode_echo. With the entrypoint being @p f. We'll use @ref
|
|
103
|
+
* cmt_abi_peek_funsel to switch on the message function selector, only one
|
|
104
|
+
* valid case in this example. Decode and if we succeed, encode it back. If the
|
|
105
|
+
* caller needs the encoded size, we can compute it by storing @p wr at the
|
|
106
|
+
* start and compute the difference.
|
|
107
|
+
*
|
|
108
|
+
* @includelineno "examples/abi_multi.c"
|
|
109
|
+
*
|
|
110
|
+
* @ingroup libcmt
|
|
111
|
+
* @{ */
|
|
112
|
+
#ifndef CMT_ABI_H
|
|
113
|
+
#define CMT_ABI_H
|
|
114
|
+
#include "buf.h"
|
|
115
|
+
#include <stdbool.h>
|
|
116
|
+
|
|
117
|
+
enum {
|
|
118
|
+
CMT_ABI_U256_LENGTH = 32, /**< length of a evm word in bytes */
|
|
119
|
+
CMT_ABI_ADDRESS_LENGTH = 20, /**< length of a evm address in bytes */
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/** Compile time equivalent to @ref cmt_abi_funsel
|
|
123
|
+
* @note don't port. use @ref cmt_abi_funsel instead */
|
|
124
|
+
#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
|
|
125
|
+
#define CMT_ABI_FUNSEL(A, B, C, D) \
|
|
126
|
+
(((uint32_t) (D) << 000) | ((uint32_t) (C) << 010) | ((uint32_t) (B) << 020) | ((uint32_t) (A) << 030))
|
|
127
|
+
#else
|
|
128
|
+
#define CMT_ABI_FUNSEL(A, B, C, D) \
|
|
129
|
+
(((uint32_t) (A) << 000) | ((uint32_t) (B) << 010) | ((uint32_t) (C) << 020) | ((uint32_t) (D) << 030))
|
|
130
|
+
#endif
|
|
131
|
+
|
|
132
|
+
/** EVM address */
|
|
133
|
+
typedef struct cmt_abi_address {
|
|
134
|
+
uint8_t data[CMT_ABI_ADDRESS_LENGTH];
|
|
135
|
+
} cmt_abi_address_t;
|
|
136
|
+
|
|
137
|
+
/** EVM u256 in big endian format */
|
|
138
|
+
typedef struct cmt_abi_u256 {
|
|
139
|
+
uint8_t data[CMT_ABI_U256_LENGTH];
|
|
140
|
+
} cmt_abi_u256_t;
|
|
141
|
+
|
|
142
|
+
typedef struct cmt_abi_bytes {
|
|
143
|
+
size_t length;
|
|
144
|
+
void *data;
|
|
145
|
+
} cmt_abi_bytes_t;
|
|
146
|
+
|
|
147
|
+
/** Create a function selector from an array of bytes
|
|
148
|
+
* @param [in] funsel function selector bytes
|
|
149
|
+
* @return
|
|
150
|
+
* - function selector converted to big endian (as expected by EVM) */
|
|
151
|
+
uint32_t cmt_abi_funsel(uint8_t a, uint8_t b, uint8_t c, uint8_t d);
|
|
152
|
+
|
|
153
|
+
/** Create a frame for the dynamic section. Read the EVM ABI for the details
|
|
154
|
+
* @param [in] me reader or writer buffer
|
|
155
|
+
* @param [out] frame start of the parameters frame
|
|
156
|
+
*
|
|
157
|
+
* @return
|
|
158
|
+
* | | |
|
|
159
|
+
* |--:|-----------------------------|
|
|
160
|
+
* | 0| success |
|
|
161
|
+
* |< 0| failure with a -errno value |
|
|
162
|
+
*/
|
|
163
|
+
int cmt_abi_mark_frame(const cmt_buf_t *me, cmt_buf_t *frame);
|
|
164
|
+
|
|
165
|
+
// put section ---------------------------------------------------------------
|
|
166
|
+
|
|
167
|
+
/** Encode a function selector into the buffer @p me
|
|
168
|
+
*
|
|
169
|
+
* @param [in,out] me a initialized buffer working as iterator
|
|
170
|
+
* @param [in] funsel function selector
|
|
171
|
+
*
|
|
172
|
+
* @return
|
|
173
|
+
* | | |
|
|
174
|
+
* |--:|-----------------------------|
|
|
175
|
+
* | 0| success |
|
|
176
|
+
* |< 0| failure with a -errno value |
|
|
177
|
+
*
|
|
178
|
+
* @note A function selector can be compute it with: @ref cmt_keccak_funsel.
|
|
179
|
+
* It is always represented in big endian. */
|
|
180
|
+
int cmt_abi_put_funsel(cmt_buf_t *me, uint32_t funsel);
|
|
181
|
+
|
|
182
|
+
/** Encode a native endianness unsigned integer of up to 32bytes of data into
|
|
183
|
+
* the buffer
|
|
184
|
+
*
|
|
185
|
+
* @param [in,out] me a initialized buffer working as iterator
|
|
186
|
+
* @param [in] n size of @p data in bytes
|
|
187
|
+
* @param [in] data pointer to a integer
|
|
188
|
+
*
|
|
189
|
+
* @return
|
|
190
|
+
* | | |
|
|
191
|
+
* |-------:|------------------------------------------|
|
|
192
|
+
* | 0| success |
|
|
193
|
+
* |-ENOBUFS| no space left in @p me |
|
|
194
|
+
* | -EDOM| integer not representable in @p 32 bytes |
|
|
195
|
+
*
|
|
196
|
+
*
|
|
197
|
+
* @code
|
|
198
|
+
* ...
|
|
199
|
+
* cmt_buf_t it = ...;
|
|
200
|
+
* uint64_t x = UINT64_C(0xdeadbeef);
|
|
201
|
+
* cmt_abi_put_uint(&it, sizeof x, &x);
|
|
202
|
+
* ...
|
|
203
|
+
* @endcode */
|
|
204
|
+
int cmt_abi_put_uint(cmt_buf_t *me, size_t data_length, const void *data);
|
|
205
|
+
|
|
206
|
+
/** Encode a big endian unsigned integer of up to 32bytes of data into the
|
|
207
|
+
* buffer
|
|
208
|
+
*
|
|
209
|
+
* @param [in,out] me a initialized buffer working as iterator
|
|
210
|
+
* @param [in] length size of @p data in bytes
|
|
211
|
+
* @param [in] data pointer to a integer
|
|
212
|
+
*
|
|
213
|
+
* @return
|
|
214
|
+
* | | |
|
|
215
|
+
* |-------:|---------------------------------------------------|
|
|
216
|
+
* | 0| success |
|
|
217
|
+
* |-ENOBUFS| no space left in @p me |
|
|
218
|
+
* | -EDOM| integer not representable in @p data_length bytes |
|
|
219
|
+
*
|
|
220
|
+
* @code
|
|
221
|
+
* ...
|
|
222
|
+
* cmt_buf_t it = ...;
|
|
223
|
+
* uint8_t small[] = {
|
|
224
|
+
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
225
|
+
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
226
|
+
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
227
|
+
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
|
228
|
+
* };
|
|
229
|
+
* cmt_abi_put_uint(&it, sizeof small, &small);
|
|
230
|
+
* ...
|
|
231
|
+
* uint8_t big[] = {
|
|
232
|
+
* 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
233
|
+
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
234
|
+
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
235
|
+
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
236
|
+
* };
|
|
237
|
+
* cmt_abi_put_uint(&it, sizeof big, &big);
|
|
238
|
+
* @endcode
|
|
239
|
+
* @note This function takes care of endianness conversions */
|
|
240
|
+
int cmt_abi_put_uint_be(cmt_buf_t *me, size_t data_length, const void *data);
|
|
241
|
+
|
|
242
|
+
/** Encode a @ref cmt_abi_u256_t into the buffer
|
|
243
|
+
*
|
|
244
|
+
* @param [in,out] me a initialized buffer working as iterator
|
|
245
|
+
* @param [in] data pointer to a @ref cmt_abi_u256_t
|
|
246
|
+
*
|
|
247
|
+
* @return
|
|
248
|
+
* | | |
|
|
249
|
+
* |-------:|---------------------------------------------------|
|
|
250
|
+
* | 0| success |
|
|
251
|
+
* |-ENOBUFS| no space left in @p me | */
|
|
252
|
+
int cmt_abi_put_uint256(cmt_buf_t *me, const cmt_abi_u256_t *value);
|
|
253
|
+
|
|
254
|
+
/** Encode a bool into the buffer
|
|
255
|
+
*
|
|
256
|
+
* @param [in,out] me a initialized buffer working as iterator
|
|
257
|
+
* @param [in] value boolean value
|
|
258
|
+
*
|
|
259
|
+
* @return
|
|
260
|
+
* | | |
|
|
261
|
+
* |-------:|------------------------|
|
|
262
|
+
* | 0| success |
|
|
263
|
+
* |-ENOBUFS| no space left in @p me |
|
|
264
|
+
*
|
|
265
|
+
* @code
|
|
266
|
+
* ...
|
|
267
|
+
* cmt_buf_t it = ...;
|
|
268
|
+
* cmt_abi_put_bool(&it, true);
|
|
269
|
+
* ...
|
|
270
|
+
* @endcode
|
|
271
|
+
* @note This function takes care of endianness conversions */
|
|
272
|
+
int cmt_abi_put_bool(cmt_buf_t *me, bool value);
|
|
273
|
+
|
|
274
|
+
/** Encode @p address (exactly @ref CMT_ABI_ADDRESS_LENGTH bytes) into the buffer
|
|
275
|
+
*
|
|
276
|
+
* @param [in,out] me initialized buffer
|
|
277
|
+
* @param [in] address a value of type @ref cmt_abi_address_t
|
|
278
|
+
*
|
|
279
|
+
* @return
|
|
280
|
+
* | | |
|
|
281
|
+
* |-------:|------------------------|
|
|
282
|
+
* | 0| success |
|
|
283
|
+
* |-ENOBUFS| no space left in @p me | */
|
|
284
|
+
int cmt_abi_put_address(cmt_buf_t *me, const cmt_abi_address_t *address);
|
|
285
|
+
|
|
286
|
+
/** Encode the static part of @b bytes into the message,
|
|
287
|
+
* used in conjunction with @ref cmt_abi_put_bytes_d
|
|
288
|
+
*
|
|
289
|
+
* @param [in,out] me initialized buffer
|
|
290
|
+
* @param [out] offset initialize for @ref cmt_abi_put_bytes_d
|
|
291
|
+
*
|
|
292
|
+
* @return
|
|
293
|
+
* | | |
|
|
294
|
+
* |-------:|------------------------|
|
|
295
|
+
* | 0| success |
|
|
296
|
+
* |-ENOBUFS| no space left in @p me | */
|
|
297
|
+
int cmt_abi_put_bytes_s(cmt_buf_t *me, cmt_buf_t *offset);
|
|
298
|
+
|
|
299
|
+
/** Encode the dynamic part of @b bytes into the message,
|
|
300
|
+
* used in conjunction with @ref cmt_abi_put_bytes_d
|
|
301
|
+
*
|
|
302
|
+
* @param [in,out] me initialized buffer
|
|
303
|
+
* @param [in] offset initialized from @ref cmt_abi_put_bytes_h
|
|
304
|
+
* @param [in] n size of @b data
|
|
305
|
+
* @param [in] data array of bytes
|
|
306
|
+
* @param [in] start starting point for offset calculation (first byte after funsel)
|
|
307
|
+
*
|
|
308
|
+
* @return
|
|
309
|
+
* | | |
|
|
310
|
+
* |-------:|------------------------|
|
|
311
|
+
* | 0| success |
|
|
312
|
+
* |-ENOBUFS| no space left in @p me | */
|
|
313
|
+
//int cmt_abi_put_bytes_d(cmt_buf_t *me, cmt_buf_t *offset, size_t n, const void *data, const void *start);
|
|
314
|
+
int cmt_abi_put_bytes_d(cmt_buf_t *me, cmt_buf_t *offset, const cmt_buf_t *frame, const cmt_abi_bytes_t *payload);
|
|
315
|
+
|
|
316
|
+
/** Reserve @b n bytes of data from the buffer into @b res to be filled by the
|
|
317
|
+
* caller
|
|
318
|
+
*
|
|
319
|
+
* @param [in,out] me initialized buffer
|
|
320
|
+
* @param [in] n amount of bytes to reserve
|
|
321
|
+
* @param [out] res slice of bytes extracted from @p me
|
|
322
|
+
* @param [in] start starting point for offset calculation (first byte after funsel)
|
|
323
|
+
*
|
|
324
|
+
* @return
|
|
325
|
+
* | | |
|
|
326
|
+
* |-------:|------------------------|
|
|
327
|
+
* | 0| success |
|
|
328
|
+
* |-ENOBUFS| no space left in @p me |
|
|
329
|
+
*
|
|
330
|
+
* @note @p me must outlive @p res.
|
|
331
|
+
* Create a duplicate otherwise */
|
|
332
|
+
int cmt_abi_reserve_bytes_d(cmt_buf_t *me, cmt_buf_t *of, size_t n, cmt_buf_t *out, const void *start);
|
|
333
|
+
|
|
334
|
+
// get section ---------------------------------------------------------------
|
|
335
|
+
|
|
336
|
+
/** Read the funsel without consuming it from the buffer @p me, 0 is returned
|
|
337
|
+
* if there are less than 4 bytes in the buffer.
|
|
338
|
+
*
|
|
339
|
+
* @return
|
|
340
|
+
* | | |
|
|
341
|
+
* |-------:|-------------------------|
|
|
342
|
+
* | != 0| function selector value |
|
|
343
|
+
* | 0| failure |
|
|
344
|
+
*
|
|
345
|
+
* @code
|
|
346
|
+
* ...
|
|
347
|
+
* if (cmt_buf_length(it) < 4)
|
|
348
|
+
* return EXIT_FAILURE;
|
|
349
|
+
* switch (cmt_abi_peek_funsel(it) {
|
|
350
|
+
* case CMT_ABI_FUNSEL(...): // known type, try to parse it
|
|
351
|
+
* case CMT_ABI_FUNSEL(...): // known type, try to parse it
|
|
352
|
+
* default:
|
|
353
|
+
* return EXIT_FAILURE;
|
|
354
|
+
* }
|
|
355
|
+
* @endcode */
|
|
356
|
+
uint32_t cmt_abi_peek_funsel(cmt_buf_t *me);
|
|
357
|
+
|
|
358
|
+
/** Consume funsel from the buffer @p me and ensure it matches @p expected_funsel
|
|
359
|
+
*
|
|
360
|
+
* @param [in,out] me initialized buffer
|
|
361
|
+
* @param [in] expected expected function selector
|
|
362
|
+
*
|
|
363
|
+
* @return
|
|
364
|
+
* | | |
|
|
365
|
+
* |-------:|------------------------|
|
|
366
|
+
* | 0| success |
|
|
367
|
+
* |-ENOBUFS| no space left in @p me |
|
|
368
|
+
* |-EBADMSG| funsel mismatch | */
|
|
369
|
+
int cmt_abi_check_funsel(cmt_buf_t *me, uint32_t expected);
|
|
370
|
+
|
|
371
|
+
/** Decode a @ref cmt_abi_u256_t from the buffer
|
|
372
|
+
*
|
|
373
|
+
* @param [in,out] me initialized buffer
|
|
374
|
+
* @param [out] data value of type @ref cmt_abi_u256_t
|
|
375
|
+
*
|
|
376
|
+
* @return
|
|
377
|
+
* | | |
|
|
378
|
+
* |-------:|---------------------------------------------------|
|
|
379
|
+
* | 0| success |
|
|
380
|
+
* |-ENOBUFS| no space left in @p me | */
|
|
381
|
+
int cmt_abi_get_uint256(cmt_buf_t *me, cmt_abi_u256_t *value);
|
|
382
|
+
|
|
383
|
+
/** Decode a unsigned integer of up to 32bytes, in native endianness, from the buffer
|
|
384
|
+
*
|
|
385
|
+
* @param [in,out] me initialized buffer
|
|
386
|
+
* @param [in] n size of @p data in bytes
|
|
387
|
+
* @param [out] data pointer to a integer
|
|
388
|
+
*
|
|
389
|
+
* @return
|
|
390
|
+
* | | |
|
|
391
|
+
* |-------:|---------------------------------------------------|
|
|
392
|
+
* | 0| success |
|
|
393
|
+
* |-ENOBUFS| no space left in @p me |
|
|
394
|
+
* | -EDOM| integer not representable in @p data_length bytes | */
|
|
395
|
+
int cmt_abi_get_uint(cmt_buf_t *me, size_t n, void *data);
|
|
396
|
+
|
|
397
|
+
/** Decode @p length big-endian bytes, up to 32, from the buffer into @p data
|
|
398
|
+
*
|
|
399
|
+
* @param [in,out] me initialized buffer
|
|
400
|
+
* @param [in] length size of @p data in bytes
|
|
401
|
+
* @param [out] data pointer to a integer
|
|
402
|
+
*
|
|
403
|
+
* @return
|
|
404
|
+
* | | |
|
|
405
|
+
* |-------:|---------------------------------------------------|
|
|
406
|
+
* | 0| success |
|
|
407
|
+
* |-ENOBUFS| no space left in @p me |
|
|
408
|
+
* | -EDOM| integer not representable in @p data_length bytes | */
|
|
409
|
+
int cmt_abi_get_uint_be(cmt_buf_t *me, size_t n, void *data);
|
|
410
|
+
|
|
411
|
+
/** Consume and decode a bool from the buffer
|
|
412
|
+
*
|
|
413
|
+
* @param [in,out] me a initialized buffer working as iterator
|
|
414
|
+
* @param [out] value boolean value
|
|
415
|
+
*
|
|
416
|
+
* @return
|
|
417
|
+
* | | |
|
|
418
|
+
* |-------:|------------------------|
|
|
419
|
+
* | 0| success |
|
|
420
|
+
* |-ENOBUFS| no space left in @p me |
|
|
421
|
+
*
|
|
422
|
+
* @code
|
|
423
|
+
* ...
|
|
424
|
+
* cmt_buf_t it = ...;
|
|
425
|
+
* bool value;
|
|
426
|
+
* int rc = cmt_abi_put_bool(&it, &value);
|
|
427
|
+
* assert(rc == 0);
|
|
428
|
+
* ...
|
|
429
|
+
* @endcode
|
|
430
|
+
* @note This function takes care of endianness conversions */
|
|
431
|
+
int cmt_abi_get_bool(cmt_buf_t *me, bool *value);
|
|
432
|
+
|
|
433
|
+
/** Consume and decode @b address from the buffer
|
|
434
|
+
*
|
|
435
|
+
* @param [in,out] me initialized buffer
|
|
436
|
+
* @param [out] address value of type @ref cmt_abi_address_t
|
|
437
|
+
*
|
|
438
|
+
* @return
|
|
439
|
+
* | | |
|
|
440
|
+
* |-------:|------------------------|
|
|
441
|
+
* | 0| success |
|
|
442
|
+
* |-ENOBUFS| no space left in @p me | */
|
|
443
|
+
int cmt_abi_get_address(cmt_buf_t *me, cmt_abi_address_t *value);
|
|
444
|
+
|
|
445
|
+
/** Create a frame of reference for the dynamic section
|
|
446
|
+
*
|
|
447
|
+
* @param [in,out] me initialized buffer
|
|
448
|
+
* @param [out] frame used when encoding dynamic values
|
|
449
|
+
* @return
|
|
450
|
+
* | | |
|
|
451
|
+
* |-------:|------------------------|
|
|
452
|
+
* | 0| success |
|
|
453
|
+
* |-ENOBUFS| no space left in @p me | */
|
|
454
|
+
int cmt_abi_start_frame(cmt_buf_t *me, void *frame);
|
|
455
|
+
|
|
456
|
+
/** Consume and decode the offset @p of
|
|
457
|
+
*
|
|
458
|
+
* @param [in,out] me initialized buffer
|
|
459
|
+
* @param [out] of offset to @p bytes data, for use in conjunction with @ref cmt_abi_get_bytes_d
|
|
460
|
+
*
|
|
461
|
+
* @return
|
|
462
|
+
* | | |
|
|
463
|
+
* |-------:|------------------------|
|
|
464
|
+
* | 0| success |
|
|
465
|
+
* |-ENOBUFS| no space left in @p me | */
|
|
466
|
+
int cmt_abi_get_bytes_s(cmt_buf_t *me, cmt_buf_t of[1]);
|
|
467
|
+
|
|
468
|
+
/** Decode @b bytes from the buffer by taking a pointer to its contents.
|
|
469
|
+
*
|
|
470
|
+
* @param [in] start initialized buffer (from the start after funsel)
|
|
471
|
+
* @param [out] of offset to @p bytes data
|
|
472
|
+
* @param [out] n amount of data available in @b bytes
|
|
473
|
+
* @param [out] data memory range with contents
|
|
474
|
+
*
|
|
475
|
+
* @return
|
|
476
|
+
* | | |
|
|
477
|
+
* |-------:|------------------------|
|
|
478
|
+
* | 0| success |
|
|
479
|
+
* |-ENOBUFS| no space left in @p me |
|
|
480
|
+
*
|
|
481
|
+
* @note @p of can be initialized by calling @ref cmt_abi_get_bytes_s */
|
|
482
|
+
int cmt_abi_get_bytes_d(const cmt_buf_t *start, cmt_buf_t of[1], size_t *n, void **data);
|
|
483
|
+
|
|
484
|
+
/** Decode @b bytes from the buffer by taking a pointer to its contents.
|
|
485
|
+
*
|
|
486
|
+
* @param [in] start initialized buffer (from the start after funsel)
|
|
487
|
+
* @param [out] of offset to @p bytes data
|
|
488
|
+
* @param [out] n amount of data available in @b bytes
|
|
489
|
+
* @param [out] bytes memory range with contents
|
|
490
|
+
*
|
|
491
|
+
* @return
|
|
492
|
+
* | | |
|
|
493
|
+
* |-------:|------------------------|
|
|
494
|
+
* | 0| success |
|
|
495
|
+
* |-ENOBUFS| no space left in @p me |
|
|
496
|
+
*
|
|
497
|
+
* @note @p of can be initialized by calling @ref cmt_abi_get_bytes_s */
|
|
498
|
+
int cmt_abi_peek_bytes_d(const cmt_buf_t *start, cmt_buf_t of[1], cmt_buf_t *bytes);
|
|
499
|
+
|
|
500
|
+
// raw codec section --------------------------------------------------------
|
|
501
|
+
|
|
502
|
+
/** Encode @p n bytes of @p data into @p out (up to 32).
|
|
503
|
+
*
|
|
504
|
+
* @param [in] n size of @p data in bytes
|
|
505
|
+
* @param [in] data integer value to encode into @p out
|
|
506
|
+
* @param [out] out encoded result
|
|
507
|
+
*
|
|
508
|
+
* @return
|
|
509
|
+
* | | |
|
|
510
|
+
* |-------:|---------------------------------------------------|
|
|
511
|
+
* | 0| success |
|
|
512
|
+
* | -EDOM| integer not representable in @p data_length bytes | */
|
|
513
|
+
int cmt_abi_encode_uint(size_t n, const void *data, uint8_t out[CMT_ABI_U256_LENGTH]);
|
|
514
|
+
|
|
515
|
+
/** Encode @p n bytes of @p data into @p out (up to 32) in reverse order.
|
|
516
|
+
*
|
|
517
|
+
* @param [in] n size of @p data in bytes
|
|
518
|
+
* @param [in] data integer value to encode into @p out
|
|
519
|
+
* @param [out] out encoded result
|
|
520
|
+
*
|
|
521
|
+
* @return
|
|
522
|
+
* | | |
|
|
523
|
+
* |-------:|---------------------------------------------------|
|
|
524
|
+
* | 0| success |
|
|
525
|
+
* | -EDOM| integer not representable in @p data_length bytes |
|
|
526
|
+
*
|
|
527
|
+
* @note use @ref cmt_abi_encode_uint instead */
|
|
528
|
+
int cmt_abi_encode_uint_nr(size_t n, const uint8_t *data, uint8_t out[CMT_ABI_U256_LENGTH]);
|
|
529
|
+
|
|
530
|
+
/** Encode @p n bytes of @p data into @p out (up to 32) in normal order.
|
|
531
|
+
*
|
|
532
|
+
* @param [in] n size of @p data in bytes
|
|
533
|
+
* @param [in] data integer value to encode into @p out
|
|
534
|
+
* @param [out] out encoded result
|
|
535
|
+
*
|
|
536
|
+
* @return
|
|
537
|
+
* | | |
|
|
538
|
+
* |-------:|---------------------------------------------------|
|
|
539
|
+
* | 0| success |
|
|
540
|
+
* | -EDOM| integer not representable in @p data_length bytes |
|
|
541
|
+
*
|
|
542
|
+
* @note use @ref cmt_abi_encode_uint instead */
|
|
543
|
+
int cmt_abi_encode_uint_nn(size_t n, const uint8_t *data, uint8_t out[CMT_ABI_U256_LENGTH]);
|
|
544
|
+
|
|
545
|
+
/** Decode @p n bytes of @p data into @p out (up to 32).
|
|
546
|
+
*
|
|
547
|
+
* @param [in] data integer value to decode into @p out
|
|
548
|
+
* @param [in] n size of @p data in bytes
|
|
549
|
+
* @param [out] out decoded output
|
|
550
|
+
*
|
|
551
|
+
* @return
|
|
552
|
+
* | | |
|
|
553
|
+
* |-------:|---------------------------------------------------|
|
|
554
|
+
* | 0| success |
|
|
555
|
+
* | -EDOM| integer not representable in @p data_length bytes | */
|
|
556
|
+
int cmt_abi_decode_uint(const uint8_t data[CMT_ABI_U256_LENGTH], size_t n, uint8_t *out);
|
|
557
|
+
|
|
558
|
+
/** Decode @p n bytes of @p data into @p out (up to 32) in reverse order.
|
|
559
|
+
*
|
|
560
|
+
* @param [in] data integer value to decode into @p out
|
|
561
|
+
* @param [in] n size of @p data in bytes
|
|
562
|
+
* @param [out] out decoded output
|
|
563
|
+
*
|
|
564
|
+
* @return
|
|
565
|
+
* | | |
|
|
566
|
+
* |-------:|---------------------------------------------------|
|
|
567
|
+
* | 0| success |
|
|
568
|
+
* | -EDOM| integer not representable in @p data_length bytes |
|
|
569
|
+
*
|
|
570
|
+
* @note if in doubt, use @ref cmt_abi_decode_uint */
|
|
571
|
+
int cmt_abi_decode_uint_nr(const uint8_t data[CMT_ABI_U256_LENGTH], size_t n, uint8_t *out);
|
|
572
|
+
|
|
573
|
+
/** Decode @p n bytes of @p data into @p out (up to 32) in normal order.
|
|
574
|
+
*
|
|
575
|
+
* @param [in] data integer value to decode into @p out
|
|
576
|
+
* @param [in] n size of @p data in bytes
|
|
577
|
+
* @param [out] out decoded output
|
|
578
|
+
*
|
|
579
|
+
* @return
|
|
580
|
+
* | | |
|
|
581
|
+
* |-------:|---------------------------------------------------|
|
|
582
|
+
* | 0| success |
|
|
583
|
+
* | -EDOM| integer not representable in @p data_length bytes |
|
|
584
|
+
*
|
|
585
|
+
* @note if in doubt, use @ref cmt_abi_decode_uint */
|
|
586
|
+
int cmt_abi_decode_uint_nn(const uint8_t data[CMT_ABI_U256_LENGTH], size_t n, uint8_t *out);
|
|
587
|
+
|
|
588
|
+
#endif /* CMT_ABI_H */
|
|
589
|
+
/** @} */
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/* Copyright Cartesi and individual authors (see AUTHORS)
|
|
2
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
/** @file
|
|
17
|
+
* @defgroup libcmt_buf buf
|
|
18
|
+
* slice of contiguous memory
|
|
19
|
+
*
|
|
20
|
+
* @ingroup libcmt
|
|
21
|
+
* @{ */
|
|
22
|
+
#ifndef CMT_BUF_H
|
|
23
|
+
#define CMT_BUF_H
|
|
24
|
+
#include <stdbool.h>
|
|
25
|
+
#include <stddef.h>
|
|
26
|
+
#include <stdint.h>
|
|
27
|
+
|
|
28
|
+
/** A slice of contiguous memory from @b begin to @b end, as an open range.
|
|
29
|
+
* Size can be taken with: `end - begin`.
|
|
30
|
+
*
|
|
31
|
+
* `begin == end` indicate an empty buffer */
|
|
32
|
+
typedef struct {
|
|
33
|
+
uint8_t *begin; /**< begin of memory region */
|
|
34
|
+
uint8_t *end; /**< end of memory region */
|
|
35
|
+
} cmt_buf_t;
|
|
36
|
+
|
|
37
|
+
/** Initialize @p me buffer backed by @p data, @p length bytes in size
|
|
38
|
+
*
|
|
39
|
+
* @param [out] me a uninitialized instance
|
|
40
|
+
* @param [in] length size in bytes of @b data
|
|
41
|
+
* @param [in] data the backing memory to be used.
|
|
42
|
+
*
|
|
43
|
+
* @note @p data memory must outlive @p me.
|
|
44
|
+
* user must copy the contents otherwise */
|
|
45
|
+
void cmt_buf_init(cmt_buf_t *me, size_t length, void *data);
|
|
46
|
+
|
|
47
|
+
/** Split a buffer in two, @b lhs with @b lhs_length bytes and @b rhs with the rest
|
|
48
|
+
*
|
|
49
|
+
* @param [in,out] me initialized buffer
|
|
50
|
+
* @param [in] lhs_length bytes in @b lhs
|
|
51
|
+
* @param [out] lhs left hand side
|
|
52
|
+
* @param [out] rhs right hand side
|
|
53
|
+
*
|
|
54
|
+
* @return
|
|
55
|
+
* - 0 success
|
|
56
|
+
* - negative value on error. -ENOBUFS when length(me) < lhs_length. */
|
|
57
|
+
int cmt_buf_split(const cmt_buf_t *me, size_t lhs_length, cmt_buf_t *lhs, cmt_buf_t *rhs);
|
|
58
|
+
|
|
59
|
+
/** Length in bytes of @p me
|
|
60
|
+
*
|
|
61
|
+
* @param [in] me initialized buffer
|
|
62
|
+
*
|
|
63
|
+
* @return
|
|
64
|
+
* - size in bytes */
|
|
65
|
+
size_t cmt_buf_length(const cmt_buf_t *me);
|
|
66
|
+
|
|
67
|
+
/** Print the contents of @b me buffer to stdout
|
|
68
|
+
*
|
|
69
|
+
* @param [in] begin start of memory region
|
|
70
|
+
* @param [in] end end of memory region
|
|
71
|
+
* @param [in] bytes_per_line bytes per line (must be a power of 2). */
|
|
72
|
+
void cmt_buf_xxd(void *begin, void *end, int bytes_per_line);
|
|
73
|
+
|
|
74
|
+
/** Take the substring @p x from @p xs start to the first @p , (comma).
|
|
75
|
+
* @param [out] x substring
|
|
76
|
+
* @param [in,out] xs string (iterator)
|
|
77
|
+
*
|
|
78
|
+
* @note @p x points inside @p xs, make a copy if it outlives @p xs. */
|
|
79
|
+
bool cmt_buf_split_by_comma(cmt_buf_t *x, cmt_buf_t *xs);
|
|
80
|
+
|
|
81
|
+
#endif /* CMT_BUF_H */
|
|
82
|
+
/** @} */
|