Skip to content

Commit 51f9f75

Browse files
committed
First draft
1 parent 4b1eaaf commit 51f9f75

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
---
2+
simd: '0177'
3+
title: Program Runtime ABI v2
4+
authors:
5+
- Alexander Meißner
6+
category: Standard
7+
type: Core
8+
status: Draft
9+
created: 2024-10-01
10+
feature: TBD
11+
---
12+
13+
## Summary
14+
15+
Align the layout of the virtual address space to large pages in order to avoid
16+
account data copies while maintaining a simple address translation logic.
17+
18+
## Motivation
19+
20+
At the moment all validator implementations have to copy (and compare) data in
21+
and out of the virtual memory of the virtual machine. There are four possible
22+
account data copy paths:
23+
24+
- Serialization: Copy from program runtime (host) to virtual machine (guest)
25+
- CPI call: Copy from virtual machine (guest) to program runtime (host)
26+
- CPI return: Copy from program runtime (host) to virtual machine (guest)
27+
- Deserialization: Copy from virtual machine (guest) to program runtime (host)
28+
29+
To avoid this a feature named "direct mapping" was designed which uses the
30+
address translation logic of the virtual machine to emulate the serialization
31+
and deserialization without actually performing copies.
32+
33+
Implementing direct mapping in the current ABI v0 and v1 was deemed to complex
34+
because of unaligned virtual memory regions and memory accesses overlapping
35+
multiple virtual memory regions. Instead the layout of the virtual address
36+
space should be adjusted so that all virtual memory regions are aligned to
37+
4 GiB.
38+
39+
## Alternatives Considered
40+
41+
What alternative designs were considered and what pros/cons does this feature
42+
have relative to them?
43+
44+
## New Terminology
45+
46+
None.
47+
48+
## Detailed Design
49+
50+
SDKs will have to support both ABI v1 and v2 for a transition period. The
51+
program runtime must only use ABI v2 if all programs in a transaction support
52+
it. Programs signal their support through their SBPF version field (TBD) while
53+
the program runtime signals which ABI is chosen through the serialized magic
54+
field.
55+
56+
### The serialization interface
57+
58+
- Writing to readonly accounts fails the transaction, even if the exact same
59+
data is written as already is there, thus even if no change occurs.
60+
- The is-executable-flag is never set.
61+
- The next rent collection epoch is not serialized.
62+
- Readonly instruction accounts get no growth padding.
63+
- For writable instruction accounts additional capacity is allocated and mapped
64+
for potential account growth. The maximum capacity is the length of the account
65+
payload at the beginning of the transaction plus 10 KiB. CPI can not grow
66+
beyond what the caller allowed as top-level instructions limit the potential
67+
growth. Thus it makes sense to preallocate this capacity in the beginning of
68+
the transaction when the writable accounts are copied in case the transaction
69+
needs to be rolled back.
70+
71+
### The serialization layout
72+
73+
The following memory regions must be mapped into the virtual machine,
74+
each starting at a 4 GiB boundary in virtual address space:
75+
76+
- Writable header:
77+
- Magic: `u32`: `0x76494241` ("ABIv" encoded in ASCII)
78+
- ABI version `u32`: `0x00000002`
79+
- Pointer to instruction data: `u64`
80+
- Length of instruction data: `u32`
81+
- Number of unique instruction accounts: `u16`
82+
- Number of instruction accounts: `u16`
83+
- Program key: `[u8; 32]`
84+
- For each unique instruction account:
85+
- Key: `[u8; 32]`
86+
- Owner: `[u8; 32]`
87+
- Flags: `u64` (bit 8 is signer, bit 16 is writable)
88+
- Lamports: `u64`
89+
- Pointer to account payload: `u64`
90+
- Account payload length: `u64`
91+
- Instruction account index indirection for aliasing:
92+
- Index to unique instruction account: `u16`
93+
- Readonly instruction data
94+
- Writable payload of account #0
95+
- Readonly payload of account #1
96+
- Writable payload of account #2
97+
- Writable payload of account #3
98+
- ...
99+
100+
### CPI costs and limits
101+
102+
- CU costs for serialization of account payloads and instruction data in CPI
103+
are removed.
104+
- Instead a small cost of TBD CU per account is introduced.
105+
- The instruction account limit in CPI will be increased to 256.
106+
- The special treatment during CPI of instruction accounts with the
107+
`is_executable` flag set is removed
108+
109+
### CPI verification
110+
111+
- The following pointers must be on the stack or heap,
112+
otherwise `SyscallError::InvalidPointer` must be thrown:
113+
- The pointer in the array of `&[AccountInfo]` / `SolAccountInfo*`
114+
- The `AccountInfo::data` field,
115+
which is a `RefCell<&[u8]>` in `sol_invoke_signed_rust`
116+
- The following pointers must point to what was originally serialized in the
117+
input regions by the program runtime,
118+
otherwise `SyscallError::InvalidPointer` must be thrown:
119+
- `AccountInfo::key` / `SolAccountInfo::key`
120+
- `AccountInfo::owner` / `SolAccountInfo::owner`
121+
- `AccountInfo::lamports` / `SolAccountInfo::lamports`
122+
- `AccountInfo::data::ptr` / `SolAccountInfo::data`
123+
124+
## Impact
125+
126+
This change is expected to drastically reduce the CU costs if all programs in
127+
a transaction support it as the cost will no longer depend on the length of the
128+
instruction account payloads or instruction data. Additionally the limit on the
129+
number of instruction accounts passed in CPI is increased, which makes it
130+
possible to pass in all the transaction accounts in CPI.
131+
132+
Otherwise, the change will be hidden in the SDK and thus be invisible to the
133+
dApp developer.
134+
135+
## Security Considerations
136+
137+
What security implications/considerations come with implementing this feature?
138+
Are there any implementation-specific guidance or pitfalls?
139+
140+
## Drawbacks *(Optional)*
141+
142+
Why should we not do this?
143+
144+
## Backwards Compatibility
145+
146+
The magic field (`u32`) and version field (`u32`) of ABI v2 are placed at the
147+
beginning, where ABI v0 and v1 would otherwise indicate the number of
148+
instruction accounts as an `u64`. Because the older ABIs will never serialize
149+
more than a few hundred accounts, it is possible to differentiate the ABI
150+
that way without breaking the older layouts.

0 commit comments

Comments
 (0)