@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.
Files changed (27) hide show
  1. package/AUTHORS +1 -0
  2. package/LICENSE +202 -0
  3. package/README.md +122 -0
  4. package/binding.gyp +53 -0
  5. package/deps/machine-guest-tools/AUTHORS +7 -0
  6. package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/abi.h +589 -0
  7. package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/buf.h +82 -0
  8. package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/io.h +168 -0
  9. package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/keccak.h +131 -0
  10. package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/merkle.h +118 -0
  11. package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/rollup.h +260 -0
  12. package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/util.h +34 -0
  13. package/deps/machine-guest-tools/sys-utils/libcmt/src/abi.c +315 -0
  14. package/deps/machine-guest-tools/sys-utils/libcmt/src/buf.c +121 -0
  15. package/deps/machine-guest-tools/sys-utils/libcmt/src/io-mock.c +319 -0
  16. package/deps/machine-guest-tools/sys-utils/libcmt/src/io.c +164 -0
  17. package/deps/machine-guest-tools/sys-utils/libcmt/src/keccak.c +156 -0
  18. package/deps/machine-guest-tools/sys-utils/libcmt/src/merkle.c +202 -0
  19. package/deps/machine-guest-tools/sys-utils/libcmt/src/rollup.c +455 -0
  20. package/deps/machine-guest-tools/sys-utils/libcmt/src/util.c +52 -0
  21. package/lib/index.d.mts +18 -0
  22. package/lib/index.d.ts +162 -0
  23. package/lib/index.js +230 -0
  24. package/lib/index.mjs +19 -0
  25. package/package.json +70 -0
  26. package/prebuilds/darwin-arm64/@deroll+cmio.node +0 -0
  27. 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
+ /** @} */