BPF programs can support up to 5 arguments (#2528)

This commit is contained in:
Jack May 2019-01-23 09:55:08 -08:00 committed by GitHub
parent 73930b5eac
commit a0bc8b8af3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 109 deletions

View File

@ -13,22 +13,21 @@
extern bool entrypoint(const uint8_t *input) { extern bool entrypoint(const uint8_t *input) {
SolKeyedAccount ka[NUM_KA]; SolKeyedAccount ka[NUM_KA];
const uint8_t *data; SolParameters params = (SolParameters) { .ka = ka };
uint64_t data_len;
if (!sol_deserialize(input, ka, NUM_KA, NULL, &data, &data_len, NULL)) { if (!sol_deserialize(input, &params, SOL_ARRAY_SIZE(ka))) {
return false; return false;
} }
if (!ka[0].is_signer) { if (!params.ka[0].is_signer) {
sol_log("Transaction not signed by key 0"); sol_log("Transaction not signed by key 0");
return false; return false;
} }
int64_t tokens = *(int64_t *)data; int64_t tokens = *(int64_t *)params.data;
if (*ka[0].tokens >= tokens) { if (*params.ka[0].tokens >= tokens) {
*ka[0].tokens -= tokens; *params.ka[0].tokens -= tokens;
*ka[2].tokens += tokens; *params.ka[2].tokens += tokens;
// sol_log_64(0, 0, *ka[0].tokens, *ka[2].tokens, tokens); // sol_log_64(0, 0, *ka[0].tokens, *ka[2].tokens, tokens);
} else { } else {
// sol_log_64(0, 0, 0xFF, *ka[0].tokens, tokens); // sol_log_64(0, 0, 0xFF, *ka[0].tokens, tokens);

View File

@ -6,26 +6,17 @@
extern bool entrypoint(const uint8_t *input) { extern bool entrypoint(const uint8_t *input) {
SolKeyedAccount ka[1]; SolKeyedAccount ka[1];
uint64_t ka_len; SolParameters params = (SolParameters) { .ka = ka };
const uint8_t *data;
uint64_t data_len;
SolClusterInfo info;
sol_log(__FILE__); sol_log(__FILE__);
if (!sol_deserialize(input, ka, SOL_ARRAY_SIZE(ka), &ka_len, &data, &data_len, &info)) { if (!sol_deserialize(input, &params, SOL_ARRAY_SIZE(ka))) {
return false; return false;
} }
sol_log("Tick height:"); // Log the provided input parameters. In the case of the no-op
sol_log_64(info.tick_height, 0, 0, 0, 0); // program, no account keys or input data are expected but real
sol_log("Program identifier:");
sol_log_key(info.program_id);
// Log the provided account keys and instruction input data. In the case of
// the no-op program, no account keys or input data are expected but real
// programs will have specific requirements so they can do their work. // programs will have specific requirements so they can do their work.
sol_log("Account keys and instruction input data:"); sol_log_params(&params);
sol_log_params(ka, ka_len, data, data_len);
return true; return true;
} }

View File

@ -6,26 +6,18 @@
extern bool entrypoint(const uint8_t *input) { extern bool entrypoint(const uint8_t *input) {
SolKeyedAccount ka[1]; SolKeyedAccount ka[1];
uint64_t ka_len; SolParameters params = (SolParameters) { .ka = ka };
const uint8_t *data;
uint64_t data_len;
SolClusterInfo info;
sol_log(__FILE__); sol_log(__FILE__);
if (!sol_deserialize(input, ka, SOL_ARRAY_SIZE(ka), &ka_len, &data, &data_len, &info)) { if (!sol_deserialize(input, &params, SOL_ARRAY_SIZE(ka))) {
return false; return false;
} }
sol_log("Tick height:");
sol_log_64(info.tick_height, 0, 0, 0, 0);
sol_log("Program identifier:");
sol_log_key(info.program_id);
// Log the provided account keys and instruction input data. In the case of // Log the provided input parameters. In the case of the no-op
// the no-op program, no account keys or input data are expected but real // program, no account keys or input data are expected but real
// programs will have specific requirements so they can do their work. // programs will have specific requirements so they can do their work.
sol_log("Account keys and instruction input data:"); sol_log_params(&params);
sol_log_params(ka, ka_len, data, data_len);
return true; return true;
} }

View File

@ -186,18 +186,22 @@ SOL_FN_PREFIX void _sol_panic(uint64_t line) {
* Asserts * Asserts
*/ */
#define sol_assert(expr) \ #define sol_assert(expr) \
if (!(expr)) { \ if (!(expr)) { \
_sol_panic(__LINE__); \ _sol_panic(__LINE__); \
} }
/** /**
* Information about the state of the cluster immediately before the program * Structure that the program's entrypoint input data is deserialized into.
* started executing the current instruction
*/ */
typedef struct { typedef struct {
SolKeyedAccount* ka; /** Pointer to an array of SolKeyedAccount, must already
point to an array of SolKeyedAccounts */
uint64_t ka_num; /** Number of SolKeyedAccount entries in `ka` */
const uint8_t *data; /** pointer to the instruction data */
uint64_t data_len; /** Length in bytes of the instruction data */
uint64_t tick_height; /** Current ledger tick */ uint64_t tick_height; /** Current ledger tick */
const SolPubkey *program_id; /** program_id of the currently executing program */ const SolPubkey *program_id; /** program_id of the currently executing program */
} SolClusterInfo; } SolParameters;
/** /**
* De-serializes the input parameters into usable types * De-serializes the input parameters into usable types
@ -210,72 +214,55 @@ typedef struct {
* at program end. * at program end.
* *
* @param input Source buffer containing serialized input parameters * @param input Source buffer containing serialized input parameters
* @param ka Pointer to an array of SolKeyedAccount to deserialize into * @param params Pointer to a SolParameters structure
* @param ka_len Number of SolKeyedAccount entries in `ka` * @return Boolean true if successful.
* @param ka_len_out If NULL, fill exactly `ka_len` accounts or fail.
* If not NULL, fill up to `ka_len` accounts and return the
* number of filled accounts in `ka_len_out`.
* @param data On return, a pointer to the instruction data
* @param data_len On return, the length in bytes of the instruction data
* @param cluster_info If not NULL, fill cluster_info
* @return Boolean true if successful
*/ */
SOL_FN_PREFIX bool sol_deserialize( SOL_FN_PREFIX bool sol_deserialize(
const uint8_t *input, const uint8_t *input,
SolKeyedAccount *ka, SolParameters *params,
uint64_t ka_len, uint64_t ka_num
uint64_t *ka_len_out,
const uint8_t **data,
uint64_t *data_len,
SolClusterInfo *cluster_info
) { ) {
if (ka_len_out == NULL) { if (NULL == input || NULL == params) {
if (ka_len != *(uint64_t *) input) { return false;
return false; }
} params->ka_num = *(uint64_t *) input;
ka_len = *(uint64_t *) input; if (ka_num < *(uint64_t *) input) {
} else { return false;
if (ka_len > *(uint64_t *) input) {
ka_len = *(uint64_t *) input;
}
*ka_len_out = ka_len;
} }
input += sizeof(uint64_t); input += sizeof(uint64_t);
for (int i = 0; i < ka_len; i++) { for (int i = 0; i < params->ka_num; i++) {
// key // key
ka[i].is_signer = *(uint64_t *) input != 0; params->ka[i].is_signer = *(uint64_t *) input != 0;
input += sizeof(uint64_t); input += sizeof(uint64_t);
ka[i].key = (SolPubkey *) input; params->ka[i].key = (SolPubkey *) input;
input += sizeof(SolPubkey); input += sizeof(SolPubkey);
// tokens // tokens
ka[i].tokens = (uint64_t *) input; params->ka[i].tokens = (uint64_t *) input;
input += sizeof(uint64_t); input += sizeof(uint64_t);
// account userdata // account userdata
ka[i].userdata_len = *(uint64_t *) input; params->ka[i].userdata_len = *(uint64_t *) input;
input += sizeof(uint64_t); input += sizeof(uint64_t);
ka[i].userdata = (uint8_t *) input; params->ka[i].userdata = (uint8_t *) input;
input += ka[i].userdata_len; input += params->ka[i].userdata_len;
// owner // owner
ka[i].owner = (SolPubkey *) input; params->ka[i].owner = (SolPubkey *) input;
input += sizeof(SolPubkey); input += sizeof(SolPubkey);
} }
// input data params->data_len = *(uint64_t *) input;
*data_len = *(uint64_t *) input;
input += sizeof(uint64_t); input += sizeof(uint64_t);
*data = input; params->data = input;
input += *data_len; input += params->data_len;
params->tick_height = *(uint64_t *) input;
input += sizeof(uint64_t);
params->program_id = (SolPubkey *) input;
input += sizeof(SolPubkey);
if (cluster_info != NULL) {
cluster_info->tick_height = *(uint64_t *) input;
input += sizeof(uint64_t);
cluster_info->program_id = (SolPubkey *) input;
input += sizeof(SolPubkey);
}
return true; return true;
} }
@ -307,35 +294,32 @@ SOL_FN_PREFIX void sol_log_array(const uint8_t *array, int len) {
} }
/** /**
* Prints the hexadecimal representation of the program's input parameters * Prints the program's input parameters
* *
* @param ka A pointer to an array of SolKeyedAccount to print * @param params Pointer to a SolParameters structure
* @param ka_len Number of SolKeyedAccount to print
* @param data A pointer to the instruction data to print
* @param data_len The length in bytes of the instruction data
*/ */
SOL_FN_PREFIX void sol_log_params( SOL_FN_PREFIX void sol_log_params(const SolParameters *params) {
const SolKeyedAccount *ka, sol_log("- Tick height:");
uint64_t ka_len, sol_log_64(params->tick_height, 0, 0, 0, 0);
const uint8_t *data, sol_log("- Program identifier:");
uint64_t data_len sol_log_key(params->program_id);
) {
sol_log("- Number of KeyedAccounts"); sol_log("- Number of KeyedAccounts");
sol_log_64(0, 0, 0, 0, ka_len); sol_log_64(0, 0, 0, 0, params->ka_num);
for (int i = 0; i < ka_len; i++) { for (int i = 0; i < params->ka_num; i++) {
sol_log("- Is signer"); sol_log(" - Is signer");
sol_log_64(0, 0, 0, 0, ka[i].is_signer); sol_log_64(0, 0, 0, 0, params->ka[i].is_signer);
sol_log("- Key"); sol_log(" - Key");
sol_log_key(ka[i].key); sol_log_key(params->ka[i].key);
sol_log("- Tokens"); sol_log(" - Tokens");
sol_log_64(0, 0, 0, 0, *ka[i].tokens); sol_log_64(0, 0, 0, 0, *params->ka[i].tokens);
sol_log("- Userdata"); sol_log(" - Userdata");
sol_log_array(ka[i].userdata, ka[i].userdata_len); sol_log_array(params->ka[i].userdata, params->ka[i].userdata_len);
sol_log("- Owner"); sol_log(" - Owner");
sol_log_key(ka[i].owner); sol_log_key(params->ka[i].owner);
} }
sol_log("- Instruction data\0"); sol_log("- Instruction data\0");
sol_log_array(data, data_len); sol_log_array(params->data, params->data_len);
} }
/**@}*/ /**@}*/