2

I am not able to filter a hash correctly, using get table / get_table_rows. Also I noticed that the abi is not generating a secondary index, although I am assuming this is not the problem, since anyway it is returning something.

Any tip would be appreciated. Thanks!

cleos get table testtesttest testtesttest hasher --index 2 --key-type sha256 -L 45d944598dccadd8c5a56e29c9786f05fa4b23402b735de61ce2912c86bac4de

is returning 3 rows instead of 1

{
  "rows": [{
      "id": 0,
      "owner": "test1",
      "hash": "cb285a3e234c39b13b170a4cc376bd002640f270d8219fe2c2f93d8c9c53491a",
      "tx": "e5aa66ed5b24a2c236257d79225de7d05bb85ad41181d3f4bd4a5c35e65d64f0"
    },{
      "id": 1,
      "owner": "test1",
      "hash": "45d944598dccadd8c5a56e29c9786f05fa4b23402b735de61ce2912c86bac4de",
      "tx": "388cbcb1351e17a7441be6513ab7d54d62eadcc32cdbafed22de43cf7584da60"
    },{
      "id": 2,
      "owner": "test1",
      "hash": "39b9193df3f4caf1518696ff85942b1dd40f3bbfb989d8f6703228dda8d28e54",
      "tx": "a021da6dec167cd4f1b6d4440061ab9273e159791c0d6ca106b3c7d72178c62b"
    }
  ],
  "more": false
}

Table implementation works within smartcontract (I am using the hash to check existance), but it is not working from cleos get table.

  private:
    TABLE hasher_rec
    {
        uint64_t id;
        name owner;
        capi_checksum256 hash;
        capi_checksum256 tx;

        uint64_t primary_key() const { return id; }
        fixed_bytes<32> by_hash() const { return checksum256_to_sha256(hash); } // key256 replaced with digest256 = typedef fixed_bytes<32>

        static fixed_bytes<32> checksum256_to_sha256(const capi_checksum256 &hash)
        {
            const uint64_t *p64 = reinterpret_cast<const uint64_t *>(&hash);
            return fixed_bytes<32>::make_from_word_sequence<uint64_t>(p64[0], p64[1], p64[2], p64[3]);
        }        


        EOSLIB_SERIALIZE(hasher_rec, (id)(owner)(hash)(tx))
    };
    typedef multi_index<name("hasher"), hasher_rec, 
        indexed_by<name("hash"), const_mem_fun<hasher_rec, fixed_bytes<32>, &hasher_rec::by_hash>>
        > hasher_table_type;

    hasher_table_type _hasher;

This is the abi

"tables": [
    {
        "name": "hasher",
        "type": "hasher_rec",
        "index_type": "i64",
        "key_names": [],
        "key_types": []
    }
],

I tried changing it to

"tables": [
    {
        "name": "hasher",
        "type": "hasher_rec",
        "index_type": "i64",
        "key_names": ["hash"],
        "key_types": ["sha256"]
    }
]

Thanks!

1

3 Answers 3

2

@gustavomick , I think the issue is with the way you pack key256 in checksum256_to_sha256

I tested your code with

static key256 checksum256_to_sha256(const checksum256 &hash)
{
const uint128_t *p128 = reinterpret_cast<const uint128_t *>(&hash);            
key256 k;
k.data()[0] = p128[0];
k.data()[1] = p128[1];
return k;
}

And it worked like a charm .

Here is your code refactored

include <eosiolib/eosio.hpp>

using namespace eosio;

class test256 : public contract {
    struct hasher_rec;

public:
    test256(account_name self) : contract{self}, _hasher{_self,_self} {}

    //@abi action
    void addhash(const hasher_rec &rec) {
       _hasher.emplace(_self, [&](auto &&r) { //payer = _self
           r = rec;
       });
    }
private:
    ///@abi table hasher i64
    struct hasher_rec
    {
        uint64_t id;
        name owner;
        checksum256 hash;
        checksum256 tx;

        uint64_t primary_key() const { return id; }
        key256 by_hash() const { return checksum256_to_sha256(hash); } // key256 replaced with digest256 = typedef fixed_bytes<32>

        static key256 checksum256_to_sha256(const checksum256 &hash)
        {
            const uint128_t *p128 = reinterpret_cast<const uint128_t *>(&hash);
            //return key256::make_from_word_sequence<uint64_t>(p64[0], p64[1], p64[2], p64[3]);
            key256 k;
            k.data()[0] = p128[0];
            k.data()[1] = p128[1];
            return k;
        }

        EOSLIB_SERIALIZE(hasher_rec, (id)(owner)(hash)(tx))
    };
typedef multi_index<N(hasher), hasher_rec,
        indexed_by<N(hash), const_mem_fun<hasher_rec, key256, &hasher_rec::by_hash>>
        > hasher_table_type;

    hasher_table_type _hasher;

};

EOSIO_ABI( test256, (addhash))

Commands to insert records:

cleos push action testchecksum addhash '{"rec":{"id":"0" ,"owner":"testchecksum","hash":"cb285a3e234c39b13b170a4cc376bd002640f270d8219fe2c2f93d8c9c53491a","tx":"e5aa66ed5b24a2c236257d79225de7d05bb85ad41181d3f4bd4a5c35e65d64f0"}}' -p testchecksum


cleos push action testchecksum addhash '{"rec":{"id":"1" ,"owner":"testchecksum","hash":"45d944598dccadd8c5a56e29c9786f05fa4b23402b735de61ce2912c86bac4de","tx":"388cbcb1351e17a7441be6513ab7d54d62eadcc32cdbafed22de43cf7584da60"}}' -p testchecksum


cleos push action testchecksum addhash '{"rec":{"id":"2" ,"owner":"testchecksum","hash":"39b9193df3f4caf1518696ff85942b1dd40f3bbfb989d8f6703228dda8d28e5","tx":"a021da6dec167cd4f1b6d4440061ab9273e159791c0d6ca106b3c7d72178c62b"}}' -p testchecksum

Command to read from table:

cleos get table testchecksum testchecksum  hasher --index 2 --key-type sha256 -L45d944598dccadd8c5a56e29c9786f05fa4b23402b735de61ce2912c86bac4de  -U45d944598dccadd8c5a56e29c9786f05fa4b23402b735de61ce2912c86bac4df



{
  "rows": [{
      "id": 1,
      "owner": "testchecksum",
      "hash": "45d944598dccadd8c5a56e29c9786f05fa4b23402b735de61ce2912c86bac4de",
      "tx": "388cbcb1351e17a7441be6513ab7d54d62eadcc32cdbafed22de43cf7584da60"
    }
  ],
  "more": false
}

You also need to remove old data from the table. I just removed $EOSROOT/eosio/nodeos/data

1
1
cleos get table testtesttest testtesttest hasher --index 2 --key-type sha256 -L 45d944598dccadd8c5a56e29c9786f05fa4b23402b735de61ce2912c86bac4de

This command giving you 3 rows because of usage of scope. Here i am assuming deployment account is testtesttest so scope declaration may be like this table_name taba(_self,_self.value). that's why it gives you three rows. if you change scope from only owne to between user and owner(assuming deployment account is testtesttest and user account is testuser) table_name taba(_self,_user) then you need to use to get ony one row per user.

cleos get table testtesttest testuser taba 
6
  • thanks, should not I expect 0 rows if it's out of scope? Nov 21, 2018 at 13:58
  • In addition , your id2 < id1 , so you will get 2 rows , -L is lower bound means less or equals , you need to pair it with -U flag upper bound e.g strickt greater then, so simply add -U 45d944598dccadd8c5a56e29c9786f05fa4b23402b735de61ce2912c86bac4df increment the last e to the next f that will give you exact match on your id Nov 21, 2018 at 17:11
  • thanks i think is a good call but seems not be working for me. something else seems to be happening. Nov 21, 2018 at 22:43
  • yes if it is not in scope then it will give 0 rows
    – Mr.Y
    Nov 22, 2018 at 4:36
  • @Mr.Y so there is a bug or ..? Nov 24, 2018 at 0:03
-1
#include <eosiolib/eosio.hpp>
#include <eosiolib/multi_index.hpp>

using namespace eosio;

class[[eosio::contract]] test256  : public contract
{
  struct hasher_rec;

  public:
    using contract::contract;

    test256(name self, name code, datastream<const char *> ds)  : contract(self, code, ds), _hasher(_self,_self.value) {}

    [[eosio::action]] 
     void addhash(const hasher_rec &rec) {
       _hasher.emplace(_self, [&](auto &&r) { 
           r = rec;
       });
    }

 private: 

    struct [[eosio::table]] hasher_rec {
        uint64_t id;
        name owner;
        checksum256 hash;
        checksum256 tx;

        uint64_t primary_key() const { return id; }

        key256 by_hash() const { return checksum256_to_sha256(hash); }

        static key256 checksum256_to_sha256(const checksum256 &hash)
        {
            const uint128_t *p128 = reinterpret_cast<const uint128_t *>(&hash);
            //return key256::make_from_word_sequence<uint64_t>(p64[0], p64[1], p64[2], p64[3]);
            key256 k;
            k.data()[0] = p128[0];
            k.data()[1] = p128[1];
            return k;
        }

        // EOSLIB_SERIALIZE(hasher_rec, (id)(owner)(hash)(tx))
    };

    typedef multi_index<"hasher"_n, hasher_rec,
        indexed_by<"hash"_n, const_mem_fun<hasher_rec, key256, &hasher_rec::by_hash>>
        > hasher_table_type;

    hasher_table_type _hasher;
};

EOSIO_DISPATCH(test256, (addhash))

From command line:

cleos push action testchecksum addhash '{"rec":{"id":"0" ,"owner":"testchecksum","hash":"cb285a3e234c39b13b170a4cc376bd002640f270d8219fe2c2f93d8c9c53491a","tx":"e5aa66ed5b24a2c236257d79225de7d05bb85ad41181d3f4bd4a5c35e65d64f0"}}'
-p testchecksum


cleos push action testchecksum addhash '{"rec":{"id":"1" ,"owner":"testchecksum","hash":"45d944598dccadd8c5a56e29c9786f05fa4b23402b735de61ce2912c86bac4de","tx":"388cbcb1351e17a7441be6513ab7d54d62eadcc32cdbafed22de43cf7584da60"}}'
-p testchecksum

Can retrieve all rows (no upper/lower):

dom@SCP-EOS3:~/scp-eos/contracts/eos$ cleos get table scoopowner scoopowner hasher --index 2 --key-type i256 {   "rows": [{
      "id": 1,
      "owner": "testchecksum",
      "hash": "45d944598dccadd8c5a56e29c9786f05fa4b23402b735de61ce2912c86bac4de",
      "tx": "e5aa66ed5b24a2c236257d79225de7d05bb85ad41181d3f4bd4a5c35e65d64f0"
    },{
      "id": 0,
      "owner": "testchecksum",
      "hash": "cb285a3e234c39b13b170a4cc376bd002640f270d8219fe2c2f93d8c9c53491a",
      "tx": "e5aa66ed5b24a2c236257d79225de7d05bb85ad41181d3f4bd4a5c35e65d64f0"
    }   ],   "more": false }

Cannot retrieve by upper/lower specification:

dom@SCP-EOS3:~/scp-eos/contracts/eos$ cleos get table scoopowner scoopowner hasher --index 2 --key-type sha256 -L 45d944598dccadd8c5a56e29c9786f05fa4b23402b735de61ce2912c86bac4dd -U 45d944598dccadd8c5a56e29c9786f05fa4b23 402b735de61ce2912c86bac4df {   "rows": [],   "more": false }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.