Program Listing for File block.cuh#
↰ Return to documentation for file (src/block.cuh
)
// cuEVM: CUDA Ethereum Virtual Machine implementation
// Copyright 2023 Stefan-Dan Ciocirlan (SBIP - Singapore Blockchain Innovation Programme)
// Author: Stefan-Dan Ciocirlan
// Data: 2023-11-30
// SPDX-License-Identifier: MIT
#ifndef _BLOCK_H_
#define _BLOCK_H_
#include "utils.h"
template <class params>
class block_t
{
public:
typedef arith_env_t<params> arith_t;
typedef typename arith_t::bn_t bn_t;
typedef cgbn_mem_t<params::BITS> evm_word_t;
typedef struct
{
evm_word_t number;
evm_word_t hash;
} block_hash_t;
typedef struct alignas(32)
{
evm_word_t coin_base;
evm_word_t difficulty;
evm_word_t number;
evm_word_t gas_limit;
evm_word_t time_stamp;
evm_word_t base_fee;
evm_word_t chain_id;
block_hash_t previous_blocks[256];
} block_data_t;
block_data_t *_content;
arith_t _arith;
__device__ __forceinline__ block_t(
arith_t arith,
block_data_t *content
) : _arith(arith),
_content(content)
{
}
__host__ block_t(
arith_t arith,
const cJSON *test
) : _arith(arith)
{
cJSON *block_json = NULL;
cJSON *element_json = NULL;
cJSON *previous_blocks_json = NULL;
size_t idx = 0;
_content = NULL;
#ifndef ONLY_CPU
CUDA_CHECK(cudaMallocManaged(
(void **)&(_content),
sizeof(block_data_t)));
#else
_content = new block_data_t;
#endif
block_json = cJSON_GetObjectItemCaseSensitive(test, "env");
element_json = cJSON_GetObjectItemCaseSensitive(block_json, "currentCoinbase");
_arith.cgbn_memory_from_hex_string(
_content->coin_base,
element_json->valuestring
);
element_json = cJSON_GetObjectItemCaseSensitive(block_json, "currentTimestamp");
_arith.cgbn_memory_from_hex_string(
_content->time_stamp,
element_json->valuestring
);
element_json = cJSON_GetObjectItemCaseSensitive(block_json, "currentNumber");
_arith.cgbn_memory_from_hex_string(
_content->number,
element_json->valuestring
);
element_json = cJSON_GetObjectItemCaseSensitive(block_json, "currentDifficulty");
_arith.cgbn_memory_from_hex_string(
_content->difficulty,
element_json->valuestring
);
element_json = cJSON_GetObjectItemCaseSensitive(block_json, "currentGasLimit");
_arith.cgbn_memory_from_hex_string(
_content->gas_limit,
element_json->valuestring
);
// element_json=cJSON_GetObjectItemCaseSensitive(block_json, "currentChainId");
//_arith.cgbn_memory_from_hex_string(_content->chain_id, element_json->valuestring);
_arith.cgbn_memory_from_size_t(_content->chain_id, 1);
element_json = cJSON_GetObjectItemCaseSensitive(block_json, "currentBaseFee");
_arith.cgbn_memory_from_hex_string(
_content->base_fee,
element_json->valuestring
);
previous_blocks_json = cJSON_GetObjectItemCaseSensitive(block_json, "previousHashes");
if (previous_blocks_json != NULL and cJSON_IsArray(previous_blocks_json))
{
idx = 0;
cJSON_ArrayForEach(element_json, previous_blocks_json)
{
element_json = cJSON_GetObjectItemCaseSensitive(element_json, "number");
_arith.cgbn_memory_from_hex_string(
_content->previous_blocks[idx].number,
element_json->valuestring
);
element_json = cJSON_GetObjectItemCaseSensitive(element_json, "hash");
_arith.cgbn_memory_from_hex_string(
_content->previous_blocks[idx].hash,
element_json->valuestring
);
idx++;
}
}
else
{
idx = 0;
// TODO: maybe fill with something else
_arith.cgbn_memory_from_size_t(_content->previous_blocks[0].number, 0);
element_json = cJSON_GetObjectItemCaseSensitive(block_json, "previousHash");
_arith.cgbn_memory_from_hex_string(
_content->previous_blocks[0].hash,
element_json->valuestring
);
idx++;
}
// fill the remaing parents with 0
for (size_t jdx = idx; jdx < 256; jdx++)
{
_arith.cgbn_memory_from_size_t(_content->previous_blocks[jdx].number, 0);
_arith.cgbn_memory_from_size_t(_content->previous_blocks[jdx].hash, 0);
}
}
__host__ __device__ __forceinline__ ~block_t()
{
_content = NULL;
}
__host__ void free_content()
{
#ifndef ONLY_CPU
CUDA_CHECK(cudaFree(_content));
#else
delete _content;
#endif
_content = NULL;
}
__host__ __device__ __forceinline__ void get_coin_base(
bn_t &coin_base)
{
cgbn_load(_arith._env, coin_base, &(_content->coin_base));
}
__host__ __device__ __forceinline__ void get_time_stamp(
bn_t &time_stamp)
{
cgbn_load(_arith._env, time_stamp, &(_content->time_stamp));
}
__host__ __device__ __forceinline__ void get_number(
bn_t &number)
{
cgbn_load(_arith._env, number, &(_content->number));
}
__host__ __device__ __forceinline__ void get_difficulty(
bn_t &difficulty)
{
cgbn_load(_arith._env, difficulty, &(_content->difficulty));
}
__host__ __device__ __forceinline__ void get_gas_limit(
bn_t &gas_limit)
{
cgbn_load(_arith._env, gas_limit, &(_content->gas_limit));
}
__host__ __device__ __forceinline__ void get_chain_id(
bn_t &chain_id)
{
cgbn_load(_arith._env, chain_id, &(_content->chain_id));
}
__host__ __device__ __forceinline__ void get_base_fee(
bn_t &base_fee)
{
cgbn_load(_arith._env, base_fee, &(_content->base_fee));
}
__host__ __device__ __forceinline__ void get_previous_hash(
bn_t &previous_hash,
bn_t &previous_number,
uint32_t &error_code)
{
uint32_t idx = 0;
bn_t number;
// ge tthe current number
get_number(number);
// if the rquest number is greater than the current block number
if (cgbn_compare(_arith._env, number, previous_number) < 1)
{
error_code = ERR_BLOCK_INVALID_NUMBER;
}
// get the distance from the current block number to the requested block number
cgbn_sub(_arith._env, number, number, previous_number);
idx = cgbn_get_ui32(_arith._env, number) - 1;
// only the last 256 blocks are stored
if (idx > 255)
{
error_code = ERR_BLOCK_INVALID_NUMBER;
}
if (error_code == ERR_NONE)
cgbn_load(_arith._env, previous_hash, &(_content->previous_blocks[idx].hash));
else
cgbn_set_ui32(_arith._env, previous_hash, 0);
}
__host__ __device__ void print()
{
uint32_t idx = 0;
bn_t number;
printf("BLOCK: \n");
printf("COINBASE: ");
_arith.print_cgbn_memory(_content->coin_base);
printf("TIMESTAMP: ");
_arith.print_cgbn_memory(_content->time_stamp);
printf("NUMBER: ");
_arith.print_cgbn_memory(_content->number);
printf("DIFICULTY: ");
_arith.print_cgbn_memory(_content->difficulty);
printf("GASLIMIT: ");
_arith.print_cgbn_memory(_content->gas_limit);
printf("CHAINID: ");
_arith.print_cgbn_memory(_content->chain_id);
printf("BASE_FEE: ");
_arith.print_cgbn_memory(_content->base_fee);
printf("PREVIOUS_BLOCKS: \n");
for (idx = 0; idx < 256; idx++)
{
printf("NUMBER: ");
_arith.print_cgbn_memory(_content->previous_blocks[idx].number);
printf("HASH: ");
_arith.print_cgbn_memory(_content->previous_blocks[idx].hash);
printf("\n");
cgbn_load(_arith._env, number, &(_content->previous_blocks[idx].number));
if (cgbn_compare_ui32(_arith._env, number, 0) == 0)
{
break;
}
}
}
__host__ cJSON *json()
{
uint32_t idx = 0;
char *hex_string_ptr = new char[arith_t::BYTES * 2 + 3];
cJSON *block_json = NULL;
cJSON *previous_blocks_json = NULL;
cJSON *previous_block_json = NULL;
block_json = cJSON_CreateObject();
_arith.hex_string_from_cgbn_memory(hex_string_ptr, _content->coin_base, 5);
cJSON_AddStringToObject(block_json, "currentCoinbase", hex_string_ptr);
_arith.hex_string_from_cgbn_memory(hex_string_ptr, _content->time_stamp);
cJSON_AddStringToObject(block_json, "currentTimestamp", hex_string_ptr);
_arith.hex_string_from_cgbn_memory(hex_string_ptr, _content->number);
cJSON_AddStringToObject(block_json, "currentNumber", hex_string_ptr);
_arith.hex_string_from_cgbn_memory(hex_string_ptr, _content->difficulty);
cJSON_AddStringToObject(block_json, "currentDifficulty", hex_string_ptr);
_arith.hex_string_from_cgbn_memory(hex_string_ptr, _content->gas_limit);
cJSON_AddStringToObject(block_json, "currentGasLimit", hex_string_ptr);
_arith.hex_string_from_cgbn_memory(hex_string_ptr, _content->chain_id);
cJSON_AddStringToObject(block_json, "currentChainId", hex_string_ptr);
_arith.hex_string_from_cgbn_memory(hex_string_ptr, _content->base_fee);
cJSON_AddStringToObject(block_json, "currentBaseFee", hex_string_ptr);
previous_blocks_json = cJSON_CreateArray();
bn_t number;
for (idx = 0; idx < 256; idx++)
{
previous_block_json = cJSON_CreateObject();
_arith.hex_string_from_cgbn_memory(
hex_string_ptr,
_content->previous_blocks[idx].number
);
cJSON_AddStringToObject(previous_block_json, "number", hex_string_ptr);
_arith.hex_string_from_cgbn_memory(
hex_string_ptr,
_content->previous_blocks[idx].hash
);
cJSON_AddStringToObject(previous_block_json, "hash", hex_string_ptr);
cJSON_AddItemToArray(previous_blocks_json, previous_block_json);
cgbn_load(_arith._env, number, &(_content->previous_blocks[idx].number));
if (cgbn_compare_ui32(_arith._env, number, 0) == 0)
{
break;
}
}
cJSON_AddItemToObject(block_json, "previousHashes", previous_blocks_json);
delete[] hex_string_ptr;
hex_string_ptr = NULL;
return block_json;
}
};
#endif