Refracting Light v3: a 128-bit experimental hash for proof-of-work

E46 / Tessera project · 7 October 2026 · Status: experimental, not externally reviewed

Abstract

Refracting Light v3 (RL v3) is a bit-serial hash with a 512-bit internal state (four coupled 128-bit lanes), a Reed-Solomon-style message record, an outward clamp, eight blank finalization steps, and a linear four-way fold to a 128-bit digest. In local testing (avalanche, strict avalanche criterion, bias, differentials, linear masks, fold cancellation, SAT, real truncated collisions up to 64 bits, and Grover simulation) it behaved like an ideal 128-bit function, indistinguishable from a SHA-256 control. It is intended for proof-of-work, not as a general-purpose replacement for standard hashes.

Name. RL-EH, Refracting Light, Event Horizon construction: entangled lanes around a hidden black-hole core, a white-hole outward clamp, and a fold (the event horizon) through which only scrambled “Hawking radiation”, the digest, escapes. The physics is a metaphor; the mechanism below is classical integer arithmetic.

1. Construction

All arithmetic is on unbounded signed integers unless reduced; divmod is floor division; rotl_w(x, n) rotates a w-bit value left by n mod w.

Clamp. outward(x) = x − 16 if x ≤ 0, else x + 15. Message bits become digits d ∈ {−16, +16}.

Record. For an n-byte message M with s = ceil(n/4): pad M with zeros to 4s bytes, split it into shards D₀…D₃, and form P[j] = D₀[j] ⊕ D₁[j] ⊕ D₂[j] ⊕ D₃[j], Q[j] = 1·D₀[j] ⊕ 2·D₁[j] ⊕ 3·D₂[j] ⊕ 4·D₃[j] in GF(2⁸) mod 0x11d. record(M) = BE64(n) ‖ D₀ ‖ D₁ ‖ D₂ ‖ D₃ ‖ P ‖ Q ‖ 0x00. The final 0x00 is v3’s 8 blank finalization steps. The code is MDS (6,4,3): any message difference changes at least 3 of 6 symbols per column.

State. Lanes ℓ = 0…3 hold 64-bit words xℓ and vℓ. IV: x = (0,1,2,3), v = (1,3,5,7), step counter i = 0.

Step (one per record bit, MSB first; all lanes updated from the old state; ν = (ℓ+1) mod 4):

z   = 257·xℓ + 17·vℓ + d·(i+ℓ+1) + rotl₆₄(xν, 11+7ℓ)
(q, r) = divmod(outward(z), 2⁶⁴)
v′  = rotl₆₄((65537·vℓ + q + d + i + ℓ + 1 + vν) mod 2⁶⁴, 13+8ℓ) ⊕ r
x′  = r ⊕ rotl₆₄(v′, ((i + 11ℓ) mod 63) + 1)
i  ← i + 1

Output. Lℓ = (xℓ << 64) | vℓ. Folded digest: H = L₀ ⊕ rotl₁₂₈(L₁, 29) ⊕ rotl₁₂₈(L₂, 61) ⊕ rotl₁₂₈(L₃, 97) (128 bits). The unfolded 512-bit state is for research only, because it exposes the whole state.

1b. SHAKE256-128 and the E46 address formula

SHAKE256 (FIPS 202, the SHA-3 family) is a sponge over the Keccak-f[1600] permutation: a 1600-bit state, of which r = 1088 bits (136 bytes) are the rate and c = 512 bits the hidden capacity.

SHAKE256(M, d) = KECCAK[c = 512](M ‖ 1111, d)

pad:     P = M ‖ 1111 ‖ 1 0* 1                  -- pad10*1 to a multiple of 136 bytes; P = P₀ ‖ P₁ ‖ … ‖ P_{k−1}
absorb:  S ← 0¹⁶⁰⁰;  for each block P_j:  S ← f(S ⊕ (P_j ‖ 0⁵¹²))
squeeze: Z ← first 1088 bits of S;  while |Z| < d:  S ← f(S);  Z ← Z ‖ first 1088 bits of S
output:  first d bits of Z

f = Keccak-f[1600]: 24 rounds of θ, ρ, π, χ, ι on a 5×5 array of 64-bit lanes

SHAKE256-128 is the first 128 bits: SHAKE256_128(x) = SHAKE256(x, 128). Alone it gives collision ≈ 2⁶⁴ and preimage ≈ 2¹²⁸ (Grover ≈ 2⁶⁴); its 512-bit capacity is not the bottleneck.

E46 single-owner address payload (256 bits):

T = "E46-address\0"      (12-byte domain tag),   pk = SLH-DSA-SHAKE-128s public key (32 bytes)
A = RL_v3_128(T ‖ pk)  ‖  SHAKE256_128(T ‖ pk)
address = Bech32m("e46" or "te46", version 0, A)

A thief needs a public key matching both halves at once. A generic preimage of the 256-bit payload costs up to ≈ 2²⁵⁶ classically, at least ≈ 2¹²⁸ even if one half is weak, and ≈ 2¹²⁸ with Grover. If either hash has a hidden flaw, the other half still stands.

2. Specification list

Item

Value

State / output

512 bits / 128 bits (folded)

Steps per message

8·(8 + 6·ceil(n/4)) + 8 (e.g. 120-byte header: 1,512)

Finalization

8 blank steps (full mixing measured after 2)

Fold

GF(2)-linear, surjective, kernel dimension 384

Speed

≈ 306k short hashes/s per M1 core in C; ≈ 16× slower than SHA-256

Implementations

Python reference, independent Python spec check, C (rl_search.c); all agree on every vector

Vectors

refracting-light-v3-test-vectors.json

Use in E46

proof-of-work; Rad IDs; half of each address (RL v3 128 ‖ SHAKE256 128)

3. Results (local, reproducible, seeded)

Test

Result

Avalanche / strict avalanche criterion

mean 64.0 of 128 bits; all 16,384 SAC cells within random expectation

Bias, differentials, linear masks

χ² and |z| within random expectation; no repeated differential; no biased mask

Fold cancellation (7 structured classes)

full GF(2) rank (128/128, 512/512); no foothold

Last-step weakness (v2)

folded minimum 24 bits → 41 in v3 (random ≈ 39): fixed by finalization

SAT (z3), scaled and reduced-step

thousands of times slower than brute force; stalls at 8–12 steps

Real truncated collisions, 40–64 bits

53 searches, 0.88 ± 0.08 × birthday bound (SHA-256 control 0.92 ± 0.08); 64-bit pair found

Grover simulation (4–8-bit outputs)

exact agreement with theory (error ≤ 2.2 × 10⁻¹⁵); full-size preimage ≈ 1.45 × 10¹⁹ iterations

4. Security level and limits

Generic security: collision ≈ 2⁶⁴, preimage ≈ 2¹²⁸ (Grover ≈ 2⁶⁴). That is adequate for proof-of-work and too short to stand alone for IDs, which E46 hashes with SHAKE256. Open questions: whether a step can be inverted, structural (non-generic) attacks, and the fold kernel under expert-designed differentials. No external cryptanalysis yet. The planned successor, RL W (1024-bit state, 512-bit output), is designed but untested.

New to the terms? See the plain-language glossary with citations: RL-V3-GLOSSARY.md. Evidence: REFRACTING-LIGHT-SPEC.md, PHASE3-RESULTS.md (sections A–L), phase3-runs/. The name “Refracting Light” is a label and does not describe a physical or quantum process.