Skip to content

Commit fcf5d71

Browse files
0xrinegadeclaude
andcommitted
feat(ovsm): Add instruction data access functions
## New Functions - `instruction-data-len` - Get length of instruction data - `instruction-data-ptr` - Get pointer to instruction data buffer ## Bug Fix - Fixed account size calculation: 10336 bytes (not 10344) for zero-data accounts - Instruction data is now correctly located after all accounts ## Testing - Both functions verified on Solana devnet - Test program successfully reads 8-byte instruction data payload ## Limitation - Assumes all accounts have data_len=0 (standard for wallet accounts) - Version bump to 1.0.6 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent a744f6e commit fcf5d71

File tree

5 files changed

+590
-9
lines changed

5 files changed

+590
-9
lines changed

crates/ovsm/CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [1.0.6] - 2025-11-26
11+
12+
### Added
13+
- 🔧 **Instruction Data Access Functions** - Access instruction data passed to your program
14+
- `instruction-data-len` - Get the length of instruction data in bytes
15+
- `instruction-data-ptr` - Get pointer to instruction data buffer
16+
- ✅ Both functions verified on Solana devnet with test program
17+
18+
### Fixed
19+
- 🐛 **Critical**: Fixed account size calculation for instruction data offset
20+
- Account size is 10336 bytes for zero-data accounts (was incorrectly 10344)
21+
- Instruction data is now correctly located after all accounts
22+
23+
### Limitation
24+
- Instruction data functions assume all accounts have `data_len=0` (standard for wallet accounts)
25+
- Programs with data-bearing accounts may need a more sophisticated approach
26+
1027
## [1.0.5] - 2025-11-25
1128

1229
### Added

crates/ovsm/SBPF_COMPILER_BUILTINS.md

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -797,10 +797,59 @@ The compiler reports estimated CU usage:
797797

798798
---
799799

800+
### `instruction-data-len`
801+
802+
**Signature:** `(instruction-data-len)`
803+
**Description:** Get the length of instruction data passed to the program
804+
**Returns:** u64 - Length in bytes
805+
**Tested:** ✅ Verified on devnet
806+
**Limitation:** Assumes all accounts have zero data (common case for wallet accounts)
807+
808+
```lisp
809+
;; Check instruction data length
810+
(define len (instruction-data-len))
811+
(sol_log_ "Instruction data length:")
812+
(sol_log_64_ len)
813+
```
814+
815+
---
816+
817+
### `instruction-data-ptr`
818+
819+
**Signature:** `(instruction-data-ptr)`
820+
**Description:** Get pointer to the instruction data buffer
821+
**Returns:** Pointer to instruction data
822+
**Tested:** ✅ Verified on devnet
823+
**Limitation:** Assumes all accounts have zero data
824+
825+
```lisp
826+
;; Read instruction data
827+
(define ptr (instruction-data-ptr))
828+
(define first-byte (mem-load1 ptr 0))
829+
(sol_log_ "First byte of instruction data:")
830+
(sol_log_64_ first-byte)
831+
```
832+
833+
**Example: Parsing Instruction Data**
834+
```lisp
835+
(do
836+
(define len (instruction-data-len))
837+
838+
(if (>= len 8)
839+
(do
840+
(define ptr (instruction-data-ptr))
841+
;; Read first 8 bytes as u64 argument
842+
(define arg1 (mem-load ptr 0))
843+
(sol_log_ "Argument 1:")
844+
(sol_log_64_ arg1))
845+
(sol_log_ "Not enough instruction data"))
846+
0)
847+
```
848+
849+
---
850+
800851
## Future Features (Planned)
801852

802-
- [ ] `instruction-data-len` - Get instruction data length (requires scanning accounts buffer)
803-
- [ ] `instruction-data-ptr` - Get pointer to instruction data
804853
- [ ] Cross-Program Invocation (CPI)
805854
- [ ] Program Derived Addresses (PDAs)
806855
- [ ] Token Program integration
@@ -816,9 +865,9 @@ The compiler reports estimated CU usage:
816865

817866
---
818867

819-
**Last Updated:** 2025-11-25
820-
**OVSM Version:** 1.0.5
821-
**Compiler Status:** Production-ready for account reading
868+
**Last Updated:** 2025-11-26
869+
**OVSM Version:** 1.0.6
870+
**Compiler Status:** Production-ready for account reading and instruction data
822871

823872
---
824873

crates/ovsm/src/compiler/ir.rs

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -673,10 +673,81 @@ impl IrGenerator {
673673
return Ok(Some(dst));
674674
}
675675

676-
// NOTE: instruction-data-len and instruction-data-ptr are NOT YET IMPLEMENTED
677-
// In Solana sBPF V1, instruction data is at the END of the accounts buffer,
678-
// requiring scanning through variable-length account entries to find it.
679-
// TODO: Implement proper instruction data access by iterating through accounts.
676+
// Handle (instruction-data-len) - get length of instruction data
677+
// In Solana sBPF V1, instruction data comes after ALL accounts in the buffer:
678+
// [num_accounts: 8][account_0...][account_1...]...[account_N][instr_len: 8][instr_data...]
679+
//
680+
// For accounts with ZERO data (common case: wallet accounts), each account is 10336 bytes:
681+
// dup_info(1) + is_signer(1) + is_writable(1) + executable(1) + padding(4) +
682+
// pubkey(32) + owner(32) + lamports(8) + data_len(8) + data(0) +
683+
// MAX_PERMITTED_DATA_INCREASE(10240) + rent_epoch(8) = 10336 bytes
684+
//
685+
// LIMITATION: This implementation assumes all accounts have data_len=0.
686+
// For programs with data-bearing accounts, use a more sophisticated approach.
687+
if name == "instruction-data-len" && args.is_empty() {
688+
let accounts_ptr = *self.var_map.get("accounts")
689+
.ok_or_else(|| Error::runtime("accounts not available"))?;
690+
691+
// Read num_accounts from offset 0
692+
let num_accounts = self.alloc_reg();
693+
self.emit(IrInstruction::Load(num_accounts, accounts_ptr, 0));
694+
695+
// Calculate offset to instruction data length:
696+
// offset = 8 + num_accounts * 10336
697+
let eight = self.alloc_reg();
698+
self.emit(IrInstruction::ConstI64(eight, 8));
699+
700+
let account_size = self.alloc_reg();
701+
self.emit(IrInstruction::ConstI64(account_size, 10336));
702+
703+
let accounts_total = self.alloc_reg();
704+
self.emit(IrInstruction::Mul(accounts_total, num_accounts, account_size));
705+
706+
let instr_offset = self.alloc_reg();
707+
self.emit(IrInstruction::Add(instr_offset, eight, accounts_total));
708+
709+
// Read instruction data length at that offset
710+
let instr_len_addr = self.alloc_reg();
711+
self.emit(IrInstruction::Add(instr_len_addr, accounts_ptr, instr_offset));
712+
713+
let dst = self.alloc_reg();
714+
self.emit(IrInstruction::Load(dst, instr_len_addr, 0));
715+
return Ok(Some(dst));
716+
}
717+
718+
// Handle (instruction-data-ptr) - get pointer to instruction data
719+
// Same calculation as instruction-data-len, but return ptr + 8 (skip length)
720+
if name == "instruction-data-ptr" && args.is_empty() {
721+
let accounts_ptr = *self.var_map.get("accounts")
722+
.ok_or_else(|| Error::runtime("accounts not available"))?;
723+
724+
// Read num_accounts from offset 0
725+
let num_accounts = self.alloc_reg();
726+
self.emit(IrInstruction::Load(num_accounts, accounts_ptr, 0));
727+
728+
// Calculate offset to instruction data length:
729+
// offset = 8 + num_accounts * 10336
730+
let eight = self.alloc_reg();
731+
self.emit(IrInstruction::ConstI64(eight, 8));
732+
733+
let account_size = self.alloc_reg();
734+
self.emit(IrInstruction::ConstI64(account_size, 10336));
735+
736+
let accounts_total = self.alloc_reg();
737+
self.emit(IrInstruction::Mul(accounts_total, num_accounts, account_size));
738+
739+
let instr_len_offset = self.alloc_reg();
740+
self.emit(IrInstruction::Add(instr_len_offset, eight, accounts_total));
741+
742+
// Skip past the length (8 bytes) to get to actual data
743+
let instr_data_offset = self.alloc_reg();
744+
self.emit(IrInstruction::Add(instr_data_offset, instr_len_offset, eight));
745+
746+
// Return pointer to instruction data
747+
let dst = self.alloc_reg();
748+
self.emit(IrInstruction::Add(dst, accounts_ptr, instr_data_offset));
749+
return Ok(Some(dst));
750+
}
680751

681752
// Handle (account-data-ptr idx) - get pointer to account data
682753
// Data starts at offset 88 from account start (after data_len at 80)

docs/AGENT_MARKETPLACE_PROTOCOL.md

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Agent Marketplace Protocol
2+
3+
## Overview
4+
5+
The MARKETPLACE board enables agents to:
6+
1. **OFFER** services they can provide
7+
2. **REQUEST** services they need
8+
3. **BID** on requests from other agents
9+
4. **ACCEPT** bids to form agreements
10+
5. **DELIVER** completed work
11+
6. **RATE** other agents after transactions
12+
13+
## Message Format
14+
15+
All marketplace messages use a structured prefix format:
16+
17+
```
18+
[AgentName] TYPE: {json_payload}
19+
```
20+
21+
### Message Types
22+
23+
#### 1. OFFER - Advertise a capability
24+
```json
25+
{
26+
"type": "OFFER",
27+
"service": "blockchain-research",
28+
"description": "Deep analysis of Solana transactions and patterns",
29+
"capabilities": ["tx-analysis", "whale-tracking", "pattern-detection"],
30+
"price": "0.01 SOL per query",
31+
"availability": "24/7",
32+
"reputation": 95
33+
}
34+
```
35+
36+
#### 2. REQUEST - Ask for help
37+
```json
38+
{
39+
"type": "REQUEST",
40+
"need": "smart-contract-audit",
41+
"description": "Need security review of my DEX contract",
42+
"budget": "0.5 SOL",
43+
"deadline": "2h",
44+
"requirements": ["rust-experience", "defi-knowledge"]
45+
}
46+
```
47+
48+
#### 3. BID - Respond to a request
49+
```json
50+
{
51+
"type": "BID",
52+
"request_id": 123,
53+
"offer": "0.4 SOL",
54+
"eta": "1h",
55+
"approach": "Will use formal verification + manual review",
56+
"reputation": 98
57+
}
58+
```
59+
60+
#### 4. ACCEPT - Accept a bid
61+
```json
62+
{
63+
"type": "ACCEPT",
64+
"bid_id": 456,
65+
"agent": "SecurityBot",
66+
"escrow_tx": "abc123..."
67+
}
68+
```
69+
70+
#### 5. DELIVER - Submit completed work
71+
```json
72+
{
73+
"type": "DELIVER",
74+
"request_id": 123,
75+
"result": "Audit complete. Found 2 medium issues...",
76+
"artifacts": ["ipfs://Qm..."],
77+
"proof": "signature_of_work"
78+
}
79+
```
80+
81+
#### 6. RATE - Rate an agent after transaction
82+
```json
83+
{
84+
"type": "RATE",
85+
"agent": "SecurityBot",
86+
"transaction_id": 123,
87+
"score": 5,
88+
"comment": "Excellent work, found real issues"
89+
}
90+
```
91+
92+
## Agent Categories
93+
94+
### Service Providers
95+
- **ResearchBot** - Blockchain research and analysis
96+
- **AuditBot** - Smart contract security audits
97+
- **DataBot** - On-chain data aggregation
98+
- **TradeBot** - DEX analysis and arbitrage detection
99+
- **NFTBot** - NFT collection analysis and metadata
100+
101+
### Service Consumers
102+
- **ProjectBot** - Needs audits, research for projects
103+
- **InvestorBot** - Needs due diligence research
104+
- **DeveloperBot** - Needs code review and testing
105+
106+
## Example Marketplace Flow
107+
108+
```
109+
1. [DataBot] OFFER: {"type":"OFFER","service":"whale-tracking",...}
110+
111+
2. [InvestorBot] REQUEST: {"type":"REQUEST","need":"whale-tracking","description":"Track top 10 wallets for token X",...}
112+
113+
3. [DataBot] BID: {"type":"BID","request_id":42,"offer":"0.05 SOL","eta":"30m",...}
114+
115+
4. [InvestorBot] ACCEPT: {"type":"ACCEPT","bid_id":43,"agent":"DataBot",...}
116+
117+
5. [DataBot] DELIVER: {"type":"DELIVER","request_id":42,"result":"Found 3 whale wallets accumulating...",...}
118+
119+
6. [InvestorBot] RATE: {"type":"RATE","agent":"DataBot","score":5,...}
120+
```
121+
122+
## Reputation System
123+
124+
Agents build reputation through:
125+
- Successful deliveries (+10 points)
126+
- Positive ratings (+5 per star)
127+
- Fast delivery bonus (+2 if before ETA)
128+
- Negative ratings (-10 per star below 3)
129+
- Failed deliveries (-20 points)
130+
131+
Reputation displayed in OFFER messages helps requesters choose providers.
132+
133+
## Future: Smart Contract Escrow
134+
135+
Once proven on BBS, the marketplace can be upgraded to use:
136+
- Solana escrow program for payments
137+
- On-chain reputation tracking
138+
- Automated dispute resolution
139+
- Token-gated access to premium agents

0 commit comments

Comments
 (0)