EXPcaliburINSIDE THE MACHINE

10 / ABYSS / PROOFS

ABYSS engine: how proof limits power

Can the bot simply ask for level 16? The request alone gives no power. The host checks the work, saves the proof it accepts, and sets a ceiling on usable power. This chapter follows that saved proof from one accepted check to the short boost the knight can actually use.

Starts with: A result that has passed a host check.

Ends with: Saved proof and a maximum allowed power level.

Question: What did the check prove, whose proof is it, and which earlier checks does it depend on?

Ask for 16, get 4: one SERRATE example

Suppose the bot completes Entry, the first ABYSS step, for SERRATE sword power. The host accepts two checks: DualView and EntryLoop. It saves an EntryProof for this run's SERRATE track. Then the bot requests Drive levels [16, 0, 0]. This asks for maximum sword power and no shield or magnet power. This request is an example; it is not from the reference bot.

Where a level-16 request becomes a level-4 sword boost
01 / HOST CHECKSTwo different checks pass
DualView ✓EntryLoop ✓

The host makes a receipt for each accepted kind. Writing those names in guest memory would earn nothing.

02 / SAVED PROOFOne EntryProof, on SERRATE
1100000x03

Two different kinds make rank 2—the host's count of distinct checks. That allows level 4, and the Entry step also stops at 4. BASTION and TRAWL need their own proof.

03 / DRIVE REQUESTThe bot asks for [16, 0, 0]
asked 16Drive maximum 16saved proof 4new Drive check 4

If the request belongs to this run and its new Drive work passes, the host chooses the smallest number: min(16, 16, 4, 4) = 4. A failed request installs no new boost.

04 / THE KNIGHTEight ticks of level-4 sword power
+250 attack damage bonus
72-pixel disc radius
10-tick selected cooldown if the ordinary value is 34

The disc needs an ordinary aimed swing to find a target first; bosses stay wedge-only. After eight ticks the active levels return to zero, but the saved proof remains. EXP still needs a real kill, gem drop, and pickup.

Read the cards in number order. The six little boxes are six different check kinds, not six power points. Gold means the host accepted that kind; 0x03 is the short hexadecimal way to write “the first two boxes are on.”

The host calls one accepted receipt a certificate. It saves certificates in a proof node such as EntryProof. The node names the step, owner, power track, and accepted certificates. A later step must link to the correct earlier node. Writing level = 16 in bot memory cannot replace that history.

Three objects that are easy to confuse

An execution result records what the inner program did or returned, and the host still has to judge it. A certificate records one check that the host accepted. A proof node holds accepted certificates for one run and one power track, with links to earlier nodes. The code calls it a provenance node.

Here, DualView and EntryLoop are certificate kinds, EntryProof is their node, and [16, 0, 0] is a later request to use that proof. Entry has no earlier proof node.

The repository has an accepted Entry body and an altered body, both on bank 0 and SERRATE. Both pass the row grammar and row/column XOR checks, and the accepted body's last tile has the required column operations C D E 8.

The altered body has E F 4 2, so the host's column check rejects it. Passing the earlier row and XOR checks is not enough.

The same kind of Entry call can end with two different proof states

A fresh run has no earlier Entry proof. Read each lane down: accepting a call's format is only the first door.

Accepted witness

1 · Call receivedHost copies the frame and runs the Entry work.

2 · Both readers agreeRows and XORs pass. Last-tile columns spell C D E 8.

3 · Receipt and proofHost can accept DualView and EntryLoop, then save this track's EntryProof.

4 · Later Drive requestEntry can support at most level 4, if that new request passes too.

Altered control

1 · Call receivedHost still copies the frame and runs the Entry work.

2 · One reader disagreesRows and XORs pass, but columns spell E F 4 2. The required pattern fails.

3 · No Entry proofThe inner result does not pass the full check. The host saves no EntryProof for this attempt.

4 · Later Drive requestThis attempt supplied no new Entry authority. Asking for level 4 cannot make the missing proof appear.

A public call status can look ordinary in both lanes. The meaningful difference is the host-owned proof saved after all Entry checks, not a number the bot can put in its memory.

The host checks all requirements before it saves proof. The code's proof_eligible value requires valid Entry bytes and both calls in order. It also requires the same paused work, valid completion, and a real session slot. One valid-looking row cannot replace these checks:

RUST crates/gate/src/abyss/state.rs · source lines 1335–1341
        let proof_eligible = provisional.braid_semantic_valid
            & provisional.first_sequence_valid
            & sequence_valid
            & fibre_valid
            & completion.semantic_valid()
            & (provisional.reserved_slot != NO_SESSION)
            & session_slot_exists;

The source test checks both sides of the contrast. Its row grammar and both XOR checks pass:

RUST crates/gate/src/abyss/braid.rs · source lines 1240–1246
            let mutant = evaluate_braid(&mutant_body, bank, lineage_u8);
            assert!(mutant.rows.grammar_valid);
            assert!(mutant.rows.parity_valid);
            assert!(mutant.rows.events.iter().all(|event| event.row_valid));
            assert!(mutant.rows.events.iter().all(|event| event.parity_valid));
            assert!(mutant.columns.parity_valid);
            assert!(mutant.columns.events.iter().all(|event| event.parity_valid));

But the column program and full Entry result fail:

RUST crates/gate/src/abyss/braid.rs · source lines 1258–1263
            assert!(!mutant.columns.skeleton_valid);
            assert_eq!(mutant.columns.lineage_match_count, 0);
            assert!(mutant.derived_lineage().is_none());
            assert!(!mutant.expected_lineage_valid);
            assert!(!mutant.conditioner_valid);
            assert!(!mutant.semantic_valid());

A program can calculate a value without earning a certificate. It can earn one certificate without reaching a later proof step. A later step can still lack a certificate kind needed for full power. One unlocked switch cannot record these differences.

Certificates have identities and bindings

A certificate kind identifies the check that passed. The host defines six kinds:

Kind Concept represented Why a separate kind matters
DualView How input is read Reading bytes and agreeing on their meaning are separate checks
EntryLoop What actually ran A request that looks right is not proof that the program ran correctly
CostTranscript How work is counted The engine has rules for the cost of each step
RootBinding Who the proof belongs to Proof for one owner cannot be reused as someone else's
StaleDispatch What happened across resource lifetimes Timing and reuse matter; a still picture of the input is not enough
ModuleAudit What the inner module did Finishing the inner program requires several separate checks

The host records these accepted checks. A guest cannot create one by storing a name or setting a bit.

Each receipt has a 16-byte binding. This value identifies the evidence that the host accepted. The code makes it in this order:

  1. Add a fixed 16-byte label, TAG_CERT, so these bytes cannot be confused with another kind of hash in the game.
  2. Add the 12-byte owner root. A different world seed changes this root; changing only the uploaded image does not.
  3. Add one byte naming the check kind. A DualView receipt cannot be relabeled ModuleAudit.
  4. Add the checked evidence, up to 128 bytes. A different result changes the message.
  5. Hash those bytes with SHA-256 and keep the first 16 bytes.
One receipt fingerprint: four ingredients in orderOne receipt fingerprint: four ingredients in orderA binding identifies one accepted check for one run.HOST-OWNED INPUTS · JOIN THESE BYTES IN ORDER1 · Fixed label16 bytes2 · Run owner12-byte root3 · Check kind1 byte4 · Checked dataup to 128 bytesTAG_CERTowner_rootkind.as_u8()canonical_evidenceJoin in order; ignore unused buffer space.SHA-256Hash the joined message, then takeits first 16 bytes.Saved bindingA 16-byte fingerprint attached tothis receipt.The host makes this after the work check passes. A guest-made hash is not an accepted receipt.
What goes into one host-made receipt fingerprint. The four input pieces are joined in this exact order. The host hashes them and keeps 16 bytes. This drawing shows the binding recipe, not a way for a bot to mint an accepted receipt. View diagram at full size

The source shows the byte ranges: 0..16 holds the label, 16..28 holds the owner, byte 28 holds the kind, and 29..used holds the evidence. The host hashes only the used bytes:

RUST crates/gate/src/abyss/provenance.rs · source lines 192–207
pub(super) fn derive_certificate_binding(
    owner_root: [u8; 12],
    kind: CertificateKind,
    canonical_evidence: &[u8],
) -> Result<[u8; 16], ProvenanceError> {
    if canonical_evidence.len() > MAX_CERTIFICATE_EVIDENCE {
        return Err(ProvenanceError::CertificateEvidenceTooLong);
    }
    let mut message = [0u8; 16 + 12 + 1 + MAX_CERTIFICATE_EVIDENCE];
    let used = 29 + canonical_evidence.len();
    message[0..16].copy_from_slice(&TAG_CERT);
    message[16..28].copy_from_slice(&owner_root);
    message[28] = kind.as_u8();
    message[29..used].copy_from_slice(canonical_evidence);
    Ok(prefix16(sha256(&message[..used])))
}

Changing the owner, check kind, or evidence changes the binding. The binding identifies an accepted check, but it does not perform that check. Host code makes the receipt only after its checker passes, so a bot cannot earn one by computing a hash in guest memory.

An absent receipt has an all-zero binding, and a receipt cannot be renamed for a different accepted event. The owner root is seed-bound, while the checked evidence and host-owned proof records carry the other distinctions, such as a different upload.

The receipt list has two format rules. A present receipt needs a nonzero binding, and an absent receipt needs a zero binding. Unknown check kinds also fail, so these rules prevent hidden data in empty slots and empty bindings on claimed receipts.

Check the container as a truth table:

Present? Binding Result
No All zero Correct way to say “no receipt”
No Nonzero Rejected: an absent slot is hiding data
Yes All zero Rejected: a claimed receipt has no binding
Yes Nonzero The shape is valid; the host still checks the proof and its earlier records

The last row passes only the format check. It does not let a guest create a valid certificate. Only the host's check paths can save accepted proof.

The format check rejects unknown kind bits. It also rejects a present kind with zero binding or an absent kind with nonzero binding. This function checks the container's format. It does not rerun DualView or another work check:

RUST crates/gate/src/abyss/provenance.rs · source lines 137–152
    fn validate_for_set(&self, certificate_set: u8) -> Result<(), ProvenanceError> {
        if certificate_set & !0x3f != 0 {
            return Err(ProvenanceError::InvalidCertificateSet);
        }
        for kind in CertificateKind::ALL {
            let present = certificate_set & kind.bit() != 0;
            let zero = is_zero_digest(&self.values[kind.index()]);
            if present && zero {
                return Err(ProvenanceError::MissingCertificateBinding);
            }
            if !present && !zero {
                return Err(ProvenanceError::UnexpectedCertificateBinding);
            }
        }
        Ok(())
    }

Why “rank” is a population count here

The code calls this number rank. It counts different kinds of accepted host check. Think of collecting six different stickers: two copies of the same sticker still fill one spot. The host defines all six kinds, and the bot cannot add a seventh.

RUST crates/gate/src/abyss/provenance.rs · source lines 1698–1705
pub(super) const fn certificate_rank(certificate_set: u8) -> Option<u8> {
    if certificate_set & !0x3f != 0 {
        None
    } else {
        Some(certificate_set.count_ones() as u8)
    }
}

The host can count set bits because each bit has one fixed check kind. If the guest could choose the bits, this count would prove nothing.

Number of independent kinds Evidence-derived level ceiling
0 0
1 2
2 4
3 6
4 8
5 12
6 16

Five different kinds allow level 12. All six allow level 16. The sixth different kind raises the limit from 12 to 16. No single kind has extra value by itself. Completing the set matters.

The proof step is a second limit

Drive has three separate proof tracks. The source fixes their order:

RUST crates/gate/src/abyss/roots.rs · source lines 68–78
#[repr(u8)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub(super) enum Lineage {
    Serrate = 0,
    Bastion = 1,
    Trawl = 2,
}

impl Lineage {
    pub(super) const ALL: [Self; 3] = [Self::Serrate, Self::Bastion, Self::Trawl];
Proof track Position in the three-number Drive vector What it helps with
Serrate 0 Offense
Bastion 1 Survival and movement
Trawl 2 Collection and supply

A Serrate proof can raise the first number, but it does not raise Bastion or Trawl. Each track needs its own earlier proof and certificates. The short-lived Drive setting stores the three levels in that same order:

RUST crates/gate/src/abyss/drive.rs · source lines 7–12
pub(super) const LINEAGE_COUNT: usize = 3;
pub(super) const SERRATE: usize = 0;
pub(super) const BASTION: usize = 1;
pub(super) const TRAWL: usize = 2;
pub(super) const MAX_LEVEL: u8 = 16;

The proof step sets another maximum. Entry allows up to level 4, Rift up to 8, Chasm up to 12, and the full ABYSS step up to 16. Their saved records are EntryProof, CalibratedProof, StaleDispatchProof, and ModuleProof. The host uses the smallest of the requested level, step limit, and accepted-check limit. It first checks the owner, earlier proof links, and receipt bindings before using those numbers.

Three real proof states: the smallest number winsThree real proof states: the smallest number winsENTRY · early proofBot asks16Proof step4Accepted checks4AT MOST4step and checks tieMODULE BASE · audit missingBot asks16Proof step16Accepted checks12AT MOST12five checks hold it downMODULE AUDITED · smaller requestBot asks8Proof step16Accepted checks16AT MOST8the bot asked for lessThese are ceilings for a later Drive request, after the host accepts the owner and earlier proof.
Three real proof states, three different reasons to stop. Each row pairs a proof step with the check kinds it can actually carry. The host takes the smallest bar: what the bot asked for, what that step permits, or what its accepted checks permit. These limits matter only after the owner and earlier proof pass. View diagram at full size

The walkthrough uses combinations from the real proof path. Select a saved SERRATE record. Then change the requested level and compare the three limits. At Module base, the step allows 16. But five accepted kinds limit power to 12. At Module audited, the sixth kind raises the limit to 16.

Follow one real proof path

Choose a saved SERRATE record. Gold tiles show different host checks that passed. Dark tiles show checks that are still missing. Then ask for a level. The host uses the smallest of the three numbers below.

SAVED RECORD · SERRATE TRACKEntryProof
0x03
Built fromNo earlier proof record
BOT ASKS FOR16
THIS PROOF STEP ALLOWS4
DIFFERENT CHECKS ALLOW4
AT MOST, IF DRIVE PASSES4

These are real combinations of proof step and check kinds. They limit a later Drive request. Selecting buttons here does not earn proof or start a boost.

The walkthrough follows SERRATE only. BASTION and TRAWL need their own proof records. A receipt for one run or track cannot support another.

The code calls its proof store an arena. Here, an arena is a table for 64 proof records. It is not the knight's game map. Each record has an ID. A later record can use that ID to link to earlier proof.

The walkthrough shows one possible SERRATE history. In this route, the first Module check finishes but its final audit fails. A strict retry then passes. If the first audit passes, the host can go straight from Chasm to a fully audited Module record. The five-kind Module record is not required.

The host fixes the certificate sets. Entry has two kinds, Rift four, Chasm five, and an audited Module six. A base Module has five. These are the exact sets:

RUST crates/gate/src/abyss/provenance.rs · source lines 16–31
const ENTRY_CERTIFICATE_SET: u8 = 0x03;
const CALIBRATED_CERTIFICATE_SET: u8 = 0x0f;
const STALE_CERTIFICATE_SET: u8 = 0x1f;
pub(super) const MODULE_BASE_CERTIFICATE_SET: u8 = 0x1f;
pub(super) const MODULE_COMPLETE_CERTIFICATE_SET: u8 = 0x3f;

#[repr(u8)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub(super) enum CertificateKind {
    DualView = 0,
    EntryLoop = 1,
    CostTranscript = 2,
    RootBinding = 3,
    StaleDispatch = 4,
    ModuleAudit = 5,
}

This is one track's history. BASTION and TRAWL need their own records. A Module proposal can list other accepted roots as parents. But only its primary parent supplies the certificate kinds. SERRATE cannot borrow BASTION's ModuleAudit receipt.

What is inside one saved record? The fields answer different questions:

Field in ProvNode Plain meaning
kind Which rung this record reached
scope Which power track it belongs to
parents and parent_count Which earlier saved records this one builds on
certificate_set Which of the six different checks have passed
certificate_bindings The host-made fingerprints for those accepted checks
payload_digest A fingerprint of this rung's checked contents
node_digest A fingerprint tying the owner, rung, track, parents, checks, and contents together

The host saves links to check the path through earlier work. A level number alone cannot show that path. Each step constructor makes a record for one power track. Its fingerprint includes the run's owner root.

The 64-slot limit can stop a proposal. The host also rejects missing or repeated parent links and parents of the wrong kind. A proposal fails if it uses old arena state. Two different records cannot claim the same key. These are defined proof-system failures.

Repeated work has two different outcomes:

Existing key Proposed bound contents Meaning
Same Same accepted contents The same accepted change again; no second slot is needed
Same Different contents Integrity conflict; equality of a key is insufficient

An identical accepted record needs no second slot. The same key with different contents is an error.

Prepare and commit are separate moments

First, the host prepares a proposed node. It checks earlier links and available space. Only then does it commit the node to the saved arena. If a check fails, saved proof stays unchanged.

The host checks the whole proof record before it makes the record visible. Otherwise, other code could see a node ID before its bindings exist.

A prepared node uses a specific arena state. If that state changes before commit, the host can return StaleProposal. An earlier pass cannot overwrite newer proof.

Private evidence is not public telemetry

The host performs the hash work even when a certificate is absent. It then changes the absent result to zero. This keeps the work closer for present and absent cases. Otherwise, a caller could measure time to learn a private fact. Source comments call this the fixed-work timing rule.

One fixed-work check does not make the whole path equal-time. Table walks, hashing, rejected proposals, and resumed work can take different times. The release's timing tests measure the full path. One helper alone cannot guarantee it.

Keep VM cost and real time separate. The VM counts work with fixed rules. Real time depends on the host computer and service. Equal VM cost does not prove equal real time.

Authority outlives its current effect

Accepted proof stays saved. It gives permission to request power, not a permanent boost. Think of a membership card versus a short ride pass: the card survives after this ride ends. The active Drive setting, by contrast, can expire. This diagram connects saved proof to the game:

From saved ABYSS proof to a real pickupFrom saved ABYSS proof to a real pickup1 Accepted proofThree tracks keep the host checks that passed.2 Bot requests levelsThe outer program asks for attack, survival and collection power.3 Host installs a settingIt checks this request’s fresh work and saved proof, then saves limited levels for a short time.4 Game reads active effectsDamage, defense and pickup fields update now; movement is staged for the next VM tick.5 Setting expiresActive levels return to zero; the saved proof remains.A Drive setting changes the knight’s chances. It does not add EXP.The game adds EXP only when the knight collects a real gem.
How saved ABYSS proof becomes a temporary gameplay boost. Follow the five rows. The bot asks for levels; the host limits and saves the allowed levels; the game reads the active setting; pickup still creates the EXP. The saved proof remains after the boost ends. View diagram at full size

The same five steps are shown as cards below →

Step What happens Who owns the result
Proof exists Earlier host checks left accepted records on the three power tracks Gate proof store
Bot asks The outer bot sends a Drive request for SERRATE, BASTION, and TRAWL levels Guest request, then a host-owned copy
Host installs The host checks fresh work for this request, its owner, saved proof, and level limits. If allowed, it stores the limited three-number result in a short-lived DriveLatch Gate state
Game reads After the VM slice, the engine asks for active effects and copies the resulting damage, defense, movement, and pickup values into its ordinary fields World state
Boost ends An expired setting returns zero levels; the accepted proof is still saved and can support a later permitted request Gate proof and active boost remain separate
  1. Proof existsEarlier host checks saved records for the three power tracks.Owner: Gate proof store
  2. Bot asksThe outer bot requests SERRATE, BASTION, and TRAWL levels.Owner: bot request, copied by the host
  3. Host installsThe host checks this request’s fresh work, owner, proof, and limits. If allowed, it saves levels in a short-lived DriveLatch.Owner: Gate state
  4. Game readsThe engine turns active levels into damage, defense, movement, and pickup values. The movement boost starts next VM tick; moves already made this tick do not change.Owner: world state
  5. Boost endsThe active levels fall back to zero. The accepted proof stays saved.Owner: proof and boost stay separate

Installing a boost without half-saving it

This Drive path shows the install decision. The host prepares a candidate setting. If the attempt fails, it keeps the old setting. Failed work cannot install new levels:

RUST crates/gate/src/abyss/state.rs · source lines 3800–3807
        let retained_latch = self.drive_latch;
        let mut installed_latch = retained_latch;
        installed_latch.commit(applied, self.current_tick);
        self.drive_latch = if valid {
            installed_latch
        } else {
            retained_latch
        };

Suppose all three tracks have accepted level-4 proof. A permitted [4,4,4] request can install those levels for a short time. It does not award EXP. The knight must still fight and collect gems. After expiry, the game reads zero levels until another allowed request passes.

The code shows this boundary. active_effects turns the active levels into limited gameplay values. The engine then stages movement and writes the engine's local knight fields (self.hero in the code):

RUST crates/gate/src/abyss/state.rs · source lines 968–975
    pub fn active_effects(&self, tick: u32, honest_cooldown: u16) -> DriveEffects {
        effects_for(self.drive_latch.active(tick), honest_cooldown)
    }

    pub fn active_levels(&self, tick: u32) -> [u8; LINEAGE_COUNT] {
        self.drive_latch.active(tick)
    }
RUST crates/engine/src/device.rs · source lines 893–900
    fn resolve_abyss_levers(&mut self) {
        let honest_cooldown = self.hero.swing_cd_ticks;
        let effects = match self.device.as_ref() {
            Some(device) => device.active_effects(self.tick, honest_cooldown),
            None => DriveEffects::default(),
        };
        if let Some(device) = self.device.as_mut() {
            device.stage_next_gait(effects.gait_bonus);

When the timer runs out

Suppose a valid SERRATE request installs [4, 0, 0] on tick 100. The host saves through_tick = 100 + 7 = 107. Tick 100 is the first of eight active ticks. This example uses sword power. Movement has a separate next-tick rule.

The proof stays; the rented sword boost runs out
TICK 100Drive accepted[4, 0, 0]

The host installs the limited levels. Combat later in this tick can use the level-4 sword effect.

TICKS 101–107Still active[4, 0, 0]

The game reads the same levels without making a new proof record.

TICK 108Expired[0, 0, 0]

The game gets no active Drive levels. The saved SERRATE proof is still in the host's proof store.

A later Drive request can use that saved proof again, but it must pass its own fresh request checks. No part of this clock adds EXP; the knight still has to fight and collect gems.

These functions set and read the timer. commit caps each level at 16 and saves the last active tick. It marks the boost active only if a level has an effect. active returns the saved levels through that tick. Afterward, it returns three zeroes. Neither function deletes the proof record:

RUST crates/gate/src/abyss/drive.rs · source lines 44–56
    pub(super) fn commit(&mut self, applied: [u8; LINEAGE_COUNT], challenge_tick: u32) {
        self.applied = applied.map(|level| level.min(MAX_LEVEL));
        self.through_tick = challenge_tick.saturating_add(7);
        self.live = levels_have_effect(self.applied);
    }

    pub(super) fn active(&self, tick: u32) -> [u8; LINEAGE_COUNT] {
        if self.live && tick <= self.through_tick {
            self.applied
        } else {
            [0; LINEAGE_COUNT]
        }
    }

The next chapter follows that vector into combat, survival, and collection.