pylibrlp

Python3 wrapper for librlp
git clone git://git.defalsify.org/pylibrlp.git
Log | Files | Refs | LICENSE

commit a796450e1d22e39c829d7a0059abef2113bd22be
parent 4527d2284d23c8b76f71553dbddc98c45f10ff81
Author: nolash <dev@holbrook.no>
Date:   Sun, 11 Apr 2021 14:53:44 +0200

Package with so sources

Diffstat:
AMANIFEST.in | 1+
Aaux/src/bits.c | 30++++++++++++++++++++++++++++++
Aaux/src/bits.h | 7+++++++
Aaux/src/decode.c | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aaux/src/decode.h | 0
Aaux/src/encode.c | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aaux/src/encode.h | 0
Aaux/src/endian.c | 44++++++++++++++++++++++++++++++++++++++++++++
Aaux/src/endian.h | 20++++++++++++++++++++
Aaux/src/rlp.c | 32++++++++++++++++++++++++++++++++
Aaux/src/rlp.h | 47+++++++++++++++++++++++++++++++++++++++++++++++
Arlpstream/__init__.py | 9+++++++++
Asetup.cfg | 26++++++++++++++++++++++++++
Asetup.py | 12++++++++++++
14 files changed, 424 insertions(+), 0 deletions(-)

diff --git a/MANIFEST.in b/MANIFEST.in @@ -0,0 +1 @@ +include aux/src/*.h diff --git a/aux/src/bits.c b/aux/src/bits.c @@ -0,0 +1,30 @@ + +int intbits_le(int len, char *n) { + char ri = 0; + char ry = 0; + char i = 0; + + if (len == 0) { + return 0; + } + + for (int b = 0; b < len; b++) { + for (i = 0; i < 8; i++) { + if (((1 << i) & *(n + b)) > 0) { + ri = i + 1; + ry = b; + } + } + } + + if (ri == 0 && ry == 0) { + ri = 1; + } + + return ri + (ry * 8); +} + +int intbytes_le(int len, char *n) { + int r = intbits_le(len, n); + return (r - 1) / 8 + 1; +} diff --git a/aux/src/bits.h b/aux/src/bits.h @@ -0,0 +1,7 @@ +#ifndef LASH_BITS_H_ +#define LASH_BITS_H_ + +char intbits_le(int len, char *n); +char intbytes_le(int len, char *n); + +#endif diff --git a/aux/src/decode.c b/aux/src/decode.c @@ -0,0 +1,111 @@ +#include <string.h> + +#include "endian.h" +#include "rlp.h" + +static int process_state_token(rlp_encoder_t *encoder) { + int len = 0; + int lenlen = 0; + int r; + unsigned char token; + + token = *encoder->ptr; + + if (token >= 0xf7) { + lenlen = token - 0xf7; + encoder->ptr++; + len = 0; + memcpy(&len, encoder->ptr, lenlen); + if (lenlen > 1 && is_le()) { + to_endian(CONVERT_LITTLEENDIAN, lenlen, &len); + } + encoder->list_ptr[encoder->depth] = (char*)&len; + encoder->ptr += lenlen; + + r = encoder->depth; + encoder->depth++; + encoder->state = RLP_LIST; + + } else if (token >= 0xc0) { + len = token - 0xc0; + if (is_le()) { + to_endian(CONVERT_LITTLEENDIAN, sizeof(len), &len); + } + encoder->list_ptr[encoder->depth] = (char*)&len; + encoder->ptr++; + + r = encoder->depth; + encoder->depth++; + encoder->state = RLP_LIST; + } else if (token >= 0xb7) { + lenlen = token - 0xb7; + encoder->ptr++; + len = 0; + memcpy(&len, encoder->ptr, lenlen); + if (lenlen > 1 && is_le()) { + to_endian(CONVERT_LITTLEENDIAN, lenlen, &len); + } + encoder->ptr += lenlen; + + encoder->list_ptr[encoder->depth] = encoder->ptr; + r = encoder->depth; + encoder->ptr += len; + encoder->depth--; + encoder->state = RLP_STRING; + } else if (token >= 0x80) { + len = token - 0x80; + encoder->ptr++; + + encoder->list_ptr[encoder->depth] = encoder->ptr; + r = encoder->depth; + encoder->ptr += len; + encoder->depth--; + encoder->state = RLP_STRING; + } else { + encoder->list_ptr[encoder->depth] = encoder->ptr; + r = encoder->depth; + encoder->ptr++; + encoder->depth--; + encoder->state = RLP_STRING; + } + + return r; +} + +static int assert_complete(rlp_encoder_t *encoder) { + int r = 0; + + if (encoder->ptr - encoder->buf < encoder->size) { + encoder->state = RLP_INCOMPLETE; + r = -1; + } else if (encoder->ptr - encoder->buf > encoder->size) { + encoder->state = RLP_OVERFLOW; + r = -1; + } else { + encoder->state = RLP_END; + } + return r; +} + +int rlp_next(rlp_encoder_t *encoder, int *zlen, char **zdest) { + int r; + + if (encoder->depth == -1) { + return assert_complete(encoder); + } + + r = process_state_token(encoder); + + switch (encoder->state) { + case RLP_LIST: + *zlen = *((int*)encoder->list_ptr[r]); + break; + + case RLP_STRING: + *zlen = encoder->ptr - encoder->list_ptr[r]; + break; + } + *zdest = encoder->list_ptr[r]; + + return 0; +} diff --git a/aux/src/decode.h b/aux/src/decode.h diff --git a/aux/src/encode.c b/aux/src/encode.c @@ -0,0 +1,85 @@ +#include <stdint.h> +#include <string.h> + +#include "rlp.h" +#include "bits.h" +#include "endian.h" + + +int rlp_add(rlp_encoder_t *encoder, int len, const char *data) { + char v; + int lenlen; + size_t r; + + r = (size_t)encoder->ptr; + + if (len == 0) { + *(encoder->ptr) = 0x80; + encoder->ptr++; + encoder->size++; + } else { + v = (char)*data; + if (len == 1 && v < 56) { + *(encoder->ptr) = v; + encoder->ptr++; + encoder->size++; + } else { + v = (char)*data; + if (len < 56) { + *(encoder->ptr) = len + 0x80; + encoder->ptr++; + memcpy(encoder->ptr, data, len); + encoder->ptr += len; + encoder->size++; + } else { + lenlen = intbytes_le(sizeof(int), (char*)&len); + *(encoder->ptr) = lenlen + 0xb7; + encoder->ptr++; + to_endian(CONVERT_BIGENDIAN, lenlen, &len); + memcpy(encoder->ptr, &len, lenlen); + to_endian(CONVERT_PLATFORM, lenlen, &len); + encoder->ptr += lenlen; + memcpy(encoder->ptr, data, len); + encoder->ptr += len; + encoder->size += 1 + lenlen; + } + } + } + + encoder->size += len; + + return (int)(r - (size_t)encoder->ptr); +} + +int rlp_descend(rlp_encoder_t *encoder) { + encoder->depth++; + encoder->list_ptr[encoder->depth] = encoder->ptr; + return encoder->depth; +} + +int rlp_ascend(rlp_encoder_t *encoder) { + size_t len; + char *ptr; + int lenlen; + + ptr = encoder->list_ptr[encoder->depth]; + len = encoder->ptr - ptr; + if (len < 56) { + memcpy(ptr + 1, ptr, len); + *(ptr) = 0xc0 + len; + encoder->ptr++; + encoder->size++; + } 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->size + 1 + lenlen; + } + encoder->depth--; + + return encoder->depth; +} diff --git a/aux/src/encode.h b/aux/src/encode.h diff --git a/aux/src/endian.c b/aux/src/endian.c @@ -0,0 +1,44 @@ +#include "endian.h" + +int is_le() { + short s = 42; + return *((unsigned char*)&s) == 42; +} + +// convert unsigned integer to little-endian representation +int to_endian(char direction, int l, void *n) { + union le un; + + if (l == 1 || is_le() == direction) { + return 0; + } + switch(l) { + case sizeof(long long): + un.ll = (long long*)n; + break; + case sizeof(int): + un.i = (int*)n; + break; + case sizeof(short): + un.s = (short*)n; + break; + default: + un.c = (char*)n; + } + flip_endian(l, &un); + + return 0; +} + +void flip_endian(int l, union le *n) { + int i; + char t; + char *ne; + + ne = (n->c)+(l-1); + for (i = 0; i < l/2; i++) { + t = *(n->c+i); + *((n->c)+i) = *(ne-i); + *(ne-i) = t; + } +} diff --git a/aux/src/endian.h b/aux/src/endian.h @@ -0,0 +1,20 @@ +#ifndef LASH_ENDIAN_H_ +#define LASH_ENDIAN_H_ + +#define CONVERT_BIGENDIAN 0x00 +#define CONVERT_LITTLEENDIAN 0x01 +#define CONVERT_PLATFORM is_le() + +union le { + short *s; + int *i; + long long *ll; + char *c; +}; + +int le(int l, void *n); +int is_le(); +int to_endian(char direction, int l, void *n); +void flip_endian(int l, union le *n); + +#endif // LASH_ENDIAN_H_ diff --git a/aux/src/rlp.c b/aux/src/rlp.c @@ -0,0 +1,32 @@ +#include <stdlib.h> + +#include "rlp.h" + +int rlp_init(rlp_encoder_t *encoder, int buffer_capacity, char *content) { + encoder->depth = 0; + if (content != NULL) { + encoder->buf = content; + encoder->alloc = 0; + encoder->state = RLP_DECODE; + encoder->size = buffer_capacity; + } else { + encoder->buf = malloc(buffer_capacity); + encoder->alloc = 1; + encoder->state = RLP_ENCODE; + encoder->size = 0; + } + encoder->ptr = encoder->buf; +} + +void rlp_free(rlp_encoder_t *encoder) { + if (encoder->alloc) { + free(encoder->buf); + } + encoder->ptr = NULL; +} + +int rlp_get(rlp_encoder_t *encoder, int *zl, char **zdest) { + *zdest = encoder->buf; + *zl = encoder->size; + return 0; +} diff --git a/aux/src/rlp.h b/aux/src/rlp.h @@ -0,0 +1,47 @@ +#ifndef RLP_T_ +#define RLP_T_ + +#include <stdlib.h> + +#ifndef RLP_MAX_LIST_DEPTH +#define RLP_MAX_LIST_DEPTH 1024 +#endif + +#define RLP_SUCCESS 0 +#define RLP_FAILURE -1 + + +enum rlp_state { + RLP_DECODE, + RLP_ENCODE, + RLP_LIST, + RLP_STRING, + RLP_END, + RLP_OVERFLOW, + RLP_INCOMPLETE, +}; + + +typedef struct rlp_encoder { + char *buf; + char alloc; + int depth; + int size; + enum rlp_state state; + char *list_ptr[RLP_MAX_LIST_DEPTH]; + char *ptr; +} rlp_encoder_t; + + +int rlp_init(rlp_encoder_t *encoder, int buffer_capacity, char *content); +void rlp_free(rlp_encoder_t *encoder); + +int rlp_descend(rlp_encoder_t *encoder); +int rlp_ascend(rlp_encoder_t *encoder); +int rlp_add(rlp_encoder_t *encoder, int len, const char *data); +size_t rlp_length(rlp_encoder_t *encoder); + +int rlp_get(rlp_encoder_t *encoder, int *zl, char **zdest); +int rlp_next(rlp_encoder_t *encoder, int *zl, char **zdest); + +#endif diff --git a/rlpstream/__init__.py b/rlpstream/__init__.py @@ -0,0 +1,9 @@ +# standard imports +import ctypes +import ctypes.util + +LIBRLP_RLP_MAX_LIST_DEPTH = 1024 + +__path_librlp = ctypes.util.find_library('rlp') +librlp = ctypes.CDLL(__path_librlp) + diff --git a/setup.cfg b/setup.cfg @@ -0,0 +1,26 @@ +[metadata] +name = rlpstream +version = 0.0.01a1 +description = Python wrapper for librlp +author = Louis Holbrook +author_email = dev@holbrook.no +url = https://gitlab.com/nolash/rlpstream + +classifiers = + Programming Language :: Python :: 3 + Operating System :: OS Independent + Development Status :: 3 - Alpha + Environment :: Console + Intended Audience :: Developers + License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+) + Topic :: Internet +# Topic :: Blockchain :: EVM +license = GPL3 +licence_files = + LICENSE.txt + +[options] +python_requires = >= 3.8 + +packages = + rlpstream diff --git a/setup.py b/setup.py @@ -0,0 +1,12 @@ +from distutils.core import setup, Extension + +rlp = Extension('rlp', + sources = ['aux/src/rlp.c', 'aux/src/endian.c', 'aux/src/bits.c', 'aux/src/encode.c', 'aux/src/decode.c'], + ) + +setup( + name='rlpstream', + version = '0.0.1a1', + ext_modules = [rlp], + packages=['rlpstream'], + )