---
title: Headers and Entry Points
description: Choose the right C SDK header and understand the macros and helpers
  that define program entry.
source_url:
  html: https://thru.org/docs/sdks/c-reference/headers-and-entry-points/
  md: https://thru.org/docs/sdks/c-reference/headers-and-entry-points.md
---

# Headers and Entry Points

Use this page when you need to know which header to include, which macros are foundational, and what the public C entry surface actually is.

## Include selection

| Include | Use it when |
| - | - |
| `#include <thru-sdk/c/tn_sdk.h>` | Default starting point for almost every downstream C program. It pulls in the base macros, transaction helpers, and core runtime helpers. |
| `#include <thru-sdk/c/tn_sdk_syscall.h>` | You need explicit syscall wrappers such as account mutation, CPI, logging, event emission, or direct exit. |
| `#include <thru-sdk/c/tn_sdk_txn.h>` | You need the public struct layouts for transactions, account metadata, block context, shadow stack, or state proofs. |
| `#include <thru-sdk/c/tn_sdk_types.h>` | You only need base public types like `tn_pubkey_t`, `tn_hash_t`, or `tn_signature_t`. |
| `#include <thru-sdk/c/tn_sdk_base.h>` | You need the low-level alignment, scratch-allocation, or utility macros directly. Most programs can stay at `tn_sdk.h`. |
| `#include <thru-sdk/c/tn_sdk_sha256.h>` | You need SHA-256 hashing for address derivation, data integrity, or custom hashing logic. |
| `#include <thru-sdk/c/tn_crypto.h>` | You need BLS12-381 cryptography: key generation, signing, verification, or signature aggregation. Use it when the installed toolchain includes `libblst.a` and headers. |
| `#include <thru-sdk/c/tn_rle.h>` | You need run-length encoding for compact bitset representation (e.g., guardian sets, validator bitmaps). |

## Main entry macro

`TSDK_ENTRYPOINT_FN` marks a function as the VM entrypoint by placing it in the startup text section and marking it `noreturn`.

```c
#include <thru-sdk/c/tn_sdk.h>

TSDK_ENTRYPOINT_FN void
start( void ) {
  tsdk_return( TSDK_SUCCESS );
}
```

## Core macros

| Macro | What it does |
| - | - |
| `TSDK_ENTRYPOINT_FN` | Marks the entrypoint function. |
| `TSDK_SUCCESS` | Canonical success return code (`0UL`). |
| `TSDK_ASSERT_OR_REVERT(cond, error_code)` | Revert immediately if a required condition is false. |
| `TSDK_LOAD(T, src)` | Safely load a value of type `T` from potentially unaligned memory. |
| `TSDK_STORE(T, dst, val)` | Safely store a value of type `T` to potentially unaligned memory. |
| `TSDK_PARAM_UNUSED` | Silence unused-parameter warnings in helper functions. |
| `TSDK_LIKELY` and `TSDK_UNLIKELY` | Branch prediction hints. |
| `TSDK_LAYOUT_*` and `TSDK_SCRATCH_ALLOC_*` | Helpers for computing and carving out scratch memory regions. |

## Core runtime helpers from `tn_sdk.h`

| Helper | Purpose |
| - | - |
| `tsdk_get_txn()` | Root pointer for transaction reads. |
| `tsdk_get_account_meta(account_idx)` | Account metadata for a transaction account index. |
| `tsdk_get_account_data_ptr(account_idx)` | Raw account-data pointer for a transaction account index. |
| `tsdk_get_current_block_ctx()` | Current block context pointer. |
| `tsdk_get_past_block_ctx(blocks_in_past)` | Historical block context pointer spaced by `TSDK_BLOCK_CTX_VM_SPACING`. |
| `tsdk_get_shadow_stack()` | Shadow stack pointer for CPI and call-depth context. |
| `tsdk_printf(...)` | Format a string and emit it through `tsys_log`. |
| `tsdk_return(code)` | Exit successfully with a return code. |
| `tsdk_revert(code)` | Exit unsuccessfully with a revert code. |

## Segment and address constants

Most applications do not need to build VM addresses manually, but the SDK exposes the segment constants that back helpers like `tsdk_get_txn()` and `tsdk_get_account_meta()`:

- `TSDK_SEG_TYPE_READONLY_DATA`
- `TSDK_SEG_TYPE_ACCOUNT_METADATA`
- `TSDK_SEG_TYPE_ACCOUNT_DATA`
- `TSDK_SEG_TYPE_STACK`
- `TSDK_SEG_TYPE_HEAP`
- `TSDK_SEG_IDX_TXN_DATA`
- `TSDK_SEG_IDX_SHADOW_STACK`
- `TSDK_SEG_IDX_PROGRAM`
- `TSDK_SEG_IDX_BLOCK_CTX`

If you are not doing very low-level VM work, prefer the helper functions over manual `TSDK_ADDR(...)` usage.

## SHA-256 hashing helpers from `tn_sdk_sha256.h`

| Helper | Purpose |
| - | - |
| `tsdk_sha256_init(sha)` | Initialize a `tsdk_sha256_t` context for incremental hashing. |
| `tsdk_sha256_append(sha, data, sz)` | Append `sz` bytes to the hash context. Returns `sha` for chaining. |
| `tsdk_sha256_fini(sha, hash)` | Finalize and write the 32-byte digest to `hash`. |
| `tsdk_sha256_hash(data, sz, hash)` | One-shot: hash `sz` bytes and write the 32-byte digest to `hash`. |

```c
#include <thru-sdk/c/tn_sdk_sha256.h>

tsdk_sha256_t sha[1];
tsdk_sha256_init( sha );
tsdk_sha256_append( sha, data, data_len );
uchar hash[32];
tsdk_sha256_fini( sha, hash );
```

## BLS cryptography helpers from `tn_crypto.h`

The Thru VM machine config includes the `with-blst.mk` layer automatically. In practice, `tn_crypto.h` is available when the installed toolchain ships `libblst.a` and the matching headers.

| Helper | Purpose |
| - | - |
| `tn_crypto_generate_keypair(pubkey, private_key, seed)` | Generate a BLS keypair from a seed. |
| `tn_crypto_derive_pubkey(pubkey, private_key)` | Derive a public key from a private key. |
| `tn_crypto_sign_message(signature, message, message_len, private_key)` | Sign a message. |
| `tn_crypto_verify_signature(signature, pubkey, message, message_len)` | Verify a single signature. |
| `tn_crypto_aggregate_signatures(aggregate, sig1, sig2)` | Aggregate two signatures. |
| `tn_crypto_aggregate_pubkeys(aggregate, pk1, pk2)` | Aggregate two public keys. |
| `tn_crypto_verify_aggregate(aggregate_sig, aggregate_pk, message, message_len)` | Verify an aggregate signature. |
| `tn_crypto_serialize_pubkey(serialized, pubkey)` | Serialize a G1 pubkey to 96-byte uncompressed format. |
| `tn_crypto_deserialize_pubkey(pubkey, serialized)` | Deserialize from 96-byte uncompressed format. |
| `tn_crypto_serialize_signature(serialized, signature)` | Serialize a G2 signature to 192-byte uncompressed format. |
| `tn_crypto_deserialize_signature(signature, serialized)` | Deserialize from 192-byte uncompressed format. |

All functions return `TN_CRYPTO_SUCCESS` (0) on success or a negative error code.

## RLE helpers from `tn_rle.h`

Run-length encoding for compact bitset representation.

| Helper | Purpose |
| - | - |
| `tn_rle_footprint(max_runs)` | Memory footprint in bytes for an RLE with `max_runs`. |
| `tn_rle_new(shmem, max_runs)` | Initialize an RLE structure in pre-allocated memory. |
| `tn_rle_encode(rle, max_runs, bitset, bit_count)` | Encode a `ulong` bitset into RLE format. |
| `tn_rle_decode(rle, bitset, max_bits, out_bit_count)` | Decode RLE back to a `ulong` bitset. |
| `tn_rle_decode_bytes(rle, bitset, max_bits, out_bit_count)` | Decode RLE to a byte-oriented bitset. |
| `tn_rle_iter_init(iter, rle)` | Initialize a memory-efficient iterator over set bits. |
| `tn_rle_iter_next_set(iter, max_bits)` | Return the next set bit index, or `TN_RLE_ITER_DONE`. |

## Notes

- Start with `tn_sdk.h` unless the task clearly requires lower-level syscall or struct work.
- Prefer `TSDK_LOAD` and `TSDK_STORE` when reading or writing fields out of byte buffers with uncertain alignment.
- Treat `tsdk_return` and `tsdk_revert` as terminal control-flow points, not ordinary function calls.
- For downstream user code, prefer the installed include path form `<thru-sdk/c/…>` consistently.
- The additional headers (`tn_sdk_sha256.h`, `tn_crypto.h`, `tn_rle.h`) are opt-in. Most programs only need `tn_sdk.h` and `tn_sdk_syscall.h`.
