Skip to content

Thru Format (thrufmt)

View as Markdown

thrufmt is the standard human-readable form for Thru public addresses (ta…) and signatures (ts…). It defines how raw binary keys and signatures are encoded, how checksums are added, and how clients should validate them. All clients are expected to match their behavior exactly, byte-for-byte.

Use thru util convert to convert between hex and thrufmt.

Convert a 32-byte hex public key to ta…:

Terminal window
$ thru --json util convert pubkey hex-to-thrufmt \
0000000000000000000000000000000000000000000000000000000000000001
{
"hex_pubkey": "0000000000000000000000000000000000000000000000000000000000000001",
"thru_pubkey": "taAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEB"
}

Convert a 64-byte hex signature to ts…:

Terminal window
$ thru --json util convert signature hex-to-thrufmt \
0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
{
"hex_signature": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"thru_signature": "tsASNFZ4mrze8BI0VniavN7wEjRWeJq83vASNFZ4mrze8BI0VniavN7wEjRWeJq83vASNFZ4mrze8BI0VniavN7x4A"
}

Drop --json for the plain-text output. Note that inverse conversions (thrufmt-to-hex) for both addresses and signatures are also supported.

Thru streams raw bytes into a base64url encoder (RFC 4648 §5). The alphabet is:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_
  • The stream never uses padding (=).
  • Encoding starts with a two-character type prefix (ta or ts) so handles can be visually distinguished.
  • All checksums are computed on the binary payload before base64 encoding.

Encoding turns a 32-byte public key into 46 printable characters (ta + 44 base64url symbols).

  1. All buffers begin with ta to flag the string as a Thru account.
  2. Stream the 32 raw public-key bytes into the base64url accumulator, while updating a byte sum.
  3. Take the sum modulo 256 (2^8) and append the single checksum byte, giving 33 total bytes.
  4. Flush the accumulator to base64url characters without padding. Those 33 bytes always expand to 44 characters, so the finished string is 46 characters long (ta + 44 base64 symbols).
checksum = (Σ pubkey[i]) & 0xFF

Decoding recomputes the sum from the decoded 32 bytes, masks it to 8 bits, and requires it to match the appended checksum byte. Any mismatch results in a decoding error, preventing truncated or mistyped addresses from being accepted.

Encoding serializes a 64-byte Ed25519 signature into a 90-character string (ts + 88 base64url symbols).

  1. All buffers begin with ts to flag the string as a Thru signature.
  2. Stream all 64 signature bytes through the base64url accumulator, while updating a running checksum.
  3. Take the sum modulo 65,536 (2^16) and append the two checksum bytes in big-endian order. That turns the payload into 66 bytes (64 data + 2 checksum).
  4. Flush the accumulator to base64url characters. Sixty-six bytes always become 88 characters, resulting in a fixed 90-character ts… string.
checksum = (Σ signature[i]) & 0xFFFF

Decoding expects a 90-character string starting with ts. After base64url decoding it verifies the checksum word from the last two bytes before returning the 64-byte signature.