Policy Engine
Deep dive into how Railguard inspects transactions and enforces your security policy.
The Policy Engine (rg-policy crate) is the heart of Railguard. It takes a transaction and returns a Verdict: either Allowed or Blocked { reason }.
Inspection Flow
Every check that fails results in an immediate Blocked verdict with a descriptive reason.
1. Global Limits
First, the engine checks transaction-level limits:
2. Destination Allowlist
If the transaction has no calldata (simple ETH transfer), the to address must be in the allowlist:
For contract calls, the destination must match a rule's contract field.
3. Selector Matching
Railguard extracts the 4-byte function selector from the calldata and matches it against allowed methods.
Selector Pre-computation
At startup, Railguard parses your method signatures and computes selectors:
This is done once at config load, not per-request, ensuring < 1ms latency.
Matching Logic
4. Argument Validation
If the matched rule has arg_constraints, Railguard decodes the calldata arguments and validates them.
ABI Decoding
Railguard uses alloy-dyn-abi to decode arguments:
Constraint Checking
Raw Transaction Handling
For eth_sendRawTransaction, Railguard must first decode the RLP-encoded signed transaction:
This extracts the same fields as eth_sendTransaction, allowing unified inspection.
Fail Closed Architecture
The Policy Engine wraps all inspection in a panic catcher:
Any panic becomes a Blocked verdict. This is intentional—security-critical code must never silently succeed when something goes wrong.
Decode Error Handling
When fail_on_decode_error is true (default), any ABI decoding failure results in Blocked:
Performance
The Policy Engine is optimized for minimal overhead:
| Operation | Target | Implementation |
|---|---|---|
| Selector lookup | O(1) | HashMap<Address, HashMap<[u8;4], Rule>> |
| Selector computation | Once at startup | Pre-hashed in RuntimePolicy::from_config() |
| ABI decoding | Per-request | alloy-dyn-abi (zero-copy where possible) |
| Total inspection | < 1ms p99 | Measured via latency_us in Receipt |
Benchmarks
Runtime Policy Structure
The RuntimePolicy struct optimizes for fast lookups:
Verdict Types
The verdict is attached to a Receipt and:
- Displayed in the TUI
- Used to generate the JSON-RPC response
- Optionally uploaded to Railguard Cloud
Next Steps
- Configuration — Full config reference
- CLI Reference — Command-line options
- TUI — Terminal interface guide