Skip to main content

Generic Transaction Protocol (GTX)

Generic Transaction Protocol (GTX) is a protocol that's built on top of Generic Transfer Value (GTV), specifically focusing on how to encode transactions in a way that Postchain can comprehend.

Postchain uses GTX for sending and receiving transactions. It's not recommended to use GTV directly, even though it's possible to construct various Rell types directly into GTV.

GTX transaction format has the following features:

  • The format is based on ASN.1 DER serialization (standardized by ITU-T, ISO, IEC)
  • Has native support for multi-signature
  • Has native support for atomic transactions

GTX transaction consists of one or more operations; its name and list of arguments define each operation. For example, one transaction might encode two operations:

 issue(<Alice account ID>, 1000, USD)
transfer(<Alice account ID>, <Bob account ID>, 100, USD)

This looks similar to making function calls, so GTX operations can be understood as a kind of RPC, where the client submits calls (operations) to be performed on the server (network of Postchain nodes). GTX transaction is a batch of such operations signed by clients who wish to perform them. Usually, operations update the database, but they might only perform checks. GTX transaction is atomic; all operations succeed or fail as a whole.

GtxMessages DEFINITIONS ::= BEGIN

IMPORTS RawGtv FROM GtvMessages;

-- All types are using the same tags as RawGtv to make gtv<->gtx encoding equivalent

-- Gtx operation
-- [ string, [ gtv ] ]
RawGtxOp ::= [5] EXPLICIT SEQUENCE {
name [2] EXPLICIT UTF8String, -- RawGtv { string } --
args [5] EXPLICIT SEQUENCE OF RawGtv -- RawGtv { array } --
}

-- Gtx Body
-- [ bytearray, [ gtxOp ], [ bytearray ] ]
RawGtxBody ::= [5] EXPLICIT SEQUENCE {
blockchainRid [1] EXPLICIT OCTET STRING, -- RawGtv { bytearray } --
operations [5] EXPLICIT SEQUENCE OF RawGtxOp,
signers [5] EXPLICIT SEQUENCE OF [1] EXPLICIT OCTET STRING -- RawGtv { bytearray} --
}

-- Gtx
-- [ gtxBody, [ bytearray] ]
RawGtx ::= [5] EXPLICIT SEQUENCE {
body RawGtxBody,
signatures [5] EXPLICIT SEQUENCE OF [1] EXPLICIT OCTET STRING -- RawGtv { bytearray } --
}
END

Generic Transfer Value (GTV)

Generic Transfer Value (GTV) is a general-purpose protocol for sending and decoding any data structure in a way that postchain can understand it.

GTV is used to express data in:

  • Primitive types (integers, strings, byte arrays, etc.)
  • Complex types (only array and dictionary)

GTV gets converted to ASN.1 DER when it's sent.

GtvMessages DEFINITIONS ::= BEGIN

DictPair ::= SEQUENCE {
name UTF8String,
value RawGtv
}

RawGtv ::= CHOICE {
null [0] NULL,
byteArray [1] OCTET STRING,
string [2] UTF8String,
integer [3] INTEGER,
dict [4] SEQUENCE OF DictPair,
array [5] SEQUENCE OF RawGtv,
bigInteger [6] INTEGER
}

END

Type conversions

Here's a table to visualize the type conversions in the Rell backend to its corresponding GTV types when inserting into and querying them.

Rell typeOperation inputQuery inputQuery output
entityGtvIntegerGtvIntegerGtvInteger
enumGtvIntegerGtvInteger (can be GtvString)GtvString
structGtvArrayGtvArray (can be GtvDict)GtvDict
integerGtvIntegerGtvIntegerGtvInteger
big_integerGtvBigIntegerGtvBigIntegerGtvBigInteger
decimalGtvStringGtvStringGtvString
booleanGtvIntegerGtvIntegerGtvInteger
rowidGtvIntegerGtvIntegerGtvInteger
jsonGtvStringGtvStringGtvString
textGtvStringGtvStringGtvString
byte_arrayGtvByteArrayGtvByteArrayGtvByteArray
nullableGtvNull or typeGtvNull or typeGtvNull or type
collectionGtvArrayGtvArrayGtvArray
text mapGtvDictGtvDictGtvDict
non-text map (e.g., [[k1, v1], [k2, v2], ...])GtvArrayGtvArrayGtvArray
named tuple (e.g., (x = 1, y = 2, z = 3))GtvDictGtvDictGtvDict
unnamed tuple (e.g., (1, 2, 3))GtvArrayGtvArrayGtvArray

Strict type conversion

Since Rell Version 0.13.9 the default behavior of GTV type conversion have changed, from non-strict to strict. The following table highlights how this affects how operation arguments gets parsed.

Operation input Rell typeTypes accepted in strictTypes accepted in non-strict
byte_arrayGtvByteArrayGtvByteArray
GtvString
integerGtvIntegerGtvInteger
GtvBigInteger
big_integerGtvBigIntegerGtvBigInteger
GtvInteger
decimalGtvStringGtvString
GtvInteger
GtvBigInteger
rowidGtvIntegerGtvInteger
GtvBigInteger

Next up

Next, we'll look at how all the technology described so far comes together to form a platform for dapp developers. We'll explore the different parts of a dapp on Chromia and how you, as a developer, can get started quickly and easily.