Skip to content

Commit 375deef

Browse files
committed
First draft
1 parent 4b1eaaf commit 375deef

File tree

1 file changed

+149
-0
lines changed

1 file changed

+149
-0
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
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`: `0x41424976`
78+
- ABI version `u32`: `0x00000002`
79+
- Pointer to instruction data: `u64`
80+
- Length of instruction data: `u32`
81+
- Number of instruction accounts: `u32`
82+
- Program key: `[u8; 32]`
83+
- For each deduplicated instruction account:
84+
- Flags: `u64` (bit 8 is signer, bit 16 is writable)
85+
- Key: `[u8; 32]`
86+
- Owner: `[u8; 32]`
87+
- Lamports: `u64`
88+
- Pointer to account payload: `u64`
89+
- Account payload length: `u64`
90+
- Instruction account index indirection for aliasing:
91+
- Index to deduplicated instruction account: `u16`
92+
- Readonly instruction data
93+
- Writable payload of account #0
94+
- Readonly payload of account #1
95+
- Writable payload of account #2
96+
- Writable payload of account #3
97+
- ...
98+
99+
### CPI costs and limits
100+
101+
- CU costs for serialization of account payloads and instruction data in CPI
102+
are removed.
103+
- Instead a small cost of TBD CU per account is introduced.
104+
- The instruction account limit in CPI will be increased to 256.
105+
- The special treatment during CPI of instruction accounts with the
106+
`is_executable` flag set is removed
107+
108+
### CPI verification
109+
110+
- The following pointers must be on the stack or heap,
111+
otherwise `SyscallError::InvalidPointer` must be thrown:
112+
- The pointer in the array of `&[AccountInfo]` / `SolAccountInfo*`
113+
- The `AccountInfo::data` field,
114+
which is a `RefCell<&[u8]>` in `sol_invoke_signed_rust`
115+
- The following pointers must point to what was originally serialized in the
116+
input regions by the program runtime,
117+
otherwise `SyscallError::InvalidPointer` must be thrown:
118+
- `AccountInfo::key` / `SolAccountInfo::key`
119+
- `AccountInfo::owner` / `SolAccountInfo::owner`
120+
- `AccountInfo::lamports` / `SolAccountInfo::lamports`
121+
- `AccountInfo::data::ptr` / `SolAccountInfo::data`
122+
123+
## Impact
124+
125+
This change is expected to drastically reduce the CU costs if all programs in
126+
a transaction support it as the cost will no longer depend on the length of the
127+
instruction account payloads or instruction data. Additionally the limit on the
128+
number of instruction accounts passed in CPI is increased, which makes it
129+
possible to pass in all the transaction accounts in CPI.
130+
131+
Otherwise, the change will be hidden in the SDK and thus be invisible to the
132+
dApp developer.
133+
134+
## Security Considerations
135+
136+
What security implications/considerations come with implementing this feature?
137+
Are there any implementation-specific guidance or pitfalls?
138+
139+
## Drawbacks *(Optional)*
140+
141+
Why should we not do this?
142+
143+
## Backwards Compatibility
144+
145+
The magic field (`u32`) and version field (`u32`) of ABI v2 are placed at the
146+
beginning, where ABI v0 and v1 would otherwise indicate the number of
147+
instruction accounts as an `u64`. Because the older ABIs will never serialize
148+
more than a few hundred accounts, it is possible to differentiate the ABI
149+
that way without breaking the older layouts.

0 commit comments

Comments
 (0)