Flagging transactions
The flagger is one of the Private Network operator's governance services in a Rayls Private Network. It runs two automatic checks over the cross-chain activity that the governance listener has decrypted from the Private Network Hub:
- a balance check, which flags token transfers between chains that would leave the sending chain with a negative net position in a token;
- a liveness check, which flags a participant whose chain has stopped submitting block headers to the Hub.
A flag is a record in the governance database. It doesn't block, reverse or freeze anything. Acting on it is the operator's decision.
The flagger works only from Hub traffic. It doesn't read the participants' Rayls Sovereign chains (Privacy Nodes in the code), and it doesn't compare against any state the chains publish.
The balance check
The flagger keeps a running net position for every combination of chain, token (resource ID) and, for ERC-721 and ERC-1155 tokens, token ID. It processes transactions in the order the listener recorded them:
| Transaction | Change to the net positions |
|---|---|
| Token registration on the Hub | The initial supply is added to the issuer's chain |
| Mint reported by the issuer | Added to the issuer's chain |
| Transfer between chains | Subtracted from the source chain and added to the destination chain. Flagged if the source would go negative. |
A chain's net position is therefore what it has been issued plus what it has received, minus what it has sent. A transfer that takes it below zero means the chain has sent more of a token than the Hub has seen it receive. That can mean, for example, tokens created on the chain without being reported to the Hub, or the same tokens sent twice.
A flagged transaction isn't applied to the net positions.
Which transactions are checked:
- Enygma transfers and delivery-versus-payment (DvP) operations are never flagged. Their zero-knowledge proofs already ensure that a sender can't spend more than it holds.
- When an Enygma transfer fails at its destination and is reversed, the flagger matches the reversal to the original and applies neither.
The liveness check
Each private relayer submits its Rayls Sovereign chain's block headers to the Hub's Proofs contract, and the listener records them. Every minute, the flagger looks at the latest header recorded for each chain.
- If it is older than
PNH_HEADER_PROOF_EXPIRATION_PERIOD(5 minutes in the reference configuration), the participant is flagged. Its record showsisFlagged: true,flagReason: "liveliness check failed, header not submitted in time"andflaggedAt. An event is added to the flag history, with the initiatorAUTOMATIC_SYSTEM_CHECK. - When the chain's headers arrive in time again, the flag clears by itself. The history is kept.
A liveness flag doesn't change the participant's status. To stop a participant, see Freezing participants.
Review flagged transactions
GET /flagged on the governance API returns every flagged transaction:
curl http://<governance-api>/flagged{
"flagged": [
{
"id": "1c0e…",
"createdAt": "2026-10-06T11:40:12Z",
"updatedAt": "2026-10-06T11:40:12Z",
"transactionId": "a83f…"
}
]
}transactionId is the transaction's ID in the governance database. Fetch the transaction with it:
curl http://<governance-api>/audit/transactions/dvp/a83f…Despite dvp in the path, this endpoint returns any transaction by its database ID: chains, addresses, amount, token, Hub transaction hash and block, and source and destination transaction hashes. Use the source chain and the token's resource ID to look at the chain's other transactions, in the Private Network Auditor Explorer or with GET /audit/transactions?sourceChainId=…&resourceId=….
To see the net positions the flagger holds, use GET /resource_info_all_chains/{resourceId} (this needs a login; see Monitoring cross-chain transactions).
To find flagged participants, use GET /audit/participants and look at isFlagged.
There is no endpoint to clear, annotate or close a flag. Flags stay in the database.
Acting on a flag
- Find out what happened, with the participant concerned. The operator sees only the Hub side; the chain's own records are with the participant.
- If tokens must stop moving, freeze the token for the participant: see Freezing tokens.
- If the participant must stop transacting altogether, freeze it: see Freezing participants.
Configuration
| Variable | Default | Meaning |
|---|---|---|
TRANSACTIONPROCESSOR_BATCHSIZE | 100 (maximum 800) | Transactions the balance check reads at a time |
TRANSACTIONPROCESSOR_CHECKINTERVAL | 1s (between 1 and 6 seconds) | How often the balance check runs |
PNH_HEADER_PROOF_EXPIRATION_PERIOD | Required; 5m in the reference configuration | How late a chain's latest header may be before the chain is flagged |
PNH_HEADER_PROOF_PURGE_PERIOD | Off | If set, once a day the flagger deletes recorded headers older than this, keeping each chain's latest |
The flagger's logs record each flag as a warning.
Updated 8 days ago
