6

When reading operations from a block, implicit accounts and contracts are returned with a key bytes and in hexadecimal format.

"parameters": {
    "entrypoint": "transfer",
    "value": {
      "prim": "Pair",
      "args": [
        {
          "bytes": "0000861299624c9a3b52be10762c64bac282b1c02316"
        },
        {
          "prim": "Pair",
          "args": [
            {
              "bytes": "0139c8ade2617663981fa2b87592c9ad92714d14c200"
            },
            {
              "int": "11446"
            }
          ]
        }
      ]
    }
  }

There are few details here:

  007-PsDELPH1.contract_id (22 bytes, 8-bit tag)
  **********************************************
  Implicit (tag 0)
  ================

  +---------------------------+----------+------------------------+
  | Name                      | Size     | Contents               |
  +===========================+==========+========================+
  | Tag                       | 1 byte   | unsigned 8-bit integer |
  +---------------------------+----------+------------------------+
  | Signature.Public_key_hash | 21 bytes | $public_key_hash       |
  +---------------------------+----------+------------------------+

  Originated (tag 1)
  ==================

  +---------------+----------+------------------------+
  | Name          | Size     | Contents               |
  +===============+==========+========================+
  | Tag           | 1 byte   | unsigned 8-bit integer |
  +---------------+----------+------------------------+
  | Contract_hash | 20 bytes | bytes                  |
  +---------------+----------+------------------------+
  | padding       | 1 byte   | padding                |
  +---------------+----------+------------------------+
  public_key_hash (21 bytes, 8-bit tag)
  *************************************

  public_key_hash (21 bytes, 8-bit tag)
  *************************************

  Ed25519 (tag 0)
  ===============

  +-------------------------+----------+------------------------+
  | Name                    | Size     | Contents               |
  +=========================+==========+========================+
  | Tag                     | 1 byte   | unsigned 8-bit integer |
  +-------------------------+----------+------------------------+
  | Ed25519.Public_key_hash | 20 bytes | bytes                  |
  +-------------------------+----------+------------------------+


  Secp256k1 (tag 1)
  =================

  +---------------------------+----------+------------------------+
  | Name                      | Size     | Contents               |
  +===========================+==========+========================+
  | Tag                       | 1 byte   | unsigned 8-bit integer |
  +---------------------------+----------+------------------------+
  | Secp256k1.Public_key_hash | 20 bytes | bytes                  |
  +---------------------------+----------+------------------------+


  P256 (tag 2)
  ============

  +----------------------+----------+------------------------+
  | Name                 | Size     | Contents               |
  +======================+==========+========================+
  | Tag                  | 1 byte   | unsigned 8-bit integer |
  +----------------------+----------+------------------------+
  | P256.Public_key_hash | 20 bytes | bytes                  |
  +----------------------+----------+------------------------+

But I am still unclear what these bytes are (b58?) and what the next steps are to convert them to KT1 or tz1.

2 Answers 2

7

Those 22 bytes are:

  • 2 bytes - encoded prefix (tz1, tz2, tz3, KT1);
  • 20 bytes - depending on the address type:
    • for tz-addresses it's public key hash;
    • for KT-addresses it's hash of the origination operation (see details in @enforser's answer).

Here is a code on C#, I believe you will understand it :)

var bytes = Hex.Parse("0000861299624c9a3b52be10762c64bac282b1c02316");
            
var prefix = (bytes[0], bytes[1], bytes[21]) switch
{
    (0, 0, _) => new byte[] { 6, 161, 159 }, // tz1
    (0, 1, _) => new byte[] { 6, 161, 161 }, // tz2
    (0, 2, _) => new byte[] { 6, 161, 164 }, // tz3
    (1, _, 0) => new byte[] { 2, 90, 121 }   // KT1
};

var pkh = bytes[0] == 0 ? bytes[2..22] : bytes[1..21];

var address = Base58.Convert(pkh, prefix); // tz1XrwX7i9Nzh8e6UmG3VnFkAeoyWdTqDf3U
6
  • in this example, which hash function do you run the value 861299624c9a3b52be10762c64bac282b1c02316 through to receive XrwX7i9Nzh8e6UmG3VnFkAeoyWdTqDf3U in return?
    – 0x10
    May 19, 2022 at 8:42
  • this is a bit misleading - according to tezos.stackexchange.com/a/4227/7981 the bytes are not actually a hash
    – 0x10
    May 26, 2022 at 5:35
  • @0x10 nothing misleading, the bytes itself are a hash. The question you mentioned is about different thing
    – Groxan
    May 26, 2022 at 18:26
  • 1
    @0x10 answering the first question, you can't use just the part of bytes 861299624c9a3b52be10762c64bac282b1c02316, but all the bytes{prefix}861299624c9a3b52be10762c64bac282b1c02316. If you read the snippet, you will see that base58 is used for encoding.
    – Groxan
    May 26, 2022 at 18:28
  • 1
    @0x10 yes, those 20 bytes are an address. And an address is a public key hash. It looks like this: 32/33 bytes public key -> blake2b -> 20 bytes address -> base58 -> tz-string address
    – Groxan
    May 27, 2022 at 12:01
3

Something to note from the accepted answer is that the KT1 addresses do not have a "public key hash". The hash used there is the blake2b 20 byte digest hash of the operation group hash and the index of the origination operation within that group that created the address.

More details here: https://tezos.stackexchange.com/a/2270/5435.

@Groxan is right that it can be computed in the same way in this context, just the words used to describe the parts of the address are a bit misleading in this case. Only addresses which have a corresponding private and public key may have a public key hash (tz addresses for Tezos).

Would have replied to the answer directly but I don't meet the points required to comment yet :)

1
  • 1
    Reasonable note. I've corrected my answer, thanks!
    – Groxan
    Dec 13, 2020 at 23:24

Your Answer

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

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