Eos: Suggestion to provide hex encoding/decoding of hash checksums.

Created on 11 Jun 2018  路  4Comments  路  Source: EOSIO/eos

It would be great to be able to safely encode/decode hash checksums within EOS smart contracts.

Here's a reference implementation for decoding a hex string into checksum256:

checksum256 decode_checksum(string hex)
{
    checksum256 buffer;

    int index = 0;
    while (index < hex.length()) {
        char c = hex[index];

        int value = 0;
        if (c >= '0' && c <= '9')
            value = (c - '0');
        else if (c >= 'A' && c <= 'F')
            value = (10 + (c - 'A'));
        else if (c >= 'a' && c <= 'f')
            value = (10 + (c - 'a'));

        buffer.hash[(index / 2)] += value << (((index + 1) % 2) * 4);
        index++;
    }

    return buffer;
}
needs review

Most helpful comment

The idea is great, but fails in some cases, for example:
input:
0D3B623F48B8061E026DD7A0D757A8A18B2A24A474BDB0C21B742EB6EE44C288
output:
0D3B623F48582CBB026DD7A0D757A8A18B2A24A474BDB0C21B742EB6EE44C288

My suggestion already using v1.3:

uint8_t from_hex(char c) {
    if (c >= '0' && c <= '9') return c - '0';
    if (c >= 'a' && c <= 'f') return c - 'a' + 10;
    if (c >= 'A' && c <= 'F') return c - 'A' + 10;
    eosio_assert(false, "Invalid hex character");
    return 0;
}

size_t from_hex(const std::string& hex_str, char* out_data, size_t out_data_len) {
    auto i = hex_str.begin();
    uint8_t* out_pos = (uint8_t*)out_data;
    uint8_t* out_end = out_pos + out_data_len;
    while (i != hex_str.end() && out_end != out_pos) {
        *out_pos = from_hex((char)(*i)) << 4;
        ++i;
        if (i != hex_str.end()) {
            *out_pos |= from_hex((char)(*i));
            ++i;
        }
        ++out_pos;
    }
    return out_pos - (uint8_t*)out_data;
}

capi_checksum256 hex_to_sha256(const std::string& hex_str) {
    eosio_assert(hex_str.length() == 64, "invalid sha256");
    capi_checksum256 checksum;
    from_hex(hex_str, (char*)checksum.hash, sizeof(checksum.hash));
    return checksum;
}

All 4 comments

it is not work.
when i use testhash(checksum256 memo), it is work fine.

The idea is great, but fails in some cases, for example:
input:
0D3B623F48B8061E026DD7A0D757A8A18B2A24A474BDB0C21B742EB6EE44C288
output:
0D3B623F48582CBB026DD7A0D757A8A18B2A24A474BDB0C21B742EB6EE44C288

My suggestion already using v1.3:

uint8_t from_hex(char c) {
    if (c >= '0' && c <= '9') return c - '0';
    if (c >= 'a' && c <= 'f') return c - 'a' + 10;
    if (c >= 'A' && c <= 'F') return c - 'A' + 10;
    eosio_assert(false, "Invalid hex character");
    return 0;
}

size_t from_hex(const std::string& hex_str, char* out_data, size_t out_data_len) {
    auto i = hex_str.begin();
    uint8_t* out_pos = (uint8_t*)out_data;
    uint8_t* out_end = out_pos + out_data_len;
    while (i != hex_str.end() && out_end != out_pos) {
        *out_pos = from_hex((char)(*i)) << 4;
        ++i;
        if (i != hex_str.end()) {
            *out_pos |= from_hex((char)(*i));
            ++i;
        }
        ++out_pos;
    }
    return out_pos - (uint8_t*)out_data;
}

capi_checksum256 hex_to_sha256(const std::string& hex_str) {
    eosio_assert(hex_str.length() == 64, "invalid sha256");
    capi_checksum256 checksum;
    from_hex(hex_str, (char*)checksum.hash, sizeof(checksum.hash));
    return checksum;
}

Very odd that there's no constructor.
Here's my version for v1.6 in which checksum256 is composed of two int128_t

    /* Convert a SHA256 sum (given as a string) to checksum256 object */
    bool hex2bin(const std::string& in, checksum256 &out)
    {
        if (in.size() != 64)
            return false;

        std::string hex{"0123456789abcdef"};
        for (int i = 0; i < 32; i++) {
            auto d1 = hex.find(in[2*i]);
            auto d2 = hex.find(in[2*i+1]);
            if (d1 == std::string::npos || d2 == std::string::npos)
                return false;

            // checksum256 is composed of little endian int128_t
            reinterpret_cast<char *>(out.data())[i/16*16 + 15-(i%16)] = (d1 << 4)  + d2;
        }
        return true;
    }

In order to focus our efforts on issues that are currently creating difficulty for the community we are closing tickets that were created prior to the EOSIO 2.0 release. If you believe this issue is still relevant please feel free to reopen it or create a new one. Thank you for your continued support of EOSIO!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

yashbhavsar007 picture yashbhavsar007  路  3Comments

williamleecn picture williamleecn  路  3Comments

toonsevrin picture toonsevrin  路  3Comments

Npizza picture Npizza  路  3Comments

chanwitkepha picture chanwitkepha  路  3Comments