EOS な serialization を C++ と Node.js で

表題の通りのことをやります。非常に基礎的な処理なのですが、いい感じのコードが見当たらなかったので、自分でテスト用に書いたものを載っけておきます。もっとイケてる方法があったら教えてほしいです。

serialize するデータ

EOS でよく使う型を適当に組み合わせます。

typevalue
nname“motokichi”
aasset“21000000 POYO”
iuint641231006505
sstring“poyo!”
bboolfalse

C++(コントラクト側)で実行する場合

#include <eosio/asset.hpp>
#include <eosio/crypto.hpp>
#include <eosio/eosio.hpp>

using namespace eosio;

class [[eosio::contract]] test : public contract
{
  public:

    using contract::contract;

    [[eosio::action]]
    void serialize(
      const name&        n,
      const asset&       a,
      const uint64_t     i,
      const std::string& s,
      const bool         b
    ) {
      size_t size = 0;
      size += pack_size(n);
      size += pack_size(a);
      size += pack_size(i);
      size += pack_size(s);
      size += pack_size(b);

      std::vector<char> buf;
      buf.resize(size);

      datastream<char*> ds(buf.data(), buf.size());
      ds << n << a << i << s << b;

      checksum256 hashed = sha256(buf.data(), buf.size());
      print(hashed);
    };
};

EOSIO.CDT v1.7.0 でコンパイルして、jungle3 にデプロイして、serialize action を実行してみます。

$ cleos --url https://jungle3.cryptolions.io push action s11ntest1111 serialize '["motokichi", "21000000 POYO", 1231006505, "poyo!", false]' -p s11ntest1111@active
executed transaction: 3e2d76342d9ec5451bafbc001ea20b7682f359d0007920d71c1dec1f35da09ec  136 bytes  198 us
#  s11ntest1111 <= s11ntest1111::serialize      {"n":"motokichi","a":"21000000 POYO","i":1231006505,"s":"poyo!","b":0}
>> 095207f69473db5e4dd7329d3f7838bf3664a6ca9465fe6cf33e52afcf5a61ef

serialize したデータの SHA-256 ハッシュとして

095207f69473db5e4dd7329d3f7838bf3664a6ca9465fe6cf33e52afcf5a61ef

が出力されました。

Node.js(クライアント側)で実行する場合

const { Serialize }                = require('eosjs');
const ecc                          = require('eosjs-ecc');
const { TextEncoder, TextDecoder } = require('util');

const buf = new Serialize.SerialBuffer({
  textEncoder: new TextEncoder(),
  textDecoder: new TextDecoder(),
});

const n = 'motokichi';
const a = '21000000 POYO';
const i = 1231006505;
const s = 'poyo!';
const b = false;

buf.pushName(n);
buf.pushAsset(a);
buf.pushNumberAsUint64(i);
buf.pushString(s);
buf.push(b);

const hashed = ecc.sha256(Buffer.from(Serialize.arrayToHex(buf.asUint8Array()), 'hex'), null);
console.log(hashed.toString('hex'));

実行してみます。

$ node serialization.js
095207f69473db5e4dd7329d3f7838bf3664a6ca9465fe6cf33e52afcf5a61ef

コントラクト上で実行したときと同様の結果となりました。

おしまい。

comments powered by Disqus