Initial version

This commit is contained in:
Alexandre Paillier
2022-03-04 18:15:37 +01:00
parent b25eaa1b48
commit 1bc8675473

View File

@@ -0,0 +1,269 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
enum {
OFFSET_CLA = 0,
OFFSET_INS,
OFFSET_P1,
OFFSET_P2,
OFFSET_LC,
OFFSET_DATA
};
typedef enum
{
// contract defined struct
TYPE_CUSTOM = 0,
// native types
TYPE_SOLIDITY_INT,
TYPE_SOLIDITY_UINT,
TYPE_SOLIDITY_ADDRESS,
TYPE_SOLIDITY_BOOL,
TYPE_SOLIDITY_STRING,
TYPE_SOLIDITY_BYTE,
TYPE_SOLIDITY_BYTES_FIX,
TYPE_SOLIDITY_BYTES_DYN
} e_type;
// APDUs INS
#define INS_STRUCT_DEF 0x18
#define INS_STRUCT_IMPL 0x1A
// TypeDesc masks
#define TYPE_MASK (0xF)
#define ARRAY_MASK (1 << 7)
#define TYPESIZE_MASK (1 << 6)
#define SIZE_MEM_BUFFER 1024
uint8_t mem_buffer[SIZE_MEM_BUFFER];
uint16_t mem_idx;
uint8_t *structs_array;
uint8_t *current_struct_fields_array;
bool set_struct_name(uint8_t *data)
{
// increment number of structs
*structs_array += 1;
// copy length
mem_buffer[mem_idx++] = data[OFFSET_LC];
// copy name
memmove(&mem_buffer[mem_idx], &data[OFFSET_DATA], data[OFFSET_LC]);
mem_idx += data[OFFSET_LC];
// initialize number of fields
current_struct_fields_array = &mem_buffer[mem_idx];
mem_buffer[mem_idx++] = 0;
return true;
}
bool set_struct_field(uint8_t *data)
{
uint8_t data_idx = OFFSET_DATA;
uint8_t type_desc, len;
// increment number of struct fields
*current_struct_fields_array += 1;
// copy TypeDesc
type_desc = data[data_idx++];
mem_buffer[mem_idx++] = type_desc;
// check TypeSize flag in TypeDesc
if (type_desc & TYPESIZE_MASK)
{
// copy TypeSize
mem_buffer[mem_idx++] = data[data_idx++];
}
if ((type_desc & TYPE_MASK) == TYPE_CUSTOM)
{
len = data[data_idx++];
// copy custom struct name length
mem_buffer[mem_idx++] = len;
// copy name
memmove(&mem_buffer[mem_idx], &data[data_idx], len);
mem_idx += len;
data_idx += len;
}
// copy length
len = data[data_idx++];
mem_buffer[mem_idx++] = len;
// copy name
memmove(&mem_buffer[mem_idx], &data[data_idx], len);
mem_idx += len;
return true;
}
void dump_mem(void)
{
uint8_t *mem = structs_array + 1;
uint8_t type_desc;
uint8_t fields_count;
for (int i = 0; i < *structs_array; ++i)
{
fwrite(mem + 1, *mem, sizeof(*mem), stdout);
printf("(");
mem += (1 + *mem);
fields_count = *mem;
mem += 1;
for (int y = 0; y < fields_count; ++y)
{
if (y > 0) printf(",");
type_desc = *mem;
mem += 1;
switch (type_desc & TYPE_MASK)
{
case TYPE_CUSTOM:
fwrite(mem + 1, *mem, sizeof(*mem), stdout);
mem += (1 + *mem);
if (type_desc & TYPESIZE_MASK) mem += 1;
break;
case TYPE_SOLIDITY_UINT:
printf("u");
case TYPE_SOLIDITY_INT:
printf("int");
if (type_desc & TYPESIZE_MASK)
{
printf("%d", (*mem * 8));
mem += 1;
}
break;
case TYPE_SOLIDITY_ADDRESS:
printf("address");
if (type_desc & TYPESIZE_MASK) mem += 1;
break;
case TYPE_SOLIDITY_BOOL:
printf("bool");
if (type_desc & TYPESIZE_MASK) mem += 1;
break;
case TYPE_SOLIDITY_STRING:
printf("string");
if (type_desc & TYPESIZE_MASK) mem += 1;
break;
case TYPE_SOLIDITY_BYTE:
printf("byte");
if (type_desc & TYPESIZE_MASK) mem += 1;
break;
case TYPE_SOLIDITY_BYTES_FIX:
printf("bytes");
if (type_desc & TYPESIZE_MASK)
{
printf("%d", *mem);
mem += 1;
}
break;
case TYPE_SOLIDITY_BYTES_DYN:
printf("bytes");
if (type_desc & TYPESIZE_MASK) mem += 1;
break;
default:
// should not be in here :^)
break;
}
if (type_desc & ARRAY_MASK) printf("[]");
printf(" ");
fwrite(mem + 1, *mem, sizeof(*mem), stdout);
mem += (1 + *mem);
}
printf(")\n");
}
}
bool handle_apdu(uint8_t *data)
{
switch (data[OFFSET_INS])
{
case INS_STRUCT_DEF:
switch (data[OFFSET_P2])
{
case 0x00:
set_struct_name(data);
break;
case 0xFF:
set_struct_field(data);
break;
default:
printf("Unknown P2 0x%x for APDU 0x%x\n", data[OFFSET_P2], data[OFFSET_INS]);
return false;
}
break;
case INS_STRUCT_IMPL:
break;
default:
printf("Unrecognized APDU");
return false;
}
return true;
}
void init_heap(void)
{
// init global variables
mem_idx = 0;
// set types pointer
structs_array = &mem_buffer[mem_idx];
// create len(types)
mem_buffer[mem_idx++] = 0;
}
int main(void)
{
uint8_t buf[256];
uint8_t idx;
int state;
uint8_t payload_size;
init_heap();
state = OFFSET_CLA;
idx = 0;
while (true)
{
if (fread(&buf[idx], sizeof(buf[0]), 1, stdin) == 0) break;
switch (state)
{
case OFFSET_CLA:
case OFFSET_INS:
case OFFSET_P1:
case OFFSET_P2:
state += 1;
idx += 1;
break;
case OFFSET_LC:
payload_size = buf[idx];
state = OFFSET_DATA;
idx += 1;
break;
case OFFSET_DATA:
if (--payload_size == 0)
{
handle_apdu(buf);
state = OFFSET_CLA;
idx = 0;
}
else idx += 1;
break;
default:
printf("Unexpected APDU state!\n");
return EXIT_FAILURE;
}
}
dump_mem();
printf("\n%d bytes used in RAM\n", mem_idx);
return EXIT_SUCCESS;
}