diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index bef94f7ba..5e8652c64 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -91,8 +91,8 @@ jobs: vcpkg-gcc-v1-notest-${{ runner.temp }}- - name: install Ubuntu dependencies run: sudo apt install -y git curl openssl build-essential cmake ccache lcov - - name: fetch vcpkg - run: cd /usr/local/share/vcpkg/ && git fetch && git reset --hard && git pull && cd - + # - name: fetch vcpkg + # run: cd /usr/local/share/vcpkg/ && git fetch --all && git checkout master && git pull && cd - - name: configure run: | export CC='gcc-10'; export CXX='g++-10' @@ -156,8 +156,8 @@ jobs: ln -s /usr/local/cmake/bin/cmake /usr/bin/cmake cmake --version git --version - - name: fetch vcpkg - run: cd /usr/local/share/vcpkg/ && git fetch && git reset --hard && git pull && cd - + # - name: fetch vcpkg + # run: cd /usr/local/share/vcpkg/ && git fetch --all && git checkout master && git pull && cd - - name: configure run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" diff --git a/bcos-c-sdk/bcos_sdk_c_common.h b/bcos-c-sdk/bcos_sdk_c_common.h index b5f7811d6..f381f2182 100644 --- a/bcos-c-sdk/bcos_sdk_c_common.h +++ b/bcos-c-sdk/bcos_sdk_c_common.h @@ -209,6 +209,23 @@ struct bcos_sdk_c_transaction_data struct bcos_sdk_c_bytes* input; }; +struct bcos_sdk_c_transaction_data_v2 +{ + int32_t version; + int64_t block_limit; + char* chain_id; + char* group_id; + char* nonce; + char* to; + char* abi; + struct bcos_sdk_c_bytes* input; + char* value; + char* gas_price; + int64_t gas_limit; + char* max_fee_per_gas; + char* max_priority_fee_per_gas; +}; + /** * @brief: transaction * @@ -224,6 +241,17 @@ struct bcos_sdk_c_transaction char* extra_data; }; +struct bcos_sdk_c_transaction_v2 +{ + struct bcos_sdk_c_transaction_data_v2* transaction_data; + struct bcos_sdk_c_bytes* data_hash; + struct bcos_sdk_c_bytes* signature; + struct bcos_sdk_c_bytes* sender; + int64_t import_time; + int32_t attribute; + char* extra_data; +}; + //--------------- transaction end--------------------------------- #ifdef __cplusplus diff --git a/bcos-c-sdk/bcos_sdk_c_uti_tx_struct.cpp b/bcos-c-sdk/bcos_sdk_c_uti_tx_struct.cpp index 286bacf28..fea933613 100644 --- a/bcos-c-sdk/bcos_sdk_c_uti_tx_struct.cpp +++ b/bcos-c-sdk/bcos_sdk_c_uti_tx_struct.cpp @@ -126,6 +126,45 @@ struct bcos_sdk_c_transaction_data* transaction_data_copy( return NULL; } +struct bcos_sdk_c_transaction_data_v2* transaction_data_copy_v2( + const bcos_sdk_c_transaction_data_v2* tx_data_src) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(tx_data_src, NULL); + + try + { + struct bcos_sdk_c_transaction_data_v2* transaction_data_struct_v2 = + (struct bcos_sdk_c_transaction_data_v2*)malloc( + sizeof(struct bcos_sdk_c_transaction_data_v2)); + transaction_data_struct_v2->version = tx_data_src->version; + transaction_data_struct_v2->block_limit = tx_data_src->block_limit; + transaction_data_struct_v2->chain_id = my_strdup(tx_data_src->chain_id); + transaction_data_struct_v2->group_id = my_strdup(tx_data_src->group_id); + transaction_data_struct_v2->nonce = my_strdup(tx_data_src->nonce); + transaction_data_struct_v2->to = my_strdup(tx_data_src->to); + transaction_data_struct_v2->abi = my_strdup(tx_data_src->abi); + transaction_data_struct_v2->input = bytes_struct_copy(tx_data_src->input); + transaction_data_struct_v2->value = my_strdup(tx_data_src->value); + transaction_data_struct_v2->gas_price = my_strdup(tx_data_src->gas_price); + transaction_data_struct_v2->gas_limit = tx_data_src->gas_limit; + transaction_data_struct_v2->max_fee_per_gas = my_strdup(tx_data_src->max_fee_per_gas); + transaction_data_struct_v2->max_priority_fee_per_gas = + my_strdup(tx_data_src->max_priority_fee_per_gas); + + return transaction_data_struct_v2; + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("transaction_data_copy_v2") << LOG_DESC("exception") + << LOG_KV("tx_data_src", tx_data_src) << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} + /** * @brief: convert tars transaction data to struct bcos_sdk_c_transaction_data * @@ -169,6 +208,54 @@ struct bcos_sdk_c_transaction_data* convert_tars_transaction_data_to_struct( return NULL; } +struct bcos_sdk_c_transaction_data_v2* convert_tars_transaction_data_to_struct_v2( + bcostars::TransactionDataUniquePtr tars_transaction_data) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(tars_transaction_data, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION( + (tars_transaction_data->version == 1), "version of tars tx data V2 must be 1", NULL); + + try + { + struct bcos_sdk_c_transaction_data_v2* transaction_data_struct_v2 = + (struct bcos_sdk_c_transaction_data_v2*)malloc( + sizeof(struct bcos_sdk_c_transaction_data_v2)); + struct bcos_sdk_c_bytes* input_bytes = create_bytes_struct( + tars_transaction_data->input.size(), tars_transaction_data->input.data()); + + transaction_data_struct_v2->input = input_bytes; + transaction_data_struct_v2->version = tars_transaction_data->version; + transaction_data_struct_v2->block_limit = tars_transaction_data->blockLimit; + transaction_data_struct_v2->chain_id = my_strdup(tars_transaction_data->chainID.data()); + transaction_data_struct_v2->group_id = my_strdup(tars_transaction_data->groupID.data()); + transaction_data_struct_v2->nonce = my_strdup(tars_transaction_data->nonce.data()); + transaction_data_struct_v2->to = my_strdup(tars_transaction_data->to.data()); + transaction_data_struct_v2->abi = my_strdup(tars_transaction_data->abi.data()); + transaction_data_struct_v2->value = my_strdup(tars_transaction_data->value.data()); + transaction_data_struct_v2->gas_price = my_strdup(tars_transaction_data->gasPrice.data()); + transaction_data_struct_v2->gas_limit = tars_transaction_data->gasLimit; + transaction_data_struct_v2->max_fee_per_gas = + my_strdup(tars_transaction_data->maxFeePerGas.data()); + transaction_data_struct_v2->max_priority_fee_per_gas = + my_strdup(tars_transaction_data->maxPriorityFeePerGas.data()); + + return transaction_data_struct_v2; + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("convert_tars_transaction_data_to_struct_v2") + << LOG_DESC("exception") + << LOG_KV("transaction data", tars_transaction_data) + << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} + + bcostars::TransactionDataUniquePtr convert_transaction_data_to_tars( struct bcos_sdk_c_transaction_data* transaction_data) { @@ -207,6 +294,53 @@ bcostars::TransactionDataUniquePtr convert_transaction_data_to_tars( return NULL; } +bcostars::TransactionDataUniquePtr convert_transaction_data_to_tars_v2( + struct bcos_sdk_c_transaction_data_v2* transaction_data) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction_data, NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction_data->group_id, NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction_data->chain_id, NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction_data->input, NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction_data->value, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION( + (transaction_data->version == 1), "version of tx data struct V2 must be 1", NULL); + + try + { + auto tars_transaction_data_v2 = std::make_unique(); + for (size_t i = 0; i < transaction_data->input->length; ++i) + { + tars_transaction_data_v2->input.push_back(transaction_data->input->buffer[i]); + } + tars_transaction_data_v2->version = (tars::Int32)transaction_data->version; + tars_transaction_data_v2->blockLimit = (tars::Int64)transaction_data->block_limit; + tars_transaction_data_v2->chainID = std::string(transaction_data->chain_id); + tars_transaction_data_v2->groupID = std::string(transaction_data->group_id); + tars_transaction_data_v2->nonce = std::string(transaction_data->nonce); + tars_transaction_data_v2->to = std::string(transaction_data->to); + tars_transaction_data_v2->abi = std::string(transaction_data->abi); + tars_transaction_data_v2->value = std::string(transaction_data->value); + tars_transaction_data_v2->gasPrice = std::string(transaction_data->gas_price); + tars_transaction_data_v2->gasLimit = (tars::Int64)transaction_data->gas_limit; + tars_transaction_data_v2->maxFeePerGas = std::string(transaction_data->max_fee_per_gas); + tars_transaction_data_v2->maxPriorityFeePerGas = + std::string(transaction_data->max_priority_fee_per_gas); + + return tars_transaction_data_v2; + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("convert_transaction_data_to_tars_v2") + << LOG_DESC("exception") << LOG_KV("transaction data", transaction_data) + << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} + bcostars::TransactionUniquePtr convert_transaction_to_tars( struct bcos_sdk_c_transaction* transaction) { @@ -253,6 +387,52 @@ bcostars::TransactionUniquePtr convert_transaction_to_tars( return NULL; } +bcostars::TransactionUniquePtr convert_transaction_to_tars_v2( + struct bcos_sdk_c_transaction_v2* transaction) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction, NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction->data_hash, NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction->signature, NULL); + + try + { + auto tars_transaction = std::make_unique(); + auto TransactionDataUniquePtr = + convert_transaction_data_to_tars_v2(transaction->transaction_data); + tars_transaction->data = *TransactionDataUniquePtr; + for (size_t i = 0; i < transaction->data_hash->length; ++i) + { + tars_transaction->dataHash.push_back(transaction->data_hash->buffer[i]); + } + for (size_t i = 0; i < transaction->signature->length; ++i) + { + tars_transaction->signature.push_back(transaction->signature->buffer[i]); + } + if (transaction->sender) + { + for (size_t i = 0; i < transaction->sender->length; ++i) + { + tars_transaction->sender.push_back(transaction->sender->buffer[i]); + } + } + tars_transaction->importTime = (tars::Int32)transaction->import_time; + tars_transaction->attribute = (tars::Int64)transaction->attribute; + tars_transaction->extraData = std::string(transaction->extra_data); + + return tars_transaction; + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("convert_transaction_to_tars_v2") << LOG_DESC("exception") + << LOG_KV("transaction", transaction) << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} + struct bcos_sdk_c_transaction* convert_tars_transaction_to_struct( bcostars::TransactionUniquePtr tars_transaction) { @@ -294,6 +474,47 @@ struct bcos_sdk_c_transaction* convert_tars_transaction_to_struct( return NULL; } +struct bcos_sdk_c_transaction_v2* convert_tars_transaction_to_struct_v2( + bcostars::TransactionUniquePtr tars_transaction) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(tars_transaction, NULL); + + try + { + struct bcos_sdk_c_transaction_v2* transaction_struct_v2 = + (struct bcos_sdk_c_transaction_v2*)malloc(sizeof(struct bcos_sdk_c_transaction_v2)); + struct bcos_sdk_c_bytes* data_hash_bytes = create_bytes_struct( + tars_transaction->dataHash.size(), tars_transaction->dataHash.data()); + struct bcos_sdk_c_bytes* signature_bytes = create_bytes_struct( + tars_transaction->signature.size(), tars_transaction->signature.data()); + struct bcos_sdk_c_bytes* sender_bytes = + create_bytes_struct(tars_transaction->sender.size(), tars_transaction->sender.data()); + auto transactionDataUniquePtr = + std::make_unique(tars_transaction->data); + + transaction_struct_v2->transaction_data = + convert_tars_transaction_data_to_struct_v2(std::move(transactionDataUniquePtr)); + transaction_struct_v2->data_hash = data_hash_bytes; + transaction_struct_v2->signature = signature_bytes; + transaction_struct_v2->sender = sender_bytes; + transaction_struct_v2->import_time = tars_transaction->importTime; + transaction_struct_v2->attribute = tars_transaction->attribute; + transaction_struct_v2->extra_data = my_strdup(tars_transaction->extraData.data()); + return transaction_struct_v2; + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("convert_tars_transaction_to_struct_v2") + << LOG_DESC("exception") << LOG_KV("transaction", tars_transaction) + << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} + /** * @brief * @@ -409,6 +630,7 @@ struct bcos_sdk_c_transaction_data* bcos_sdk_create_transaction_data_struct_with << LOG_DESC("exception") << LOG_KV("group_id", group_id) << LOG_KV("chain_id", chain_id) << LOG_KV("to", std::string(to ? to : "")) << LOG_KV("bytes_input", bytes_input) + << LOG_KV("bytes_input_length", bytes_input_length) << LOG_KV("abi", std::string(abi ? abi : "")) << LOG_KV("block_limit", block_limit) << LOG_KV("error", errorMsg); bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); @@ -973,3 +1195,633 @@ struct bcos_sdk_c_transaction* bcos_sdk_decode_transaction_struct_with_json( return NULL; } + +struct bcos_sdk_c_transaction_data_v2* bcos_sdk_create_transaction_data_struct_with_hex_input_v2( + const char* group_id, const char* chain_id, const char* to, const char* input, const char* abi, + int64_t block_limit, const char* value, const char* gas_price, int64_t gas_limit, + const char* max_fee_per_gas, const char* max_priority_fee_per_gas) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(group_id, NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(chain_id, NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(input, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION((input[0] != '\0'), "input can not be empty string", NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION((block_limit > 0), "block limit must > 0", NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(value, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION((value[0] != '\0'), "value can not be empty string", NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(gas_price, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION( + (gas_price[0] != '\0'), "gas_price can not be empty string", NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION((gas_limit >= 0), "gas limit must >= 0", NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(max_fee_per_gas, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION( + (max_fee_per_gas[0] != '\0'), "max_fee_per_gas can not be empty string", NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(max_priority_fee_per_gas, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION((max_priority_fee_per_gas[0] != '\0'), + "max_priority_fee_per_gas can not be empty string", NULL); + + try + { + struct bcos_sdk_c_transaction_data_v2* transaction_data_struct_v2 = + (struct bcos_sdk_c_transaction_data_v2*)malloc( + sizeof(struct bcos_sdk_c_transaction_data_v2)); + std::string toStr = to ? to : ""; + std::string abiStr = abi ? abi : ""; + auto bytesInput = fromHexString(input); + TransactionBuilder builder; + std::string nonceStr = builder.generateRandomStr(); + + transaction_data_struct_v2->version = 1; + transaction_data_struct_v2->block_limit = block_limit; + transaction_data_struct_v2->group_id = my_strdup(group_id); + transaction_data_struct_v2->chain_id = my_strdup(chain_id); + transaction_data_struct_v2->to = my_strdup(toStr.data()); + transaction_data_struct_v2->abi = my_strdup(abiStr.data()); + transaction_data_struct_v2->nonce = my_strdup(nonceStr.data()); + transaction_data_struct_v2->input = + create_bytes_struct(bytesInput->size(), reinterpret_cast(bytesInput->data())); + transaction_data_struct_v2->value = my_strdup(value); + transaction_data_struct_v2->gas_price = my_strdup(gas_price); + transaction_data_struct_v2->gas_limit = gas_limit; + transaction_data_struct_v2->max_fee_per_gas = my_strdup(max_fee_per_gas); + transaction_data_struct_v2->max_priority_fee_per_gas = my_strdup(max_priority_fee_per_gas); + + return transaction_data_struct_v2; + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("bcos_sdk_create_transaction_data_struct_with_hex_input_v2") + << LOG_DESC("exception") << LOG_KV("group_id", group_id) + << LOG_KV("chain_id", chain_id) << LOG_KV("to", std::string(to ? to : "")) + << LOG_KV("input", input) << LOG_KV("abi", std::string(abi ? abi : "")) + << LOG_KV("block_limit", block_limit) << LOG_KV("value", value) + << LOG_KV("gas_price", gas_price) << LOG_KV("gas_limit", gas_limit) + << LOG_KV("max_fee_per_gas", max_fee_per_gas) + << LOG_KV("max_priority_fee_per_gas", max_priority_fee_per_gas) + << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} + +struct bcos_sdk_c_transaction_data_v2* bcos_sdk_create_transaction_data_struct_with_bytes_v2( + const char* group_id, const char* chain_id, const char* to, const unsigned char* bytes_input, + uint32_t bytes_input_length, const char* abi, int64_t block_limit, const char* value, + const char* gas_price, int64_t gas_limit, const char* max_fee_per_gas, + const char* max_priority_fee_per_gas) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(group_id, NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(chain_id, NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(bytes_input, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION( + (bytes_input_length > 0), "bytes input length must > 0", NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION((block_limit > 0), "block limit must > 0", NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(value, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION((value[0] != '\0'), "value can not be empty string", NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(gas_price, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION( + (gas_price[0] != '\0'), "gas_price can not be empty string", NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION((gas_limit >= 0), "gas limit must >= 0", NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(max_fee_per_gas, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION( + (max_fee_per_gas[0] != '\0'), "max_fee_per_gas can not be empty string", NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(max_priority_fee_per_gas, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION((max_priority_fee_per_gas[0] != '\0'), + "max_priority_fee_per_gas can not be empty string", NULL); + + try + { + struct bcos_sdk_c_transaction_data_v2* transaction_data_struct_v2 = + (struct bcos_sdk_c_transaction_data_v2*)malloc( + sizeof(struct bcos_sdk_c_transaction_data_v2)); + std::string toStr = to ? to : ""; + std::string abiStr = abi ? abi : ""; + TransactionBuilder builder; + std::string nonceStr = builder.generateRandomStr(); + + transaction_data_struct_v2->version = 1; + transaction_data_struct_v2->block_limit = block_limit; + transaction_data_struct_v2->group_id = my_strdup(group_id); + transaction_data_struct_v2->chain_id = my_strdup(chain_id); + transaction_data_struct_v2->to = my_strdup(toStr.data()); + transaction_data_struct_v2->abi = my_strdup(abiStr.data()); + transaction_data_struct_v2->nonce = my_strdup(nonceStr.data()); + transaction_data_struct_v2->input = create_bytes_struct( + bytes_input_length, const_cast(reinterpret_cast(bytes_input))); + transaction_data_struct_v2->value = my_strdup(value); + transaction_data_struct_v2->gas_price = my_strdup(gas_price); + transaction_data_struct_v2->gas_limit = gas_limit; + transaction_data_struct_v2->max_fee_per_gas = my_strdup(max_fee_per_gas); + transaction_data_struct_v2->max_priority_fee_per_gas = my_strdup(max_priority_fee_per_gas); + + return transaction_data_struct_v2; + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("bcos_sdk_create_transaction_data_struct_with_bytes_v2") + << LOG_DESC("exception") << LOG_KV("group_id", group_id) + << LOG_KV("chain_id", chain_id) << LOG_KV("to", std::string(to ? to : "")) + << LOG_KV("bytes_input", bytes_input) + << LOG_KV("bytes_input_length", bytes_input_length) + << LOG_KV("abi", std::string(abi ? abi : "")) + << LOG_KV("block_limit", block_limit) << LOG_KV("value", value) + << LOG_KV("gas_price", gas_price) << LOG_KV("gas_limit", gas_limit) + << LOG_KV("max_fee_per_gas", max_fee_per_gas) + << LOG_KV("max_priority_fee_per_gas", max_priority_fee_per_gas) + << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} + +void bcos_sdk_destroy_transaction_data_struct_v2( + struct bcos_sdk_c_transaction_data_v2* transaction_data) +{ + if (transaction_data == NULL) + { + return; + } + + if (transaction_data && transaction_data->chain_id) + { + bcos_sdk_c_free(transaction_data->chain_id); + } + + if (transaction_data && transaction_data->group_id) + { + bcos_sdk_c_free(transaction_data->group_id); + } + + if (transaction_data && transaction_data->nonce) + { + bcos_sdk_c_free(transaction_data->nonce); + } + + if (transaction_data && transaction_data->to) + { + bcos_sdk_c_free(transaction_data->to); + } + + if (transaction_data && transaction_data->abi) + { + bcos_sdk_c_free((void*)transaction_data->abi); + } + + if (transaction_data && transaction_data->input) + { + if (transaction_data->input->buffer) + { + bcos_sdk_c_free(transaction_data->input->buffer); + } + bcos_sdk_c_free((void*)transaction_data->input); + } + + if (transaction_data && transaction_data->value) + { + bcos_sdk_c_free(transaction_data->value); + } + + if (transaction_data && transaction_data->gas_price) + { + bcos_sdk_c_free(transaction_data->gas_price); + } + + if (transaction_data && transaction_data->max_fee_per_gas) + { + bcos_sdk_c_free(transaction_data->max_fee_per_gas); + } + + if (transaction_data && transaction_data->max_priority_fee_per_gas) + { + bcos_sdk_c_free(transaction_data->max_priority_fee_per_gas); + } + + bcos_sdk_c_free(transaction_data); +} + +const char* bcos_sdk_encode_transaction_data_struct_v2( + struct bcos_sdk_c_transaction_data_v2* transaction_data) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction_data, NULL); + + try + { + auto tars_transaction_data = convert_transaction_data_to_tars_v2(transaction_data); + TransactionBuilder builder; + auto encodedTransactionData = builder.encodeTransactionData(*tars_transaction_data); + auto hex_tx_data_str = bcos::toHexString(*encodedTransactionData); + return strdup(hex_tx_data_str->c_str()); + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("bcos_sdk_encode_transaction_data_struct_v2") + << LOG_DESC("exception") << LOG_KV("transaction_data", transaction_data) + << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} + +const char* bcos_sdk_encode_transaction_data_struct_to_json_v2( + struct bcos_sdk_c_transaction_data_v2* transaction_data) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction_data, NULL); + + try + { + auto tars_transaction_data_v2 = convert_transaction_data_to_tars_v2(transaction_data); + auto json_str = tars_transaction_data_v2->writeToJsonString(); + return strdup(json_str.c_str()); + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("bcos_sdk_encode_transaction_data_struct_to_json_v2") + << LOG_DESC("exception") << LOG_KV("transaction_data", transaction_data) + << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} + +struct bcos_sdk_c_transaction_data_v2* bcos_sdk_decode_transaction_data_struct_v2( + const char* transaction_data_hex_str) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction_data_hex_str, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION((transaction_data_hex_str[0] != '\0'), + "transaction_data_hex_str can not be empty string", NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION((strlen(transaction_data_hex_str) % 2 != 1), + "the length of transaction_data_hex_str must be an even number", NULL); + + try + { + TransactionBuilder builder; + auto tx_data_bytes = fromHexString(transaction_data_hex_str); + auto tars_tx_data_v2 = builder.decodeTransactionData(*tx_data_bytes); + return convert_tars_transaction_data_to_struct_v2(std::move(tars_tx_data_v2)); + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("bcos_sdk_decode_transaction_data_struct_v2") + << LOG_DESC("exception") << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} + +struct bcos_sdk_c_transaction_data_v2* bcos_sdk_decode_transaction_data_struct_with_json_v2( + const char* transaction_data_json_str) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction_data_json_str, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION((transaction_data_json_str[0] != '\0'), + "transaction_data_json_str can not be empty string", NULL); + + try + { + TransactionBuilder builder; + auto transactionData = + builder.createTransactionDataWithJson(std::string(transaction_data_json_str)); + + return convert_tars_transaction_data_to_struct_v2(std::move(transactionData)); + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("bcos_sdk_decode_transaction_data_struct_with_json_v2") + << LOG_DESC("exception") + << LOG_KV("transaction_data_json_str", transaction_data_json_str) + << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} + +const char* bcos_sdk_calc_transaction_data_struct_hash_v2( + int crypto_type, struct bcos_sdk_c_transaction_data_v2* transaction_data) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction_data, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION( + (crypto_type == BCOS_C_SDK_ECDSA_TYPE || crypto_type == BCOS_C_SDK_SM_TYPE), + "invalid crypto type, it must be BCOS_C_SDK_ECDSA_TYPE(ecdsa crypto type) or " + "BCOS_C_SDK_SM_TYPE(sm crypto type)", + NULL); + + try + { + auto tars_transaction_data_v2 = convert_transaction_data_to_tars_v2(transaction_data); + TransactionBuilder builder; + auto transactionDataHash = builder.calculateTransactionDataHash( + crypto_type == BCOS_C_SDK_ECDSA_TYPE ? CryptoType::Secp256K1 : CryptoType::SM2, + *tars_transaction_data_v2); + return strdup(bcos::toHexStringWithPrefix(transactionDataHash).c_str()); + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("bcos_sdk_calc_transaction_data_struct_hash_v2") + << LOG_DESC("exception") << LOG_KV("crypto_type", crypto_type) + << LOG_KV("transaction_data", transaction_data) + << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} + +const char* bcos_sdk_calc_transaction_data_struct_hash_with_hex_v2( + int crypto_type, const char* transaction_data_hex) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction_data_hex, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION( + (crypto_type == BCOS_C_SDK_ECDSA_TYPE || crypto_type == BCOS_C_SDK_SM_TYPE), + "invalid crypto type, it must be BCOS_C_SDK_ECDSA_TYPE(ecdsa crypto type) or " + "BCOS_C_SDK_SM_TYPE(sm crypto type)", + NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION( + (transaction_data_hex[0] != '\0'), "transaction_data_hex can not be empty string", NULL); + + try + { + struct bcos_sdk_c_transaction_data_v2* transaction_data_struct_v2 = + bcos_sdk_decode_transaction_data_struct_v2(transaction_data_hex); + auto tars_transaction_data_v2 = + convert_transaction_data_to_tars_v2(transaction_data_struct_v2); + TransactionBuilder builder; + auto transactionDataHash = builder.calculateTransactionDataHash( + crypto_type == BCOS_C_SDK_ECDSA_TYPE ? CryptoType::Secp256K1 : CryptoType::SM2, + *tars_transaction_data_v2); + return strdup(bcos::toHexStringWithPrefix(transactionDataHash).c_str()); + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("bcos_sdk_calc_transaction_data_struct_hash_with_hex_v2") + << LOG_DESC("exception") << LOG_KV("crypto_type", crypto_type) + << LOG_KV("transaction_data_hex", transaction_data_hex) + << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} + +struct bcos_sdk_c_transaction_v2* bcos_sdk_create_transaction_struct_v2( + struct bcos_sdk_c_transaction_data_v2* transaction_data, const char* signature, + const char* transaction_data_hash, int32_t attribute, const char* extra_data) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction_data, NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(signature, NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction_data_hash, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION( + (signature[0] != '\0'), "signature can not be empty string", NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION( + (transaction_data_hash[0] != '\0'), "transaction_data_hash can not be empty string", NULL); + + try + { + struct bcos_sdk_c_transaction_v2* transaction_struct_v2 = + (struct bcos_sdk_c_transaction_v2*)malloc(sizeof(struct bcos_sdk_c_transaction_v2)); + transaction_struct_v2->transaction_data = transaction_data_copy_v2(transaction_data); + transaction_struct_v2->sender = NULL; + transaction_struct_v2->import_time = 0; + transaction_struct_v2->attribute = attribute; + transaction_struct_v2->extra_data = my_strdup(extra_data); + // signature + auto signatureWithoutHex = fromHexString(signature); + struct bcos_sdk_c_bytes* signature_bytes = + (struct bcos_sdk_c_bytes*)malloc(sizeof(struct bcos_sdk_c_bytes)); + signature_bytes->length = signatureWithoutHex->size(); + signature_bytes->buffer = (uint8_t*)malloc(signatureWithoutHex->size()); + memcpy(signature_bytes->buffer, signatureWithoutHex->data(), signatureWithoutHex->size()); + transaction_struct_v2->signature = signature_bytes; + // data_hash + auto dataHashArray = bcos::crypto::HashType(transaction_data_hash); + struct bcos_sdk_c_bytes* data_hash_bytes = + (struct bcos_sdk_c_bytes*)malloc(sizeof(struct bcos_sdk_c_bytes)); + data_hash_bytes->length = dataHashArray.size(); + data_hash_bytes->buffer = (uint8_t*)malloc(dataHashArray.size()); + memcpy(data_hash_bytes->buffer, dataHashArray.data(), dataHashArray.size()); + transaction_struct_v2->data_hash = data_hash_bytes; + + return transaction_struct_v2; + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("bcos_sdk_create_transaction_struct_v2") + << LOG_DESC("exception") << LOG_KV("signature", signature) + << LOG_KV("transaction_data_hash", transaction_data_hash) + << LOG_KV("attribute", attribute) << LOG_KV("extra_data", extra_data) + << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} + +void bcos_sdk_destroy_transaction_struct_v2(struct bcos_sdk_c_transaction_v2* transaction) +{ + if (transaction == NULL) + { + return; + } + + if (transaction && transaction->transaction_data) + { + bcos_sdk_destroy_transaction_data_struct_v2(transaction->transaction_data); + } + + if (transaction && transaction->data_hash) + { + if (transaction->data_hash->buffer) + { + bcos_sdk_c_free(transaction->data_hash->buffer); + } + bcos_sdk_c_free(transaction->data_hash); + } + + if (transaction && transaction->signature) + { + if (transaction->signature->buffer) + { + bcos_sdk_c_free(transaction->signature->buffer); + } + bcos_sdk_c_free(transaction->signature); + } + + if (transaction && transaction->sender) + { + if (transaction->sender->buffer) + { + bcos_sdk_c_free(transaction->sender->buffer); + } + bcos_sdk_c_free(transaction->sender); + } + + if (transaction && transaction->extra_data) + { + bcos_sdk_c_free(transaction->extra_data); + } + + bcos_sdk_c_free(transaction); +} + +const char* bcos_sdk_create_encoded_transaction_v2( + struct bcos_sdk_c_transaction_data_v2* transaction_data, const char* signature, + const char* transaction_data_hash, int32_t attribute, const char* extra_data) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction_data, NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(signature, NULL); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction_data_hash, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION( + (signature[0] != '\0'), "signature can not be empty string", NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION( + (transaction_data_hash[0] != '\0'), "transaction_data_hash can not be empty string", NULL); + + try + { + TransactionBuilder builder; + auto tars_tx_data_v2 = convert_transaction_data_to_tars_v2(transaction_data); + auto signedBytes = builder.createSignedTransaction(*tars_tx_data_v2, + *fromHexString(signature), bcos::crypto::HashType(transaction_data_hash), attribute, + extra_data ? std::string(extra_data) : std::string()); + return strdup(bcos::toHexStringWithPrefix(*signedBytes).c_str()); + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("bcos_sdk_create_encoded_transaction_v2") + << LOG_DESC("exception") << LOG_KV("signature", signature) + << LOG_KV("transaction_data_hash", transaction_data_hash) + << LOG_KV("attribute", attribute) << LOG_KV("extra_data", extra_data) + << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + return NULL; +} + +const char* bcos_sdk_encode_transaction_struct_v2(struct bcos_sdk_c_transaction_v2* transaction) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction, NULL); + + try + { + auto tars_transaction_v2 = convert_transaction_to_tars_v2(transaction); + TransactionBuilder builder; + auto encodedTransaction = builder.encodeTransaction(*tars_transaction_v2); + auto hex_tx_str = toHexStringWithPrefix(*encodedTransaction); + return strdup(hex_tx_str.c_str()); + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("bcos_sdk_encode_transaction_struct_v2") + << LOG_DESC("exception") << LOG_KV("transaction", transaction) + << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} + +const char* bcos_sdk_encode_transaction_struct_to_json_v2( + struct bcos_sdk_c_transaction_v2* transaction) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction, NULL); + + try + { + auto tars_transaction_v2 = convert_transaction_to_tars_v2(transaction); + auto json_str = tars_transaction_v2->writeToJsonString(); + return strdup(json_str.c_str()); + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("bcos_sdk_encode_transaction_struct_to_json_v2") + << LOG_DESC("exception") << LOG_KV("transaction", transaction) + << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} + +struct bcos_sdk_c_transaction_v2* bcos_sdk_decode_transaction_struct_v2( + const char* transaction_hex_str) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction_hex_str, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION( + (transaction_hex_str[0] != '\0'), "transaction_hex_str can not be empty string", NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION((strlen(transaction_hex_str) % 2 != 1), + "the length of transaction_hex_str must be an even number", NULL); + + try + { + TransactionBuilder builder; + auto tx_bytes = fromHexString(transaction_hex_str); + auto tars_tx = builder.decodeTransaction(*tx_bytes); + return convert_tars_transaction_to_struct_v2(std::move(tars_tx)); + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("bcos_sdk_decode_transaction_struct") + << LOG_DESC("exception") + << LOG_KV("transaction_hex_str", transaction_hex_str) + << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} + +struct bcos_sdk_c_transaction_v2* bcos_sdk_decode_transaction_struct_with_json_v2( + const char* transaction_json_str) +{ + bcos_sdk_clear_last_error(); + BCOS_SDK_C_PARAMS_VERIFICATION(transaction_json_str, NULL); + BCOS_SDK_C_PARAMS_VERIFY_CONDITION( + (transaction_json_str[0] != '\0'), "transaction_json_str can not be empty string", NULL); + + try + { + TransactionBuilder builder; + auto transaction = builder.createTransactionWithJson(std::string(transaction_json_str)); + + return convert_tars_transaction_to_struct_v2(std::move(transaction)); + } + catch (const std::exception& e) + { + std::string errorMsg = boost::diagnostic_information(e); + BCOS_LOG(WARNING) << LOG_BADGE("bcos_sdk_decode_transaction_struct_with_json_v2") + << LOG_DESC("exception") + << LOG_KV("transaction_json_str", transaction_json_str) + << LOG_KV("error", errorMsg); + bcos_sdk_set_last_error_msg(-1, errorMsg.c_str()); + } + + return NULL; +} diff --git a/bcos-c-sdk/bcos_sdk_c_uti_tx_struct.h b/bcos-c-sdk/bcos_sdk_c_uti_tx_struct.h index e275b093d..4075c51c3 100644 --- a/bcos-c-sdk/bcos_sdk_c_uti_tx_struct.h +++ b/bcos-c-sdk/bcos_sdk_c_uti_tx_struct.h @@ -193,6 +193,52 @@ struct bcos_sdk_c_transaction* bcos_sdk_decode_transaction_struct(const char* tr struct bcos_sdk_c_transaction* bcos_sdk_decode_transaction_struct_with_json( const char* transaction_json_str); +struct bcos_sdk_c_transaction_data_v2* bcos_sdk_create_transaction_data_struct_with_hex_input_v2( + const char* group_id, const char* chain_id, const char* to, const char* input, const char* abi, + int64_t block_limit, const char* value, const char* gas_price, int64_t gas_limit, const char* max_fee_per_gas, const char* max_priority_fee_per_gas); + +struct bcos_sdk_c_transaction_data_v2* bcos_sdk_create_transaction_data_struct_with_bytes_v2( + const char* group_id, const char* chain_id, const char* to, const unsigned char* bytes_input, + uint32_t bytes_input_length, const char* abi, int64_t block_limit, const char* value, const char* gas_price, int64_t gas_limit, const char* max_fee_per_gas, const char* max_priority_fee_per_gas); + +void bcos_sdk_destroy_transaction_data_struct_v2(struct bcos_sdk_c_transaction_data_v2* transaction_data); + +const char* bcos_sdk_encode_transaction_data_struct_v2(struct bcos_sdk_c_transaction_data_v2* transaction_data); + +const char* bcos_sdk_encode_transaction_data_struct_to_json_v2(struct bcos_sdk_c_transaction_data_v2* transaction_data); + +struct bcos_sdk_c_transaction_data_v2* bcos_sdk_decode_transaction_data_struct_v2( + const char* transaction_data_hex_str); + +struct bcos_sdk_c_transaction_data_v2* bcos_sdk_decode_transaction_data_struct_with_json_v2( + const char* transaction_data_json_str); + +const char* bcos_sdk_calc_transaction_data_struct_hash_v2( + int crypto_type, struct bcos_sdk_c_transaction_data_v2* transaction_data); + +const char* bcos_sdk_calc_transaction_data_struct_hash_with_hex_v2( + int crypto_type, const char* transaction_data_hex); + +struct bcos_sdk_c_transaction_v2* bcos_sdk_create_transaction_struct_v2( + struct bcos_sdk_c_transaction_data_v2* transaction_data, const char* signature, + const char* transaction_data_hash, int32_t attribute, const char* extra_data); + +void bcos_sdk_destroy_transaction_struct_v2(struct bcos_sdk_c_transaction_v2* transaction); + +const char* bcos_sdk_create_encoded_transaction_v2( + struct bcos_sdk_c_transaction_data_v2* transaction_data, const char* signature, + const char* transaction_data_hash, int32_t attribute, const char* extra_data); + +const char* bcos_sdk_encode_transaction_struct_v2(struct bcos_sdk_c_transaction_v2* transaction); + +const char* bcos_sdk_encode_transaction_struct_to_json_v2(struct bcos_sdk_c_transaction_v2* transaction); + +struct bcos_sdk_c_transaction_v2* bcos_sdk_decode_transaction_struct_v2( + const char* transaction_hex_str); + +struct bcos_sdk_c_transaction_v2* bcos_sdk_decode_transaction_struct_with_json_v2( + const char* transaction_json_str); + #ifdef __cplusplus } #endif diff --git a/bindings/java/jni/src/main/c/jni/org_fisco_bcos_sdk_jni_utilities_tx_TransactionStructBuilderJniObj.cpp b/bindings/java/jni/src/main/c/jni/org_fisco_bcos_sdk_jni_utilities_tx_TransactionStructBuilderJniObj.cpp index 0ab13580a..e96679b59 100644 --- a/bindings/java/jni/src/main/c/jni/org_fisco_bcos_sdk_jni_utilities_tx_TransactionStructBuilderJniObj.cpp +++ b/bindings/java/jni/src/main/c/jni/org_fisco_bcos_sdk_jni_utilities_tx_TransactionStructBuilderJniObj.cpp @@ -6,275 +6,359 @@ struct bcos_sdk_c_bytes* convert_to_bytes_struct(JNIEnv* env, jobject bytesObj) { - if (bytesObj == NULL) + try + { + if (bytesObj == NULL) + { + return NULL; + } + + struct bcos_sdk_c_bytes* bytes = + (struct bcos_sdk_c_bytes*)malloc(sizeof(struct bcos_sdk_c_bytes)); + jclass bytesClass = env->GetObjectClass(bytesObj); + jfieldID bufferField = env->GetFieldID(bytesClass, "buffer", "[B"); + jfieldID lengthField = env->GetFieldID(bytesClass, "length", "I"); + + jbyteArray bufferArray = (jbyteArray)env->GetObjectField(bytesObj, bufferField); + jbyte* bufferData = env->GetByteArrayElements(bufferArray, nullptr); + jsize bufferLength = env->GetArrayLength(bufferArray); + bytes->length = (uint32_t)env->GetIntField(bytesObj, lengthField); + bytes->buffer = (uint8_t*)malloc(bufferLength * sizeof(uint8_t)); + memcpy(bytes->buffer, bufferData, bufferLength); + + env->ReleaseByteArrayElements(bufferArray, bufferData, 0); + + return bytes; + } + catch (...) { return NULL; } - - struct bcos_sdk_c_bytes* bytes = - (struct bcos_sdk_c_bytes*)malloc(sizeof(struct bcos_sdk_c_bytes)); - jclass bytesClass = env->GetObjectClass(bytesObj); - jfieldID bufferField = env->GetFieldID(bytesClass, "buffer", "[B"); - jfieldID lengthField = env->GetFieldID(bytesClass, "length", "I"); - - jbyteArray bufferArray = (jbyteArray)env->GetObjectField(bytesObj, bufferField); - jbyte* bufferData = env->GetByteArrayElements(bufferArray, nullptr); - jsize bufferLength = env->GetArrayLength(bufferArray); - bytes->length = (uint32_t)env->GetIntField(bytesObj, lengthField); - bytes->buffer = (uint8_t*)malloc(bufferLength * sizeof(uint8_t)); - memcpy(bytes->buffer, bufferData, bufferLength); - - env->ReleaseByteArrayElements(bufferArray, bufferData, 0); - - return bytes; } jobject convert_to_bytes_jobject(JNIEnv* env, const struct bcos_sdk_c_bytes* bytes_struct) { - if (bytes_struct == NULL) - { - return NULL; - } - - jclass txBytesClass = env->FindClass("org/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes"); - if (txBytesClass == NULL) + try { - env->FatalError( - "No such class, className: " - "org/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes"); + if (bytes_struct == NULL) + { + return NULL; + } + + jclass txBytesClass = + env->FindClass("org/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes"); + if (txBytesClass == NULL) + { + env->FatalError( + "No such class, className: " + "org/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes"); + } + jmethodID txBytesMtd = env->GetMethodID(txBytesClass, "", "()V"); + if (txBytesMtd == NULL) + { + env->FatalError("No such constructor in TransactionBytes, constructor()"); + } + jfieldID bufferField = env->GetFieldID(txBytesClass, "buffer", "[B"); + jfieldID lengthField = env->GetFieldID(txBytesClass, "length", "I"); + + jobject jTxBytesObj = env->NewObject(txBytesClass, txBytesMtd); + // buffer + jbyteArray bufferArray = env->NewByteArray(bytes_struct->length); + env->SetByteArrayRegion( + bufferArray, 0, bytes_struct->length, reinterpret_cast(bytes_struct->buffer)); + env->SetObjectField(jTxBytesObj, bufferField, bufferArray); + // length + env->SetIntField(jTxBytesObj, lengthField, bytes_struct->length); + + env->DeleteLocalRef(bufferArray); + + return jTxBytesObj; } - jmethodID txBytesMtd = env->GetMethodID(txBytesClass, "", "()V"); - if (txBytesMtd == NULL) + catch (...) { - env->FatalError("No such constructor in TransactionBytes, constructor()"); + return NULL; } - jfieldID bufferField = env->GetFieldID(txBytesClass, "buffer", "[B"); - jfieldID lengthField = env->GetFieldID(txBytesClass, "length", "I"); - - jobject jTxBytesObj = env->NewObject(txBytesClass, txBytesMtd); - // buffer - jbyteArray bufferArray = env->NewByteArray(bytes_struct->length); - env->SetByteArrayRegion( - bufferArray, 0, bytes_struct->length, reinterpret_cast(bytes_struct->buffer)); - env->SetObjectField(jTxBytesObj, bufferField, bufferArray); - // length - env->SetIntField(jTxBytesObj, lengthField, bytes_struct->length); - - env->DeleteLocalRef(bufferArray); - - return jTxBytesObj; } struct bcos_sdk_c_transaction_data* convert_to_tx_data_struct( JNIEnv* env, jobject transactionObject) { - bcos_sdk_c_transaction_data* tx_data_struct = - (struct bcos_sdk_c_transaction_data*)malloc(sizeof(struct bcos_sdk_c_transaction_data)); - jclass txDataClass = env->GetObjectClass(transactionObject); - - // version - jfieldID versionField = env->GetFieldID(txDataClass, "version", "I"); - tx_data_struct->version = env->GetIntField(transactionObject, versionField); - - // blockLimit - jfieldID blockLimitField = env->GetFieldID(txDataClass, "blockLimit", "J"); - tx_data_struct->block_limit = env->GetLongField(transactionObject, blockLimitField); - - // chainId - jfieldID chainIdField = env->GetFieldID(txDataClass, "chainId", "Ljava/lang/String;"); - jstring chainIdString = (jstring)env->GetObjectField(transactionObject, chainIdField); - const char* chainIdValue = env->GetStringUTFChars(chainIdString, nullptr); - tx_data_struct->chain_id = strdup(chainIdValue); - - // groupId - jfieldID groupIdField = env->GetFieldID(txDataClass, "groupId", "Ljava/lang/String;"); - jstring groupIdString = (jstring)env->GetObjectField(transactionObject, groupIdField); - const char* groupIdValue = env->GetStringUTFChars(groupIdString, nullptr); - tx_data_struct->group_id = strdup(groupIdValue); - - // nonce - jfieldID nonceField = env->GetFieldID(txDataClass, "nonce", "Ljava/lang/String;"); - jstring nonceString = (jstring)env->GetObjectField(transactionObject, nonceField); - const char* nonceValue = env->GetStringUTFChars(nonceString, nullptr); - tx_data_struct->nonce = strdup(nonceValue); - - // to - jfieldID toField = env->GetFieldID(txDataClass, "to", "Ljava/lang/String;"); - jstring toString = (jstring)env->GetObjectField(transactionObject, toField); - const char* toValue = env->GetStringUTFChars(toString, nullptr); - tx_data_struct->to = strdup(toValue); - - // abi - jfieldID abiField = env->GetFieldID(txDataClass, "abi", "Ljava/lang/String;"); - jstring abiString = (jstring)env->GetObjectField(transactionObject, abiField); - const char* abiValue = env->GetStringUTFChars(abiString, nullptr); - tx_data_struct->abi = strdup(abiValue); - - // input - jfieldID inputField = - env->GetFieldID(txDataClass, "input", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes;"); - jobject inputObject = env->GetObjectField(transactionObject, inputField); - tx_data_struct->input = convert_to_bytes_struct(env, inputObject); - - // release source - env->ReleaseStringUTFChars(chainIdString, chainIdValue); - env->ReleaseStringUTFChars(groupIdString, groupIdValue); - env->ReleaseStringUTFChars(nonceString, nonceValue); - env->ReleaseStringUTFChars(toString, toValue); - env->ReleaseStringUTFChars(abiString, abiValue); - - return tx_data_struct; + try + { + bcos_sdk_c_transaction_data* tx_data_struct = + (struct bcos_sdk_c_transaction_data*)malloc(sizeof(struct bcos_sdk_c_transaction_data)); + jclass txDataClass = env->GetObjectClass(transactionObject); + + // version + jfieldID versionField = env->GetFieldID(txDataClass, "version", "I"); + tx_data_struct->version = env->GetIntField(transactionObject, versionField); + + // blockLimit + jfieldID blockLimitField = env->GetFieldID(txDataClass, "blockLimit", "J"); + tx_data_struct->block_limit = env->GetLongField(transactionObject, blockLimitField); + + // chainId + jfieldID chainIdField = env->GetFieldID(txDataClass, "chainId", "Ljava/lang/String;"); + jstring chainIdString = (jstring)env->GetObjectField(transactionObject, chainIdField); + const char* chainIdValue = env->GetStringUTFChars(chainIdString, nullptr); + tx_data_struct->chain_id = strdup(chainIdValue); + + // groupId + jfieldID groupIdField = env->GetFieldID(txDataClass, "groupId", "Ljava/lang/String;"); + jstring groupIdString = (jstring)env->GetObjectField(transactionObject, groupIdField); + const char* groupIdValue = env->GetStringUTFChars(groupIdString, nullptr); + tx_data_struct->group_id = strdup(groupIdValue); + + // nonce + jfieldID nonceField = env->GetFieldID(txDataClass, "nonce", "Ljava/lang/String;"); + jstring nonceString = (jstring)env->GetObjectField(transactionObject, nonceField); + const char* nonceValue = env->GetStringUTFChars(nonceString, nullptr); + tx_data_struct->nonce = strdup(nonceValue); + + // to + jfieldID toField = env->GetFieldID(txDataClass, "to", "Ljava/lang/String;"); + jstring toString = (jstring)env->GetObjectField(transactionObject, toField); + const char* toValue = env->GetStringUTFChars(toString, nullptr); + tx_data_struct->to = strdup(toValue); + + // abi + jfieldID abiField = env->GetFieldID(txDataClass, "abi", "Ljava/lang/String;"); + jstring abiString = (jstring)env->GetObjectField(transactionObject, abiField); + const char* abiValue = env->GetStringUTFChars(abiString, nullptr); + tx_data_struct->abi = strdup(abiValue); + + // input + jfieldID inputField = env->GetFieldID( + txDataClass, "input", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes;"); + jobject inputObject = env->GetObjectField(transactionObject, inputField); + struct bcos_sdk_c_bytes* inputStruct = convert_to_bytes_struct(env, inputObject); + if (inputStruct == NULL) + { + THROW_JNI_EXCEPTION(env, "exception in convert_to_bytes_struct"); + } + tx_data_struct->input = inputStruct; + + // release source + env->ReleaseStringUTFChars(chainIdString, chainIdValue); + env->ReleaseStringUTFChars(groupIdString, groupIdValue); + env->ReleaseStringUTFChars(nonceString, nonceValue); + env->ReleaseStringUTFChars(toString, toValue); + env->ReleaseStringUTFChars(abiString, abiValue); + + return tx_data_struct; + } + catch (...) + { + return NULL; + } } jobject convert_to_tx_data_jobject( JNIEnv* env, const struct bcos_sdk_c_transaction_data* transactionData) { - jclass txDataClass = env->FindClass("org/fisco/bcos/sdk/jni/utilities/tx/TransactionData"); - if (txDataClass == NULL) - { - env->FatalError( - "No such class, className: " - "org/fisco/bcos/sdk/jni/utilities/tx/TransactionData"); - } - jmethodID txDataMtd = env->GetMethodID(txDataClass, "", "()V"); - if (txDataMtd == NULL) - { - env->FatalError("No such constructor in TransactionData, constructor()"); - } - jobject jTxDataObj = env->NewObject(txDataClass, txDataMtd); - - // version - jfieldID versionField = env->GetFieldID(txDataClass, "version", "I"); - env->SetIntField(jTxDataObj, versionField, transactionData->version); - // block_limit - jfieldID blockLimitField = env->GetFieldID(txDataClass, "blockLimit", "J"); - env->SetLongField(jTxDataObj, blockLimitField, transactionData->block_limit); - // chain_id - jfieldID chainIdField = env->GetFieldID(txDataClass, "chainId", "Ljava/lang/String;"); - env->SetObjectField(jTxDataObj, chainIdField, env->NewStringUTF(transactionData->chain_id)); - // group_id - jfieldID groupIdField = env->GetFieldID(txDataClass, "groupId", "Ljava/lang/String;"); - env->SetObjectField(jTxDataObj, groupIdField, env->NewStringUTF(transactionData->group_id)); - // nonce - jfieldID nonceField = env->GetFieldID(txDataClass, "nonce", "Ljava/lang/String;"); - env->SetObjectField(jTxDataObj, nonceField, env->NewStringUTF(transactionData->nonce)); - // to - jfieldID toField = env->GetFieldID(txDataClass, "to", "Ljava/lang/String;"); - env->SetObjectField(jTxDataObj, toField, env->NewStringUTF(transactionData->to)); - // abi - jfieldID abiField = env->GetFieldID(txDataClass, "abi", "Ljava/lang/String;"); - env->SetObjectField(jTxDataObj, abiField, env->NewStringUTF(transactionData->abi)); - - // input - jobject jInput = convert_to_bytes_jobject(env, transactionData->input); - jfieldID inputField = - env->GetFieldID(txDataClass, "input", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes;"); - env->SetObjectField(jTxDataObj, inputField, jInput); - - // release - env->DeleteLocalRef(jInput); - - return jTxDataObj; + try + { + jclass txDataClass = env->FindClass("org/fisco/bcos/sdk/jni/utilities/tx/TransactionData"); + if (txDataClass == NULL) + { + env->FatalError( + "No such class, className: " + "org/fisco/bcos/sdk/jni/utilities/tx/TransactionData"); + } + jmethodID txDataMtd = env->GetMethodID(txDataClass, "", "()V"); + if (txDataMtd == NULL) + { + env->FatalError("No such constructor in TransactionData, constructor()"); + } + jobject jTxDataObj = env->NewObject(txDataClass, txDataMtd); + + // version + jfieldID versionField = env->GetFieldID(txDataClass, "version", "I"); + env->SetIntField(jTxDataObj, versionField, transactionData->version); + // block_limit + jfieldID blockLimitField = env->GetFieldID(txDataClass, "blockLimit", "J"); + env->SetLongField(jTxDataObj, blockLimitField, transactionData->block_limit); + // chain_id + jfieldID chainIdField = env->GetFieldID(txDataClass, "chainId", "Ljava/lang/String;"); + env->SetObjectField(jTxDataObj, chainIdField, env->NewStringUTF(transactionData->chain_id)); + // group_id + jfieldID groupIdField = env->GetFieldID(txDataClass, "groupId", "Ljava/lang/String;"); + env->SetObjectField(jTxDataObj, groupIdField, env->NewStringUTF(transactionData->group_id)); + // nonce + jfieldID nonceField = env->GetFieldID(txDataClass, "nonce", "Ljava/lang/String;"); + env->SetObjectField(jTxDataObj, nonceField, env->NewStringUTF(transactionData->nonce)); + // to + jfieldID toField = env->GetFieldID(txDataClass, "to", "Ljava/lang/String;"); + env->SetObjectField(jTxDataObj, toField, env->NewStringUTF(transactionData->to)); + // abi + jfieldID abiField = env->GetFieldID(txDataClass, "abi", "Ljava/lang/String;"); + env->SetObjectField(jTxDataObj, abiField, env->NewStringUTF(transactionData->abi)); + + // input + jobject jInput = convert_to_bytes_jobject(env, transactionData->input); + if (jInput == NULL) + { + THROW_JNI_EXCEPTION(env, "exception in convert_to_bytes_jobject"); + } + jfieldID inputField = env->GetFieldID( + txDataClass, "input", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes;"); + env->SetObjectField(jTxDataObj, inputField, jInput); + + // release + env->DeleteLocalRef(jInput); + + return jTxDataObj; + } + catch (...) + { + return NULL; + } } jobject convert_to_tx_jobject(JNIEnv* env, const struct bcos_sdk_c_transaction* tx_struct) { - jclass txClass = env->FindClass("org/fisco/bcos/sdk/jni/utilities/tx/Transaction"); - if (txClass == NULL) - { - env->FatalError( - "No such class, className: " - "org/fisco/bcos/sdk/jni/utilities/tx/Transaction"); - } - jmethodID txMtd = env->GetMethodID(txClass, "", "()V"); - if (txMtd == NULL) - { - env->FatalError("No such constructor in Transaction, constructor()"); - } - jfieldID txDataField = - env->GetFieldID(txClass, "transactionData", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionData;"); - jfieldID dataHashField = - env->GetFieldID(txClass, "dataHash", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes;"); - jfieldID signatureField = - env->GetFieldID(txClass, "signature", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes;"); - jfieldID senderField = - env->GetFieldID(txClass, "sender", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes;"); - jfieldID importTimeField = env->GetFieldID(txClass, "importTime", "J"); - jfieldID attributeField = env->GetFieldID(txClass, "attribute", "I"); - jfieldID extraDataField = env->GetFieldID(txClass, "extraData", "Ljava/lang/String;"); - - jobject javaTxObj = env->NewObject(txClass, txMtd); - // TransactionData - jobject javaTxDataObj = convert_to_tx_data_jobject(env, tx_struct->transaction_data); - env->SetObjectField(javaTxObj, txDataField, javaTxDataObj); - // DataHash - jobject javaDataHashObj = convert_to_bytes_jobject(env, tx_struct->data_hash); - env->SetObjectField(javaTxObj, dataHashField, javaDataHashObj); - // Signature - jobject javaSignatureObj = convert_to_bytes_jobject(env, tx_struct->signature); - env->SetObjectField(javaTxObj, signatureField, javaSignatureObj); - // Sender - jobject javaSenderObj = convert_to_bytes_jobject(env, tx_struct->sender); - env->SetObjectField(javaTxObj, senderField, javaSenderObj); - // ImportTime - env->SetLongField(javaTxObj, importTimeField, tx_struct->import_time); - // Attribute - env->SetIntField(javaTxObj, attributeField, tx_struct->attribute); - // ExtraData - jstring javaExtraData = env->NewStringUTF(tx_struct->extra_data); - env->SetObjectField(javaTxObj, extraDataField, javaExtraData); - - return javaTxObj; + try + { + jclass txClass = env->FindClass("org/fisco/bcos/sdk/jni/utilities/tx/Transaction"); + if (txClass == NULL) + { + env->FatalError( + "No such class, className: " + "org/fisco/bcos/sdk/jni/utilities/tx/Transaction"); + } + jmethodID txMtd = env->GetMethodID(txClass, "", "()V"); + if (txMtd == NULL) + { + env->FatalError("No such constructor in Transaction, constructor()"); + } + jfieldID txDataField = env->GetFieldID( + txClass, "transactionData", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionData;"); + jfieldID dataHashField = env->GetFieldID( + txClass, "dataHash", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes;"); + jfieldID signatureField = env->GetFieldID( + txClass, "signature", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes;"); + jfieldID senderField = env->GetFieldID( + txClass, "sender", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes;"); + jfieldID importTimeField = env->GetFieldID(txClass, "importTime", "J"); + jfieldID attributeField = env->GetFieldID(txClass, "attribute", "I"); + jfieldID extraDataField = env->GetFieldID(txClass, "extraData", "Ljava/lang/String;"); + + jobject javaTxObj = env->NewObject(txClass, txMtd); + // TransactionData + jobject javaTxDataObj = convert_to_tx_data_jobject(env, tx_struct->transaction_data); + if (javaTxDataObj == NULL) + { + THROW_JNI_EXCEPTION(env, "exception in convert_to_tx_data_jobject"); + } + env->SetObjectField(javaTxObj, txDataField, javaTxDataObj); + // DataHash + jobject javaDataHashObj = convert_to_bytes_jobject(env, tx_struct->data_hash); + if (javaDataHashObj == NULL) + { + THROW_JNI_EXCEPTION(env, "exception in convert_to_bytes_jobject"); + } + env->SetObjectField(javaTxObj, dataHashField, javaDataHashObj); + // Signature + jobject javaSignatureObj = convert_to_bytes_jobject(env, tx_struct->signature); + if (javaSignatureObj == NULL) + { + THROW_JNI_EXCEPTION(env, "exception in convert_to_bytes_jobject"); + } + env->SetObjectField(javaTxObj, signatureField, javaSignatureObj); + // Sender + jobject javaSenderObj = convert_to_bytes_jobject(env, tx_struct->sender); + if (javaSenderObj == NULL) + { + THROW_JNI_EXCEPTION(env, "exception in convert_to_bytes_jobject"); + } + env->SetObjectField(javaTxObj, senderField, javaSenderObj); + // ImportTime + env->SetLongField(javaTxObj, importTimeField, tx_struct->import_time); + // Attribute + env->SetIntField(javaTxObj, attributeField, tx_struct->attribute); + // ExtraData + jstring javaExtraData = env->NewStringUTF(tx_struct->extra_data); + env->SetObjectField(javaTxObj, extraDataField, javaExtraData); + + return javaTxObj; + } + catch (...) + { + return NULL; + } } struct bcos_sdk_c_transaction* convert_to_tx_struct(JNIEnv* env, jobject jTxObj) { - jclass javaTxClass = env->GetObjectClass(jTxObj); - jfieldID transactionDataField = env->GetFieldID( - javaTxClass, "transactionData", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionData;"); - jfieldID dataHashField = - env->GetFieldID(javaTxClass, "dataHash", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes;"); - jfieldID signatureField = - env->GetFieldID(javaTxClass, "signature", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes;"); - jfieldID senderField = - env->GetFieldID(javaTxClass, "sender", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes;"); - jfieldID importTimeField = env->GetFieldID(javaTxClass, "importTime", "J"); - jfieldID attributeField = env->GetFieldID(javaTxClass, "attribute", "I"); - jfieldID extraDataField = env->GetFieldID(javaTxClass, "extraData", "Ljava/lang/String;"); - - struct bcos_sdk_c_transaction* txStruct = - (struct bcos_sdk_c_transaction*)malloc(sizeof(struct bcos_sdk_c_transaction)); - // TransactionData - jobject javaTxDataObj = env->GetObjectField(jTxObj, transactionDataField); - struct bcos_sdk_c_transaction_data* txDataStruct = - convert_to_tx_data_struct(env, javaTxDataObj); - txStruct->transaction_data = txDataStruct; - // DataHash - jobject javaDataHashObj = env->GetObjectField(jTxObj, dataHashField); - struct bcos_sdk_c_bytes* dataHashStruct = convert_to_bytes_struct(env, javaDataHashObj); - txStruct->data_hash = dataHashStruct; - // Signature - jobject javaSignatureObj = env->GetObjectField(jTxObj, signatureField); - struct bcos_sdk_c_bytes* signatureStruct = convert_to_bytes_struct(env, javaSignatureObj); - txStruct->signature = signatureStruct; - // Sender - jobject javaSenderObj = env->GetObjectField(jTxObj, senderField); - struct bcos_sdk_c_bytes* senderStruct = convert_to_bytes_struct(env, javaSenderObj); - txStruct->sender = senderStruct; - // ImportTime - jlong importTimeValue = env->GetLongField(jTxObj, importTimeField); - txStruct->import_time = (int64_t)importTimeValue; - // Attribute - jint attributeValue = env->GetIntField(jTxObj, attributeField); - txStruct->attribute = (int32_t)attributeValue; - // ExtraData - jstring javaExtraData = (jstring)env->GetObjectField(jTxObj, extraDataField); - const char* extraDataValue = env->GetStringUTFChars(javaExtraData, NULL); - txStruct->extra_data = strdup(extraDataValue); - - env->ReleaseStringUTFChars(javaExtraData, extraDataValue); - - return txStruct; + try + { + jclass javaTxClass = env->GetObjectClass(jTxObj); + jfieldID transactionDataField = env->GetFieldID(javaTxClass, "transactionData", + "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionData;"); + jfieldID dataHashField = env->GetFieldID( + javaTxClass, "dataHash", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes;"); + jfieldID signatureField = env->GetFieldID( + javaTxClass, "signature", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes;"); + jfieldID senderField = env->GetFieldID( + javaTxClass, "sender", "Lorg/fisco/bcos/sdk/jni/utilities/tx/TransactionBytes;"); + jfieldID importTimeField = env->GetFieldID(javaTxClass, "importTime", "J"); + jfieldID attributeField = env->GetFieldID(javaTxClass, "attribute", "I"); + jfieldID extraDataField = env->GetFieldID(javaTxClass, "extraData", "Ljava/lang/String;"); + + struct bcos_sdk_c_transaction* txStruct = + (struct bcos_sdk_c_transaction*)malloc(sizeof(struct bcos_sdk_c_transaction)); + // TransactionData + jobject javaTxDataObj = env->GetObjectField(jTxObj, transactionDataField); + struct bcos_sdk_c_transaction_data* txDataStruct = + convert_to_tx_data_struct(env, javaTxDataObj); + if (txDataStruct == NULL) + { + THROW_JNI_EXCEPTION(env, "exception in convert_to_tx_data_struct"); + } + txStruct->transaction_data = txDataStruct; + // DataHash + jobject javaDataHashObj = env->GetObjectField(jTxObj, dataHashField); + struct bcos_sdk_c_bytes* dataHashStruct = convert_to_bytes_struct(env, javaDataHashObj); + if (dataHashStruct == NULL) + { + THROW_JNI_EXCEPTION(env, "exception in convert_to_bytes_struct"); + } + txStruct->data_hash = dataHashStruct; + // Signature + jobject javaSignatureObj = env->GetObjectField(jTxObj, signatureField); + struct bcos_sdk_c_bytes* signatureStruct = convert_to_bytes_struct(env, javaSignatureObj); + if (signatureStruct == NULL) + { + THROW_JNI_EXCEPTION(env, "exception in convert_to_bytes_struct"); + } + txStruct->signature = signatureStruct; + // Sender + jobject javaSenderObj = env->GetObjectField(jTxObj, senderField); + struct bcos_sdk_c_bytes* senderStruct = convert_to_bytes_struct(env, javaSenderObj); + if (senderStruct == NULL) + { + THROW_JNI_EXCEPTION(env, "exception in convert_to_bytes_struct"); + } + txStruct->sender = senderStruct; + // ImportTime + jlong importTimeValue = env->GetLongField(jTxObj, importTimeField); + txStruct->import_time = (int64_t)importTimeValue; + // Attribute + jint attributeValue = env->GetIntField(jTxObj, attributeField); + txStruct->attribute = (int32_t)attributeValue; + // ExtraData + jstring javaExtraData = (jstring)env->GetObjectField(jTxObj, extraDataField); + const char* extraDataValue = env->GetStringUTFChars(javaExtraData, NULL); + txStruct->extra_data = strdup(extraDataValue); + + env->ReleaseStringUTFChars(javaExtraData, extraDataValue); + + return txStruct; + } + catch (...) + { + return NULL; + } } void destroy_bytes_jobject(JNIEnv* env, jobject jTxBytes) @@ -302,6 +386,10 @@ Java_org_fisco_bcos_sdk_jni_utilities_tx_TransactionStructBuilderJniObj_encodeTr { struct bcos_sdk_c_transaction_data* tx_data_struct = convert_to_tx_data_struct(env, jTransactionDataObj); + if (tx_data_struct == NULL) + { + THROW_JNI_EXCEPTION(env, "exception in convert_to_tx_data_struct"); + } const char* tx_data_hex = bcos_sdk_encode_transaction_data_struct(tx_data_struct); if (!bcos_sdk_is_last_opr_success()) { @@ -334,6 +422,10 @@ Java_org_fisco_bcos_sdk_jni_utilities_tx_TransactionStructBuilderJniObj_encodeTr { struct bcos_sdk_c_transaction_data* tx_data_struct = convert_to_tx_data_struct(env, jTransactionDataObj); + if (tx_data_struct == NULL) + { + THROW_JNI_EXCEPTION(env, "exception in convert_to_tx_data_struct"); + } const char* tx_data_json = bcos_sdk_encode_transaction_data_struct_to_json(tx_data_struct); if (!bcos_sdk_is_last_opr_success()) { @@ -373,6 +465,10 @@ Java_org_fisco_bcos_sdk_jni_utilities_tx_TransactionStructBuilderJniObj_decodeTr } jobject jTxDataObj = convert_to_tx_data_jobject(env, tx_data_struct); + if (jTxDataObj == NULL) + { + THROW_JNI_EXCEPTION(env, "exception in convert_to_tx_data_jobject"); + } // release source if (tx_data_struct) @@ -395,6 +491,10 @@ Java_org_fisco_bcos_sdk_jni_utilities_tx_TransactionStructBuilderJniObj_calcTran { struct bcos_sdk_c_transaction_data* tx_data_struct = convert_to_tx_data_struct(env, jTransactionDataObj); + if (tx_data_struct == NULL) + { + THROW_JNI_EXCEPTION(env, "exception in convert_to_tx_data_struct"); + } int crypto_type = jCrytpTyte; const char* tx_data_hash = bcos_sdk_calc_transaction_data_struct_hash(crypto_type, tx_data_struct); @@ -431,6 +531,10 @@ Java_org_fisco_bcos_sdk_jni_utilities_tx_TransactionStructBuilderJniObj_createEn jint jAttribute, jstring jExtraData) { struct bcos_sdk_c_transaction_data* tx_data_struct = convert_to_tx_data_struct(env, jTxDataObj); + if (tx_data_struct == NULL) + { + THROW_JNI_EXCEPTION(env, "exception in convert_to_tx_data_struct"); + } const char* signature = env->GetStringUTFChars(jSignature, NULL); const char* tx_data_hash = env->GetStringUTFChars(jTxDataHash, NULL); int attribute = jAttribute; @@ -472,6 +576,10 @@ Java_org_fisco_bcos_sdk_jni_utilities_tx_TransactionStructBuilderJniObj_encodeTr JNIEnv* env, jclass, jobject jTransactionObj) { struct bcos_sdk_c_transaction* tx_struct = convert_to_tx_struct(env, jTransactionObj); + if (tx_struct == NULL) + { + THROW_JNI_EXCEPTION(env, "exception in convert_to_tx_struct"); + } const char* tx_hex = bcos_sdk_encode_transaction_struct(tx_struct); if (!bcos_sdk_is_last_opr_success()) { @@ -504,6 +612,10 @@ Java_org_fisco_bcos_sdk_jni_utilities_tx_TransactionStructBuilderJniObj_encodeTr JNIEnv* env, jclass, jobject jTransactionObj) { struct bcos_sdk_c_transaction* tx_struct = convert_to_tx_struct(env, jTransactionObj); + if (tx_struct == NULL) + { + THROW_JNI_EXCEPTION(env, "exception in convert_to_tx_struct"); + } const char* tx_json = bcos_sdk_encode_transaction_struct_to_json(tx_struct); if (!bcos_sdk_is_last_opr_success()) { diff --git a/bindings/java/jni/src/test/java/org/fisco/bcos/sdk/jni/test/tx/TestTxStruct.java b/bindings/java/jni/src/test/java/org/fisco/bcos/sdk/jni/test/tx/TestTxStruct.java index 1a49588c5..81c8f77d0 100644 --- a/bindings/java/jni/src/test/java/org/fisco/bcos/sdk/jni/test/tx/TestTxStruct.java +++ b/bindings/java/jni/src/test/java/org/fisco/bcos/sdk/jni/test/tx/TestTxStruct.java @@ -97,7 +97,7 @@ public static void main(String[] args) throws JniException, InterruptedException Usage(); } - String endpoint = "127.0.0.1:22200"; + String endpoint = "127.0.0.1:20200"; String group = "group0"; String node = ""; JniConfig jniConfig = Utility.newJniConfig(Arrays.asList(endpoint)); @@ -107,7 +107,7 @@ public static void main(String[] args) throws JniException, InterruptedException System.out.println("build Rpc"); rpcJniObj.start(); - boolean smCrypto = true; + boolean smCrypto = false; long keyPair = KeyPairJniObj.createJniKeyPair(smCrypto ? 1 : 0); String jniKeyPairAddress = KeyPairJniObj.getJniKeyPairAddress(keyPair); diff --git a/sample/tx/CMakeLists.txt b/sample/tx/CMakeLists.txt index 4b6e1352f..f6a8783e0 100644 --- a/sample/tx/CMakeLists.txt +++ b/sample/tx/CMakeLists.txt @@ -7,5 +7,8 @@ target_link_libraries(hello_sample_hsm PUBLIC ${BCOS_C_SDK_STATIC_TARGET}) add_executable(tx_struct_test tx_struct_test.c) target_link_libraries(tx_struct_test PUBLIC ${BCOS_C_SDK_STATIC_TARGET}) +add_executable(tx_struct_v2_test tx_struct_v2_test.c) +target_link_libraries(tx_struct_v2_test PUBLIC ${BCOS_C_SDK_STATIC_TARGET}) + # add_executable(tx_sign_perf tx_sign_perf.cpp) # target_link_libraries(tx_sign_perf PUBLIC ${BCOS_C_SDK_STATIC_TARGET}) \ No newline at end of file diff --git a/sample/tx/tx_struct_v2_test.c b/sample/tx/tx_struct_v2_test.c new file mode 100644 index 000000000..6cfea678f --- /dev/null +++ b/sample/tx/tx_struct_v2_test.c @@ -0,0 +1,479 @@ +/* + * Copyright (C) 2021 FISCO BCOS. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file tx_struct_v2_test.c + * @author: lucasli + * @date 2023-11-29 + */ +#include "bcos-c-sdk/bcos_sdk_c_error.h" +#include "bcos-c-sdk/bcos_sdk_c_rpc.h" +#include "bcos-c-sdk/bcos_sdk_c_uti_abi.h" +#include "bcos-c-sdk/bcos_sdk_c_uti_keypair.h" +#include +#include +#include +#include +#include +#include + + +#ifdef _WIN32 +#include +#else +#include +#endif + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +// HelloWorld Source Code: + +// HelloWorld Source Code: +/** +pragma solidity>=0.4.24 <0.6.11; + +contract HelloWorld { + string name; + + constructor() public { + name = "Hello, World!"; + } + + function get() public view returns (string memory) { + return name; + } + + function set(string memory n) public { + name = n; + } +} +*/ +const char* g_hw_bin = + "608060405234801561001057600080fd5b506040518060400160405280600d81526020017f48656c6c6f2c20576f72" + "6c6421000000000000000000000000000000000000008152506000908051906020019061005c929190610062565b50" + "610107565b828054600181600116156101000203166002900490600052602060002090601f01602090048101928260" + "1f106100a357805160ff19168380011785556100d1565b828001600101855582156100d1579182015b828111156100" + "d05782518255916020019190600101906100b5565b5b5090506100de91906100e2565b5090565b61010491905b8082" + "11156101005760008160009055506001016100e8565b5090565b90565b610310806101166000396000f3fe60806040" + "5234801561001057600080fd5b50600436106100365760003560e01c80634ed3885e1461003b5780636d4ce63c1461" + "00f6575b600080fd5b6100f46004803603602081101561005157600080fd5b81019080803590602001906401000000" + "0081111561006e57600080fd5b82018360208201111561008057600080fd5b80359060200191846001830284011164" + "0100000000831117156100a257600080fd5b91908080601f0160208091040260200160405190810160405280939291" + "90818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050" + "50610179565b005b6100fe610193565b60405180806020018281038252838181518152602001915080519060200190" + "80838360005b8381101561013e578082015181840152602081019050610123565b50505050905090810190601f1680" + "1561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b8060" + "00908051906020019061018f929190610235565b5050565b6060600080546001816001161561010002031660029004" + "80601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203" + "1660029004801561022b5780601f106102005761010080835404028352916020019161022b565b8201919060005260" + "20600020905b81548152906001019060200180831161020e57829003601f168201915b5050505050905090565b8280" + "54600181600116156101000203166002900490600052602060002090601f016020900481019282601f106102765780" + "5160ff19168380011785556102a4565b828001600101855582156102a4579182015b828111156102a3578251825591" + "602001919060010190610288565b5b5090506102b191906102b5565b5090565b6102d791905b808211156102d35760" + "008160009055506001016102bb565b5090565b9056fea2646970667358221220b5943f43c48cc93c6d71cdcf27aee5" + "072566c88755ce9186e32ce83b24e8dc6c64736f6c634300060a0033"; + +const char* g_hw_sm_bin = + "608060405234801561001057600080fd5b506040518060400160405280600d81526020017f48656c6c6f2c20576f72" + "6c6421000000000000000000000000000000000000008152506000908051906020019061005c929190610062565b50" + "610107565b828054600181600116156101000203166002900490600052602060002090601f01602090048101928260" + "1f106100a357805160ff19168380011785556100d1565b828001600101855582156100d1579182015b828111156100" + "d05782518255916020019190600101906100b5565b5b5090506100de91906100e2565b5090565b61010491905b8082" + "11156101005760008160009055506001016100e8565b5090565b90565b610310806101166000396000f3fe60806040" + "5234801561001057600080fd5b50600436106100365760003560e01c8063299f7f9d1461003b5780633590b49f1461" + "00be575b600080fd5b610043610179565b604051808060200182810382528381815181526020019150805190602001" + "9080838360005b83811015610083578082015181840152602081019050610068565b50505050905090810190601f16" + "80156100b05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61" + "0177600480360360208110156100d457600080fd5b81019080803590602001906401000000008111156100f1576000" + "80fd5b82018360208201111561010357600080fd5b8035906020019184600183028401116401000000008311171561" + "012557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380" + "828437600081840152601f19601f82011690508083019250505050505050919291929050505061021b565b005b6060" + "60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190" + "818152602001828054600181600116156101000203166002900480156102115780601f106101e65761010080835404" + "0283529160200191610211565b820191906000526020600020905b8154815290600101906020018083116101f45782" + "9003601f168201915b5050505050905090565b8060009080519060200190610231929190610235565b5050565b8280" + "54600181600116156101000203166002900490600052602060002090601f016020900481019282601f106102765780" + "5160ff19168380011785556102a4565b828001600101855582156102a4579182015b828111156102a3578251825591" + "602001919060010190610288565b5b5090506102b191906102b5565b5090565b6102d791905b808211156102d35760" + "008160009055506001016102bb565b5090565b9056fea26469706673582212209871cb2bcf390d53645807cbaedfe0" + "52d739ef9cff9d84787f74c4f379e1854664736f6c634300060a0033"; + +const char* g_hw_abi = + "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[]," + "\"name\":\"get\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]" + ",\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":" + "\"string\",\"name\":\"n\",\"type\":\"string\"}],\"name\":\"set\",\"outputs\":[]," + "\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"; + +/* +{ + "6d4ce63c": "get()", + "4ed3885e": "set(string)" +} + +{ + "299f7f9d": "get()", + "3590b49f": "set(string)" +} +*/ + +void usage(void) +{ + printf("Desc: tx struct v2 test sample\n"); + printf("Usage: tx_struct_v2_test \n"); + printf("Example:\n"); + printf(" ./tx_struct_v2_test ./config.ini group0\n"); + exit(0); +} + +int convertCharToHexNumber(char hexChar) { + if (hexChar >= '0' && hexChar <= '9') + return hexChar - '0'; + if (hexChar >= 'a' && hexChar <= 'f') + return hexChar - 'a' + 10; + if (hexChar >= 'A' && hexChar <= 'F') + return hexChar - 'A' + 10; + return -1; +} + +struct bcos_sdk_c_bytes* fromHexString(const char* hexedString) { + unsigned startIndex = (strlen(hexedString) >= 2 && hexedString[0] == '0' && hexedString[1] == 'x') ? 2 : 0; + struct bcos_sdk_c_bytes* bytesData = (struct bcos_sdk_c_bytes*)malloc(sizeof(struct bcos_sdk_c_bytes)); + bytesData->buffer = (uint8_t*)malloc((strlen(hexedString) - startIndex + 1) / 2); + bytesData->length = 0; + + if (strlen(hexedString) % 2) { + int h = convertCharToHexNumber(hexedString[startIndex++]); + if (h == -1) { + // Handle error + free(bytesData->buffer); + free(bytesData); + return NULL; + } + bytesData->buffer[bytesData->length++] = (uint8_t)h; + } + for (unsigned i = startIndex; i < strlen(hexedString); i += 2) { + int highValue = convertCharToHexNumber(hexedString[i]); + int lowValue = convertCharToHexNumber(hexedString[i + 1]); + if (highValue == -1 || lowValue == -1) { + // Handle error + free(bytesData->buffer); + free(bytesData); + return NULL; + } + bytesData->buffer[bytesData->length++] = (uint8_t)((highValue << 4) + lowValue); + } + return bytesData; +} + +// contract address +char* contract_address = NULL; + +// callback for rpc interfaces +void on_deploy_resp_callback(struct bcos_sdk_c_struct_response* resp) +{ + if (resp->error != BCOS_SDK_C_SUCCESS) + { + printf("\t deploy contract failed, error: %d, message: %s\n", resp->error, resp->desc); + exit(-1); + } + + const char* cflag = "contractAddress\" : \""; + // find the "contractAddress": "0xxxxx" + char* p0 = strstr((char*)resp->data, cflag); + if (p0 == NULL) + { + printf("\t cannot find the \"contractAddress\" filed, resp: %s\n", (char*)resp->data); + exit(-1); + } + + char* p1 = (char*)p0 + strlen(cflag); + char* p2 = strstr(p1, "\""); + if (p2 == NULL) + { + printf("\t cannot find the \"contractAddress\" filed, resp: %s\n", (char*)resp->data); + exit(-1); + } + + contract_address = (char*)malloc(p2 - p1 + 1); + + memcpy(contract_address, p1, p2 - p1); + contract_address[p2 - p1] = '\0'; + + printf(" [TxStructV2Test] contractAddress ===>>>>: %s\n", contract_address); + printf(" [TxStructV2Test] transaction receipt ===>>>>: %s\n", (char*)resp->data); +} + +/* resp->data 的数据结构 +{ + "id" : 2, + "jsonrpc" : "2.0", + "result" : + { + "blockNumber" : 113, + "checksumContractAddress" : "", + "contractAddress" : "", + "extraData" : "ExtraData", + "from" : "0x69df04bec1c36551be6298f7e4c2f867592a4b37", + "gasUsed" : "13063", + "hash" : "0x7d816bbde4aef3bd4c084b0887982f2c50cb9a50975a4d07328ec5fd5dd4e6e6", + "input" : "0x3590b49f0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001748656c6c6f20464953434f2d42434f5320332e30212121000000000000000000", + "logEntries" : [], + "message" : "", + "output" : "0x", + "status" : 0, + "to" : "0xcd6787f79a8da1b4a607dd59c79c7c08209230c1", + "transactionHash" : "0x05424cb9f92e1f1cd9b7ebe7a7e86d628d71c67edc6cf9cadac1967d279f8017", + "version" : 0 + } +} +*/ +void on_send_tx_resp_callback(struct bcos_sdk_c_struct_response* resp) +{ + if (resp->error != BCOS_SDK_C_SUCCESS) + { + printf("\t send tx failed, error: %d, message: %s\n", resp->error, resp->desc); + exit(-1); + } + + printf(" ===>> send tx resp: %s\n", (char*)resp->data); +} + +void on_call_resp_callback(struct bcos_sdk_c_struct_response* resp) +{ + if (resp->error != BCOS_SDK_C_SUCCESS) + { + printf("\t call failed, error: %d, message: %s\n", resp->error, resp->desc); + exit(-1); + } + + printf(" ===>> call resp: %s\n", (char*)resp->data); +} + +int main(int argc, char** argv) +{ + if (argc < 3) + { + usage(); + } + + const char* config = argv[1]; + const char* group_id = argv[2]; + + printf("[TxStructV2Test] params ===>>>> \n"); + printf("\t # config: %s\n", config); + printf("\t # group_id: %s\n", group_id); + + // const char* version = bcos_sdk_version(); + // printf("\t # c-sdk version: \n%s", version); + // bcos_sdk_c_free((void*)version); + + // 1. create sdk object by config + void* sdk = bcos_sdk_create_by_config_file(config); + // check success or not + if (!bcos_sdk_is_last_opr_success()) + { + printf( + " bcos_sdk_create_by_config_file failed, error: %s\n", bcos_sdk_get_last_error_msg()); + exit(-1); + } + + printf(" [TxStructV2Test] start sdk ... \n"); + + // 2. start bcos c sdk + bcos_sdk_start(sdk); + if (!bcos_sdk_is_last_opr_success()) + { + printf(" [TxStructV2Test] bcos_sdk_start failed, error: %s\n", bcos_sdk_get_last_error_msg()); + exit(-1); + } + + int sm_crypto = 0; + int wasm = 0; + + // 3. get sm_crypto of the group_id + bcos_sdk_get_group_wasm_and_crypto(sdk, group_id, &wasm, &sm_crypto); + if (!bcos_sdk_is_last_opr_success()) + { + printf(" [CallHello] bcos_sdk_group_sm_crypto failed, error: %s\n", + bcos_sdk_get_last_error_msg()); + exit(-1); + } + + printf(" [TxStructV2Test] sm crypto: %d\n", sm_crypto); + // 4. get chain_id of the group_id + const char* chain_id = bcos_sdk_get_group_chain_id(sdk, group_id); + if (!bcos_sdk_is_last_opr_success()) + { + printf(" [TxStructV2Test] bcos_sdk_get_group_chain_id failed, error: %s\n", + bcos_sdk_get_last_error_msg()); + exit(-1); + } + + printf(" [TxStructV2Test] chain id: %s\n", chain_id); + // 5. get blocklimit of the group_id + int64_t block_limit = bcos_rpc_get_block_limit(sdk, group_id); + if (block_limit < 0) + { + printf(" [TxStructV2Test] group not exist, group: %s\n", group_id); + exit(-1); + } + + printf(" [TxStructV2Test] block limit: %d\n", (int32_t)block_limit); + // 6. load or create keypair for transaction sign + void* key_pair = bcos_sdk_create_keypair(sm_crypto); + if (!key_pair) + { + printf(" [TxStructV2Test] create keypair failed, error: %s\n", bcos_sdk_get_last_error_msg()); + exit(-1); + } + + // printf(" [TxStructV2Test] bcos_sdk_get_keypair_type: %d\n", + // bcos_sdk_get_keypair_type(key_pair)); + + // 7. get account address of the keypair + const char* address = bcos_sdk_get_keypair_address(key_pair); + printf(" [TxStructV2Test] new account, address: %s\n", address); + + const char* extra_data = "ExtraData"; + const char* value = "33"; + const char* gasPrice = "0"; + int64_t gasLimit = 0; + const char* maxFeePerGas = "11"; + const char* maxPriorityFeePerGas = "22"; + + // printf(" [TxStructV2Test] extra_data: %s, value: %s, gasPrice: %s, gasLimit: %ld, maxFeePerGas: %s, maxPriorityFeePerGas: %s\n", extra_data, value, gasPrice, gasLimit, maxFeePerGas, maxPriorityFeePerGas); + + // 8. deploy HelloWorld contract + struct bcos_sdk_c_transaction_data_v2* transaction_data_v2_deploy = bcos_sdk_create_transaction_data_struct_with_hex_input_v2( + group_id, chain_id, "", sm_crypto ? g_hw_sm_bin : g_hw_bin, "", block_limit, value, gasPrice, gasLimit, maxFeePerGas, maxPriorityFeePerGas); + const char* transaction_data_hash_deploy = + bcos_sdk_calc_transaction_data_struct_hash_v2(sm_crypto, transaction_data_v2_deploy); + const char* signed_hash_deploy = + bcos_sdk_sign_transaction_data_hash(key_pair, transaction_data_hash_deploy); + const char* signed_tx_deploy = bcos_sdk_create_encoded_transaction_v2( + transaction_data_v2_deploy, signed_hash_deploy, transaction_data_hash_deploy, 0, extra_data); + printf(" [TxStructV2Test] create deploy contract transaction success, signed_tx_deploy: %s\n", signed_tx_deploy); + + // call rpc interface, send transaction + bcos_rpc_send_transaction(sdk, group_id, "", signed_tx_deploy, 0, on_deploy_resp_callback, NULL); + // wait for async operation done, just for sample + sleep(5); + + printf(" [TxStructV2Test] set operation\n"); + // 9. HelloWorld set + // 9.1 abi encode params + const char* set_data = + bcos_sdk_abi_encode_method(g_hw_abi, "set", "[\"Hello FISCO-BCOS 3.0!!!\"]", sm_crypto); + // 9.2 create signed transaction + { + // 9.2.1 create transaction data with hex input + struct bcos_sdk_c_transaction_data_v2* transaction_data_v2 = bcos_sdk_create_transaction_data_struct_with_hex_input_v2( + group_id, chain_id, contract_address, set_data, g_hw_abi, block_limit, value, gasPrice, gasLimit, maxFeePerGas, maxPriorityFeePerGas); + // create transaction data with bytes input + struct bcos_sdk_c_bytes* input_bytes = fromHexString(set_data); + transaction_data_v2 = bcos_sdk_create_transaction_data_struct_with_bytes_v2( + group_id, chain_id, contract_address, input_bytes->buffer, input_bytes->length, g_hw_abi, block_limit, value, gasPrice, gasLimit, maxFeePerGas, maxPriorityFeePerGas); + + // 9.2.1.1 encode tx data to hex + const char* hex_tx_data = bcos_sdk_encode_transaction_data_struct_v2(transaction_data_v2); + printf(" [TxStructV2Test] tx_data_hex: %s\n", hex_tx_data); + // 9.2.1.2 decode hex tx data + struct bcos_sdk_c_transaction_data_v2* decode_tx_data = bcos_sdk_decode_transaction_data_struct_v2(hex_tx_data); + // 9.2.1.3 encode tx data to json + const char* json_tx_data = bcos_sdk_encode_transaction_data_struct_to_json_v2(decode_tx_data); + printf(" [TxStructV2Test] tx_data_json: %s\n", json_tx_data); + // 9.2.1.4 decode json to tx data struct + decode_tx_data = bcos_sdk_decode_transaction_data_struct_with_json_v2(json_tx_data); + + // 9.2.2 calc transaction data hash + const char* transaction_data_hash = + bcos_sdk_calc_transaction_data_struct_hash_v2(sm_crypto, decode_tx_data); + printf(" [TxStructV2Test] set tx hash: %s\n", transaction_data_hash); + transaction_data_hash = bcos_sdk_calc_transaction_data_struct_hash_with_hex_v2(sm_crypto, hex_tx_data); + printf(" [TxStructV2Test] set tx hash with tx_data_hex: %s\n", transaction_data_hash); + + // 9.2.3 sign transaction hash + const char* signed_hash = + bcos_sdk_sign_transaction_data_hash(key_pair, transaction_data_hash); + + // 9.2.4 create signed transaction + const char* signed_tx = bcos_sdk_create_encoded_transaction_v2( + decode_tx_data, signed_hash, transaction_data_hash, 0, extra_data); + + // 9.2.4.1 create transaction struct + struct bcos_sdk_c_transaction_v2* transaction = bcos_sdk_create_transaction_struct_v2(decode_tx_data, + signed_hash, transaction_data_hash, 0, extra_data); + // 9.2.4.2 encode tx to hex + const char* hex_tx = bcos_sdk_encode_transaction_struct_v2(transaction); + printf(" [TxStructV2Test] tx_hex: %s\n", hex_tx); + // 9.2.4.3 decode hex to tx + struct bcos_sdk_c_transaction_v2* decode_tx = bcos_sdk_decode_transaction_struct_v2(hex_tx); + // 9.2.4.4 encode tx to json + const char* json_tx = bcos_sdk_encode_transaction_struct_to_json_v2(decode_tx); + printf(" [TxStructV2Test] tx_json: %s\n", json_tx); + // 9.2.4.5 decode json to tx + decode_tx = bcos_sdk_decode_transaction_struct_with_json_v2(json_tx); + const char* hex_tx2 = bcos_sdk_encode_transaction_struct_v2(decode_tx); + + printf(" [TxStructV2Test] signed_tx: %s\n", signed_tx); + printf(" [TxStructV2Test] hex_tx: %s\n", hex_tx); + printf(" [TxStructV2Test] hex_tx2: %s\n", hex_tx2); + + // 9.3 call rpc interface, sendTransaction + bcos_rpc_send_transaction(sdk, group_id, "", signed_tx, 0, on_send_tx_resp_callback, NULL); + + // wait for async operation done, just for sample + sleep(3); + + // free + if (input_bytes && input_bytes->buffer) + { + bcos_sdk_c_free(input_bytes->buffer); + } + bcos_sdk_destroy_transaction_data_struct_v2(transaction_data_v2); + bcos_sdk_destroy_transaction_data_struct_v2(decode_tx_data); + bcos_sdk_destroy_transaction_struct_v2(transaction); + bcos_sdk_destroy_transaction_struct_v2(decode_tx); + bcos_sdk_c_free((void*)transaction_data_hash); + bcos_sdk_c_free((void*)signed_hash); + bcos_sdk_c_free((void*)signed_tx); + bcos_sdk_c_free((void*)hex_tx_data); + bcos_sdk_c_free((void*)json_tx_data); + bcos_sdk_c_free((void*)hex_tx); + bcos_sdk_c_free((void*)json_tx); + } + + // wait for async operation done, just for sample + sleep(3); + + // free chain_id + bcos_sdk_c_free((void*)chain_id); + // free address + bcos_sdk_c_free((void*)address); + if (contract_address) + { + bcos_sdk_c_free((void*)contract_address); + } + + // stop sdk + bcos_sdk_stop(sdk); + // release sdk + bcos_sdk_destroy(sdk); + // release keypair + bcos_sdk_destroy_keypair(key_pair); + + return 0; +}