| name | stf-analysis |
| description | Analyze State Transition Function implementations for correctness, threading issues, non-determinism, and simplification opportunities. Use when analyzing STF code, checking threading model, finding non-determinism sources, or reviewing execution layer. |
STF Analysis Skill
Use this skill to analyze State Transition Function implementations for:
- Threading correctness (Send/Sync bounds)
- Non-determinism sources
- Simplification opportunities
- Test coverage gaps
Analysis Checklist
1. Threading Model Analysis
Check for unnecessary Send/Sync bounds:
grep -rn "Send + Sync\|: Send\|: Sync" crates/
Questions to answer:
2. Non-Determinism Sources
Check for common non-determinism issues:
grep -rn "\.iter()\|\.into_iter()" --include="*.rs" crates/app/stf/
Common sources:
3. Atomicity Verification
Verify checkpoint/restore pattern:
let checkpoint = storage.checkpoint();
let result = do_operation();
if result.is_err() {
storage.restore(checkpoint);
}
Check:
4. Gas Configuration
Gas metering is configured via StorageGasConfig passed to the STF at construction:
use evolve_stf::{Stf, StorageGasConfig};
let gas_config = StorageGasConfig {
storage_get_charge: 10,
storage_set_charge: 10,
storage_remove_charge: 10,
};
let stf = Stf::new(begin_blocker, end_blocker, tx_validator, post_tx, gas_config);
Key types:
StorageGasConfig - defines gas costs for storage operations
GasCounter - tracks gas during execution (Infinite or Finite mode)
ERR_OUT_OF_GAS - returned when gas limit exceeded
The gas config is stored in the STF and used in do_begin_block to configure gas metering for the block. This avoids the overhead of reading config from storage every block.
5. Resource Limits
Verify security limits exist:
| Resource | Expected Limit | Location |
|---|
| Overlay entries | ~100,000 | execution_state.rs |
| Events per tx | ~10,000 | execution_state.rs |
| Key size | ~256 bytes | execution_state.rs |
| Value size | ~1 MB | execution_state.rs |
| Call depth | ~64 | invoker.rs |
6. Test Coverage Gaps
Property tests that should exist:
#[test]
fn prop_execution_state_model() { }
#[test]
fn prop_gas_counter_model() { }
#[test]
fn test_gas_calculation_accuracy() { }
#[test]
fn prop_apply_block_failure_invariance() { }
#[test]
fn prop_determinism() { }
7. Simplification Opportunities
Look for:
-
Unused trait bounds
-
Atomic overhead without threading
-
Dead code paths
Output Template
After analysis, produce a report:
## STF Analysis Report
### Threading Model
- Execution model: [single-threaded / parallel]
- Concurrency locations: [list]
- Unnecessary bounds: [list]
### Non-Determinism Risks
- [x] HashMap iteration in into_changes() - NEEDS SORTING
- [ ] No floating point usage - OK
- [ ] No system time in execution - OK
### Atomicity
- [x] Checkpoints before state changes - OK
- [x] Restore on all error paths - OK
- [ ] Missing: [any gaps]
### Resource Limits
- [x] Overlay: 100,000 entries
- [x] Call depth: 64 levels
- [ ] Missing: [any gaps]
### Test Gaps
- [ ] Determinism test missing
- [ ] Call depth exhaustion test missing
### Simplification Recommendations
1. Remove Send+Sync from ReadonlyKV, add to warm_cache only
2. Replace AtomicU64 with Cell<u64> in metrics (if Sync not needed)
3. [other recommendations]
Quick Commands
rg "Send \+ Sync|: Send|: Sync" crates/app/stf/src/
rg "\.into_iter\(\)|\.iter\(\)" crates/app/stf/src/ -A 2
rg "checkpoint\(\)|restore\(" crates/app/stf/src/
rg "return Err" crates/app/stf/src/invoker.rs -B 5
cargo test -p evolve_stf -- --list 2>&1 | grep "test "