Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Created two cmd line utilities for converting between hex and json #16

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
6 changes: 6 additions & 0 deletions tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,11 @@ find_package(Threads)
add_executable(name name.cpp)
target_link_libraries(name abieos ${CMAKE_THREAD_LIBS_INIT})

add_executable(generate_hex_from_json util_generate_hex_from_json.cpp ../src/abieos.cpp)
ericpassmore marked this conversation as resolved.
Show resolved Hide resolved
target_link_libraries(generate_hex_from_json abieos ${CMAKE_THREAD_LIBS_INIT})

add_executable(generate_json_from_hex util_generate_json_from_hex.cpp ../src/abieos.cpp)
target_link_libraries(generate_json_from_hex abieos ${CMAKE_THREAD_LIBS_INIT})

add_custom_command( TARGET name POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink $<TARGET_FILE:name> ${CMAKE_CURRENT_BINARY_DIR}/name2num )
add_custom_command( TARGET name POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink $<TARGET_FILE:name> ${CMAKE_CURRENT_BINARY_DIR}/num2name )
102 changes: 102 additions & 0 deletions tools/test_utils.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/usr/bin/env bash

Transaction_ABI="https://raw.githubusercontent.com/eosnetworkfoundation/mandel-eosjs/main/src/transaction.abi.json"
ericpassmore marked this conversation as resolved.
Show resolved Hide resolved

######################################
PREFIX="Hex from JSON:"
if [ -f ../build/tools/generate_hex_from_json ]; then
# no args test ###############
if ../build/tools/generate_hex_from_json 2>>/dev/null ; then
echo "error: no arguments and still success ../build/tools/generate_hex_from_json"
exit 1
fi
echo "${PREFIX} Passed No Args Test"

# download ABI ################
curl ${Transaction_ABI} --output ../test/transaction.abi.json 2>>/dev/null
# Bool test ###################
true_byte=$(../build/tools/generate_hex_from_json -f ../test/transaction.abi.json -x bool -j true)
if [ "${true_byte}" != "01" ] ; then
echo "error: ${PREFIX} expected byte 01 from bool true but got ${true_byte}"
exit 1
fi
echo "${PREFIX} Passed Bool Test"

# Int test ####################
two_byte=$(../build/tools/generate_hex_from_json -f ../test/transaction.abi.json -x int8 -j 2)
if [ "${two_byte}" != "02" ] ; then
echo "error: ${PREFIX} expected byte 02 from 2 int8 but got ${two_byte}"
exit 1
fi
echo "${PREFIX} Passed Int8 as 2 Test"
# Int test ####################
neg_two_byte=$(../build/tools/generate_hex_from_json -f ../test/transaction.abi.json -x int8 -j -2)
if [ "${neg_two_byte}" != "FE" ] ; then
echo "error: ${PREFIX} expected byte FE from -2 int8 but got ${neg_two_byte}"
exit 1
fi
echo "${PREFIX} Passed Int8 as -2 Test"
# name test ###################
name_byte=$(../build/tools/generate_hex_from_json -f ../test/transaction.abi.json -x name -j '"bigliontest1"')
if [ "${name_byte}" != "103256795217993B" ] ; then
echo "error: ${PREFIX} expected byte 103256795217993B from name but got ${neg_two_byte}"
exit 1
fi
echo "${PREFIX} Passed Name Test"
else
echo "Not Found ../build/tools/generate_hex_from_json"
exit 1
fi


###################################################


PREFIX="JSON from HEX:"
if [ -f ../build/tools/generate_json_from_hex ]; then
# no args test ###############
if ../build/tools/generate_json_from_hex 2>>/dev/null ; then
echo "error: no arguments and still success ../build/tools/generate_json_from_hex"
exit 1
fi
echo "${PREFIX} Passed No Args Test"

# download ABI ##################
curl ${Transaction_ABI} --output ../test/transaction.abi.json 2>>/dev/null
# Bool test #####################
true_byte=$(../build/tools/generate_json_from_hex -f ../test/transaction.abi.json -x bool -h 01)
if [ "${true_byte}" != "true" ] ; then
echo "error: ${PREFIX} expected true from bool 01 but got ${true_byte}"
exit 1
fi
echo "${PREFIX} Passed Bool Test"

# Int test #####################
two_byte=$(../build/tools/generate_json_from_hex -f ../test/transaction.abi.json -x int8 -h 02)
if [ "${two_byte}" != "2" ] ; then
echo "error: ${PREFIX} expected 2 from 02 int8 but got ${two_byte}"
exit 1
fi
echo "${PREFIX} Passed Int8 as 02 Test"
# Int test #####################
neg_two_byte=$(../build/tools/generate_json_from_hex -f ../test/transaction.abi.json -x int8 -h FE)
if [ "${neg_two_byte}" != "-2" ] ; then
echo "error: ${PREFIX} expected -2 from FE int8 but got ${neg_two_byte}"
exit 1
fi
echo "${PREFIX} Passed Int8 as FE Test"
# name test #####################
name_byte=$(../build/tools/generate_json_from_hex -f ../test/transaction.abi.json -x name -h 103256795217993B)
if [ "${name_byte}" != '"bigliontest1"' ] ; then
echo "error: ${PREFIX} expected \"bigliontest1\" from name but got ${neg_two_byte}"
exit 1
fi
echo "${PREFIX} Passed Name Test"
else
echo "Not Found ../build/tools/generate_json_from_hex"
exit 1
fi

# clean up
[ -f ../test/transaction.abi.json ] && rm ../test/transaction.abi.json
echo "Success all tests passed"
148 changes: 148 additions & 0 deletions tools/util_generate_hex_from_json.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
//
// Created by Eric Passmore on 1/14/23.
ericpassmore marked this conversation as resolved.
Show resolved Hide resolved
// Purpose: command line option to generate hex code from JSON
// may be used to generate serialization tests cases in other languages and external packages
//

#include "../src/abieos.h"
ericpassmore marked this conversation as resolved.
Show resolved Hide resolved
#include <filesystem>
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <unistd.h>
#include <vector>

// Main work done here four steps
// 1) create empty context
// 2) set the context
// 3) parse json to binary
// 4) create hex from bin
// abiContractName: enum with contract names
// schema: the name of the data type or reference to schema in the ABI contract
// json: the name and values
// verbose: flag to print out step by step messages
std::string generate_hex_from_json(const char *abi_definition, const char *contract_name, const char *schema, const char *json, bool verbose) {
if (verbose) std::cerr << "Schema is: " << schema << " and json is " << json << std::endl << std::endl;

// create empty context
abieos_context_s *context = abieos_create();
ericpassmore marked this conversation as resolved.
Show resolved Hide resolved
if (! context) throw std::runtime_error("unable to create context");
if (verbose) std::cerr << "step 1 of 4: created empty ABI context" << std::endl;

// set the transaction context.
// first get the contract_id
uint64_t contract_id = abieos_string_to_name(context, contract_name);
if (contract_id == 0) {
std::cerr << "Error: abieos_string_to_name " << abieos_get_error(context) << std::endl;
throw std::runtime_error("unable to set context");
}
// use our id and set the ABI
bool successSettingAbi = abieos_set_abi(context, contract_id, abi_definition);
if (! successSettingAbi) {
std::cerr << "Error: abieos_set_abi " << abieos_get_error(context) << std::endl;
throw std::runtime_error("unable to set context");
}
if (verbose) std::cerr << "step 2 of 4: established context for transactions, packed transactions, and state history" << std::endl;

// convert from json to binary. binary stored with context
// get contract id returns integer for the ABI contract we passed in by name
bool successJsonToBin = abieos_json_to_bin_reorderable(
context,
contract_id,
schema,
json
);
if (!successJsonToBin) {
std::cerr << "failed in step 3: using context " << contract_name << std::endl;
throw std::runtime_error(abieos_get_error(context));
}
if (verbose) std::cerr << "step 3 of 4: completed parsing json to binary" << std::endl;

// now time to return the hex string
std::string hex = abieos_get_bin_hex(context);
if (verbose) std::cerr << "step 4 of 4: converted binary to hex" << std::endl << std::endl;
return hex;
}

// prints usage
void help(const char* exec_name) {

std::cerr << "Usage " << exec_name << ": -f -j JSON -x type [-v]" << std::endl;
std::cerr << "\t-f file with ABI definition" << std::endl;
std::cerr << "\t-v verbose, print out steps" << std::endl;
std::cerr << "\t-j json: string to convert to hex" << std::endl;
std::cerr << "\t-x type: a specific data type or schema section (example uint16, action, name, uint8[])" << std::endl;
std::cerr << "\texample: generate_hex_from_json -f ./transaction.abi -x bool -j true" << std::endl << std::endl;
}

// reads file returning string of contents
std::string retrieveFileContents(const std::string &filename ) {
try {
std::ifstream ifs(filename, std::ios::in);
std::string string_of_file_contents((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
return string_of_file_contents;
} catch(std::filesystem::filesystem_error const& ex) {
std::cerr << "unable to read ABI file at path: " << filename << std::endl;
exit(EXIT_FAILURE);
}
}

int main(int argc, char *argv[]) {
// static string for our contract id
static const char *contract_name = "eosio";
// input string to transform to hex code
std::string json;
// schema name ex: bool
std::string type;
// hex value returned ex: 01
std::string hex;
// file containing ABI definition
std::string abiFileName;
// string with contents of ABI file
std::string abiDefinition;
// default verbose setting
bool verbose = false;
int opt;

try {
while ((opt = getopt(argc, argv, "vf:j:x:")) != -1) {
switch (opt) {
case 'f': abiFileName = optarg; break;
case 'v': verbose = true; break;
case 'j': json = optarg; break;
case 'x': type = optarg; break;
case '?':
exit(EXIT_FAILURE);
default:
exit(EXIT_FAILURE);
}
}

// check for required params
if (json.empty() || type.empty() || abiFileName.empty()) {
help(*argv);
exit(EXIT_FAILURE);
}

// this is an important step
// here we grab the ABI definition and stuff it in a string
abiDefinition = retrieveFileContents(abiFileName);

hex = generate_hex_from_json(
abiDefinition.c_str(),
contract_name,
type.c_str(),
json.c_str(),
verbose
);
if (hex.length() > 0) {
std::cout << hex << std::endl;
} else {
std::cerr << "no json value" << std::endl;
}
return 0;
} catch (std::exception& e) {
std::cerr << "no json value: error " << e.what() << std::endl;
ericpassmore marked this conversation as resolved.
Show resolved Hide resolved
return 1;
}
}
Loading