-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
libdriver #24
libdriver #24
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comments.
b1b3059
to
5050981
Compare
linux/libdriver/base/buf.c
Outdated
} | ||
void evm_buf_xxd(void *p, void *q, int l) | ||
{ | ||
assert(p); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better convert these asserts into returning error codes.
linux/libdriver/ioctl/rollup.c
Outdated
{ | ||
munmap(me->tx->data, me->tx->length); | ||
munmap(me->rx->data, me->rx->length); | ||
close(me->fd); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better to reset all me
fields when uninitializing, in case the user tries to call rollup driver functions again the failure will be more deterministic. A detail is that fd
must not be set to 0, but to -1
.
linux/libdriver/ioctl/rollup.c
Outdated
|
||
void *rollup_driver_get_tx(struct rollup_driver *me, size_t *max) | ||
{ | ||
*max = me->tx->length; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better check if max
is not NULL
, and only set it in this case. Same for the function below.
linux/libdriver/base/keccak.h
Outdated
@@ -0,0 +1,131 @@ | |||
/** @file | |||
* @defgroup libevm_keccak keccak | |||
* Keccak 256 digest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be noted that this implementation does not follow the FIPS-202 based standard (aka finalized NIST SHA-3), it follows the Ethereum Keccak-256.
efc8b50
to
af82b44
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comments.
linux/libdriver/base/merkle.h
Outdated
* | ||
* @param [in] me initialized state | ||
* @param [out] root root hash of the merkle tree */ | ||
void evm_merkle_get(evm_merkle_t *me, uint8_t root[EVM_KECCAK_MDLEN]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we follow the same names as the ones in back-merkle-tree.cpp
from the emulator repo? It's the same functionality, after all. So evm_merkle_get_root_hash
, evm_merkle_push_back
, evm_merkle_push_back_from_data
. I don't think you need evm_merkle_pad_back
, but we might at some point.
linux/libdriver/base/abi.h
Outdated
* @note @p me must outlive @p res. | ||
* Create a duplicate otherwise */ | ||
int | ||
evm_abi_res_bytes_d(evm_buf_t *me, evm_buf_t *of, size_t n, evm_buf_t *out, const void *start); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You really don't like writing. :) I think Eduardo also doesn't like writing long names. But I would use reserve
because most people will think res
means result
.
linux/libdriver/base/abi.h
Outdated
* @param [in] data integer value to decode into @p out | ||
* @param [in] n size of @p data in bytes | ||
* @param [out] out decoded output */ | ||
int evm_abi_dec_uint(const uint8_t data[EVM_WORD_LEN], size_t n, uint8_t out[n]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same for encode
, decode
. In fact, dec
almost always means decrement
, decrease
.
linux/libdriver/base/buf.h
Outdated
/** A slice of contiguous memory from @b p to @b q. | ||
* Size can be taken with: `q - p`. */ | ||
typedef struct { | ||
uint8_t *p; /**< start of memory region */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here as well. Why call something p
and q
if you can write begin
and end
. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And is this inclusive or not? If you use begin
, end
, most C++ programmers will understand that begin == end
means the buffer is empty.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't use end
because it is a reserved keyword for example in Lua, and what if someone wants to bind this to Lua, although this file is to low level to be exposed in Lua. You could prefix with something or could use start
and finish
instead. Just be careful with names that are reserved keywords in other languages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it was in Lua, it would be a field in a table, where end
is not reserved. It’s a bit more awkward to use, but it would still work. I have no idea what the reserved words are in Go or Rust. Anyway, start and finish is better than p and q. ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, changing it to begin
, end
pair.
linux/libdriver/base/buf.h
Outdated
* | ||
* @note @p data memory must outlive @p me. | ||
* user must copy the contents otherwise */ | ||
void evm_buf_init(evm_buf_t *me, size_t n, void *data); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have been using len
or length
for the size of things. Now n
. I suggest you always use length
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I usually like size
because it matches the same number of characters of data
:), but I am fine with any of the names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is some next level OCD right there. 😂 Anyway, I just think we should stick to one word for the concept.
* @return | ||
* - 0 on success | ||
* - negative value on error. errno values from `ioctl` */ | ||
int rollup_driver_revert(struct rollup_driver *me); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, the low-level driver has this more general API, in which you could potentially call revert down some call chain, rather than having to pass some flag up the chain until the call to finish. But the higher level API will still be like the old finish. Is that the idea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct, it also maps closer to the new driver implementation.
* @return | ||
* - pointer to the buffer. | ||
* @note memory is valid until @ref rollup_driver_fini is called. */ | ||
void *rollup_driver_get_tx(struct rollup_driver *me, size_t *max); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd use length
instead of max
, for consistency.
* | ||
* @param [in] me A sucessfuly initialized state by @ref rollup_driver_init | ||
* @param [in] accept @p true if this input was processed successfuly | ||
* @param [out] n size in bytes of the current input. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd use length
again. And would say that is the length in bytes of the newly received input. "Current" is kind of ambiguous in a function that asks for the "next" input.
linux/libdriver/base/rollup.h
Outdated
* - @ref evm_rollup_init */ | ||
typedef struct { | ||
struct rollup_driver rollup_driver[1]; | ||
evm_buf_t tx[1], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you declare tx[1]
as some aesthetic trick so you can write rollup->tx->length
instead of rollup->tx.length
? I have never seen this but I like it. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, basically syntactic sugar to pass F(x) instead of F(&x) everywhere.
linux/libdriver/base/rollup.h
Outdated
|
||
typedef struct { | ||
uint8_t sender[EVM_ADDRESS_LEN]; | ||
uint64_t blockNumber; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we camelCase in any of our APIs. Can se use the same names we used in input_metadata
, to the extent possible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it from here: cartesi/rollups-contracts#84, but I can change to the one we used on the driver. Will cause less changes in other the other tools as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’d stick with the convention in the C structure for input_metadata we had before.
078c405
to
573dc5d
Compare
linux/libcmt/src/merkle.c
Outdated
if (me->n == UINT64_MAX) | ||
return -ENOBUFS; | ||
|
||
unsigned n = ((uint64_t)ffsll(++me->n)-1u); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/merkle.c: In function ‘cmt_merkle_push_back’:
src/merkle.c:37:33: warning: implicit declaration of function ‘ffsll’ [-Wimplicit-function-declaration]
37 | unsigned n = ((uint64_t)ffsll(++me->n)-1u);
cp -f doc/html $(DESTDIR)$(PREFIX)/share/libcmt/html | ||
|
||
clean: | ||
rm -f $(mock_BINS) $(ioctl_BINS) $(tests_BINS) $(tools_BINS) $(OBJ) $(OBJ:%.o=%.d) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not cleaning libcmt_mock.a
yet.
cp -f include/libcmt/*.h $(TARGET_DESTDIR)$(TARGET_PREFIX)/include/libcmt/ | ||
cp -f include/libcmt/ioctl/*.h $(TARGET_DESTDIR)$(TARGET_PREFIX)/include/libcmt/ | ||
mkdir -p $(TARGET_DESTDIR)$(TARGET_PREFIX)/lib/pkgconfig | ||
sed 's|ARG_PREFIX|$(TARGET_PREFIX)|g' tools/templates/libcmt.pc \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The .pc
files in tools/templates/
are missing in the repo.
doc.build: examples.build doc/theme | ||
doxygen doc/Doxyfile | ||
|
||
ioctl.install: libcmt.a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For binding in other programming languages that cannot link to C static libraries, we also want to install a shared library, and we have to make sure all public C APIs are exported to the .so
file, probably need to add CMT_API
define to every public function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that those languages need some extra glue code, the way Lua does it comes to mind.
Wouldn't that be layer responsible for creating the .so
as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many can just dlopen
and FFI. So I think it’s good to have a .so
.
,cmt_rollup_inspect_t *inspect); | ||
|
||
/** | ||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Documentation is missing, making the function not show up in Doxygen.
uint64_t length; | ||
} tx[1], rx[1]; | ||
}; | ||
#include <libcmt/rollup-driver-api.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use relative includes, so we can allow people to copy these include headers in non standard directories.
Unless these files are not going to be installed in the public API, then maybe the should be moved to src
directory.
switch (type) { | ||
case CMT_ROLLUP_ADVANCE_STATE: | ||
memcpy(tx, rx, n); /* echo */ | ||
cmt_rollup_driver_write_output(R, n); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All official examples deserve proper error handling for all functions, to no influence people not caring about errors. I noticed this example is in the documentation, so changes here should reflect the documentation.
It is possible to generate warnings about unused error codes by adding something like
#define CMT_API __attribute__((__warn_unused_result__))
CMT_API int cmt_rollup_driver_write_output(struct cmt_rollup_driver *me, uint64_t n);
just temporality, so you can make sure all the code base is considering the errors.
|
||
void *cmt_rollup_driver_get_tx(struct cmt_rollup_driver *me, size_t *max) | ||
{ | ||
*max = me->tx->length; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should not crash if max
is NULL.
} | ||
|
||
int cmt_rollup_driver_fini(struct cmt_rollup_driver *me) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think all _fini
should invalidate all internal structure fields. I know using me
after finalizing it is stated as undefined, but we should try to minimize the amount of undefined things that could happen. Leaving this way it could crash or not, cleaning it up it's likely that any subsequent function call will either fail or crash.
linux/libcmt/include/libcmt/buf.h
Outdated
/** Declare a cmt_buf_t with stack backed memory. | ||
* @param [in] N - size in bytes | ||
* @note don't port */ | ||
#define CMT_BUF_DECL(S, L) cmt_buf_t S[1] = {{ \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I run clang-tidy
I get this error:
/home/bart/projects/cartesi/machine-emulator-sdk/fs/external/tools/linux/libcmt/tests/abi.c:155:2: warning: The left operand of '+' is a garbage value [clang-analyzer-core.UndefinedBinaryOperatorResult]
CMT_BUF_DECL(b, 64);
^
./include/libcmt/buf.h:26:22: note: expanded from macro 'CMT_BUF_DECL'
.end = (S)->begin + L, \
^
I think these macros may not work as expected everywhere. I would vote to remove them, and make tests, examples and everything use the non macro version.
linux/libcmt/src/rollup.c
Outdated
{ | ||
if (!me) return -EINVAL; | ||
|
||
memcpy(me->tx, data, length); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if length is bigger than tx
buffer? Needs bounds checking before copying.
bf631fc
to
b12cdda
Compare
b12cdda
to
ad2e3eb
Compare
ad2e3eb
to
e26576c
Compare
linux/libcmt/include/libcmt/rollup.h
Outdated
* - 0 success | ||
* - -ENOBUFS no space left in @p me */ | ||
int | ||
cmt_rollup_emit_report(cmt_rollup_t *me |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that the name of this function is wrong. It emits an exception so it probably should be cmt_rollup_emit_exception
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What a terrible copy pasta... nice catch.
d2c9b18
to
c3b1bde
Compare
mock: components can be compiled natively: ioctl: require the cartesi headers and a riscv compiler:
c3b1bde
to
45510a1
Compare
migrated to: #29 |
THIS IS WORK IN PROGRESS
Work being done in the context of: cartesi/machine-emulator#137.
libcmt
.