Created
July 10, 2019 11:36
-
-
Save yaronvel/17810d39cc86613b0899874e5b9c438f to your computer and use it in GitHub Desktop.
This file contains hidden or 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 unsigned int bool; | |
#define TRUE 1 | |
#define FALSE 0 | |
typedef struct _rlp_elem { | |
unsigned char* content; | |
uint len; | |
struct _rlp_elem* list; | |
bool is_list; | |
struct _rlp_elem* next; | |
} rlp_elem; | |
/*****************************************************************************/ | |
static rlp_elem* get_n_elem(rlp_elem* list, uint n) { | |
uint i; | |
rlp_elem* curr; | |
if(list == NULL || list->list == NULL) return NULL; | |
curr = list->list; | |
for(i = 0 ; i < n ; i++) { | |
if(curr->next == NULL) return NULL; | |
curr = curr->next; | |
} | |
return curr; | |
} | |
/*****************************************************************************/ | |
static uint decode_single_byte(unsigned char* input, rlp_elem* output) { | |
output->content = input; | |
output->len = 1; | |
output->is_list = FALSE; | |
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_elem* output) { | |
unsigned char first_byte = input[0]; | |
uint len_num_bytes; | |
uint string_len; | |
output->is_list = FALSE; | |
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 uint decode_list(unsigned char* input, rlp_elem* list, rlp_elem** scrath_pad) { | |
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; | |
rlp_elem* prev = NULL; | |
rlp_elem* curr; | |
//printf("decode list start %u\n", cntr++); | |
if(first_byte <= 0xf7) { | |
list_len = first_byte - 0xc0; | |
len_num_bytes = 0; | |
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; | |
} | |
//printf("list len %u\n", list_len); | |
outputs_ind = 0; | |
list->is_list = TRUE; | |
curr = list->list = (*scrath_pad)++; | |
for(elm_ind = 0 ; /*elm_ind < list_len*/ current_input < input + list_len + len_num_bytes + 1 /* elm_ind < 20*/ ; elm_ind++) | |
{ | |
first_byte = current_input[0]; | |
memset(curr, 0x00, sizeof(rlp_elem)); | |
if(first_byte <= 0x7f) elm_len = decode_single_byte(current_input,curr); | |
else if(first_byte <= 0xbf) elm_len = decode_string(current_input,curr); | |
else { | |
curr->list = (*scrath_pad)++; | |
memset(curr->list, 0x00, sizeof(rlp_elem)); | |
elm_len = decode_list(current_input, | |
curr, | |
scrath_pad); | |
} | |
current_input += elm_len; | |
outputs_ind += 1; | |
if(prev != NULL) prev->next = curr; | |
prev = curr; | |
curr = (*scrath_pad)++; | |
} | |
//printf("decode list end %u\n", cntr--); | |
return list_len + len_num_bytes + 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_elem(const char* name, rlp_elem* elem) { | |
uint i; | |
if(elem->is_list){ | |
printf("list start\n"); | |
print_elem(name, elem->list); | |
} | |
else { | |
for(i = 0 ; i < elem->len ;i++) { | |
printf("%02X", elem->content[i]); | |
} | |
printf("\n"); | |
} | |
if(elem->next == NULL) printf("list end\n"); | |
else print_elem(name, elem->next); | |
} | |
/*****************************************************************************/ | |
static void print_single_elem(const char* name, rlp_elem* elem) { | |
uint i; | |
printf("%s: ", name); | |
if(elem == NULL) { | |
printf("NULL\n"); | |
return; | |
} | |
for(i = 0 ; i < elem->len ;i++) { | |
printf("%02X", elem->content[i]); | |
} | |
printf("\n"); | |
} | |
#define CHECK_RLP_RESULT(_rlp_items, _index, _value){\ | |
if(get_n_elem(_rlp_items,_index)->len != sizeof(_value)) return (-1 * 2 * (_index) - 1);\ | |
if(memcmp(get_n_elem(_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 | |
}; | |
rlp_elem elem[20] = {0}; | |
rlp_elem* list = elem; | |
rlp_elem* elem_ptr = elem + 1; | |
uint num_elem, i; | |
decode_list(rlp_data, list, &elem_ptr); | |
uint trim_len; | |
print_single_elem("parentHash", get_n_elem(list,0)); | |
print_single_elem("ommersHash", get_n_elem(list,1)); | |
print_single_elem("beneficiary", get_n_elem(list,2)); | |
print_single_elem("stateRoot", get_n_elem(list,3)); | |
print_single_elem("transactionsRoot", get_n_elem(list,4)); | |
print_single_elem("receiptsRoot", get_n_elem(list,5)); | |
print_single_elem("logsBloom", get_n_elem(list,6)); | |
print_single_elem("difficulty", get_n_elem(list,7)); | |
print_single_elem("number", get_n_elem(list,8)); | |
print_single_elem("gasLimit", get_n_elem(list,9)); | |
print_single_elem("gasUsed", get_n_elem(list,10)); | |
print_single_elem("timestamp", get_n_elem(list,11)); | |
print_single_elem("extraData", get_n_elem(list,12)); | |
print_single_elem("mixHash", get_n_elem(list,13)); | |
print_single_elem("nonce", get_n_elem(list,14)); | |
CHECK_RLP_RESULT(list, 0, parnetHash); | |
CHECK_RLP_RESULT(list, 1, ommersHash); | |
CHECK_RLP_RESULT(list, 2, beneficiary); | |
CHECK_RLP_RESULT(list, 3, stateRoot); | |
CHECK_RLP_RESULT(list, 4, transactionRoot); | |
CHECK_RLP_RESULT(list, 5, receiptsRoot); | |
CHECK_RLP_RESULT(list, 6, logsBloom); | |
CHECK_RLP_RESULT(list, 7, difficulty); | |
CHECK_RLP_RESULT(list, 8, blockNumber); | |
CHECK_RLP_RESULT(list, 9, gasLimit); | |
CHECK_RLP_RESULT(list, 10, gasUsed); | |
CHECK_RLP_RESULT(list, 11, timestamp); | |
CHECK_RLP_RESULT(list, 12, extraData); | |
CHECK_RLP_RESULT(list, 13, mixHash); | |
CHECK_RLP_RESULT(list, 14, nonce); | |
trim_len = remove_last_field_from_rlp(rlp_data, get_n_elem(list,14)->len); | |
if(trim_len != (sizeof(rlp_data) - 9)) return -20; | |
trim_len = remove_last_field_from_rlp(rlp_data, get_n_elem(list,13)->len); | |
if(trim_len != (sizeof(rlp_data) - 42)) return -21; | |
memset(elem, 0x00, sizeof(elem)); | |
list = elem; | |
elem_ptr = elem + 1; | |
decode_list(rlp_data, list, &elem_ptr); | |
print_single_elem("parentHash", get_n_elem(list,0)); | |
print_single_elem("ommersHash", get_n_elem(list,1)); | |
print_single_elem("beneficiary", get_n_elem(list,2)); | |
print_single_elem("stateRoot", get_n_elem(list,3)); | |
print_single_elem("transactionsRoot", get_n_elem(list,4)); | |
print_single_elem("receiptsRoot", get_n_elem(list,5)); | |
print_single_elem("logsBloom", get_n_elem(list,6)); | |
print_single_elem("difficulty", get_n_elem(list,7)); | |
print_single_elem("number", get_n_elem(list,8)); | |
print_single_elem("gasLimit", get_n_elem(list,9)); | |
print_single_elem("gasUsed", get_n_elem(list,10)); | |
print_single_elem("timestamp", get_n_elem(list,11)); | |
print_single_elem("extraData", get_n_elem(list,12)); | |
print_single_elem("mixHash", get_n_elem(list,13)); | |
print_single_elem("nonce", get_n_elem(list,14)); | |
CHECK_RLP_RESULT(list, 0, parnetHash); | |
CHECK_RLP_RESULT(list, 1, ommersHash); | |
CHECK_RLP_RESULT(list, 2, beneficiary); | |
CHECK_RLP_RESULT(list, 3, stateRoot); | |
CHECK_RLP_RESULT(list, 4, transactionRoot); | |
CHECK_RLP_RESULT(list, 5, receiptsRoot); | |
CHECK_RLP_RESULT(list, 6, logsBloom); | |
CHECK_RLP_RESULT(list, 7, difficulty); | |
CHECK_RLP_RESULT(list, 8, blockNumber); | |
CHECK_RLP_RESULT(list, 9, gasLimit); | |
CHECK_RLP_RESULT(list, 10, gasUsed); | |
CHECK_RLP_RESULT(list, 11, timestamp); | |
CHECK_RLP_RESULT(list, 12, extraData); | |
//CHECK_RLP_RESULT(list, 13, mixHash); | |
//CHECK_RLP_RESULT(list, 14, nonce); | |
return 0; | |
} | |
#if 0 | |
static void test2() { | |
unsigned char rlp[] = | |
{0xf9, 0x02, 0x18, 0xa0, 0xb4, 0x95, 0xa1, 0xd7, 0xe6, 0x66, 0x31, 0x52, 0xae, 0x92, 0x70, 0x8d, 0xa4, 0x84, 0x33, 0x37, 0xb9, 0x58, 0x14, 0x60, 0x15, 0xa2, 0x80, 0x2f, 0x41, 0x93, 0xa4, 0x10, 0x04, 0x46, 0x98, 0xc9, 0xa0, 0x6b, 0x17, 0xb9, 0x38, 0xc6, 0xe4, 0xef, 0x18, 0xb2, 0x6a, 0xd8, 0x1b, 0x9c, 0xa3, 0x51, 0x5f, 0x27, 0xfd, 0x9c, 0x4e, 0x82, 0xaa, 0xc5, 0x6a, 0x1f, 0xd8, 0xea, 0xb2, 0x88, 0x78, 0x5e, 0x41, 0x94, 0x50, 0x88, 0xd6, 0x23, 0xba, 0x0f, 0xcf, 0x01, 0x31, 0xe0, 0x89, 0x7a, 0x91, 0x73, 0x4a, 0x4d, 0x83, 0x59, 0x6a, 0xa0, 0xa0, 0x76, 0xab, 0x0b, 0x89, 0x9e, 0x83, 0x87, 0x43, 0x6f, 0xf2, 0x65, 0x8e, 0x29, 0x88, 0xf8, 0x3c, 0xbf, 0x1a, 0xf1, 0x59, 0x0b, 0x9f, 0xe9, 0xfe, 0xca, 0x37, 0x14, 0xf8, 0xd1, 0x82, 0x49, 0x40, 0xa0, 0x56, 0xe8, 0x1f, 0x17, 0x1b, 0xcc, 0x55, 0xa6, 0xff, 0x83, 0x45, 0xe6, 0x92, 0xc0, 0xf8, 0x6e, 0x5b, 0x48, 0xe0, 0x1b, 0x99, 0x6c, 0xad, 0xc0, 0x01, 0x62, 0x2f, 0xb5, 0xe3, 0x63, 0xb4, 0x21, 0xa0, 0x56, 0xe8, 0x1f, 0x17, 0x1b, 0xcc, 0x55, 0xa6, 0xff, 0x83, 0x45, 0xe6, 0x92, 0xc0, 0xf8, 0x6e, 0x5b, 0x48, 0xe0, 0x1b, 0x99, 0x6c, 0xad, 0xc0, 0x01, 0x62, 0x2f, 0xb5, 0xe3, 0x63, 0xb4, 0x21, 0xb9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x03, 0xfe, 0x80, 0x2f, 0xfe, 0x03, 0x82, 0x13, 0x88, 0x80, 0x84, 0x55, 0xba, 0x42, 0x60, 0xa0, 0x47, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x66, 0x63, 0x37, 0x39, 0x64, 0x33, 0x32, 0x64, 0x2f, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x2f, 0x67, 0x6f, 0x31, 0x2e, 0x34, 0xa0, 0x65, 0xe1, 0x2e, 0xec, 0x23, 0xfe, 0x65, 0x55, 0xe6, 0xbc, 0xdb, 0x47, 0xaa, 0x25, 0x26, 0x9a, 0xe1, 0x06, 0xe5, 0xf1, 0x6b, 0x54, 0xe1, 0xe9, 0x2d, 0xce, 0xe2, 0x5e, 0x1c, 0x8a, 0xd0, 0x37, 0x88, 0x2e, 0x93, 0x44, 0xe0, 0xcb, 0xde, 0x83, 0xce}; | |
rlp_item items[15]; | |
decode_list(rlp, 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]); | |
} | |
/*****************************************************************************/ | |
#endif | |
static void test6() { | |
unsigned char rlp[] = | |
{0xf9,0x01,0xa7,0x01,0x83,0x1d,0xe5,0xd2,0xb9,0x01,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x9d,0xf8,0x9b,0x94,0xdd,0x97,0x4d,0x5c,0x2e,0x29,0x28,0xde,0xa5,0xf7,0x1b,0x98,0x25,0xb8,0xb6,0x46,0x68,0x6b,0xd2,0x00,0xf8,0x63,0xa0,0xdd,0xf2,0x52,0xad,0x1b,0xe2,0xc8,0x9b,0x69,0xc2,0xb0,0x68,0xfc,0x37,0x8d,0xaa,0x95,0x2b,0xa7,0xf1,0x63,0xc4,0xa1,0x16,0x28,0xf5,0x5a,0x4d,0xf5,0x23,0xb3,0xef,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x13,0x4f,0x34,0xbf,0x05,0x91,0xc1,0xdb,0x52,0xc8,0x45,0x54,0x19,0xbe,0xe2,0x68,0x89,0x6a,0x6e,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf2,0x88,0x90,0xdb,0xed,0x02,0xa2,0xea,0x3a,0xb9,0x76,0xc7,0xa2,0x95,0x3e,0xd5,0x63,0x30,0x7c,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xc1,0x6d,0x67,0x4e,0xc8,0x00,0x00}; | |
rlp_elem elem[1000] = {0}; | |
rlp_elem* list = elem; | |
rlp_elem* elem_ptr = elem + 1; | |
uint num_elem, i; | |
decode_list(rlp, list, &elem_ptr); | |
print_elem("", list->list); | |
rlp_elem* num3 = list->list->next->next->next; | |
rlp_elem* num3_0 = num3->list->list; | |
rlp_elem* num3_0_1 = num3_0->next; | |
rlp_elem* num3_0_1_0 = num3_0_1->list; | |
for(i = 0 ; i < num3_0_1_0->len ;i++) { | |
printf("%02X", num3_0_1_0->content[i]); | |
} | |
printf("\n"); | |
} | |
//item #3 in list (logs) -> item #0 in list (first event) -> item #1 in list (topics) -> item #0 (first topic = function signature) | |
/*****************************************************************************/ | |
// mult start here | |
static unsigned __int128 decode_number128(unsigned char* input, uint len) { | |
uint i; | |
unsigned __int128 result; | |
result = 0; | |
for(i = 0 ; i < len ; i++) { | |
result = result << 8; | |
result += (unsigned char)input[i]; | |
} | |
return result; | |
} | |
/*****************************************************************************/ | |
static int check_pow(unsigned char* difficulty, | |
uint difficulty_len, | |
unsigned char* ethash, | |
unsigned __int128* result_lsb, | |
unsigned __int128* result_msb) { | |
unsigned __int128 difficulty_value = decode_number128(difficulty, difficulty_len); | |
unsigned __int128 ethash_value[4]; | |
unsigned __int128 result[4]; | |
unsigned __int128 max_uint64 = 0xFFFFFFFFFFFFFFFFL; | |
unsigned __int128 temp; | |
unsigned __int128 temp2; | |
uint i; | |
if(difficulty_len > 8) printf("error: unexpected difficulty len\n"); | |
memset(result, 0x00, sizeof(result)); | |
for(i = 0 ; i < 4; i++) ethash_value[i] = decode_number128(ethash + 8*i, 8); | |
temp = difficulty_value * ethash_value[3]; | |
result[3] = temp & max_uint64; | |
result[2] = temp >> 64; | |
temp = difficulty_value * ethash_value[2]; | |
temp2 = (temp & max_uint64) + result[2]; | |
result[2] = temp2 & max_uint64; | |
result[1] = (temp2 >> 64) + (temp >> 64); | |
temp = difficulty_value * ethash_value[1]; | |
temp2 = (temp & max_uint64) + result[1]; | |
result[1] = temp2 & max_uint64; | |
result[0] = (temp2 >> 64) + (temp >> 64);; | |
temp = difficulty_value * ethash_value[0]; | |
temp2 = (temp & max_uint64) + result[0]; | |
result[0] = temp2 & max_uint64; | |
printf("0x%016lx%016lx%016lx%016lx\n", (long unsigned int)result[0] , (long unsigned int)result[1], (long unsigned int)result[2], (long unsigned int)result[3]); | |
if(result_lsb != NULL && result_msb != NULL) { | |
*result_lsb = result[3] | (result[2] << 64); | |
*result_msb = result[1] | (result[0] << 64); | |
} | |
return ((temp2 >> 64) + (temp >> 64)) == 0; | |
} | |
/*****************************************************************************/ | |
static int check_pow_test1() { | |
unsigned char difficulty[] = {0x05, 0x8d, 0x4d, 0x00, 0x3a, 0x5e, 0xae}; | |
unsigned char ethash[32] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x46, 0x85, 0xc4, 0x3f, 0x3d, 0xca, 0xa0, 0x1f, 0x90, 0x80, 0x7d, 0xd8, 0x42, 0x36, 0x88, 0xe5, 0xf7, 0xfd, 0xae, 0x78, 0x50, 0xb7, 0x80, 0xb8, 0xf}; | |
unsigned __int128 result_lsb, result_msb, expected_result_lsb, expected_result_msb; | |
// result was calculated here https://defuse.ca/big-number-calculator.htm | |
expected_result_msb = (unsigned __int128)0x54cf0cbc0ab198d4L << 64 | 0x0ffa2c5eda6b3488L; | |
expected_result_lsb = (unsigned __int128)0xd5a05ec42eff1218L << 64 | 0x6e6f9ceab0789c32L; | |
if( ! check_pow(difficulty, sizeof(difficulty), ethash, &result_lsb, &result_msb) ) return -1; | |
if(result_msb != expected_result_msb) return -2; | |
if(result_lsb != expected_result_lsb) return -3; | |
printf("check_pow_test1 succesful\n"); | |
return 0; | |
} | |
/*****************************************************************************/ | |
static int check_pow_test2() { | |
unsigned char difficulty[] = {0x15, 0x8a, 0x9d, 0x31, 0x9b, 0x5d}; | |
// 0x158a9d319b5d | |
unsigned char ethash[32] = {0x01, 0x02, 0xf0, 0xa0, 0xaa, 0xbb, 0xcf, 0x48, 0x85, 0xc4, 0x3e, 0x3d, 0xcb, 0xa7, 0x1f, 0x92, 0x80, 0x7e, 0xd4, 0x41, 0x36, 0x48, 0xe5, 0xff, 0x0d, 0xae, 0x78, 0x50, 0xb7, 0x80, 0xb8, 0xf3}; | |
//0x0102f0a0aabbcf4885c43e3dcba71f92807ed4413648e5ff0dae7850b780b8f3 | |
// result was calculated here https://defuse.ca/big-number-calculator.htm | |
// result = 0x15c9f1e45d2e773de1188aca16b761899ebb7451135586982cfcde13af9dc7477c07415147 | |
// 256 bit result is 0x2e773de1188aca16b761899ebb7451135586982cfcde13af9dc7477c07415147. rest is overflow | |
unsigned __int128 result_lsb, result_msb, expected_result_lsb, expected_result_msb; | |
expected_result_msb = (unsigned __int128)0x2e773de1188aca16L << 64 | 0xb761899ebb745113L; | |
expected_result_lsb = (unsigned __int128)0x5586982cfcde13afL << 64 | 0x9dc7477c07415147L; | |
// overflow is expected | |
if( check_pow(difficulty, sizeof(difficulty), ethash, &result_lsb, &result_msb) ) return -1; | |
if(result_msb != expected_result_msb) return -2; | |
if(result_lsb != expected_result_lsb) return -3; | |
printf("check_pow_test2 succesful\n"); | |
return 0; | |
} | |
/*****************************************************************************/ | |
static int check_pow_test3() { | |
unsigned char difficulty[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |
// 0xffffffffffffffff | |
unsigned char ethash[32] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |
// 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff | |
// result was calculated here https://defuse.ca/big-number-calculator.htm | |
// result = 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff0000000000000001 | |
// 256 bit result is 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000001. rest is overflow | |
unsigned __int128 result_lsb, result_msb, expected_result_lsb, expected_result_msb; | |
expected_result_msb = (unsigned __int128)0xffffffffffffffffL << 64 | 0xffffffffffffffffL; | |
expected_result_lsb = (unsigned __int128)0xffffffffffffffffL << 64 | 0x0000000000000001L; | |
// overflow is expected | |
if( check_pow(difficulty, sizeof(difficulty), ethash, &result_lsb, &result_msb) ) return -1; | |
if(result_msb != expected_result_msb) return -2; | |
if(result_lsb != expected_result_lsb) return -3; | |
printf("check_pow_test3 succesful\n"); | |
return 0; | |
} | |
/*****************************************************************************/ | |
int main() { | |
//printf("%s\n", test1() >= 0 ? "test succesful" : "test failed"); | |
//test2(); | |
// unsigned char difficulty[] = {0x05, 0x8d, 0x4d, 0x00, 0x3a, 0x5e, 0xae}; | |
// unsigned char ethash[32] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x46, 0x85, 0xc4, 0x3f, 0x3d, 0xca, 0xa0, 0x1f, 0x90, 0x80, 0x7d, 0xd8, 0x42, 0x36, 0x88, 0xe5, 0xf7, 0xfd, 0xae, 0x78, 0x50, 0xb7, 0x80, 0xb8, 0xf}; | |
/* | |
unsigned char difficulty[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |
unsigned char ethash[32] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |
printf("%d\n", check_pow(difficulty, sizeof(difficulty), ethash)); | |
*/ | |
/* | |
printf("%d\n", check_pow_test1()); | |
printf("%d\n", check_pow_test2()); | |
printf("%d\n", check_pow_test3()); | |
*/ | |
printf("%d\n", test1()); | |
test6(); | |
return 0; | |
} | |
/*****************************************************************************/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment