Skip to content

Important Notice:

This is a Working Draft of the DATEX Specification. This is document is work in progress and may change at any time. It is not intended to be used for production purposes.

9 Structure of a DATEX Block

9.1 Overview

A DATEX Block consists of 4 main sections:

  • A Routing Header, which mainly contains information about the sender and receivers of the block, and important information about the block (e.g. block size)
  • A Signature, if the block is signed. Everything after this section (Header and Body) is signed by the sender and can also optionally be encrypted
  • A Block Header, which contains meta data about the current block (type, timestamp, id, flags)
  • A Body, which contains executable DATEX instructions

9.2 The Routing Header

The Routing Header is not encrypted or signed, the content always needs to be parseable by all nodes.

NameStartEndSizeContentDescription
Magic Number02201 64Fixed value (0x01 and 'd')
Version Number231
VERSION: Uint8
Version number starting from 0x01
Block Size352
SIZE: Uint16
Total block size in bytes
TTL561
TTL: Uint8
Time-to-live for this block, get decremented with each node redirection
Priority671
PRIORITY: Uint8
Routing priority of this block
Signed / Encrypted781
SECURITY: Uint8
0x00: not signed or encrypted, 0x01: signed, 0x02: encrypted, 0x03: signed and encrypted
DATEX.Endpoint {
	TYPE: Uint8
	ID: Uint8[18]
	INSTANCE: Uint16
}

PointerId {
	TYPE: Uint8
	IDENTIFIER: Uint8[18]
	INSTANCE: Uint16
	TIMESTAMP: Uint32 # unix ts in seconds, starting from 25. Juli 23
	COUNTER: Uint8
}

ReceiverEndpoint {
	ENDPOINT: Endpoint
	optional KEY: Uint8[512] # only if Receivers.FLAGS.ENDPOINTS_HAVE_KEYS
}

ReceiverEndpoints {
	COUNT: Uint16 # if MAX, flood, no RECEIVERS
	ENDPOINTS: ReceiverEndpoint[COUNT]
}

Receivers {
	FLAGS: Uint8
		HAS_POINTER_ID:           FLAGS & 0b00000001,
		HAS_ENDPOINTS:            FLAGS & 0b00000010,
		ENDPOINTS_HAVE_KEYS:      FLAGS & 0b00000100
	optional POINTER_ID: PointerId
	optional ENDPOINTS: ReceiverEndpoints
}

RoutingHeader {
	MAGIC_NUMBER: Uint16 {0x01, 0x64},
	VERSION: Uint8,
	TTL: Uint8,
	FLAGS: Uint8
		HAS_UNENCRYPTED_SIGNATURE: FLAGS & 0b00000001,
		HAS_ENCRYPTION:            FLAGS & 0b00000010,
		HAS_ENCRYPTED_SIGNATURE:   FLAGS & 0b00000100,
		IS_LARGE_SIZE:             FLAGS & 0b00001000
	BLOCK_SIZE: IS_LARGE_SIZE ? Uint32 : Uint16,

	SCOPE_ID: Uint32
	BLOCK_INDEX: Uint16
	BLOCK_SUB_INDEX: Uint16

	SENDER_TYPE: Uint8,
	optional SENDER: Uint8[20] # only exists if SENDER_TYPE != 255, otherwise SENDER is @@any
	optional RECEIVERS: Receivers
}

BlockHeader {
	
	FLAGS: Uint21
		BLOCK_TYPE:    FLAGS & 0b111100000000000000000,
		ALLOW_EXECUTE: FLAGS & 0b000010000000000000000,
		END_OF_BLOCK:  FLAGS & 0b000001000000000000000, # if a subdivided block has only a single signature, it is sent with the last block containing the END_OF_BLOCK flag
		END_OF_SCOPE:  FLAGS & 0b000000100000000000000,
		HAS_EXPIRATION_TIMESTAMP:   FLAGS & 0b000000010000000000000,
		HAS_ON_BEHALF_OF:           FLAGS & 0b000000001000000000000,
		HAS_REPRESENTED_BY:         FLAGS & 0b000000000100000000000,
		IS_COMPRESSED:              FLAGS & 0b000000000010000000000,
		_RESERVED_:    FLAGS & 0b000000000001111111111,
	CREATION_TIMESTAMP: Uint43, # unix ts in ms, starting from 25. Juli 23
	optional EXPIRATION_OFFSET: Uint32, # unix ts in seconds, starting from CREATION_TIMESTAMP
	optional REPRESENTED_BY: Endpoint
	optional IV: Uint8[16]
}

DXB {
	ROUTING_HEADER: RoutingHeader,
	optional UNENCRYPTED_SIGNATURE: Uint8[192],
	optional ENCRYPTED_SIGNATURE: Uint[x] # used instead SIGNATURE to hide identity of signing endpoint (when using ON_BEHALF_OF)
	# optional start signed part:
	optional BLOCK_HEADER: BlockHeader
	# optional start encrypted part:
	ENCRYPTED_FLAGS: Uint8
		DEVICE_TYPE: ENCRYPTED_FLAGS & 0b11110000
	optional ON_BEHALF_OF: Endpoint,
	BODY: DXBBody
}

9.3 The Block Header

The Block Header is part of the signed and encrypted part. If the block is signed, the header cannot be altered, and it can't be read by non-receiving parties if the block is encrypted.

NameStartEndSizeContentDescription
Scope ID044
SID: Uint32
Scope ID, unique for a certain sender for a certain period of time
Scope Block Index462
BLOCK_INDEX: Uint16
Index of the block within the current scope
Scope Block Inc682
SIZE: Uint16
Incremented for each block of a scope
Type891
TYPE: Uint8
Block type. See Block Types
Flags9101
FLAGS: Uint8
executable, end of scope, device type
Timestamp10188
TIME: Uint64
Time in ms since 2022-01-22 (to be changed)