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
 | |
| 
 | |
| /**@}*/
 |