Created
June 18, 2019 19:47
-
-
Save yaronvel/5708575b435aef3253c8d0f270c8785f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
const char* fields[] = { | |
"parentHash", | |
"ommersHash", | |
"beneficiary", | |
"stateRoot", | |
"transactionsRoot", | |
"receiptsRoot", | |
"logsBloom", | |
"difficulty", | |
"number", | |
"gasLimit", | |
"gasUsed", | |
"timestamp", | |
"extraData", | |
"mixHash", | |
"nonce" | |
}; | |
typedef unsigned int uint; | |
typedef struct _rlp_item { | |
unsigned char* content; | |
uint len; /* length in bytes */ | |
} rlp_item; | |
/*****************************************************************************/ | |
static uint decode_single_byte(unsigned char* input, rlp_item* output) { | |
output->content = input; | |
output->len = 1; | |
return 1; | |
} | |
/*****************************************************************************/ | |
static uint decode_number(unsigned char* input, uint len) { | |
uint i, result; | |
result = 0; | |
for(i = 0 ; i < len ; i++) { | |
result = result << 8; | |
result += (unsigned char)input[i]; | |
} | |
return result; | |
} | |
/*****************************************************************************/ | |
static uint decode_string(unsigned char* input, rlp_item* output) { | |
unsigned char first_byte = input[0]; | |
uint len_num_bytes; | |
uint string_len; | |
if(first_byte <= 0xb7) { | |
output->len = first_byte - 0x80; | |
output->content = input + 1; | |
len_num_bytes = 1; | |
} | |
else { | |
len_num_bytes = first_byte - 0xb7; | |
string_len = decode_number(input + 1, len_num_bytes); | |
output->len = string_len; | |
output->content = input + 1 + len_num_bytes; | |
len_num_bytes++; | |
} | |
return output->len + len_num_bytes; | |
} | |
/*****************************************************************************/ | |
static void decode_list(unsigned char* input, rlp_item* outputs) { | |
unsigned char first_byte = input[0]; | |
uint len_num_bytes; | |
uint list_len; | |
uint elm_ind; | |
uint elm_len; | |
uint outputs_ind; | |
unsigned char* current_input = input; | |
if(first_byte <= 0xf7) { | |
list_len = first_byte - 0xc0; | |
current_input = input + 1; | |
} | |
else { | |
len_num_bytes = first_byte - 0xf7; | |
list_len = decode_number(input + 1, len_num_bytes); | |
current_input = input + 1 + len_num_bytes; | |
} | |
outputs_ind = 0; | |
for(elm_ind = 0 ; /*elm_ind < list_len*/ current_input < input + list_len /* elm_ind < 20*/ ; elm_ind++) | |
{ | |
first_byte = current_input[0]; | |
if(first_byte <= 0x7f) elm_len = decode_single_byte(current_input,outputs + outputs_ind); | |
else if(first_byte <= 0xbf) elm_len = decode_string(current_input,outputs + outputs_ind); | |
else printf( "error: recursive list\n"); | |
current_input += elm_len; | |
outputs_ind += 1; | |
} | |
} | |
/*****************************************************************************/ | |
static uint remove_last_field_from_rlp(unsigned char* rlp, uint field_len) { | |
uint field_len_field_len; | |
uint rlp_org_len; | |
uint rlp_final_len; | |
uint rlp_len_num_bytes; | |
if(rlp[0] <= 0xf7) printf("error: rlp is too short\n"); | |
rlp_len_num_bytes = rlp[0] - 0xf7; | |
rlp_org_len = decode_number(rlp + 1, rlp_len_num_bytes); | |
if(field_len >= 55) printf("error: unexpected field_len\n"); | |
if(rlp_org_len <= 55 - field_len) printf("error: rlp is too short\n"); | |
if(field_len == 0) field_len_field_len = 0; // would happen once evey 2^64 blocks... | |
else if(field_len <= 55) field_len_field_len = 1; | |
else printf("error: unexpected field_len\n"); | |
rlp_final_len = rlp_org_len - (field_len + field_len_field_len); | |
// make sure number of bytes wasn't chage | |
if(rlp_final_len <= 256) printf("error: unexpcted rlp len\n"); | |
if(rlp_org_len >= 256 * 256) printf("error: unexpecpted rlp len\n"); | |
// new length is exactly 2 bytes | |
rlp[1] = rlp_final_len >> 8; | |
rlp[2] = rlp_final_len & 0xFF; | |
return rlp_final_len + 3; | |
} | |
/*****************************************************************************/ | |
/* tests */ | |
/*****************************************************************************/ | |
static void print_elm(const char* name, rlp_item* item) { | |
uint i; | |
printf("%s 0x", name); | |
for(i = 0 ; i < item->len ;i++) printf("%02X", item->content[i]); | |
printf("\n"); | |
} | |
#define CHECK_RLP_RESULT(_rlp_items, _index, _value){\ | |
if((_rlp_items[_index]).len != sizeof(_value)) return (-1 * 2 * (_index) - 1);\ | |
if(memcmp((_rlp_items[_index]).content, (_value), sizeof(_value))) return (-1 * 2 * (_index) - 2);\ | |
} | |
/*****************************************************************************/ | |
static int test1() { | |
unsigned char rlp_data[] = | |
{0xf9, 0x02, 0x10, 0xa0, 0x4d, 0x1e, 0x1f, 0x82, 0x40, 0x0b, 0x58, 0x55, 0xf1, 0xec, 0xc1, 0xf6, 0x9e, 0xe5, 0x5b, 0x94, 0xe6, 0x3f, 0x66, 0x8f, 0xf4, 0x41, 0xff, 0xf5, 0xab, 0x5c, 0x54, 0x5e, 0x39, 0xa1, 0x8d, 0x0a, 0xa0, 0xfc, 0x45, 0x8f, 0x61, 0x6c, 0x83, 0x92, 0x48, 0xdc, 0x81, 0x59, 0xb9, 0x1c, 0x6a, 0x57, 0xa0, 0xab, 0xb5, 0xdf, 0x8f, 0x5c, 0xdf, 0x87, 0x49, 0x03, 0xe3, 0xbe, 0x8f, 0x47, 0x84, 0x77, 0x89, 0x94, 0x82, 0x9b, 0xd8, 0x24, 0xb0, 0x16, 0x32, 0x6a, 0x40, 0x1d, 0x08, 0x3b, 0x33, 0xd0, 0x92, 0x29, 0x33, 0x33, 0xa8, 0x30, 0xa0, 0x39, 0x69, 0x11, 0x34, 0x5f, 0xd5, 0xb3, 0x4b, 0x31, 0x89, 0x88, 0x2e, 0x15, 0x73, 0xb8, 0x7f, 0xa6, 0x4a, 0x11, 0xa3, 0x4d, 0x81, 0x0b, 0xbd, 0x77, 0xcb, 0xb3, 0xeb, 0xb4, 0xa1, 0x30, 0x11, 0xa0, 0x1e, 0x93, 0x38, 0x5b, 0xe2, 0x50, 0x04, 0x7b, 0xd0, 0xb5, 0xfc, 0xad, 0x90, 0x4c, 0x42, 0xe4, 0xbf, 0x4c, 0xed, 0x18, 0xda, 0xcc, 0x72, 0x9f, 0xc6, 0x8c, 0xd4, 0xe3, 0x87, 0x17, 0x27, 0xf0, 0xa0, 0x48, 0x52, 0xb4, 0x18, 0x9d, 0x25, 0x34, 0xc3, 0x79, 0xb1, 0x36, 0x5d, 0xf9, 0xbe, 0x0a, 0x51, 0xc1, 0x7f, 0x09, 0xf7, 0xd0, 0x34, 0x56, 0x13, 0x04, 0x0b, 0x1f, 0xa0, 0x20, 0x48, 0x18, 0x06, 0xb9, 0x01, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x42, 0x00, 0x10, 0x02, 0x00, 0x40, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x01, 0x68, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x90, 0x00, 0x80, 0x00, 0x00, 0x4c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x09, 0x00, 0x04, 0x21, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xa0, 0x4d, 0x00, 0x00, 0x00, 0x01, 0xa4, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x04, 0x30, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x80, 0x20, 0x00, 0x20, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x04, 0x80, 0x02, 0x00, 0x02, 0x01, 0x02, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x40, 0x40, 0x00, 0x80, 0x80, 0x20, 0x00, 0x14, 0x12, 0x00, 0x00, 0x80, 0x10, 0x00, 0x01, 0x30, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x05, 0x20, 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x0a, 0x42, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xa2, 0x00, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x84, 0x02, 0x10, 0x00, 0x01, 0x10, 0x02, 0x80, 0x87, 0x05, 0x8d, 0x4d, 0x00, 0x3a, 0x5e, 0xae, 0x83, 0x47, 0xb7, 0x60, 0x83, 0x66, 0x25, 0xf7, 0x83, 0x66, 0x07, 0xa1, 0x84, 0x5a, 0x2b, 0x46, 0xbb, 0x8f, 0xe4, 0xb8, 0x83, 0xe5, 0xbd, 0xa9, 0xe7, 0xa5, 0x9e, 0xe4, 0xbb, 0x99, 0xe9, 0xb1, 0xbc, 0xa0, 0x52, 0x47, 0x69, 0x1a, 0xb0, 0x95, 0x3f, 0xa5, 0xc5, 0xc2, 0xc8, 0x4b, 0x0b, 0x14, 0x2b, 0x6d, 0x62, 0xe9, 0xdc, 0x5f, 0x35, 0xa8, 0x65, 0xed, 0x19, 0x7b, 0x9c, 0xd3, 0x73, 0x6a, 0xf6, 0xf1, 0x88, 0x85, 0x72, 0x87, 0x40, 0x01, 0x60, 0x21, 0x8d}; | |
const unsigned char parnetHash[32] = { | |
0x4d,0x1e,0x1f,0x82,0x40,0x0b,0x58,0x55,0xf1,0xec,0xc1,0xf6,0x9e, | |
0xe5,0x5b,0x94,0xe6,0x3f,0x66,0x8f,0xf4,0x41,0xff,0xf5,0xab,0x5c, | |
0x54,0x5e,0x39,0xa1,0x8d,0x0a | |
}; | |
const unsigned char ommersHash[32] = { | |
0xfc, 0x45, 0x8f, 0x61, 0x6c, 0x83, 0x92, 0x48, 0xdc, 0x81, 0x59, 0xb9, 0x1c, | |
0x6a, 0x57, 0xa0, 0xab, 0xb5, 0xdf, 0x8f, 0x5c, 0xdf, 0x87, 0x49, 0x03, 0xe3, | |
0xbe, 0x8f, 0x47, 0x84, 0x77, 0x89 | |
}; | |
const unsigned char beneficiary[20] = { | |
0x82, 0x9B, 0xD8, 0x24, 0xB0, 0x16, 0x32, 0x6A, 0x40, 0x1D, 0x08, 0x3B, 0x33, | |
0xD0, 0x92, 0x29, 0x33, 0x33, 0xA8, 0x30 | |
}; | |
const unsigned char stateRoot[32] = { | |
0x39, 0x69, 0x11, 0x34, 0x5F, 0xD5, 0xB3, 0x4B, 0x31, 0x89, 0x88, 0x2E, 0x15, | |
0x73, 0xB8, 0x7F, 0xA6, 0x4A, 0x11, 0xA3, 0x4D, 0x81, 0x0B, 0xBD, 0x77, 0xCB, | |
0xB3, 0xEB, 0xB4, 0xA1, 0x30, 0x11 | |
}; | |
const unsigned char transactionRoot[32] = { | |
0x1E, 0x93, 0x38, 0x5B, 0xE2, 0x50, 0x04, 0x7B, 0xD0, 0xB5, 0xFC, 0xAD, 0x90, | |
0x4C, 0x42, 0xE4, 0xBF, 0x4C, 0xED, 0x18, 0xDA, 0xCC, 0x72, 0x9F, 0xC6, 0x8C, | |
0xD4, 0xE3, 0x87, 0x17, 0x27, 0xF0 | |
}; | |
const unsigned char receiptsRoot[32] = { | |
0x48, 0x52, 0xB4, 0x18, 0x9D, 0x25, 0x34, 0xC3, 0x79, 0xB1, 0x36, 0x5D, 0xF9, | |
0xBE, 0x0A, 0x51, 0xC1, 0x7F, 0x09, 0xF7, 0xD0, 0x34, 0x56, 0x13, 0x04, 0x0B, | |
0x1F, 0xA0, 0x20, 0x48, 0x18, 0x06 | |
}; | |
const unsigned char logsBloom[256] = { | |
0x04, 0x00, 0x20, 0x00, 0x00, 0x42, 0x00, 0x10, 0x02, 0x00, 0x40, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x01, 0x68, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x90, 0x00, 0x80, 0x00, 0x00, 0x4C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x09, 0x00, 0x04, 0x21, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xA0, 0x4D, 0x00, 0x00, 0x00, 0x01, 0xA4, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x04, 0x30, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x80, 0x20, 0x00, 0x20, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x04, 0x80, 0x02, 0x00, 0x02, 0x01, 0x02, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x40, 0x40, 0x00, 0x80, 0x80, 0x20, 0x00, 0x14, 0x12, 0x00, 0x00, 0x80, 0x10, 0x00, 0x01, 0x30, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x05, 0x20, 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x0A, 0x42, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xA2, 0x00, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x84, 0x02, 0x10, 0x00, 0x01, 0x10, 0x02, 0x80 | |
}; | |
const unsigned char difficulty[] = { | |
0x05, 0x8D, 0x4D, 0x00, 0x3A, 0x5E, 0xAE | |
}; | |
const unsigned char blockNumber[3] = { | |
0x47, 0xB7, 0x60 | |
}; | |
const unsigned char gasLimit[3] = { | |
0x66, 0x25, 0xF7 | |
}; | |
const unsigned char gasUsed[3] = { | |
0x66, 0x07, 0xA1 | |
}; | |
const unsigned char timestamp[4] = { | |
0x5A, 0x2B, 0x46, 0xBB | |
}; | |
const unsigned char extraData[] = { | |
0xE4, 0xB8, 0x83, 0xE5, 0xBD, 0xA9, 0xE7, 0xA5, 0x9E, 0xE4, 0xBB, 0x99, 0xE9, 0xB1, 0xBC | |
}; | |
const unsigned char mixHash[] = { | |
0x52, 0x47, 0x69, 0x1A, 0xB0, 0x95, 0x3F, 0xA5, 0xC5, 0xC2, 0xC8, 0x4B, 0x0B, 0x14, 0x2B, | |
0x6D, 0x62, 0xE9, 0xDC, 0x5F, 0x35, 0xA8, 0x65, 0xED, 0x19, 0x7B, 0x9C, 0xD3, 0x73, 0x6A, 0xF6, 0xF1 | |
}; | |
const unsigned char nonce[] = { | |
0x85, 0x72, 0x87, 0x40, 0x01, 0x60, 0x21, 0x8D | |
}; | |
uint trim_len; | |
rlp_item items[15]; | |
decode_list(rlp_data, items); | |
print_elm("parentHash", &items[0]); | |
print_elm("ommersHash", &items[1]); | |
print_elm("beneficiary", &items[2]); | |
print_elm("stateRoot", &items[3]); | |
print_elm("transactionsRoot", &items[4]); | |
print_elm("receiptsRoot", &items[5]); | |
print_elm("logsBloom", &items[6]); | |
print_elm("difficulty", &items[7]); | |
print_elm("number", &items[8]); | |
print_elm("gasLimit", &items[9]); | |
print_elm("gasUsed", &items[10]); | |
print_elm("timestamp", &items[11]); | |
print_elm("extraData", &items[12]); | |
print_elm("mixHash", &items[13]); | |
print_elm("nonce", &items[14]); | |
CHECK_RLP_RESULT(items, 0, parnetHash); | |
CHECK_RLP_RESULT(items, 1, ommersHash); | |
CHECK_RLP_RESULT(items, 2, beneficiary); | |
CHECK_RLP_RESULT(items, 3, stateRoot); | |
CHECK_RLP_RESULT(items, 4, transactionRoot); | |
CHECK_RLP_RESULT(items, 5, receiptsRoot); | |
CHECK_RLP_RESULT(items, 6, logsBloom); | |
CHECK_RLP_RESULT(items, 7, difficulty); | |
CHECK_RLP_RESULT(items, 8, blockNumber); | |
CHECK_RLP_RESULT(items, 9, gasLimit); | |
CHECK_RLP_RESULT(items, 10, gasUsed); | |
CHECK_RLP_RESULT(items, 11, timestamp); | |
CHECK_RLP_RESULT(items, 12, extraData); | |
CHECK_RLP_RESULT(items, 13, mixHash); | |
CHECK_RLP_RESULT(items, 14, nonce); | |
print_elm("parentHash", &items[0]); | |
print_elm("ommersHash", &items[1]); | |
print_elm("beneficiary", &items[2]); | |
print_elm("stateRoot", &items[3]); | |
print_elm("transactionsRoot", &items[4]); | |
print_elm("receiptsRoot", &items[5]); | |
print_elm("logsBloom", &items[6]); | |
print_elm("difficulty", &items[7]); | |
print_elm("number", &items[8]); | |
print_elm("gasLimit", &items[9]); | |
print_elm("gasUsed", &items[10]); | |
print_elm("timestamp", &items[11]); | |
print_elm("extraData", &items[12]); | |
print_elm("mixHash", &items[13]); | |
print_elm("nonce", &items[14]); | |
printf("removing nonce %u\n", items[14].len); | |
trim_len = remove_last_field_from_rlp(rlp_data, items[14].len); | |
if(trim_len != (sizeof(rlp_data) - 9)) return -20; | |
trim_len = remove_last_field_from_rlp(rlp_data, items[13].len); | |
if(trim_len != (sizeof(rlp_data) - 42)) return -21; | |
memset(items, 0x00, sizeof(items)); | |
decode_list(rlp_data, items); | |
print_elm("parentHash", &items[0]); | |
print_elm("ommersHash", &items[1]); | |
print_elm("beneficiary", &items[2]); | |
print_elm("stateRoot", &items[3]); | |
print_elm("transactionsRoot", &items[4]); | |
print_elm("receiptsRoot", &items[5]); | |
print_elm("logsBloom", &items[6]); | |
print_elm("difficulty", &items[7]); | |
print_elm("number", &items[8]); | |
print_elm("gasLimit", &items[9]); | |
print_elm("gasUsed", &items[10]); | |
print_elm("timestamp", &items[11]); | |
print_elm("extraData", &items[12]); | |
print_elm("mixHash", &items[13]); | |
print_elm("nonce", &items[14]); | |
CHECK_RLP_RESULT(items, 0, parnetHash); | |
CHECK_RLP_RESULT(items, 1, ommersHash); | |
CHECK_RLP_RESULT(items, 2, beneficiary); | |
CHECK_RLP_RESULT(items, 3, stateRoot); | |
CHECK_RLP_RESULT(items, 4, transactionRoot); | |
CHECK_RLP_RESULT(items, 5, receiptsRoot); | |
CHECK_RLP_RESULT(items, 6, logsBloom); | |
CHECK_RLP_RESULT(items, 7, difficulty); | |
CHECK_RLP_RESULT(items, 8, blockNumber); | |
CHECK_RLP_RESULT(items, 9, gasLimit); | |
CHECK_RLP_RESULT(items, 10, gasUsed); | |
CHECK_RLP_RESULT(items, 11, timestamp); | |
CHECK_RLP_RESULT(items, 12, extraData); | |
//CHECK_RLP_RESULT(items, 13, mixHash); | |
//CHECK_RLP_RESULT(items, 14, nonce); | |
return 0; | |
} | |
/*****************************************************************************/ | |
int main() { | |
printf("%s\n", test1() >= 0 ? "test succesful" : "test failed"); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment