Program Listing for File test_message.cu#
↰ Return to documentation for file (src/test/test_message.cu
)
// 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
#include "../message.cuh"
template<class params>
__host__ __device__ __forceinline__ void test_message(
arith_env_t<params> &arith,
typename transaction_t<params>::transaction_data_t *transaction_data,
uint32_t &instance)
{
typedef transaction_t<params> transaction_t;
typedef message_t<params> message_t;
typedef arith_env_t<params> arith_t;
typedef typename arith_t::bn_t bn_t;
transaction_t *transaction;
message_t *message;
transaction = new transaction_t(arith, transaction_data);
//transaction->print();
uint8_t type;
//uint32_t error_code;
//error_code = ERR_SUCCESS;
// transaction values
bn_t nonce, gas_limit, to, value, sender, max_fee_per_gas, max_priority_fee_per_gas, gas_price;
transaction->get_nonce(nonce);
printf("nonce: %08x\n", cgbn_get_ui32(arith._env, nonce));
transaction->get_gas_limit(gas_limit);
printf("gas_limit: %08x\n", cgbn_get_ui32(arith._env, gas_limit));
transaction->get_to(to);
printf("to: %08x\n", cgbn_get_ui32(arith._env, to));
transaction->get_value(value);
printf("value: %08x\n", cgbn_get_ui32(arith._env, value));
transaction->get_sender(sender);
printf("sender: %08x\n", cgbn_get_ui32(arith._env, sender));
transaction->get_max_fee_per_gas(max_fee_per_gas);
printf("max_fee_per_gas: %08x\n", cgbn_get_ui32(arith._env, max_fee_per_gas));
transaction->get_max_priority_fee_per_gas(max_priority_fee_per_gas);
printf("max_priority_fee_per_gas: %08x\n", cgbn_get_ui32(arith._env, max_priority_fee_per_gas));
transaction->get_gas_price(gas_price);
printf("gas_price: %08x\n", cgbn_get_ui32(arith._env, gas_price));
type = transaction->_content->type;
printf("type: %u\n", type);
uint8_t opcode=OP_CALL;
size_t size=transaction->_content->data_init.size;
uint8_t *data=transaction->_content->data_init.data;
uint32_t depth=0;
bn_t ret_offset, ret_size;
cgbn_set_ui32(arith._env, ret_offset, 0);
cgbn_set_ui32(arith._env, ret_size, 0);
message = new message_t(
arith,
sender,
to,
to,
gas_limit,
value,
depth,
opcode,
to,
data,
size,
data,
size,
ret_offset,
ret_size,
0);
ONE_THREAD_PER_INSTANCE(
message->print();
)
delete message;
message = NULL;
delete transaction;
transaction = NULL;
}
template<class params>
__global__ void kernel_message(
cgbn_error_report_t *report,
typename transaction_t<params>::transaction_data_t *transanctions_data,
uint32_t count
) {
uint32_t instance=(blockIdx.x*blockDim.x + threadIdx.x)/params::TPI;
if(instance>=count)
return;
typedef arith_env_t<params> arith_t;
arith_t arith(cgbn_report_monitor, report, instance);
test_message(arith, &(transanctions_data[instance]), instance);
}
template<class params>
void run_test() {
typedef arith_env_t<params> arith_t;
typedef transaction_t<params> transaction_t;
typedef typename transaction_t::transaction_data_t transaction_data_t;
transaction_data_t *transactions_data;
arith_t arith(cgbn_report_monitor, 0);
#ifndef ONLY_CPU
CUDA_CHECK(cudaDeviceReset());
CUDA_CHECK(cudaDeviceSetLimit(cudaLimitMallocHeapSize, 1024*1024*1024));
CUDA_CHECK(cudaDeviceSetLimit(cudaLimitStackSize, 64*1024));
cgbn_error_report_t *report;
#endif
//read the json file with the transactions
cJSON *root = get_json_from_file("input/evm_arith.json");
if(root == NULL) {
printf("Error: could not read the json file\n");
exit(1);
}
const cJSON *test = NULL;
test = cJSON_GetObjectItemCaseSensitive(root, "arith");
printf("Generating transactions\n");
size_t transactions_count=1;
transaction_t::get_transactions(transactions_data, test, transactions_count);
printf("no_transactions: %lu\n", transactions_count);
printf("Global transactions generated\n");
#ifndef ONLY_CPU
// create a cgbn_error_report for CGBN to report back errors
CUDA_CHECK(cgbn_error_report_alloc(&report));
printf("Running GPU kernel ...\n");
// launch kernel with blocks=ceil(instance_count/IPB) and threads=TPB
kernel_message<params><<<transactions_count, params::TPI>>>(report, transactions_data, transactions_count);
//kernel_message<params><<<1, params::TPI>>>(report, transactions_data, 1);
// error report uses managed memory, so we sync the device (or stream) and check for cgbn errors
CUDA_CHECK(cudaDeviceSynchronize());
CGBN_CHECK(report);
CUDA_CHECK(cgbn_error_report_free(report));
printf("GPU kernel finished\n");
#else
printf("Running CPU kernel ...\n");
for(uint32_t idx=0; idx<transactions_count; idx++) {
test_message(arith, &(transactions_data[idx]), idx);
}
//test_message(arith, &(transactions_data[0]), 0);
printf("CPU kernel finished\n");
#endif
// print the results
printf("Printing the results stdout/json...\n");
cJSON_Delete(root);
root = cJSON_CreateObject();
transaction_t *transaction;
cJSON *post = cJSON_CreateArray();
for(uint32_t idx=0; idx<transactions_count; idx++) {
transaction = new transaction_t(arith, &(transactions_data[idx]));
cJSON_AddItemToArray(post, transaction->json());
transaction->print();
delete transaction;
}
transaction_t::free_instances(transactions_data, transactions_count);
transactions_data = NULL;
transactions_count = 0;
transaction = NULL;
cJSON_AddItemToObject(root, "post", post);
char *json_str=cJSON_Print(root);
FILE *fp=fopen("output/evm_message.json", "w");
fprintf(fp, "%s", json_str);
fclose(fp);
free(json_str);
json_str=NULL;
cJSON_Delete(root);
root=NULL;
printf("Results printed\n");
#ifndef ONLY_CPU
CUDA_CHECK(cudaDeviceReset());
#endif
}
int main() {
run_test<utils_params>();
}