|
| 1 | +# OVSM Crate - CLAUDE.md |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +**OVSM** (Open Versatile Seeker Mind) is a LISP-dialect interpreter and sBPF compiler for Solana blockchain automation and on-chain program development. |
| 6 | + |
| 7 | +## Architecture |
| 8 | + |
| 9 | +``` |
| 10 | +src/ |
| 11 | +├── lib.rs # Public API exports |
| 12 | +├── error.rs # Error types (OvsmError, Result) |
| 13 | +├── lexer/ # S-expression tokenizer |
| 14 | +│ └── sexpr_scanner.rs |
| 15 | +├── parser/ # AST construction |
| 16 | +│ └── sexpr_parser.rs |
| 17 | +├── runtime/ # Interpreter |
| 18 | +│ └── lisp_evaluator.rs |
| 19 | +├── compiler/ # sBPF code generation |
| 20 | +│ ├── mod.rs # Compiler orchestration |
| 21 | +│ └── ir.rs # IR generation (4800+ lines, main logic) |
| 22 | +├── decompiler/ # sBPF to OVSM reverse engineering |
| 23 | +├── ai/ # AI-assisted code generation |
| 24 | +├── metrics/ # Performance metrics |
| 25 | +├── parallel/ # Concurrent execution |
| 26 | +└── tools/ # Utility functions |
| 27 | +``` |
| 28 | + |
| 29 | +## Key Components |
| 30 | + |
| 31 | +### Lexer (`lexer/sexpr_scanner.rs`) |
| 32 | +- Tokenizes LISP S-expressions |
| 33 | +- Handles: `(`, `)`, strings, numbers, symbols, comments |
| 34 | +- Line/column tracking for error messages |
| 35 | + |
| 36 | +### Parser (`parser/sexpr_parser.rs`) |
| 37 | +- Builds AST from tokens |
| 38 | +- Expression types: `ToolCall`, `Variable`, `StringLiteral`, `IntLiteral`, etc. |
| 39 | +- Validates syntax structure |
| 40 | + |
| 41 | +### Evaluator (`runtime/lisp_evaluator.rs`) |
| 42 | +- Interprets OVSM code in-memory |
| 43 | +- Built-in functions: arithmetic, control flow, data structures |
| 44 | +- MCP tool integration for blockchain operations |
| 45 | + |
| 46 | +### Compiler (`compiler/ir.rs`) - **MOST IMPORTANT FILE** |
| 47 | +- Generates sBPF bytecode from OVSM source |
| 48 | +- 4800+ lines containing ALL macro implementations |
| 49 | +- Key sections: |
| 50 | + - Struct operations (lines ~1100-1600) |
| 51 | + - Account access (lines ~3500-3900) |
| 52 | + - CPI helpers (lines ~1900-3000) |
| 53 | + - Event emission (lines ~4000-4100) |
| 54 | + - Sysvar access (lines ~4100-4230) |
| 55 | + - PDA caching (lines ~4320-4500) |
| 56 | + |
| 57 | +## Building & Testing |
| 58 | + |
| 59 | +```bash |
| 60 | +# Build the crate |
| 61 | +cargo build -p ovsm |
| 62 | + |
| 63 | +# Run all tests |
| 64 | +cargo test -p ovsm |
| 65 | + |
| 66 | +# Run specific test module |
| 67 | +cargo test -p ovsm sexpr # Lexer/parser tests |
| 68 | +cargo test -p ovsm lisp_evaluator # Evaluator tests |
| 69 | + |
| 70 | +# Compile an OVSM file to sBPF |
| 71 | +cargo run --bin osvm -- ovsm compile input.ovsm -o output.so |
| 72 | +``` |
| 73 | + |
| 74 | +## Adding New Macros |
| 75 | + |
| 76 | +When implementing new macros in `compiler/ir.rs`: |
| 77 | + |
| 78 | +1. **Location**: Add after existing similar macros (e.g., CPI macros near other CPIs) |
| 79 | +2. **Pattern**: Match on `name == "macro-name" && args.len() == N` |
| 80 | +3. **Registers**: Use `self.alloc_reg()` for temp registers |
| 81 | +4. **Instructions**: Emit via `self.emit(IrInstruction::*)` |
| 82 | +5. **Return**: Always `return Ok(Some(result_reg))` or `Ok(Some(zero))` |
| 83 | + |
| 84 | +Example: |
| 85 | +```rust |
| 86 | +if name == "my-macro" && args.len() == 2 { |
| 87 | + let arg1 = self.generate_expr(&args[0].value)? |
| 88 | + .ok_or_else(|| Error::runtime("arg1 has no result"))?; |
| 89 | + let result = self.alloc_reg(); |
| 90 | + self.emit(IrInstruction::ConstI64(result, 42)); |
| 91 | + return Ok(Some(result)); |
| 92 | +} |
| 93 | +``` |
| 94 | + |
| 95 | +## Important Constants |
| 96 | + |
| 97 | +- **Account size**: 10336 bytes in serialized input |
| 98 | +- **Account offsets**: |
| 99 | + - is_signer: +1 |
| 100 | + - is_writable: +2 |
| 101 | + - owner: +40 |
| 102 | + - lamports: +56 |
| 103 | + - data_len: +64 |
| 104 | + - data: +72 |
| 105 | +- **Input pointer (R1)**: 1 |
| 106 | +- **Heap base**: 0x300000000 |
| 107 | + |
| 108 | +## Available Macros Reference |
| 109 | + |
| 110 | +### Struct Operations |
| 111 | +- `define-struct`, `struct-size`, `struct-offset`, `struct-field-size` |
| 112 | +- `struct-get`, `struct-set`, `struct-ptr`, `struct-idl` |
| 113 | + |
| 114 | +### Account Access |
| 115 | +- `account-data-ptr`, `account-data-len`, `account-lamports` |
| 116 | +- `is-signer`, `is-writable`, `assert-signer`, `assert-writable`, `assert-owner` |
| 117 | +- `zerocopy-load`, `zerocopy-store` |
| 118 | + |
| 119 | +### CPI Helpers |
| 120 | +- `system-transfer`, `system-create-account` |
| 121 | +- `spl-token-transfer`, `spl-token-transfer-signed` |
| 122 | +- `spl-token-mint-to`, `spl-token-burn` |
| 123 | + |
| 124 | +### PDA Operations |
| 125 | +- `derive-pda`, `create-pda`, `get-ata` |
| 126 | +- `pda-cache-init`, `pda-cache-store`, `pda-cache-lookup` |
| 127 | + |
| 128 | +### Events & Sysvars |
| 129 | +- `emit-event`, `emit-log` |
| 130 | +- `clock-unix-timestamp`, `clock-epoch`, `rent-minimum-balance` |
| 131 | +- `instruction-count`, `assert-not-cpi` |
| 132 | + |
| 133 | +### Borsh Serialization |
| 134 | +- `borsh-serialize`, `borsh-deserialize`, `borsh-size` |
| 135 | + |
| 136 | +## Test Coverage |
| 137 | + |
| 138 | +- 469/469 tests passing (100%) |
| 139 | +- Integration tests in `tests/lisp_e2e_tests.rs` |
| 140 | +- Compilation tests in `/tmp/*.ovsm` during development |
0 commit comments