From b63daf0aa6396b7222d588e3d752aad415b301e9 Mon Sep 17 00:00:00 2001 From: Marcelo Politzer <251334+mpolitzer@users.noreply.github.com> Date: Wed, 20 Sep 2023 10:47:02 -0300 Subject: [PATCH] Update yield driver with output unification --- drivers/cartesi/Kconfig | 1 - drivers/cartesi/Makefile | 2 +- drivers/cartesi/libstream256.c | 107 ------ drivers/cartesi/libstream256.h | 31 -- drivers/cartesi/libyield.c | 6 +- drivers/cartesi/rollup.c | 335 +++--------------- include/uapi/linux/cartesi/rollup.h | 98 +---- include/uapi/linux/cartesi/yield.h | 29 +- .../selftests/drivers/cartesi/Makefile | 2 +- .../selftests/drivers/cartesi/rollup_read.c | 57 +++ 10 files changed, 135 insertions(+), 533 deletions(-) delete mode 100644 drivers/cartesi/libstream256.c delete mode 100644 drivers/cartesi/libstream256.h create mode 100644 tools/testing/selftests/drivers/cartesi/rollup_read.c diff --git a/drivers/cartesi/Kconfig b/drivers/cartesi/Kconfig index b1dcb90995f7..46b0a3916fd4 100644 --- a/drivers/cartesi/Kconfig +++ b/drivers/cartesi/Kconfig @@ -17,7 +17,6 @@ config CARTESI_YIELD_DRIVER config CARTESI_ROLLUP_DRIVER bool "Cartesi Machine Rollup Device" depends on CARTESI_MACHINE - depends on CRYPTO_KECCAK default y help Cartesi Machine Rollup Device diff --git a/drivers/cartesi/Makefile b/drivers/cartesi/Makefile index f601cd315347..0cc18a10dde7 100644 --- a/drivers/cartesi/Makefile +++ b/drivers/cartesi/Makefile @@ -1,2 +1,2 @@ obj-$(CONFIG_CARTESI_YIELD_DRIVER) += yield.o libyield.o -obj-$(CONFIG_CARTESI_ROLLUP_DRIVER) += rollup.o libyield.o libstream256.o +obj-$(CONFIG_CARTESI_ROLLUP_DRIVER) += rollup.o libyield.o diff --git a/drivers/cartesi/libstream256.c b/drivers/cartesi/libstream256.c deleted file mode 100644 index 9ffd516aca73..000000000000 --- a/drivers/cartesi/libstream256.c +++ /dev/null @@ -1,107 +0,0 @@ -#include -#include -#include "libstream256.h" - -static bool in_bounds(const struct stream256 *me, size_t bytes) -{ - return me->length - me->offset >= bytes; -} - -static size_t align256(size_t n) -{ - return PTR_ALIGN(n, sizeof(union be256)); -} - -static void pad(struct stream256 *me, size_t n) -{ - size_t misaligned = align256(n) - n; - - if (misaligned) { - memset(me->data + me->offset, 0, misaligned); - me->offset += misaligned; - } -} - -void stream256_reset(struct stream256 *me) -{ - me->offset = 0; -} - -int stream256_encode_u64(struct stream256 *me, uint64_t x) -{ - union be256 u; - - be256_from_u64(&u, x); - if (!in_bounds(me, sizeof(u))) - return -ENOBUFS; - memcpy(me->data + me->offset, u.data, sizeof(u)); - me->offset += sizeof(u); - - return 0; -} - -int stream256_encode_address(struct stream256 *me, uint8_t *p, size_t n) -{ - if (!in_bounds(me, align256(n))) - return -ENOBUFS; - pad(me, n); - memcpy(me->data + me->offset, p, n); - me->offset += n; - - return 0; -} - -int stream256_encode_buf(struct stream256 *me, uint8_t *p, size_t n) -{ - if (!in_bounds(me, align256(n))) - return -ENOBUFS; - memcpy(me->data + me->offset, p, n); - me->offset += n; - pad(me, n); - - return 0; -} - -int stream256_encode_ubuf(struct stream256 *me, uint8_t *p, size_t n) -{ - int ret; - - if (!in_bounds(me, align256(n))) - return -ENOBUFS; - if ((ret = copy_from_user(me->data + me->offset, p, n))) - return ret; - me->offset += n; - pad(me, n); - - return 0; -} - -int stream256_encode_keccak(struct shash_desc *keccak, - const struct stream256 *me, struct stream256 *hash, uint64_t *index) -{ - if (!in_bounds(hash, align256(sizeof(union be256)))) - return -ENOBUFS; - crypto_shash_init(keccak); - crypto_shash_update(keccak, me->data, me->offset); - crypto_shash_final(keccak, hash->data + hash->offset); - if (index) - *index = hash->offset / sizeof(union be256); - hash->offset += sizeof(union be256); - return 0; -} - -void be256_from_u64(union be256 *me, uint64_t x) -{ - me->be64[0] = 0; - me->be64[1] = 0; - me->be64[2] = 0; - me->be64[3] = cpu_to_be64(x); -} - -int be256_to_u64(union be256 *me, uint64_t *x) -{ - if (me->be64[0] || me->be64[1] || me->be64[2]) - return -EDOM; - *x = be64_to_cpu(me->be64[3]); - return 0; -} diff --git a/drivers/cartesi/libstream256.h b/drivers/cartesi/libstream256.h deleted file mode 100644 index bf05d13310a6..000000000000 --- a/drivers/cartesi/libstream256.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef LIBSTREAM_H -#define LIBSTREAM_H -#include -#include - -struct stream256 { - u8 *data; - u64 offset, length; -}; - -union be256 { - __be64 be64[4]; - __be32 be32[8]; - __be16 be16[16]; - u8 data[32]; -}; - -typedef int (*stream256_encode_buf_t)(struct stream256 *me, u8 *p, size_t n); - -void stream256_reset (struct stream256 *me); -int stream256_encode_u64 (struct stream256 *me, u64 x); -int stream256_encode_address(struct stream256 *me, u8 *p, size_t n); -int stream256_encode_buf (struct stream256 *me, u8 *p, size_t n); -int stream256_encode_ubuf(struct stream256 *me, u8 *p, size_t n); -int stream256_encode_keccak(struct shash_desc *keccak, - const struct stream256 *me, struct stream256 *hash, uint64_t*index); - -void be256_from_u64(union be256 *me, uint64_t x); -int be256_to_u64(union be256 *me, uint64_t *x); - -#endif /* LIBSTREAM_H */ diff --git a/drivers/cartesi/libyield.c b/drivers/cartesi/libyield.c index f8cf22e198d4..db90452ed653 100644 --- a/drivers/cartesi/libyield.c +++ b/drivers/cartesi/libyield.c @@ -18,10 +18,8 @@ static int _yield_validate(u64 dev, u64 cmd, u64 reason) if (reason != HTIF_YIELD_REASON_PROGRESS && reason != HTIF_YIELD_REASON_RX_ACCEPTED && reason != HTIF_YIELD_REASON_RX_REJECTED && - reason != HTIF_YIELD_REASON_TX_VOUCHER && - reason != HTIF_YIELD_REASON_TX_NOTICE && - reason != HTIF_YIELD_REASON_TX_REPORT && - reason != HTIF_YIELD_REASON_TX_EXCEPTION) { + reason != HTIF_YIELD_REASON_TX_OUTPUT && + reason != HTIF_YIELD_REASON_TX_VERIFIABLE_OUTPUT) { return -EINVAL; } diff --git a/drivers/cartesi/rollup.c b/drivers/cartesi/rollup.c index 6d80cbb3a58e..f7847a24affd 100644 --- a/drivers/cartesi/rollup.c +++ b/drivers/cartesi/rollup.c @@ -17,7 +17,6 @@ #include #include #include -#include "libstream256.h" #include "libyield.h" #include @@ -30,16 +29,10 @@ /* NOTE: keep in sync with node_paths */ #define TX_BUFFER_INDEX 0 #define RX_BUFFER_INDEX 1 -#define INPUT_METADATA_INDEX 2 -#define VOUCHER_HASHES_INDEX 3 -#define NOTICE_HASHES_INDEX 4 static const char *node_paths[] = { "tx_buffer", "rx_buffer", - "input_metadata", - "voucher_hashes", - "notice_hashes", }; static atomic_t rollup_probe_once = ATOMIC_INIT(1); @@ -47,25 +40,11 @@ static atomic_t rollup_probe_once = ATOMIC_INIT(1); struct rollup_device { struct platform_device *pdev; struct miscdevice mdev; - struct shash_desc *keccak; struct mutex lock; atomic_t rollup_status; int next_request_type; - struct stream256 buffers[ARRAY_SIZE(node_paths)]; -}; - -struct rx_header { - union be256 offset; - union be256 length; -}; - -struct input_metadata_header { - uint8_t padding[sizeof(union be256) - CARTESI_ROLLUP_ADDRESS_SIZE]; - uint8_t msg_sender[CARTESI_ROLLUP_ADDRESS_SIZE]; - union be256 blocknumber; - union be256 timestamp; - union be256 epoch_number; - union be256 input_number; + size_t input_length; + struct rollup_bytes buffers[ARRAY_SIZE(node_paths)]; }; static struct rollup_device *to_rollup_device(struct file *file) @@ -76,18 +55,15 @@ static struct rollup_device *to_rollup_device(struct file *file) static long rollup_ioctl_finish(struct rollup_device *rollup, unsigned long arg) { - long i, ret; - u64 rx_length, reason; + long ret; + u64 input_length, reason; struct rollup_finish finish; - struct stream256 *rx = &rollup->buffers[RX_BUFFER_INDEX]; + struct rollup_bytes *rx = &rollup->buffers[RX_BUFFER_INDEX]; + struct rollup_bytes *tx = &rollup->buffers[TX_BUFFER_INDEX]; struct yield_request rep; - // NOTE: pointer is known to be aligned - struct rx_header *rx_header = (void *)rx->data; - - if ((ret = copy_from_user(&finish, (void __user*)arg, sizeof(finish)))) { + if ((ret = copy_from_user(&finish, (void __user*)arg, sizeof(finish)))) return -EFAULT; - } reason = finish.accept_previous_request? HTIF_YIELD_REASON_RX_ACCEPTED: @@ -96,28 +72,32 @@ static long rollup_ioctl_finish(struct rollup_device *rollup, unsigned long arg) if (mutex_lock_interruptible(&rollup->lock)) return -ERESTARTSYS; - if ((ret = cartesi_yield(HTIF_YIELD_MANUAL, reason, 0, &rep))) { + memcpy(tx->data, finish.output_hash, sizeof(finish.output_hash)); + if ((ret = cartesi_yield(HTIF_YIELD_MANUAL, reason, sizeof(finish.output_hash), &rep))) { ret = -EIO; goto unlock; } - if (rep.data != CARTESI_ROLLUP_ADVANCE_STATE && - rep.data != CARTESI_ROLLUP_INSPECT_STATE) { + if (rep.reason != CARTESI_ROLLUP_ADVANCE_STATE && + rep.reason != CARTESI_ROLLUP_INSPECT_STATE) { ret = -EOPNOTSUPP; goto unlock; } - rollup->next_request_type = rep.data; - finish.next_request_type = rep.data; + reason = rep.reason; - if ((ret = be256_to_u64(&rx_header->length, &rx_length))) + if (rx->length < rep.data) { + ret = -ENOBUFS; goto unlock; + } + input_length = rep.data; - for (i = 0; i < ARRAY_SIZE(node_paths); ++i) - stream256_reset(&rollup->buffers[i]); + rollup->next_request_type = reason; + rollup->input_length = input_length; + finish.next_request_type = reason; mutex_unlock(&rollup->lock); - finish.next_request_payload_length = rx_length; + finish.next_request_payload_length = input_length; if ((ret = copy_to_user((void __user*)arg, &finish, sizeof(finish)))) return -EFAULT; @@ -127,128 +107,22 @@ static long rollup_ioctl_finish(struct rollup_device *rollup, unsigned long arg) return ret; } -static long copy_rx(struct rollup_device *rollup, struct rollup_bytes *payload) -{ - long ret; - struct stream256 *rx = &rollup->buffers[RX_BUFFER_INDEX]; - struct rx_header *rxh = (void *)rx->data; - u64 data_length, data_bytes_to_copy; - - if ((ret = be256_to_u64(&rxh->length, &data_length))) - return ret; - - // length we received in `rxh` must fit into `rx` - if (data_length > rx->length - sizeof(*rxh)) - return -EIO; - - // it must also fit into the buffer the user provided - if (data_length > payload->length) - return -ENOBUFS; - - data_bytes_to_copy = min(data_length, payload->length); - return copy_to_user((void __user*)payload->data, rxh + 1, data_bytes_to_copy); -} - -static long rollup_ioctl_read_advance(struct rollup_device *rollup, unsigned long arg) -{ - long ret; - struct stream256 *im = &rollup->buffers[INPUT_METADATA_INDEX]; - struct input_metadata_header *imh = (void *)im->data; - struct rollup_advance_state advance; - - if (rollup->next_request_type != CARTESI_ROLLUP_ADVANCE_STATE) - return -EOPNOTSUPP; - - if ((ret = copy_from_user(&advance, (void __user*)arg, sizeof(advance)))) - return -EFAULT; - - if (mutex_lock_interruptible(&rollup->lock)) - return -ERESTARTSYS; - - if ((ret = copy_rx(rollup, &advance.payload))) { - ret = -EFAULT; - goto unlock; - } - - memcpy(advance.metadata.msg_sender, &imh->msg_sender, sizeof(advance.metadata.msg_sender)); - if ((ret = be256_to_u64(&imh->blocknumber, &advance.metadata.block_number)) || - (ret = be256_to_u64(&imh->timestamp, &advance.metadata.timestamp)) || - (ret = be256_to_u64(&imh->epoch_number, &advance.metadata.epoch_index)) || - (ret = be256_to_u64(&imh->input_number, &advance.metadata.input_index))) { - goto unlock; - } - mutex_unlock(&rollup->lock); - - if ((ret = copy_to_user((void __user*)arg, &advance, sizeof(advance)))) - return -EFAULT; - - return 0; -unlock: - mutex_unlock(&rollup->lock); - return ret; -} - -static long rollup_ioctl_read_inspect(struct rollup_device *rollup, unsigned long arg) +static long rollup_ioctl_read_input(struct rollup_device *rollup, unsigned long arg) { long ret = 0; - struct rollup_inspect_state inspect; + struct rollup_bytes input; + struct rollup_bytes *rx = &rollup->buffers[RX_BUFFER_INDEX]; - if (rollup->next_request_type != CARTESI_ROLLUP_INSPECT_STATE) - return -EOPNOTSUPP; - - if ((ret = copy_from_user(&inspect, (void __user*)arg, sizeof(inspect)))) + if ((ret = copy_from_user(&input, (void __user*)arg, sizeof(input)))) return -EFAULT; - if (mutex_lock_interruptible(&rollup->lock)) - return -ERESTARTSYS; - - if ((ret = copy_rx(rollup, &inspect.payload))) { - ret = -EFAULT; - goto unlock; - } - - /* fall-through */ -unlock: - mutex_unlock(&rollup->lock); - return ret; -} - -static long rollup_ioctl_voucher(struct rollup_device *rollup, unsigned long arg) -{ - long ret = 0; - struct rollup_voucher voucher; - struct stream256 *tx = &rollup->buffers[TX_BUFFER_INDEX], - *vh = &rollup->buffers[VOUCHER_HASHES_INDEX]; - struct yield_request rep; - - if (rollup->next_request_type == CARTESI_ROLLUP_INSPECT_STATE) { - dev_warn(&rollup->pdev->dev, "trying to emit a voucher during a inspect\n"); - return -EOPNOTSUPP; - } - - if ((ret = copy_from_user(&voucher, (void __user*)arg, sizeof(voucher)))) { - dev_warn(&rollup->pdev->dev, "failed to read voucher struct\n"); - return -EFAULT; - } + if (input.length < rollup->input_length) + return -ENOBUFS; if (mutex_lock_interruptible(&rollup->lock)) return -ERESTARTSYS; - stream256_reset(tx); - if ((ret = stream256_encode_address(tx, voucher.destination, sizeof(voucher.destination))) || - (ret = stream256_encode_u64(tx, 0x40)) || - (ret = stream256_encode_u64(tx, voucher.payload.length)) || - (ret = stream256_encode_ubuf(tx, voucher.payload.data, voucher.payload.length)) || - (ret = stream256_encode_keccak(rollup->keccak, tx, vh, &voucher.index))) { - goto unlock; - } - - if ((ret = cartesi_yield(HTIF_YIELD_AUTOMATIC, HTIF_YIELD_REASON_TX_VOUCHER, 0, &rep))) { - ret = -EIO; - goto unlock; - } - - if ((ret = copy_to_user((void __user*)arg, &voucher, sizeof(voucher)))) { + if ((ret = copy_to_user(input.data, rx->data, rollup->input_length))) { ret = -EFAULT; goto unlock; } @@ -259,112 +133,38 @@ static long rollup_ioctl_voucher(struct rollup_device *rollup, unsigned long arg return ret; } -static long rollup_ioctl_notice(struct rollup_device *rollup, unsigned long arg) +static long rollup_ioctl_write_output(struct rollup_device *rollup, unsigned long arg, u64 reason) { long ret = 0; - struct rollup_notice notice; - struct stream256 *tx = &rollup->buffers[TX_BUFFER_INDEX], - *nh = &rollup->buffers[NOTICE_HASHES_INDEX]; - struct yield_request rep; + struct rollup_bytes output; + struct rollup_bytes *tx = &rollup->buffers[TX_BUFFER_INDEX]; - if (rollup->next_request_type == CARTESI_ROLLUP_INSPECT_STATE) { - dev_warn(&rollup->pdev->dev, "trying to emit a notice during a inspect\n"); - return -EOPNOTSUPP; - } - - if ((ret = copy_from_user(¬ice, (void __user*)arg, sizeof(notice)))) { - dev_warn(&rollup->pdev->dev, "failed to read notice struct\n"); + if ((ret = copy_from_user(&output, (void __user*)arg, sizeof(output)))) return -EFAULT; - } + + if (tx->length < output.length) + return -ENOBUFS; if (mutex_lock_interruptible(&rollup->lock)) return -ERESTARTSYS; - stream256_reset(tx); - if ((ret = stream256_encode_u64(tx, 0x20)) || - (ret = stream256_encode_u64(tx, notice.payload.length)) || - (ret = stream256_encode_ubuf(tx, notice.payload.data, notice.payload.length)) || - (ret = stream256_encode_keccak(rollup->keccak, tx, nh, ¬ice.index))) { + if ((ret = copy_from_user(tx->data, output.data, output.length))) { + ret = -EFAULT; goto unlock; } - if ((ret = cartesi_yield(HTIF_YIELD_AUTOMATIC, HTIF_YIELD_REASON_TX_NOTICE, 0, &rep))) { + if ((ret = cartesi_yield(HTIF_YIELD_AUTOMATIC, reason, output.length, &rep))) { ret = -EIO; goto unlock; } - if ((ret = copy_to_user((void __user*)arg, ¬ice, sizeof(notice)))) { - ret = -EFAULT; - goto unlock; - } - /* fall-through */ unlock: mutex_unlock(&rollup->lock); return ret; } -static long yield_simple_payload(stream256_encode_buf_t enc, struct stream256 *tx, struct rollup_bytes *payload, u64 cmd, u64 reason) -{ - long ret; - struct yield_request rep; - - stream256_reset(tx); - if ((ret = stream256_encode_u64(tx, 0x20)) || - (ret = stream256_encode_u64(tx, payload->length)) || - (ret = enc(tx, payload->data, payload->length))) { - return ret; - } - - if ((ret = cartesi_yield(cmd, reason, 0, &rep))) { - return -EIO; - } - return 0; -} - -static long rollup_ioctl_report(struct rollup_device *rollup, unsigned long arg) -{ - long ret = 0; - struct rollup_report report; - struct stream256 *tx = &rollup->buffers[TX_BUFFER_INDEX]; - - if ((ret = copy_from_user(&report, (void __user*)arg, sizeof(report)))) { - dev_warn(&rollup->pdev->dev, "failed to read report struct\n"); - return -EFAULT; - } - - if (mutex_lock_interruptible(&rollup->lock)) - return -ERESTARTSYS; - - ret = yield_simple_payload(stream256_encode_ubuf, tx, &report.payload, - HTIF_YIELD_AUTOMATIC, HTIF_YIELD_REASON_TX_REPORT); - - mutex_unlock(&rollup->lock); - return ret; -} - -static long rollup_ioctl_exception(struct rollup_device *rollup, unsigned long arg) -{ - long ret = 0; - struct rollup_exception exception; - struct stream256 *tx = &rollup->buffers[TX_BUFFER_INDEX]; - - if ((ret = copy_from_user(&exception, (void __user*)arg, sizeof(exception)))) { - dev_warn(&rollup->pdev->dev, "failed to read exception struct\n"); - return -EFAULT; - } - - if (mutex_lock_interruptible(&rollup->lock)) - return -ERESTARTSYS; - - ret = yield_simple_payload(stream256_encode_ubuf, tx, &exception.payload, - HTIF_YIELD_MANUAL, HTIF_YIELD_REASON_TX_EXCEPTION); - - mutex_unlock(&rollup->lock); - return ret; -} - /* * We enforce only one user at a time here with the open/close. */ @@ -397,40 +197,16 @@ static long rollup_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if ((rollup = to_rollup_device(file)) == NULL) return -EBADF; - if ((rollup->next_request_type == CARTESI_ROLLUP_INITIAL_STATE) && !( - (cmd == IOCTL_ROLLUP_FINISH) || - (cmd == IOCTL_ROLLUP_THROW_EXCEPTION))) { - - int ret; - struct stream256 *tx = &rollup->buffers[TX_BUFFER_INDEX]; - unsigned char msg[] = "first ioctl must be either `finish' or `throw_exception'"; - struct rollup_bytes bytes = {msg, sizeof(msg)-1}; - dev_warn(&rollup->pdev->dev, msg); - if (mutex_lock_interruptible(&rollup->lock)) - return -ERESTARTSYS; - - ret = yield_simple_payload(stream256_encode_buf, tx, &bytes, - HTIF_YIELD_MANUAL, HTIF_YIELD_REASON_TX_EXCEPTION); - - mutex_unlock(&rollup->lock); - return -EBADE; - } switch (cmd) { case IOCTL_ROLLUP_FINISH: return rollup_ioctl_finish(rollup, arg); - case IOCTL_ROLLUP_READ_ADVANCE_STATE: - return rollup_ioctl_read_advance(rollup, arg); - case IOCTL_ROLLUP_READ_INSPECT_STATE: - return rollup_ioctl_read_inspect(rollup, arg); - case IOCTL_ROLLUP_WRITE_NOTICE: - return rollup_ioctl_notice(rollup, arg); - case IOCTL_ROLLUP_WRITE_REPORT: - return rollup_ioctl_report(rollup, arg); - case IOCTL_ROLLUP_WRITE_VOUCHER: - return rollup_ioctl_voucher(rollup, arg); - case IOCTL_ROLLUP_THROW_EXCEPTION: - return rollup_ioctl_exception(rollup, arg); + case IOCTL_ROLLUP_READ_INPUT: + return rollup_ioctl_read_input(rollup, arg); + case IOCTL_ROLLUP_WRITE_OUTPUT: + return rollup_ioctl_write_output(rollup, arg, HTIF_YIELD_REASON_TX_OUTPUT); + case IOCTL_ROLLUP_WRITE_VERIFIABLE_OUTPUT: + return rollup_ioctl_write_output(rollup, arg, HTIF_YIELD_REASON_TX_VERIFIABLE_OUTPUT); } return -ENOIOCTLCMD; } @@ -442,6 +218,7 @@ static const struct file_operations rollup_fileops = { .unlocked_ioctl = rollup_ioctl }; +// TODO: there are only two regions now, simplify this static int find_memory_regions(struct rollup_device *rollup) { int i, j, err = 0; @@ -449,7 +226,7 @@ static int find_memory_regions(struct rollup_device *rollup) for (i = 0; !err && i < ARRAY_SIZE(node_paths); ++i) { u64 xs[2]; - struct stream256 *bi = &rollup->buffers[i]; + struct rollup_bytes *bi = &rollup->buffers[i]; struct device_node *buffer = of_find_node_by_name(node, node_paths[i]); err = of_property_read_u64_array(buffer, "reg", xs, 2); @@ -461,11 +238,10 @@ static int find_memory_regions(struct rollup_device *rollup) if ((bi->data = devm_ioremap(rollup->mdev.this_device, xs[0], xs[1])) == NULL) return -ENODEV; bi->length = xs[1]; - bi->offset = 0; /* do buffers intersect => malformed IO */ for (j = 0; j < i; ++j) { - struct stream256 *bj = &rollup->buffers[j]; + struct rollup_bytes *bj = &rollup->buffers[j]; if ((bi->data <= bj->data && bj->data < bi->data + bi->length) || (bj->data <= bi->data && bi->data < bj->data + bj->length)) return -EIO; @@ -478,7 +254,6 @@ static int find_memory_regions(struct rollup_device *rollup) static int rollup_driver_probe(struct platform_device *pdev) { struct rollup_device *rollup; - struct crypto_shash *alg; int ret = -ENXIO; if (!atomic_dec_and_test(&rollup_probe_once)) { @@ -506,29 +281,15 @@ static int rollup_driver_probe(struct platform_device *pdev) goto free_miscdevice; } - alg = crypto_alloc_shash("keccak-256-generic", CRYPTO_ALG_TYPE_SHASH, 0); - if (IS_ERR(alg)) { - dev_err(&pdev->dev, "failed to create keccak-256\n"); - goto free_miscdevice; - } - - rollup->keccak = kmalloc(sizeof(rollup->keccak) + crypto_shash_descsize(alg), GFP_KERNEL); - if (!rollup->keccak) { - dev_err(&pdev->dev, "failed to allocate memory\n"); - goto free_digest; - } - rollup->keccak->tfm = alg; - platform_set_drvdata(pdev, rollup); rollup->pdev = pdev; rollup->next_request_type = CARTESI_ROLLUP_INITIAL_STATE; + rollup->input_length = 0; mutex_init(&rollup->lock); pr_info(MODULE_DESC ": Module loaded\n"); return 0; -free_digest: - crypto_free_shash(alg); free_miscdevice: misc_deregister(&rollup->mdev); free_rollup: @@ -539,8 +300,6 @@ static int rollup_driver_probe(struct platform_device *pdev) static int rollup_driver_remove(struct platform_device *pdev) { struct rollup_device *rollup = platform_get_drvdata(pdev); - crypto_free_shash(rollup->keccak->tfm); - kfree(rollup->keccak); misc_deregister(&rollup->mdev); kfree(rollup); dev_info(&pdev->dev, "unregistered\n"); diff --git a/include/uapi/linux/cartesi/rollup.h b/include/uapi/linux/cartesi/rollup.h index 9db3e03488de..2fdc6fb386a5 100644 --- a/include/uapi/linux/cartesi/rollup.h +++ b/include/uapi/linux/cartesi/rollup.h @@ -4,8 +4,6 @@ #define CARTESI_ROLLUP_ADVANCE_STATE 0 #define CARTESI_ROLLUP_INSPECT_STATE 1 -#define CARTESI_ROLLUP_ADDRESS_SIZE 20 - #include #include #include @@ -15,23 +13,6 @@ struct rollup_bytes { __u64 length; }; -struct rollup_input_metadata { - __u8 msg_sender[CARTESI_ROLLUP_ADDRESS_SIZE]; - __u64 block_number; - __u64 timestamp; - __u64 epoch_index; - __u64 input_index; -}; - -struct rollup_advance_state { - struct rollup_input_metadata metadata; - struct rollup_bytes payload; -}; - -struct rollup_inspect_state { - struct rollup_bytes payload; -}; - struct rollup_finish { /* True if previous request should be accepted */ /* False if previous request should be rejected */ @@ -39,25 +20,7 @@ struct rollup_finish { int next_request_type; /* either CARTESI_ROLLUP_ADVANCE or CARTESI_ROLLUP_INSPECT */ int next_request_payload_length; -}; - -struct rollup_voucher { - __u8 destination[CARTESI_ROLLUP_ADDRESS_SIZE]; - struct rollup_bytes payload; - __u64 index; -}; - -struct rollup_notice { - struct rollup_bytes payload; - __u64 index; -}; - -struct rollup_report { - struct rollup_bytes payload; -}; - -struct rollup_exception { - struct rollup_bytes payload; + uint8_t output_hash[32]; }; /* Finishes processing of current advance or inspect. @@ -86,70 +49,29 @@ struct rollup_exception { * EFAULT in case of invalid arguments * ERESTARTSYS in case of an internal lock error * EDOM in case of an integer larger than 64bits is received */ -#define IOCTL_ROLLUP_READ_ADVANCE_STATE _IOWR(0xd3, 0, struct rollup_advance_state) - -/* Obtains arguments to inspect state - * How: - * Reads from rx buffer and copy to payload - * on success: - * Returns 0 - * on failure: - * EOPNOTSUPP in case the driver is not currently processing an inspect state - * EFAULT in case of invalid arguments - * ERESTARTSYS in case of an internal lock error */ -#define IOCTL_ROLLUP_READ_INSPECT_STATE _IOWR(0xd3, 0, struct rollup_inspect_state) +#define IOCTL_ROLLUP_READ_INPUT _IOWR(0xd3, 1, struct rollup_bytes) -/* Outputs a new voucher. - * How: Computes the Keccak-256 hash of address+payload and then, atomically: - * - Copies the (address+be32(0x40)+be32(payload_length)+payload) to the tx buffer - * - Copies the hash to the next available slot in the voucher-hashes memory range - * - Yields automatic with tx-voucher - * - Fills in the index field with the corresponding slot from voucher-hashes +/* Outputs a message. + * - Copy the bytes to tx-buffer + * - Yields automatic with tx-output * on success: * Returns 0 * on failure: * EOPNOTSUPP in case the driver is currently processing an inspect state * EFAULT in case of invalid arguments * ERESTARTSYS in case of an internal lock error - * EDOM in case of an integer larger than 64bits is received * EIO in case of yield device error */ -#define IOCTL_ROLLUP_WRITE_VOUCHER _IOWR(0xd3, 1, struct rollup_voucher) +#define IOCTL_ROLLUP_WRITE_OUTPUT _IOWR(0xd3, 2, struct rollup_bytes) -/* Outputs a new notice. - * How: Computes the Keccak-256 hash of payload and then, atomically: - * - Copies the (be32(0x20)+be32(payload_length)+payload) to the tx buffer - * - Copies the hash to the next available slot in the notice-hashes memory range - * - Yields automatic with tx-notice - * - Fills in the index field with the corresponding slot from notice-hashes +/* Outputs a verifiable message. + * - Copy the bytes to tx-buffer + * - Yields automatic with tx-verifiable-output * on success: * Returns 0 * on failure: * EOPNOTSUPP in case the driver is currently processing an inspect state * EFAULT in case of invalid arguments * ERESTARTSYS in case of an internal lock error - * EDOM in case of an integer larger than 64bits is received - * EIO in case of yield device error */ -#define IOCTL_ROLLUP_WRITE_NOTICE _IOWR(0xd3, 2, struct rollup_notice) - -/* Outputs a new report. - * - Copies the (be32(0x20)+be32(payload_length)+payload) to the tx buffer - * - Yields automatic with tx-report - * on success: - * Returns 0 - * on failure: - * EFAULT in case of invalid arguments - * ERESTARTSYS in case of an internal lock error - * EIO in case of yield device error */ -#define IOCTL_ROLLUP_WRITE_REPORT _IOWR(0xd3, 3, struct rollup_report) - -/* Throws an exeption. - * - Copies the (be32(0x20)+be32(payload_length)+payload) to the tx buffer - * - Yields manual with tx-exception - * on success: - * Returns 0 - * on failure: - * EFAULT in case of invalid arguments - * ERESTARTSYS in case of an internal lock error * EIO in case of yield device error */ -#define IOCTL_ROLLUP_THROW_EXCEPTION _IOWR(0xd3, 4, struct rollup_exception) +#define IOCTL_ROLLUP_WRITE_VERIFIABLE_OUTPUT _IOWR(0xd3, 3, struct rollup_bytes) #endif diff --git a/include/uapi/linux/cartesi/yield.h b/include/uapi/linux/cartesi/yield.h index f17297dd9254..b09de254f2e0 100644 --- a/include/uapi/linux/cartesi/yield.h +++ b/include/uapi/linux/cartesi/yield.h @@ -17,18 +17,23 @@ struct yield_request { __u32 data; }; -#define HTIF_DEVICE_YIELD 2 - -#define HTIF_YIELD_AUTOMATIC 0 -#define HTIF_YIELD_MANUAL 1 - -#define HTIF_YIELD_REASON_PROGRESS 0 -#define HTIF_YIELD_REASON_RX_ACCEPTED 1 -#define HTIF_YIELD_REASON_RX_REJECTED 2 -#define HTIF_YIELD_REASON_TX_VOUCHER 3 -#define HTIF_YIELD_REASON_TX_NOTICE 4 -#define HTIF_YIELD_REASON_TX_REPORT 5 -#define HTIF_YIELD_REASON_TX_EXCEPTION 6 +#define HTIF_DEVICE_YIELD 2 + +#define HTIF_YIELD_AUTOMATIC 0 +#define HTIF_YIELD_MANUAL 1 + +#define HTIF_YIELD_REASON_PROGRESS 0 + +/* read as one of: */ +#define HTIF_YIELD_REASON_ADVANCE_STATE 0 +#define HTIF_YIELD_REASON_INSPECT_STATE 1 + +/* write as one of: */ +#define HTIF_YIELD_REASON_PROGRESS 0 +#define HTIF_YIELD_REASON_RX_ACCEPTED 1 +#define HTIF_YIELD_REASON_RX_REJECTED 2 +#define HTIF_YIELD_REASON_TX_OUTPUT 3 +#define HTIF_YIELD_REASON_TX_VERIFIABLE_OUTPUT 4 #define IOCTL_YIELD _IOWR(0xd1, 0, struct yield_request) diff --git a/tools/testing/selftests/drivers/cartesi/Makefile b/tools/testing/selftests/drivers/cartesi/Makefile index 5b520e5ff06b..66114fb1d07f 100644 --- a/tools/testing/selftests/drivers/cartesi/Makefile +++ b/tools/testing/selftests/drivers/cartesi/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only CFLAGS += -I../../../../../usr/include/ -TEST_GEN_PROGS := rollup_exception rollup_inspect yield +TEST_GEN_PROGS := rollup_read #rollup_exception rollup_inspect yield top_srcdir ?=../../../../.. diff --git a/tools/testing/selftests/drivers/cartesi/rollup_read.c b/tools/testing/selftests/drivers/cartesi/rollup_read.c new file mode 100644 index 000000000000..16d4aeae3665 --- /dev/null +++ b/tools/testing/selftests/drivers/cartesi/rollup_read.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include "../../kselftest_harness.h" + +#define ROLLUP_DEVICE_NAME "/dev/rollup" + + +FIXTURE(rollup) { + int fd; +}; +FIXTURE_SETUP(rollup) { + self->fd = open(ROLLUP_DEVICE_NAME, O_RDWR); + ASSERT_GT(self->fd, 0) { + TH_LOG("fixture error: %s\n", strerror(self->fd)); + } +} +FIXTURE_TEARDOWN(rollup) { + close(self->fd); +} +TEST_F(rollup, echo) { + int ret = 0; + + uint8_t hash[32] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + }; + struct rollup_finish finish = { + .accept_previous_request = true, + }; + static uint8_t buf[4096]; + struct rollup_bytes rx = {buf, sizeof(buf)}; + + ASSERT_EQ(ioctl(self->fd, IOCTL_ROLLUP_FINISH, (unsigned long) &finish), 0); + ASSERT_EQ(finish.next_request_type, CARTESI_ROLLUP_ADVANCE_STATE); + + // read input + int rc = ioctl(self->fd, IOCTL_ROLLUP_READ_INPUT, (unsigned long) &rx); + if (rc) printf("%s\n", strerror(errno)); + ASSERT_EQ(rc, 0); + + // echo it back + ASSERT_EQ(ioctl(self->fd, IOCTL_ROLLUP_WRITE_OUTPUT, (unsigned long) &rx), 0); + + // echo it back as verifiable + ASSERT_EQ(ioctl(self->fd, IOCTL_ROLLUP_WRITE_VERIFIABLE_OUTPUT, (unsigned long) &rx), 0); + + // TODO: update the hash + // we are done + memcpy(finish.output_hash, hash, sizeof(finish.output_hash)); + ASSERT_EQ(ioctl(self->fd, IOCTL_ROLLUP_FINISH, (unsigned long) &finish), 0); +} + +TEST_HARNESS_MAIN