implement integer parsing

This commit is contained in:
Michele Balistreri 2018-07-16 15:49:19 +03:00
parent 4d4af9d7bc
commit fbf4a5ac95
5 changed files with 62 additions and 30 deletions

View File

@ -29,27 +29,27 @@
#include <stdbool.h>
struct {
uint8_t *buffer;
uint8_t *barrier;
uint8_t* buffer;
uint8_t* barrier;
int list_len;
uint8_t *list;
uint8_t* list;
uint8_t *dst_addr;
uint8_t* dst_addr;
int value_len;
uint8_t *value;
uint8_t* value;
int data_len;
uint8_t *data;
uint8_t* data;
uint8_t *v;
uint8_t *r;
uint8_t *s;
uint8_t* v;
uint8_t* r;
uint8_t* s;
bool is_signed;
bool is_valid;
} typedef EthTx;
} typedef eth_tx_t;
/**
* Takes an EthTx structure where the buffer and barrier fields must be populated and fills the other fields by parsing the content of the buffer.
@ -57,7 +57,7 @@ struct {
*
* Only accepts unsigned transactions, where v is the chain id (for now on 1 byte only) and r and s are empty as per EIP-155
*/
int eth_parse(EthTx *tx);
int eth_parse(eth_tx_t* tx);
/**
* Signs a previously parsed transaction. The transaction is modified in place.
@ -67,6 +67,6 @@ int eth_parse(EthTx *tx);
* Additionally, it must be possible to increase the barrier pointer by 64 bytes. This will always happen because the
* the empty r and s component as substituted by the signature.
*/
int eth_sign(EthTx *tx, const uint8_t *priv_key);
int eth_sign(eth_tx_t* tx, const uint8_t* priv_key);
#endif /* ETH_H_ */

View File

@ -36,7 +36,12 @@
* the function will not fail but the next pointer will point to NULL, indicating that this was the last field.
*
**/
int rlp_parse(uint8_t *item, uint8_t **value, uint8_t **next, uint8_t *barrier);
int rlp_parse(const uint8_t* item, uint8_t** value, uint8_t** next, const uint8_t* barrier);
/**
* Takes an RLP item and reads its content as a big endian uint32. Returns -1 on failure, 0 otherwise.
*/
int rlp_read_uint32(const uint8_t* item, uint32_t* value, uint8_t** next, const uint8_t* barrier);
/**
* Returns the number of bytes needed to encode the given len.
@ -46,6 +51,6 @@ int rlp_len_of_len(int len);
/**
* Writes the given length to the buffer. The is_list parameter encodes if the element is a list.
*/
void rlp_write_len(uint8_t *buf, int len, int is_list);
void rlp_write_len(uint8_t* buf, int len, int is_list);
#endif /* RLP_H_ */

View File

@ -32,7 +32,7 @@
#define ETH_ASSERT_NEXT(len, min, max, next) if (ETH_WRONG_LEN(len, min, max) || next == NULL) return -1;
#define ETH_ASSERT_LAST(len, min, max, next) if (ETH_WRONG_LEN(len, min, max) || next != NULL) return -1;
int eth_parse(EthTx *tx) {
int eth_parse(eth_tx_t* tx) {
if (tx->buffer == NULL || tx->barrier <= tx->buffer) {
return -1;
}
@ -40,8 +40,8 @@ int eth_parse(EthTx *tx) {
tx->is_signed = false;
tx->is_valid = false;
uint8_t *value;
uint8_t *next;
uint8_t* value;
uint8_t* next;
int len;
// Enter the list
@ -89,7 +89,7 @@ int eth_parse(EthTx *tx) {
return 0;
}
int eth_sign(EthTx *tx, const uint8_t *privkey) {
int eth_sign(eth_tx_t* tx, const uint8_t* privkey) {
if (!tx->is_valid || tx->is_signed) return -1;
int tx_len = tx->barrier - tx->buffer;

View File

@ -25,25 +25,25 @@
#include <stddef.h>
#include "rlp.h"
static inline int rlp_1_byte_length(uint8_t *item, uint8_t **value) {
*value = &item[1];
static inline int rlp_1_byte_length(const uint8_t* item, uint8_t** value) {
*value = (uint8_t*) &item[1];
return item[0] & 0x3f;
}
// length can be up to 4 bytes
static inline int rlp_x_bytes_length(uint8_t *item, uint8_t **value) {
static inline int rlp_x_bytes_length(const uint8_t* item, uint8_t** value) {
switch(item[0] & 0x3f) {
case 0x38:
*value = &item[2];
*value = (uint8_t*) &item[2];
return item[1];
case 0x39:
*value = &item[3];
*value = (uint8_t*) &item[3];
return (item[1] << 8) | item[2];
case 0x3a:
*value = &item[4];
*value = (uint8_t*) &item[4];
return (item[1] << 16) | (item[2] << 8) | item[3];
case 0x3b:
*value = &item[5];
*value = (uint8_t*) &item[5];
return (item[1] << 24) | (item[2] << 16) | (item[3] << 8) | item[4];
default:
*value = NULL;
@ -51,11 +51,11 @@ static inline int rlp_x_bytes_length(uint8_t *item, uint8_t **value) {
}
}
int rlp_parse(uint8_t *item, uint8_t **value, uint8_t **next, uint8_t *barrier) {
int rlp_parse(const uint8_t* item, uint8_t** value, uint8_t** next, const uint8_t* barrier) {
int len;
if (item[0] < 0x80) {
*value = item;
*value = (uint8_t*) item;
len = 1;
} else if (item[0] < 0xb8) {
len = rlp_1_byte_length(item, value);
@ -84,6 +84,33 @@ int rlp_parse(uint8_t *item, uint8_t **value, uint8_t **next, uint8_t *barrier)
return len;
}
int rlp_read_uint32(const uint8_t* item, uint32_t* value, uint8_t** next, const uint8_t* barrier) {
uint8_t* v;
int len = rlp_parse(item, &v, next, barrier);
switch(len) {
case -1:
return -1;
case 0:
*value = 0;
break;
case 1:
*value = v[0];
break;
case 2:
*value = (v[0] << 8 | v[1]);
break;
case 3:
*value = (v[0] << 16 | (v[1] << 8) | v[2]);
break;
*value = (v[0] << 24 | (v[1] << 16) | (v[2] << 8) | v[3]);
break;
}
return 0;
}
int rlp_len_of_len(int len) {
if (len < 56) {
return 1;
@ -100,7 +127,7 @@ int rlp_len_of_len(int len) {
return -1;
}
void rlp_write_len(uint8_t *buf, int len, int is_list) {
void rlp_write_len(uint8_t* buf, int len, int is_list) {
uint8_t prefix;
if (is_list) {

View File

@ -121,7 +121,7 @@ void test_rlp_parse(void) {
}
void test_eth_parse(void) {
EthTx tx;
eth_tx_t tx;
tx.buffer = TX2;
tx.barrier = &TX2[TX2_LEN];
@ -174,7 +174,7 @@ void test_eth_parse(void) {
}
void test_eth_sign(void) {
EthTx tx;
eth_tx_t tx;
tx.buffer = TX1;
tx.barrier = &TX1[TX1_LEN];