diff --git a/src/utils.cpp b/src/utils.cpp index 79d2fbd..fe72632 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1,184 +1,167 @@ -#include "ethyl/utils.hpp" - -#include -#include +#include "utils.hpp" #include #include +#include extern "C" { -#include "crypto/keccak.h" -} - -std::string utils::decimalToHex(uint64_t decimal) { - std::stringstream ss; - ss << std::hex << decimal; - return ss.str(); + #include "crypto/keccak.h" } -std::vector utils::fromHexString(std::string hex_str) { - std::vector bytes; +namespace utils { - // Check for "0x" prefix and remove it - if(hex_str.size() >= 2 && hex_str[0] == '0' && hex_str[1] == 'x') { - hex_str = hex_str.substr(2); + std::string decimalToHex(uint64_t decimal) { + std::stringstream ss; + ss << std::hex << decimal; + return ss.str(); } - for (unsigned int i = 0; i < hex_str.length(); i += 2) { - std::string byteString = hex_str.substr(i, 2); - //if (byteString[0] == 0) byteString[0] = '0'; - //if (byteString[1] == 0) byteString[1] = '0'; - unsigned char byte = static_cast(strtol(byteString.c_str(), nullptr, 16)); - bytes.push_back(byte); - } + std::vector fromHexString(const std::string& hex_str) { + size_t offset = 0; + std::string cleaned_hex; - return bytes; -} + if (hex_str.size() >= 2 && hex_str.substr(0, 2) == "0x") { + offset = 2; + } -uint64_t utils::fromHexStringToUint64(std::string hex_str) { - // Check for "0x" prefix and remove it - if(hex_str.size() >= 2 && hex_str[0] == '0' && hex_str[1] == 'x') { - hex_str = hex_str.substr(2); - } + cleaned_hex = hex_str.substr(offset); + if (cleaned_hex.length() % 2 != 0) { + throw std::invalid_argument("Hex string must have an even length"); + } - uint64_t value = std::stoull(hex_str, nullptr, 16); - return value; -} + std::vector bytes; + bytes.reserve(cleaned_hex.length() / 2); -std::array utils::fromHexString32Byte(std::string hex_str) { - std::vector bytesVec = fromHexString(hex_str); + for (size_t i = 0; i < cleaned_hex.length(); i += 2) { + unsigned char byte = static_cast(std::stoul(cleaned_hex.substr(i, 2), nullptr, 16)); + bytes.push_back(byte); + } - if(bytesVec.size() != 32) { - throw std::invalid_argument("Input string length should be 64 characters for 32 bytes"); + return bytes; } - std::array bytesArr; - std::copy(bytesVec.begin(), bytesVec.end(), bytesArr.begin()); + uint64_t fromHexStringToUint64(std::string hex_str) { + if(hex_str.size() >= 2 && hex_str[0] == '0' && hex_str[1] == 'x') { + hex_str = hex_str.substr(2); + } - return bytesArr; -} - -std::array utils::hash(std::string in) { - std::vector bytes; - - // Check for "0x" prefix and if exists, convert the hex to bytes - if(in.size() >= 2 && in[0] == '0' && in[1] == 'x') { - bytes = fromHexString(in); - in = std::string(bytes.begin(), bytes.end()); + return std::stoull(hex_str, nullptr, 16); } - std::array hash; - keccak(reinterpret_cast(in.c_str()), in.size(), hash.data(), 32); - return hash; -} -// Function to get the function signature for Ethereum contract interaction -std::string utils::getFunctionSignature(const std::string& function) { - std::array hash = utils::hash(function); + std::array fromHexString32Byte(std::string hex_str) { + std::vector bytesVec = fromHexString(hex_str); - // Convert the hash to hex string - std::string hashHex = toHexString(hash); + if(bytesVec.size() != 32) { + throw std::invalid_argument("Input string length should be 64 characters for 32 bytes"); + } - // Return the first 8 characters of the hex string (4 bytes) plus 0x prefix - return "0x" + hashHex.substr(0, 8); -} - -std::string utils::padToNBytes(const std::string& input, size_t byte_count, utils::PaddingDirection direction) { - std::string output = input; - bool has0xPrefix = false; + std::array bytesArr; + std::copy(bytesVec.begin(), bytesVec.end(), bytesArr.begin()); - // Check if input starts with "0x" prefix - if (output.substr(0, 2) == "0x") { - has0xPrefix = true; - output = output.substr(2); // remove "0x" prefix for now + return bytesArr; } - // Calculate padding size based on byteCount * 2 (since each byte is represented by 2 hex characters) - size_t targetHexStringSize = byte_count * 2; - size_t nextMultiple = (output.size() + targetHexStringSize - 1) / targetHexStringSize * targetHexStringSize; - size_t paddingSize = nextMultiple - output.size(); - std::string padding(paddingSize, '0'); + std::array hash(std::string in) { + std::vector bytes; + + if(in.size() >= 2 && in[0] == '0' && in[1] == 'x') { + bytes = fromHexString(in); + in = std::string(bytes.begin(), bytes.end()); + } - if (direction == PaddingDirection::LEFT) { - output = padding + output; - } else { - output += padding; + std::array hash; + keccak(reinterpret_cast(in.c_str()), in.size(), hash.data(), 32); + return hash; } - // If input started with "0x", add it back - if (has0xPrefix) { - output = "0x" + output; + std::string getFunctionSignature(const std::string& function) { + std::array hash = utils::hash(function); + std::string hashHex = toHexString(hash); + return "0x" + hashHex.substr(0, 8); } - return output; -} + std::string padToNBytes(const std::string& input, size_t byte_count, PaddingDirection direction) { + std::string output = input; + bool has0xPrefix = false; -std::string utils::padTo32Bytes(const std::string& input, PaddingDirection direction) { - return padToNBytes(input, 32, direction); -} + if (output.substr(0, 2) == "0x") { + has0xPrefix = true; + output = output.substr(2); + } -std::string utils::padTo8Bytes(const std::string& input, PaddingDirection direction) { - return padToNBytes(input, 8, direction); -} + size_t targetHexStringSize = byte_count * 2; + size_t nextMultiple = (output.size() + targetHexStringSize - 1) / targetHexStringSize * targetHexStringSize; + size_t paddingSize = nextMultiple - output.size(); + std::string padding(paddingSize, '0'); -std::vector utils::intToBytes(uint64_t num) { - if (num == 0) - return std::vector{}; + if (direction == PaddingDirection::LEFT) { + output = padding + output; + } else { + output += padding; + } - std::stringstream stream; - stream << std::hex << num; - std::string hex = stream.str(); - if (hex.length() % 2) { hex = "0" + hex; } + if (has0xPrefix) { + output = "0x" + output; + } - std::vector result(hex.length() / 2); - for (size_t i = 0; i < hex.length(); i += 2) { - std::string byteString = hex.substr(i, 2); - unsigned char byte = static_cast(std::stoi(byteString, nullptr, 16)); - result[i / 2] = byte; + return output; } - return result; -} + std::vector intToBytes(uint64_t num) { + if (num == 0) + return std::vector{}; -std::vector utils::removeLeadingZeros(std::vector vec) { - auto it = vec.begin(); - while(it != vec.end() && *it == 0) { - ++it; - } - vec.erase(vec.begin(), it); - return vec; -} + std::stringstream stream; + stream << std::hex << num; + std::string hex = stream.str(); + if (hex.length() % 2) { hex = "0" + hex; } -std::string utils::generateRandomString(size_t length) { - srand(static_cast(time(nullptr))); // Seed the random number generator - const char charset[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - const int64_t max_index = sizeof(charset) - 1; + std::vector result(hex.length() / 2); + for (size_t i = 0; i < hex.length(); i += 2) { + std::string byteString = hex.substr(i, 2); + unsigned char byte = static_cast(std::stoi(byteString, nullptr, 16)); + result[i / 2] = byte; + } - std::string randomString; + return result; + } - for (size_t i = 0; i < length; ++i) { - randomString += charset[static_cast(rand() % max_index)]; + std::vector removeLeadingZeros(std::vector vec) { + auto it = vec.begin(); + while(it != vec.end() && *it == 0) { + ++it; + } + vec.erase(vec.begin(), it); + return vec; } - return randomString; -} + std::string generateRandomString(size_t length) { + srand(static_cast(time(nullptr))); // Seed the random number generator + const char charset[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + const int64_t max_index = sizeof(charset) - 1; -std::string utils::trimAddress(const std::string& address) { - if (address.length() <= 42) { - // Address is already 20 bytes or shorter, no need to trim - return address; - } + std::string randomString; + for (size_t i = 0; i < length; ++i) { + randomString += charset[static_cast(rand() % max_index)]; + } - // Check if the address starts with "0x" or "0X" - if (address.substr(0, 2) != "0x" && address.substr(0, 2) != "0X") { - return address; + return randomString; } - // Find the first non-zero character after "0x" - size_t firstNonZero = address.find_first_not_of('0', 2); - if (firstNonZero == std::string::npos) { - // Address only contains zeros, return "0x" followed by 20 bytes of zero - return "0x" + std::string(40, '0'); + std::string trimAddress(const std::string& address) { + if (address.length() <= 42) { + return address; + } + + if (address.substr(0, 2) != "0x" && address.substr(0, 2) != "0X") { + return address; + } + + size_t firstNonZero = address.find_first_not_of('0', 2); + if (firstNonZero == std::string::npos) { + return "0x" + std::string(40, '0'); + } + + return "0x" + address.substr(firstNonZero, 40); } - // Trim and return the address - return "0x" + address.substr(firstNonZero, 40); -} +}