Program bank integration (#1462)

Native, BPF and Lua loaders integrated into the bank
This commit is contained in:
jackcmay
2018-10-16 09:43:49 -07:00
committed by GitHub
parent 1b2e9122d5
commit d09889b1dd
26 changed files with 1379 additions and 841 deletions

View File

@ -24,7 +24,7 @@ typedef struct {
typedef struct {
SolPubkey *key;
int64_t tokens;
int64_t* tokens;
uint64_t userdata_len;
uint8_t *userdata;
SolPubkey *program_id;
@ -50,7 +50,7 @@ SOL_FN_PREFIX void _sol_panic(uint64_t line) {
SOL_FN_PREFIX int sol_deserialize(uint8_t *src, uint64_t num_ka, SolKeyedAccounts *ka,
uint8_t **userdata, uint64_t *userdata_len) {
if (num_ka != *(uint64_t *)src) {
return -1;
return 0;
}
src += sizeof(uint64_t);
@ -61,8 +61,8 @@ SOL_FN_PREFIX int sol_deserialize(uint8_t *src, uint64_t num_ka, SolKeyedAccount
src += SIZE_PUBKEY;
// tokens
ka[i].tokens = *(uint64_t *)src;
src += sizeof(uint64_t);
ka[i].tokens = (int64_t *)src;
src += sizeof(int64_t);
// account userdata
ka[i].userdata_len = *(uint64_t *)src;
@ -79,7 +79,7 @@ SOL_FN_PREFIX int sol_deserialize(uint8_t *src, uint64_t num_ka, SolKeyedAccount
src += sizeof(uint64_t);
*userdata = src;
return 0;
return 1;
}
@ -105,7 +105,7 @@ SOL_FN_PREFIX void print_params(uint64_t num_ka, SolKeyedAccounts *ka,
print_key(ka[i].key);
// tokens
sol_print(0, 0, 0, 0, ka[i].tokens);
sol_print(0, 0, 0, 0, *ka[i].tokens);
// account userdata
print_userdata(ka[i].userdata, ka[i].userdata_len);
@ -117,14 +117,24 @@ SOL_FN_PREFIX void print_params(uint64_t num_ka, SolKeyedAccounts *ka,
print_userdata(userdata, userdata_len);
}
void entrypoint(char *buf) {
uint64_t entrypoint(char *buf) {
SolKeyedAccounts ka[3];
uint64_t userdata_len;
uint8_t *userdata;
if (0 != sol_deserialize((uint8_t *)buf, 3, ka, &userdata, &userdata_len)) {
return;
if (1 != sol_deserialize((uint8_t *)buf, 3, ka, &userdata, &userdata_len)) {
return 1;
}
print_params(3, ka, userdata, userdata_len);
int64_t tokens = *(int64_t*)userdata;
if (*ka[0].tokens >= tokens) {
*ka[0].tokens -= tokens;
*ka[2].tokens += tokens;
//sol_print(0, 0, *ka[0].tokens, *ka[2].tokens, tokens);
} else {
//sol_print(0, 0, 0xFF, *ka[0].tokens, tokens);
}
return 0;
}

9
programs/bpf/noop_c/build.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/bash -ex
OUTDIR="${1:-../../../target/release/}"
THISDIR=$(dirname "$0")
mkdir -p "$OUTDIR"
/usr/local/opt/llvm/bin/clang -Werror -target bpf -O2 -emit-llvm -fno-builtin -o "$OUTDIR"/noop_c.bc -c "$THISDIR"/src/noop.c
/usr/local/opt/llvm/bin/llc -march=bpf -filetype=obj -function-sections -o "$OUTDIR"/noop_c.o "$OUTDIR"/noop_c.bc
#/usr/local/opt/llvm/bin/llvm-objdump -color -source -disassemble "$OUTDIR"/noop_c.o

3
programs/bpf/noop_c/dump.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
/usr/local/opt/llvm/bin/llvm-objdump -color -source -disassemble ../../../target/release/noop_c.o

View File

@ -0,0 +1,133 @@
//#include <stdint.h>
//#include <stddef.h>
#if 1
// one way to define a helper function is with index as a fixed value
#define BPF_TRACE_PRINTK_IDX 6
static int (*sol_print)(int, int, int, int, int) = (void *)BPF_TRACE_PRINTK_IDX;
#else
// relocation is another option
extern int sol_print(int, int, int, int, int);
#endif
typedef long long unsigned int uint64_t;
typedef long long int int64_t;
typedef unsigned char uint8_t;
typedef enum { false = 0, true } bool;
#define SIZE_PUBKEY 32
typedef struct {
uint8_t x[SIZE_PUBKEY];
} SolPubkey;
typedef struct {
SolPubkey *key;
int64_t* tokens;
uint64_t userdata_len;
uint8_t *userdata;
SolPubkey *program_id;
} SolKeyedAccounts;
// TODO support BPF function calls rather then forcing everything to be inlined
#define SOL_FN_PREFIX __attribute__((always_inline)) static
// TODO move this to a registered helper
SOL_FN_PREFIX void sol_memcpy(void *dst, void *src, int len) {
for (int i = 0; i < len; i++) {
*((uint8_t *)dst + i) = *((uint8_t *)src + i);
}
}
#define sol_panic() _sol_panic(__LINE__)
SOL_FN_PREFIX void _sol_panic(uint64_t line) {
sol_print(0, 0, 0xFF, 0xFF, line);
char *pv = (char *)1;
*pv = 1;
}
SOL_FN_PREFIX int sol_deserialize(uint8_t *src, uint64_t num_ka, SolKeyedAccounts *ka,
uint8_t **userdata, uint64_t *userdata_len) {
if (num_ka != *(uint64_t *)src) {
return 0;
}
src += sizeof(uint64_t);
// TODO fixed iteration loops ok? unrolled?
for (int i = 0; i < num_ka; i++) { // TODO this should end up unrolled, confirm
// key
ka[i].key = (SolPubkey *)src;
src += SIZE_PUBKEY;
// tokens
ka[i].tokens = (int64_t *)src;
src += sizeof(int64_t);
// account userdata
ka[i].userdata_len = *(uint64_t *)src;
src += sizeof(uint64_t);
ka[i].userdata = src;
src += ka[i].userdata_len;
// program_id
ka[i].program_id = (SolPubkey *)src;
src += SIZE_PUBKEY;
}
// tx userdata
*userdata_len = *(uint64_t *)src;
src += sizeof(uint64_t);
*userdata = src;
return 1;
}
// -- Debug --
SOL_FN_PREFIX void print_key(SolPubkey *key) {
for (int j = 0; j < SIZE_PUBKEY; j++) {
sol_print(0, 0, 0, j, key->x[j]);
}
}
SOL_FN_PREFIX void print_userdata(uint8_t *data, int len) {
for (int j = 0; j < len; j++) {
sol_print(0, 0, 0, j, data[j]);
}
}
SOL_FN_PREFIX void print_params(uint64_t num_ka, SolKeyedAccounts *ka,
uint8_t *userdata, uint64_t userdata_len) {
sol_print(0, 0, 0, 0, num_ka);
for (int i = 0; i < num_ka; i++) {
// key
print_key(ka[i].key);
// tokens
sol_print(0, 0, 0, 0, *ka[i].tokens);
// account userdata
print_userdata(ka[i].userdata, ka[i].userdata_len);
// program_id
print_key(ka[i].program_id);
}
// tx userdata
print_userdata(userdata, userdata_len);
}
// -- Program entrypoint --
uint64_t entrypoint(char *buf) {
SolKeyedAccounts ka[1];
uint64_t userdata_len;
uint8_t *userdata;
if (1 != sol_deserialize((uint8_t *)buf, 1, ka, &userdata, &userdata_len)) {
return 0;
}
print_params(1, ka, userdata, userdata_len);
return 1;
}

View File

@ -49,7 +49,7 @@ SOL_FN_PREFIX void _sol_panic(uint64_t line) {
SOL_FN_PREFIX int sol_deserialize(uint8_t *src, uint64_t num_ka, SolKeyedAccounts *ka,
uint8_t **userdata, uint64_t *userdata_len) {
if (num_ka != *(uint64_t *)src) {
return -1;
return 0;
}
src += sizeof(uint64_t);
@ -78,9 +78,55 @@ SOL_FN_PREFIX int sol_deserialize(uint8_t *src, uint64_t num_ka, SolKeyedAccount
src += sizeof(uint64_t);
*userdata = src;
return 0;
return 1;
}
// // -- Debug --
SOL_FN_PREFIX void print_key(SolPubkey *key) {
for (int j = 0; j < SIZE_PUBKEY; j++) {
sol_print(0, 0, 0, j, key->x[j]);
}
}
SOL_FN_PREFIX void print_userdata(uint8_t *data, int len) {
for (int j = 0; j < len; j++) {
sol_print(0, 0, 0, j, data[j]);
}
}
SOL_FN_PREFIX void print_params(uint64_t num_ka, SolKeyedAccounts *ka,
uint8_t *userdata, uint64_t userdata_len) {
sol_print(0, 0, 0, 0, num_ka);
for (int i = 0; i < num_ka; i++) {
// key
print_key(ka[i].key);
// tokens
sol_print(0, 0, 0, 0, ka[i].tokens);
// account userdata
print_userdata(ka[i].userdata, ka[i].userdata_len);
// program_id
print_key(ka[i].program_id);
}
// tx userdata
print_userdata(userdata, userdata_len);
}
// void entrypoint(char *buf) {
// SolKeyedAccounts ka[3];
// uint64_t userdata_len;
// uint8_t *userdata;
// if (0 != sol_deserialize((uint8_t *)buf, 3, ka, &userdata, &userdata_len)) {
// return;
// }
// print_params(3, ka, userdata, userdata_len);
// }
// -- TicTacToe --
// Board Coodinates
@ -279,92 +325,48 @@ SOL_FN_PREFIX Result game_keep_alive(Game *self, SolPubkey *player,
return Result_Ok;
}
void entrypoint(uint8_t *buf) {
SolKeyedAccounts ka[3];
uint64_t entrypoint(uint8_t *buf) {
SolKeyedAccounts ka[4];
uint64_t userdata_len;
uint8_t *userdata;
int err = 0;
if (0 != sol_deserialize(buf, 3, ka, &userdata, &userdata_len)) {
sol_panic();
if (1 != sol_deserialize(buf, 4, ka, &userdata, &userdata_len)) {
return 0;
}
if (sizeof(Game) > ka[1].userdata_len) {
sol_print(0, 0, 0xFF, sizeof(Game), ka[1].userdata_len);
sol_panic();
if (sizeof(Game) > ka[2].userdata_len) {
sol_print(0, 0, 0xFF, sizeof(Game), ka[2].userdata_len);
return 0;
}
Game game;
sol_memcpy(&game, ka[1].userdata, ka[1].userdata_len);
sol_memcpy(&game, ka[2].userdata, ka[2].userdata_len);
Command command = *userdata;
sol_print(0, 0, 0, 0, command);
//sol_print(0, 0, 0, 0, command);
switch (command) {
case Command_Init:
game_create(&game, ka[2].key);
game_create(&game, ka[3].key);
break;
case Command_Join:
err = game_join(&game, ka[0].key, userdata[8]);
err = game_join(&game, ka[3].key, userdata[8]);
break;
case Command_KeepAlive:
err = game_keep_alive(&game, ka[0].key, /*TODO*/ 0);
err = game_keep_alive(&game, ka[3].key, /*TODO*/ 0);
break;
case Command_Move:
err = game_next_move(&game, ka[0].key, userdata[8], userdata[9]);
err = game_next_move(&game, ka[3].key, userdata[8], userdata[9]);
break;
default:
sol_panic();
return 0;
}
sol_memcpy(ka[1].userdata, &game, ka[1].userdata_len);
sol_memcpy(ka[2].userdata, &game, ka[2].userdata_len);
sol_print(0, 0, 0, err, game.state);
return 1;
}
// // -- Debug --
// SOL_FN_PREFIX void print_key(SolPubkey *key) {
// for (int j = 0; j < SIZE_PUBKEY; j++) {
// sol_print(0, 0, 0, j, key->x[j]);
// }
// }
// SOL_FN_PREFIX void print_userdata(uint8_t *data, int len) {
// for (int j = 0; j < len; j++) {
// sol_print(0, 0, 0, j, data[j]);
// }
// }
// SOL_FN_PREFIX void print_params(uint64_t num_ka, SolKeyedAccounts *ka,
// uint8_t *userdata, uint64_t userdata_len) {
// sol_print(0, 0, 0, 0, num_ka);
// for (int i = 0; i < num_ka; i++) {
// // key
// print_key(ka[i].key);
// // tokens
// sol_print(0, 0, 0, 0, ka[i].tokens);
// // account userdata
// print_userdata(ka[i].userdata, ka[i].userdata_len);
// // program_id
// print_key(ka[i].program_id);
// }
// // tx userdata
// print_userdata(userdata, userdata_len);
// }
// void entrypoint(char *buf) {
// SolKeyedAccounts ka[3];
// uint64_t userdata_len;
// uint8_t *userdata;
// if (0 != sol_deserialize((uint8_t *)buf, 3, ka, &userdata_len, &userdata)) {
// return;
// }
// print_params(3, ka, userdata, userdata_len);
// }