Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Create a fix to support requested encoding type in next_key #9917

Merged
merged 10 commits into from
Jan 20, 2021
155 changes: 155 additions & 0 deletions plugins/chain_plugin/chain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2408,9 +2408,164 @@ read_only::get_table_rows_result read_only::get_kv_table_rows_context( const rea
walk_table_row_range( lb_itr, ub_itr, false );
}

// Set result.next_key
set_kv_next_key(p.encode_type, index_type, result);

return result;
}

template <typename UInt, typename T>
UInt read_only::float_from_bytes(T& t, const std::string& next_key_bytes) const {
std::stringstream ss;
ss << std::hex << next_key_bytes;
UInt val;
ss >> val;
UInt mask = 0;
UInt signbit = (static_cast<UInt>(1) << (std::numeric_limits<UInt>::digits - 1));
if (!(val & signbit)) //flip mask if val is positive
mask = ~mask;
val ^=(mask | signbit);
return val;
}

template <typename T>
void read_only::convert_from_bytes( T& t, const std::string& next_key_bytes) const {
if constexpr (std::is_floating_point_v<T>) {
if constexpr (sizeof(T) == 4) {
uint32_t val = float_from_bytes<uint32_t>(t, next_key_bytes);
std::memcpy(&t, &val, sizeof(T));
}else {
static_assert(sizeof(T) == 8, "Unknown floating point type");
uint64_t val = float_from_bytes<uint64_t>(t, next_key_bytes);
std::memcpy(&t, &val, sizeof(T));
}
}else if constexpr (std::is_integral_v<T>) {
std::stringstream ss;
ss << std::hex << next_key_bytes;
auto unsigned_val = static_cast<std::make_unsigned_t<T>>(t);
kimjh2005 marked this conversation as resolved.
Show resolved Hide resolved
ss >> unsigned_val;
if (unsigned_val > std::numeric_limits<T>::max()) {
t = unsigned_val + static_cast<std::make_unsigned_t<T>>(std::numeric_limits<T>::min());
}
else {
t = unsigned_val + std::numeric_limits<T>::min();
}
}else {
EOS_ASSERT(false, chain::contract_table_query_exception, "Unsupported type to convert from bytes");
}

}
void read_only::convert_to_hex(const int& n, string& str) const {
std::stringstream ss1;
ss1<< std::hex << std::uppercase << n;
ss1 >> str;
}

void read_only::set_kv_next_key(const string& encode_type, const string& index_type, read_only::get_table_rows_result& result) const {
if (result.more == true) {
if (encode_type == "bytes") {
result.next_key = result.next_key_bytes;
}else if (encode_type == "string") {
result.next_key = boost::algorithm::unhex(result.next_key_bytes);
boost::algorithm::trim_right_if( result.next_key, []( char c ){ return c == '\0'; } );
}else if (encode_type == "name") {
std::string s = result.next_key_bytes;
brianjohnson5972 marked this conversation as resolved.
Show resolved Hide resolved
std::stringstream ss;
ss << std::hex << s;
uint64_t ull;
ss >> ull;
name nm(ull);
result.next_key = nm.to_string();
}else if (encode_type == "hex") {
if (index_type == "uint64") {
uint64_t u64;
brianjohnson5972 marked this conversation as resolved.
Show resolved Hide resolved
convert_from_bytes(u64, result.next_key_bytes);
convert_to_hex(u64, result.next_key);
}else if (index_type == "uint32") {
uint32_t u32;
convert_from_bytes(u32, result.next_key_bytes);
convert_to_hex(u32, result.next_key);
}else if (index_type == "uint16") {
uint16_t u16;
convert_from_bytes(u16, result.next_key_bytes);
convert_to_hex(u16, result.next_key);
}else if (index_type == "uint8") {
uint8_t u8;
convert_from_bytes(u8, result.next_key_bytes);
convert_to_hex(u8, result.next_key);
}else if (index_type == "int64") {
int64_t i64;
convert_from_bytes(i64, result.next_key_bytes);
convert_to_hex(i64, result.next_key);
}else if (index_type == "int32") {
int32_t i32;
convert_from_bytes(i32, result.next_key_bytes);
convert_to_hex(i32, result.next_key);
}else if (index_type == "int16") {
int16_t i16;
convert_from_bytes(i16, result.next_key_bytes);
convert_to_hex(i16, result.next_key);
}else if (index_type == "int8") {
int8_t i8;
convert_from_bytes(i8, result.next_key_bytes);
convert_to_hex(i8, result.next_key);
}else if( index_type == "sha256" || index_type == "i256" ) {
result.next_key = result.next_key_bytes;
} else if( index_type == "ripemd160" ) {
result.next_key = result.next_key_bytes;
}else {
EOS_ASSERT(false, chain::contract_table_query_exception, "Unsupported index type/encode_type: ${t}/${e} ", ("t", index_type)("e", encode_type));
brianjohnson5972 marked this conversation as resolved.
Show resolved Hide resolved
}

}else if (encode_type == "dec") {
if (index_type == "float64") {
double d;
brianjohnson5972 marked this conversation as resolved.
Show resolved Hide resolved
convert_from_bytes(d, result.next_key_bytes);
result.next_key = std::to_string(d);
}else if (index_type == "float32") {
float f;
convert_from_bytes(f, result.next_key_bytes);
result.next_key = std::to_string(f);
}else if (index_type == "uint64" ) {
uint64_t u64;
convert_from_bytes(u64, result.next_key_bytes);
result.next_key = std::to_string(u64);
}else if (index_type == "uint32") {
uint32_t u32;
convert_from_bytes(u32, result.next_key_bytes);
result.next_key = std::to_string(u32);
}else if (index_type == "uint16") {
uint16_t u16;
convert_from_bytes(u16, result.next_key_bytes);
result.next_key = std::to_string(u16);
}else if (index_type == "uint8") {
uint8_t u8;
convert_from_bytes(u8, result.next_key_bytes);
result.next_key = std::to_string(u8);
}else if (index_type == "int64") {
int64_t i64;
convert_from_bytes(i64, result.next_key_bytes);
result.next_key = std::to_string(i64);
}else if (index_type == "int32") {
int32_t i32;
convert_from_bytes(i32, result.next_key_bytes);
result.next_key = std::to_string(i32);
}else if (index_type == "int16") {
int16_t i16;
convert_from_bytes(i16, result.next_key_bytes);
result.next_key = std::to_string(i16);
}else if (index_type == "int8") {
int8_t i8;
convert_from_bytes(i8, result.next_key_bytes);
result.next_key = std::to_string(i8);
}else {
EOS_ASSERT(false, chain::contract_table_query_exception, "Unsupported index type/encode_type: ${t}/${e} ", ("t", index_type)("e", encode_type));
brianjohnson5972 marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}


struct table_receiver
: chain::backing_store::table_only_error_receiver<table_receiver, chain::contract_table_query_exception> {
table_receiver(read_only::get_table_by_scope_result& result, const read_only::get_table_by_scope_params& params)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,13 @@ class read_only {
void make_prefix(eosio::name table_name, eosio::name index_name, uint8_t status, vector<char> &prefix)const;
get_table_rows_result get_kv_table_rows( const get_kv_table_rows_params& params )const;
get_table_rows_result get_kv_table_rows_context( const read_only::get_kv_table_rows_params& p, eosio::chain::kv_context &kv_context, const abi_def &abi )const;
void set_kv_next_key(const string& encode_type, const string& index_type, read_only::get_table_rows_result& result) const;
void convert_to_hex(const int& n, string& str) const;
template <typename T>
void convert_from_bytes( T& t, const std::string& next_key_bytes)const;
template <typename UInt, typename T>
UInt float_from_bytes(T& t, const std::string& next_key_bytes)const;


struct get_table_by_scope_params {
name code; // mandatory
Expand Down
Loading