Skip to content

Instantly share code, notes, and snippets.

@Semisol
Created May 7, 2024 16:27
Show Gist options
  • Save Semisol/cecfded3eab9497bc56142724add1c3c to your computer and use it in GitHub Desktop.
Save Semisol/cecfded3eab9497bc56142724add1c3c to your computer and use it in GitHub Desktop.

Binary encoding for Nostr events

Definitions

All integers are little endian.

Bit ranges are inclusive and start from the least significant bit.

Event

An event is divided into 4 segments:

Header segment

The header segment is a 64 bit integer that defines the event version and length.

Fixed-size segment

This size of this segment is fixed and contains information such as the event kind, and a pointer to the content in the data segment.

Data segment

This segment contains data that is referenced.

A pointer to the data segment is a 64 bit integer with the most significant 32 bits representing the offset, and the least significant 32 bits representing the length in bytes.

The offset MUST be aligned to 8 bytes and the base is assumed to be the start of the data segment.

Multiple pointers MAY point to the same data segment.

ID/Signature segment

The size of this segment is fixed, and the size varies depending on the version.

Event header

The header is a single 64-bit integer, with the bits 0..31 containing the length of the entire event in bytes, excluding the signature segment. The bits 32..47 contain the version, and 48..63 are reserved.

v0 and v1 event encodings

Fixed-size segment

The fixed-size segment is 64 bytes.

  • Bytes 0..31 contain the public key of the author.
  • Bytes 32..39 contain the event kind as a 64-bit unsigned integer.
  • Bytes 40..47 contain the event timestamp in ms as a 64-bit signbed integer as an offset from the unix epoch.
  • Bytes 48..55 contain a pointer to the content.
  • Bytes 56..63 contain a pointer to the event tags table. The length of this pointer MUST be divisible by 8.

Data segment

Event content

This is encoded literally.

Tags table

The tags table is a list of pointers to tags. The amount of entries is determined by the length specified by the pointer to this table.

Tag

A tag is a list of pointers to the string values comprising each tag. The amount of entries is determined by the length specified by the pointer to this tag.

ID/Signature segment

This segment is 96 bytes, with bytes 0..31 representing the ID, and bytes 32..95 representing the signature.

Signing

For version 0 events, the event must be converted into the NIP-01 format then hashed with SHA256 for the ID. For version 1 events, the entire event, excluding the ID/signature segment, must be hashed with SHA256 for the ID.

All events are signed with the ID as the hash using secp256k1.

v0 event restrictions

  • All timestamps must be aligned to 1 second
  • All values in tags and the content must be UTF-8
  • Kinds must be below 65536
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment