RequantTESTNET
Requant research

How TNet works

TNet v1 is Requant's work function: an eight-layer int8 network with exact integer requantization between layers. A miner runs many input rows through the network; pieces of the output rows are lottery tickets; a node checks a winning ticket by recomputing one row. This page describes the construction as specified in spec/07 and frozen in ADR 0016.

In one paragraph

Every epoch has eight fixed 8192 × 8192 int8 weight matrices, derived from a seed on the chain. For a block header and a nonce, the miner derives up to 65,536 input rows of 8192 int8 values, multiplies them through the eight layers and, after each layer, rounds the int32 results back to int8 with an exact fixed-point rule. Each output row is cut into 32 pieces of 256 bytes; each piece is hashed with the header, nonce, row and piece index, and a hash below the network target wins the block. The block carries the nonce, the row and piece indices and the 256-byte piece. A node recomputes that single row through the eight layers, compares the piece and checks the hash.

The construction

Epoch weights. For layer l = 0 … 7:

W_l = int8( expand( SHA256("abacus/tnet-w" || epoch_seed || LE32(l)), n·n ) )

expand is a SHA-256 counter stream. The matrices are stored row-major.

Inputs for one attempt. For a header digest and a 64-bit nonce:

s   = SHA256("abacus/tnet-x0" || header_digest || LE64(nonce))
X_0 = int8( expand(s, b·n) )            # b rows of n int8 values
X_l = requant( X_{l-1} · W_{l-1} )      # l = 1 … 8

Requantization. After each layer the exact int32 product is mapped back to int8:

requant(y) = clamp( (y·M + 2^23) >> 24, −128, 127 )

This is round-half-up fixed-point scaling, computed exactly. It is the nonlinear step that stops the eight layers from being merged into one matrix.

Tickets. Row i of the last layer is cut into n/w = 32 pieces c of w = 256 bytes:

h = SHA256( X_8[i, c·w … (c+1)·w] || 0x54 || header_digest || LE64(nonce) || LE32(i) || LE32(c) )

A ticket (nonce, i, c) wins if h, read as a 256-bit number, is at most the block target.

Frozen parameters

ParameterValueMeaning
n8192layer width; weight matrices are 8192 × 8192
L8number of layers
w256 bytesticket width; 32 tickets per row
M2505requantization multiplier, round(2^24 / (74·√8192)), which keeps the spread of activations constant from layer to layer
B65,536maximum row index per nonce
Weights per epoch512 MiBeight 8192 × 8192 int8 matrices

Rows are independent, so a miner may process any number of rows per GPU pass; results are identical at any batch size.

What one ticket costs

  • One full attempt (65,536 rows) is L·b·n² ≈ 3.5 × 10^13 multiply-accumulates and yields 2,097,152 tickets.
  • One ticket costs L·n·w ≈ 16.8 million multiply-accumulates, whatever strategy is used. Processing rows in batches is the cheapest way; mining single rows was measured at 42–51× more expensive per ticket.
  • One verification recomputes one row: L·n² ≈ 537 million multiply-accumulates.

What a block carries

The work data in a block is (nonce, i, c, piece): 8 + 4 + 4 + 256 = 272 bytes. This is the proof of work only. The block header, the difficulty target, the transactions and the epoch weights are not part of the 272 bytes.

The piece is included so that the cheap check comes first: a node hashes the piece with the header and compares it with the target before recomputing anything. A forged header therefore costs its author a full SHA-256 grind before it can cost a node a recomputation.

How a node verifies

  1. Check that the hash of the piece, header and indices meets the target.
  2. Recompute row i of the attempt: derive its input from the header and nonce, multiply through the eight layers with the epoch weights, requantize after each layer.
  3. Compare piece c of the recomputed row with the piece in the block, byte for byte.

The verifier keeps the weights transposed so that each output value is a contiguous int8 dot product. The Requant node, a portable build that selects AVX2 at run time, verifies a claim in 11.2 ms on 8 threads and 21.7 ms on one thread of an AMD Ryzen 7 8745HS laptop processor (SPEC.md; details in measurements).

Why this shape

RequirementHow TNet meets it
Work runs on tensor cores86.7–88.2% of an attempt is int8 matrix multiplication on the measured GPUs
Cheap verificationOne row instead of 65,536; no proof system
No reuse across attemptsEvery input row is derived from the header and nonce; weights change every epoch
No shortcut from linearityExact rounding between layers; one error after the first layer changes 55% of the last layer's values
Nothing to grind for freeThe only free inputs are the nonce and the indices, each of which costs a full row computation
Reproducible everywhereInteger arithmetic only; GPU kernels match the Rust and Python references byte for byte

On the Requant chain

  • Requant uses TNet v1 unchanged. The research construction compares leading zero bits of h; Requant compares h with a 256-bit target (SPEC.md).
  • Epochs. The weights change every 1440 blocks, about one day at 60-second blocks. Epoch e takes its seed from a block 60 blocks before it starts: seed_e = H("requant/epoch", LE64(e) || id(block e·1440 − 60)), so every node derives the next weights (about 7 s on one core) before they are needed. The first epoch's seed comes from the chain identifier.
  • Memory. A node keeps the 512 MiB of weights in a file read through the operating system's page cache, so the node process itself stays small.
  • Requantization in the node is written as clamp(floor((y·2505 + 2^23) / 2^24), −128, 127), the same function as above.
  • Consensus parameters, the header format and difficulty adjustment are in the chain rules.

Test vectors and references

  • Frozen test vectors: spec/vectors (rows 0, 1, 255 and 65535 at the frozen parameters, and a small n = 256 instance checked in Python).
  • Rust reference: tnet.rs; Python reference: tnet.py; the Requant node's own implementation is in crates/tnet.