librlp

C library for the Recursive Length Prefix (RLP) serialization format
git clone git://git.defalsify.org/librlp.git
Log | Files | Refs | LICENSE

commit 9e005761f5b5678af99b274f3965e003cee0fff4
parent 9256d605e0a852bea498a33ac4bcec5db1c5e043
Author: nolash <dev@holbrook.no>
Date:   Sat, 10 Apr 2021 15:09:30 +0200

Add test vectors from spec page

Diffstat:
MMakefile | 2++
Msrc/rlp.c | 23++++++++++++++++++-----
Msrc/rlp.h | 5++---
Mtests/check_bits | 0
Mtests/check_rlp | 0
Mtests/check_rlp.c | 19+++++++++++++++++++
Atests/check_vector.c | 122+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 163 insertions(+), 8 deletions(-)

diff --git a/Makefile b/Makefile @@ -6,9 +6,11 @@ build: tests_build: build gcc -I./src -g3 tests/check_rlp.c src/bits.o src/rlp.o src/endian.o -o tests/check_rlp -lcheck gcc -I./src -g3 tests/check_bits.c src/bits.o src/rlp.o src/endian.o -o tests/check_bits -lcheck + gcc -I./src -g3 tests/check_vector.c src/bits.o src/rlp.o src/endian.o -o tests/check_vector -lcheck check: tests_build tests/check_rlp tests/check_bits + tests/check_vector .PHONY test: check diff --git a/src/rlp.c b/src/rlp.c @@ -64,17 +64,30 @@ int rlp_descend(rlp_encoder_t *encoder) { } int rlp_ascend(rlp_encoder_t *encoder) { - size_t l; + size_t len; char *ptr; + int lenlen; ptr = encoder->list_ptr[encoder->depth]; - l = encoder->ptr - ptr; - if (l < 56) { - memcpy(ptr+1, ptr, l); - *(ptr) = 0xc0 + l; + len = encoder->ptr - ptr; + if (len < 56) { + memcpy(ptr + 1, ptr, len); + *(ptr) = 0xc0 + len; encoder->ptr++; + } else { + lenlen = intbytes_le(sizeof(size_t), (char*)&len); + memcpy(ptr + 1 + lenlen, ptr, len); + *ptr = lenlen + 0xf7; + to_endian(CONVERT_BIGENDIAN, lenlen, &len); + memcpy(ptr+1, &len, lenlen); + to_endian(CONVERT_PLATFORM, lenlen, &len); + encoder->ptr += (lenlen + 1); } encoder->depth--; return encoder->depth + 1; } + +size_t rlp_length(rlp_encoder_t *encoder) { + return encoder->ptr - encoder->buf; +} diff --git a/src/rlp.h b/src/rlp.h @@ -2,6 +2,7 @@ #define RLP_T_ #include <stdint.h> +#include <stdlib.h> #ifndef RLP_MAX_LIST_DEPTH #define RLP_MAX_LIST_DEPTH 1024 @@ -12,16 +13,14 @@ typedef struct rlp_encoder { char *list_ptr[RLP_MAX_LIST_DEPTH]; char *buf; char *ptr; - size_t len; } rlp_encoder_t; int rlp_init(rlp_encoder_t *encoder, int buffer_capacity); void rlp_free(rlp_encoder_t *encoder); int rlp_descend(rlp_encoder_t *encoder); -//static int list_register(rlp_encoder_t *encoder); int rlp_ascend(rlp_encoder_t *encoder); int rlp_add(rlp_encoder_t *encoder, int len, char *data); -int rlp_finish(rlp_encoder_t *encoder); +size_t rlp_length(rlp_encoder_t *encoder); #endif diff --git a/tests/check_bits b/tests/check_bits Binary files differ. diff --git a/tests/check_rlp b/tests/check_rlp Binary files differ. diff --git a/tests/check_rlp.c b/tests/check_rlp.c @@ -219,6 +219,24 @@ START_TEST(rlp_encode_list_nested_test) { rlp_free(&encoder); } END_TEST + +START_TEST(rlp_encode_list_long_test) { + char v[56]; + char target[4] = {0xf8, 58, 0xb8, 56}; + int r; + + rlp_encoder_t encoder; + rlp_init(&encoder, 1024); + + r = rlp_descend(&encoder); + rlp_add(&encoder, 56, (char*)v); + r = rlp_ascend(&encoder); + ck_assert_mem_eq(encoder.buf, target, 4); + + rlp_free(&encoder); +} +END_TEST + Suite *rlp_suite(void) { Suite *s; TCase *tci; @@ -246,6 +264,7 @@ Suite *rlp_suite(void) { tcase_add_test(tcl, rlp_encode_list_single_depth_test); tcase_add_test(tcl, rlp_encode_list_adjacent_test); tcase_add_test(tcl, rlp_encode_list_nested_test); + tcase_add_test(tcl, rlp_encode_list_long_test); suite_add_tcase(s, tcl); return s; diff --git a/tests/check_vector.c b/tests/check_vector.c @@ -0,0 +1,122 @@ +#include <check.h> +#include <stdlib.h> +#include <string.h> + +#include "rlp.h" + +START_TEST(rlp_dog_test) { + rlp_encoder_t encoder; + + rlp_init(&encoder, 1024); + char *x_dog = "dog"; + char r_dog[4] = {0x83, 'd', 'o', 'g'}; + rlp_add(&encoder, 3, x_dog); + ck_assert_mem_eq(encoder.buf, r_dog, 4); + + rlp_free(&encoder); +} +END_TEST + +START_TEST(rlp_catdog_test) { + rlp_encoder_t encoder; + + rlp_init(&encoder, 1024); + + char *x_dog = "dog"; + char *x_cat = "cat"; + char r_catdog[9] = {0xc8, 0x83, 'c', 'a', 't', 0x83, 'd', 'o', 'g'}; + rlp_descend(&encoder); + rlp_add(&encoder, 3, x_cat); + rlp_add(&encoder, 3, x_dog); + rlp_ascend(&encoder); + ck_assert_mem_eq(encoder.buf, r_catdog, 9); + + rlp_free(&encoder); +} +END_TEST + +START_TEST(rlp_lorem_test) { + rlp_encoder_t encoder; + + rlp_init(&encoder, 1024); + + char *lorem = "Lorem ipsum dolor sit amet, consectetur adipisicing elit"; + char target[2] = {0xb8, 0x38}; + + rlp_add(&encoder, strlen(lorem), lorem); + ck_assert_mem_eq(encoder.buf, target, 2); + ck_assert_mem_eq(encoder.buf+2, lorem, strlen(lorem)); + + rlp_free(&encoder); +} +END_TEST + +START_TEST(rlp_set_theoretical_representation_of_three) { + + char target[8] = {0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0}; + + rlp_encoder_t encoder; + + rlp_init(&encoder, 1024); + + // [  []  [ [] ]  [ [] [ []] ]  ] + rlp_descend(&encoder); + + rlp_descend(&encoder); + rlp_ascend(&encoder); + + rlp_descend(&encoder); + rlp_descend(&encoder); + rlp_ascend(&encoder); + rlp_ascend(&encoder); + + rlp_descend(&encoder); + rlp_descend(&encoder); + rlp_ascend(&encoder); + rlp_descend(&encoder); + rlp_descend(&encoder); + rlp_ascend(&encoder); + rlp_ascend(&encoder); + rlp_ascend(&encoder); + + rlp_ascend(&encoder); + + ck_assert_mem_eq(encoder.buf, target, 8); + + rlp_free(&encoder); +} +END_TEST + + +Suite *rlp_vector_suite(void) { + Suite *s; + TCase *tcb; + + s = suite_create("rlp_vector"); + tcb = tcase_create("basic"); // examples from https://eth.wiki/fundamentals/rlp + tcase_add_test(tcb, rlp_dog_test); + tcase_add_test(tcb, rlp_catdog_test); + tcase_add_test(tcb, rlp_lorem_test); + tcase_add_test(tcb, rlp_set_theoretical_representation_of_three); + suite_add_tcase(s, tcb); + + + return s; +} + + +int main(void) { + int num_fail; + + Suite *s; + SRunner *sr; + + s = rlp_vector_suite(); + sr = srunner_create(s); + + srunner_run_all(sr, CK_VERBOSE); + num_fail = srunner_ntests_failed(sr); + srunner_free(sr); + + return (num_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +}