138 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			138 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								#pragma once
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @brief Solana BPF loader deserializer to be used when deploying
							 | 
						||
| 
								 | 
							
								 * a program with `BPFLoader2111111111111111111111111111111111` or
							 | 
						||
| 
								 | 
							
								 * `BPFLoaderUpgradeab1e11111111111111111111111`
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <sol/types.h>
							 | 
						||
| 
								 | 
							
								#include <sol/pubkey.h>
							 | 
						||
| 
								 | 
							
								#include <sol/entrypoint.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef __cplusplus
							 | 
						||
| 
								 | 
							
								extern "C" {
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Maximum number of bytes a program may add to an account during a single realloc
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#define MAX_PERMITTED_DATA_INCREASE (1024 * 10)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * De-serializes the input parameters into usable types
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Use this function to deserialize the buffer passed to the program entrypoint
							 | 
						||
| 
								 | 
							
								 * into usable types.  This function does not perform copy deserialization,
							 | 
						||
| 
								 | 
							
								 * instead it populates the pointers and lengths in SolAccountInfo and data so
							 | 
						||
| 
								 | 
							
								 * that any modification to lamports or account data take place on the original
							 | 
						||
| 
								 | 
							
								 * buffer.  Doing so also eliminates the need to serialize back into the buffer
							 | 
						||
| 
								 | 
							
								 * at the end of the program.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param input Source buffer containing serialized input parameters
							 | 
						||
| 
								 | 
							
								 * @param params Pointer to a SolParameters structure
							 | 
						||
| 
								 | 
							
								 * @return Boolean true if successful.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static bool sol_deserialize(
							 | 
						||
| 
								 | 
							
								  const uint8_t *input,
							 | 
						||
| 
								 | 
							
								  SolParameters *params,
							 | 
						||
| 
								 | 
							
								  uint64_t ka_num
							 | 
						||
| 
								 | 
							
								) {
							 | 
						||
| 
								 | 
							
								  if (NULL == input || NULL == params) {
							 | 
						||
| 
								 | 
							
								    return false;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  params->ka_num = *(uint64_t *) input;
							 | 
						||
| 
								 | 
							
								  input += sizeof(uint64_t);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (int i = 0; i < params->ka_num; i++) {
							 | 
						||
| 
								 | 
							
								    uint8_t dup_info = input[0];
							 | 
						||
| 
								 | 
							
								    input += sizeof(uint8_t);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (i >= ka_num) {
							 | 
						||
| 
								 | 
							
								      if (dup_info == UINT8_MAX) {
							 | 
						||
| 
								 | 
							
								        input += sizeof(uint8_t);
							 | 
						||
| 
								 | 
							
								        input += sizeof(uint8_t);
							 | 
						||
| 
								 | 
							
								        input += sizeof(uint8_t);
							 | 
						||
| 
								 | 
							
								        input += 4; // padding
							 | 
						||
| 
								 | 
							
								        input += sizeof(SolPubkey);
							 | 
						||
| 
								 | 
							
								        input += sizeof(SolPubkey);
							 | 
						||
| 
								 | 
							
								        input += sizeof(uint64_t);
							 | 
						||
| 
								 | 
							
								        uint64_t data_len = *(uint64_t *) input;
							 | 
						||
| 
								 | 
							
								        input += sizeof(uint64_t);
							 | 
						||
| 
								 | 
							
								        input += data_len;
							 | 
						||
| 
								 | 
							
								        input += MAX_PERMITTED_DATA_INCREASE;
							 | 
						||
| 
								 | 
							
								        input = (uint8_t*)(((uint64_t)input + 8 - 1) & ~(8 - 1)); // padding
							 | 
						||
| 
								 | 
							
								        input += sizeof(uint64_t);
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        input += 7; // padding
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      continue;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (dup_info == UINT8_MAX) {
							 | 
						||
| 
								 | 
							
								      // is signer?
							 | 
						||
| 
								 | 
							
								      params->ka[i].is_signer = *(uint8_t *) input != 0;
							 | 
						||
| 
								 | 
							
								      input += sizeof(uint8_t);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // is writable?
							 | 
						||
| 
								 | 
							
								      params->ka[i].is_writable = *(uint8_t *) input != 0;
							 | 
						||
| 
								 | 
							
								      input += sizeof(uint8_t);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // executable?
							 | 
						||
| 
								 | 
							
								      params->ka[i].executable = *(uint8_t *) input;
							 | 
						||
| 
								 | 
							
								      input += sizeof(uint8_t);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      input += 4; // padding
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // key
							 | 
						||
| 
								 | 
							
								      params->ka[i].key = (SolPubkey *) input;
							 | 
						||
| 
								 | 
							
								      input += sizeof(SolPubkey);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // owner
							 | 
						||
| 
								 | 
							
								      params->ka[i].owner = (SolPubkey *) input;
							 | 
						||
| 
								 | 
							
								      input += sizeof(SolPubkey);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // lamports
							 | 
						||
| 
								 | 
							
								      params->ka[i].lamports = (uint64_t *) input;
							 | 
						||
| 
								 | 
							
								      input += sizeof(uint64_t);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // account data
							 | 
						||
| 
								 | 
							
								      params->ka[i].data_len = *(uint64_t *) input;
							 | 
						||
| 
								 | 
							
								      input += sizeof(uint64_t);
							 | 
						||
| 
								 | 
							
								      params->ka[i].data = (uint8_t *) input;
							 | 
						||
| 
								 | 
							
								      input += params->ka[i].data_len;
							 | 
						||
| 
								 | 
							
								      input += MAX_PERMITTED_DATA_INCREASE;
							 | 
						||
| 
								 | 
							
								      input = (uint8_t*)(((uint64_t)input + 8 - 1) & ~(8 - 1)); // padding
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // rent epoch
							 | 
						||
| 
								 | 
							
								      params->ka[i].rent_epoch = *(uint64_t *) input;
							 | 
						||
| 
								 | 
							
								      input += sizeof(uint64_t);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      params->ka[i].is_signer = params->ka[dup_info].is_signer;
							 | 
						||
| 
								 | 
							
								      params->ka[i].is_writable = params->ka[dup_info].is_writable;
							 | 
						||
| 
								 | 
							
								      params->ka[i].executable = params->ka[dup_info].executable;
							 | 
						||
| 
								 | 
							
								      params->ka[i].key = params->ka[dup_info].key;
							 | 
						||
| 
								 | 
							
								      params->ka[i].owner = params->ka[dup_info].owner;
							 | 
						||
| 
								 | 
							
								      params->ka[i].lamports = params->ka[dup_info].lamports;
							 | 
						||
| 
								 | 
							
								      params->ka[i].data_len = params->ka[dup_info].data_len;
							 | 
						||
| 
								 | 
							
								      params->ka[i].data = params->ka[dup_info].data;
							 | 
						||
| 
								 | 
							
								      params->ka[i].rent_epoch = params->ka[dup_info].rent_epoch;
							 | 
						||
| 
								 | 
							
								      input += 7; // padding
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  params->data_len = *(uint64_t *) input;
							 | 
						||
| 
								 | 
							
								  input += sizeof(uint64_t);
							 | 
						||
| 
								 | 
							
								  params->data = input;
							 | 
						||
| 
								 | 
							
								  input += params->data_len;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  params->program_id = (SolPubkey *) input;
							 | 
						||
| 
								 | 
							
								  input += sizeof(SolPubkey);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef __cplusplus
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**@}*/
							 |