Skip to content

refactor: rework adress definitions & introduce region reservation#7

Draft
nagisa wants to merge 26 commits into
anza-xyz:masterfrom
nagisa:abiv2-address-definition-refactor
Draft

refactor: rework adress definitions & introduce region reservation#7
nagisa wants to merge 26 commits into
anza-xyz:masterfrom
nagisa:abiv2-address-definition-refactor

Conversation

@nagisa

@nagisa nagisa commented Jun 11, 2026

Copy link
Copy Markdown

In order to introduce sysvar regions, it is becoming necessary to make our address space allocation somewhat more future proof. One of such future proofing example is allocating enough reserved space for account payloads if we were to increase the number of accounts that can be specified in a transaction.

This, however, introduces a concept of a "gap" between regions which did not exist before and complicates the conversions between region indices and guest addresses.

After a few experiments I found that adding a structure and some methods to describe the expected memory layout is the least ugly option. As we only have one gap currently, the conversion in either direction is still relatively straightforward.

yihau and others added 25 commits June 8, 2026 23:00
Having host addresses represented by VmSlice seems not right? I switched
those functions to return a regular raw pointer. Which in turn
simplified the memory mapping creation somewhat.
* Create tests

* @nagisa's review
* Write function to update account permissions

* Add unit test

* Add integration test

* Use all accounts as mutable
Co-authored-by: Lucas <lucas.tnagel@gmail.com>
* Fix account mapping

* Add test and fix edge case

* Verify account owner for permissions

* Fix rebase problems

* Remove optimization

* Change condition

* @nagisa's review

* Update program-runtime/src/memory_context.rs

Co-authored-by: Simonas Kazlauskas <github@kazlauskas.me>

* Format file

---------

Co-authored-by: Simonas Kazlauskas <github@kazlauskas.me>
* Implement syscall

* Write a test

* Amend function with writability change

* Finish implementation

* Specify index in transction

* @nagisa's review
* Implement syscall

* Write integration test

* @nagisa's review

* Change name
In order to introduce sysvar regions, it is becoming necessary to make
our address space allocation somewhat more future proof. One of such
future proofing example is allocating enough reserved space for account
payloads if we were to increase the number of accounts that can be
specified in a transaction.

This, however, introduces a concept of a "gap" between regions which did
not exist before and complicates the conversions between region indices
and guest addresses.

After a few experiments I found that adding a structure and some methods
to describe the expected memory layout is the least ugly option.
@nagisa nagisa requested a review from Copilot June 11, 2026 14:32
@nagisa nagisa requested a review from a team as a code owner June 11, 2026 14:32
Lichtso
Lichtso previously approved these changes Jun 11, 2026
Lichtso
Lichtso previously approved these changes Jun 11, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors ABIv2 guest memory address definitions by introducing a GuestMemorySection abstraction, and extends the memory layout to reserve space for future “sysvar regions” via an address-space gap.

Changes:

  • Introduce GuestMemorySection to describe guest memory layout in a structured way and compute per-section region indices/guest address ranges.
  • Add a reserved “gap” to support sysvar regions while keeping region indices contiguous.
  • Update transaction context, syscalls, and memory mapping code to use section-based address/range calculations instead of hard-coded base constants.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
transaction-context/src/vm_addresses.rs Adds GuestMemorySection, defines the new ABIv2 section layout, introduces sysvar reservation, and computes NUM_REGIONS.
transaction-context/src/transaction.rs Updates scratchpad and region computations to use GuestMemorySection; adjusts region resize dispatch.
transaction-context/src/transaction_accounts.rs Switches account payload region addressing to section-based ranges.
transaction-context/src/instruction.rs Updates instruction frame VM slice addressing to section-based ranges.
transaction-context/src/instruction_accounts.rs Updates resize payload VM address computation to section-based ranges.
syscalls/src/lib.rs Updates region index/address handling and adjusts tests to iterate the new section layout.
program-runtime/src/memory_context.rs Reworks ABIv2 region construction using the new section model (but currently contains debug leftovers).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +92 to 103
return_data_scratchpad: VmSlice::new(
vm_addresses::RETURN_DATA_SCRATCHPAD_SECTION
.guest_address_range()
.start,
0,
),
cpi_scratchpad: VmSlice::new(
GUEST_INSTRUCTION_DATA_BASE_ADDRESS.saturating_add(
GUEST_REGION_SIZE.saturating_mul(number_of_top_level_instructions as u64),
),
vm_addresses::INSTRUCTION_DATA_SECTION
.guest_address_range()
.start,
0,
),
Comment on lines 301 to 311
if let Some(caller_index) = caller_index {
self.transaction_frame.total_number_of_instructions_in_trace = self
.transaction_frame
.total_number_of_instructions_in_trace
.saturating_add(1);
instruction.index_of_caller_instruction = caller_index;
let next_ptr = self
.transaction_frame
.cpi_scratchpad
.ptr()
.saturating_add(GUEST_REGION_SIZE);
self.transaction_frame.cpi_scratchpad = VmSlice::new(next_ptr, 0);
let section = vm_addresses::INSTRUCTION_DATA_SECTION;
let scratchpad_addrs =
section.guest_address_range_for(caller_index.saturating_add(1) as usize);
self.transaction_frame.cpi_scratchpad = VmSlice::new(scratchpad_addrs.start, 0);
}
Comment on lines +734 to 741
a if vm_addresses::INSTRUCTION_DATA_SECTION.contains_guest_ptr(a) => {
if !old_region.writable {
return Err(InstructionError::InvalidArgument);
}
let ix_address = vm_address
.checked_sub(GUEST_INSTRUCTION_DATA_BASE_ADDRESS)
let ix_idx = vm_addresses::INSTRUCTION_ACCOUNTS_SECTION
.region_index_containing(a)
.ok_or(InstructionError::InvalidArgument)?;
let ix_idx = abiv2_region_index_from_vm_address(ix_address);
let ix = self.instruction_data.get_mut(ix_idx);
Comment on lines 1135 to 1140
assert_eq!(
transaction_context.transaction_frame.cpi_scratchpad.ptr(),
GUEST_INSTRUCTION_DATA_BASE_ADDRESS.saturating_add(GUEST_REGION_SIZE.saturating_mul(3))
vm_addresses::INSTRUCTION_ACCOUNTS_SECTION
.guest_address_range_for(3)
.start
);
Comment thread program-runtime/src/memory_context.rs
Comment on lines +299 to 303
let section = INSTRUCTION_ACCOUNTS_SECTION;
let regions = v2_regions
.get_mut(dbg!(section.region_index_range()))
.unwrap();
transaction_context.instruction_accounts_regions(regions);
Comment on lines +139 to +143
pub const INSTRUCTION_DATA_SECTION: GuestMemorySection =
GuestMemorySection::new_following(SYSVAR_ACCOUNT_SECTION, MAX_INSTRUCTION_TRACE_LENGTH);
pub const INSTRUCTION_ACCOUNTS_SECTION: GuestMemorySection =
GuestMemorySection::new_following(INSTRUCTION_DATA_SECTION, MAX_INSTRUCTION_TRACE_LENGTH);

@nagisa

nagisa commented Jun 11, 2026

Copy link
Copy Markdown
Author

Looks like I'll need to make modifications to sbpf before this can land – AlignedMemoryMapping has code internally to create all the intermediate mappings that are now making things go wrong, or maybe this idea is bust actually... will find out.

@nagisa nagisa marked this pull request as draft June 11, 2026 15:13
@Lichtso

Lichtso commented Jun 11, 2026

Copy link
Copy Markdown

What things go wrong?

How is this different from what we had before when AlignedMemoryMapping skipped the first region where the text section / bytecode resides (before SBPFv3)?

@nagisa

nagisa commented Jun 11, 2026

Copy link
Copy Markdown
Author

What things go wrong?

How is this different from what we had before when AlignedMemoryMapping skipped the first region where the text section / bytecode resides (before SBPFv3)?

Well, I guess its not AlignedMemoryMapping that's going wrong, but there's definitely a mismatch between what this PR is implementing and what AlignedMemoryMapping is implementing. To start with, AlignedMemoryMapping still creates all the 0x10??? mappings to fill the reserved gap I allocated for the accounts. If we continue including the filler regions with AlignedMemoryMapping, there's little point to this PR, other than it being a very slightly nicer to read code.

And then we still have some code that directly deal with get_regions_mut() but now that has all those introduced fake regions that the new code on agave size disagrees with.


There's point to be made that we might be fine with those filler regions being present, as it how we achieve efficient address translation. When we start reusing the MemoryMapping between transactions this mapping setup becomes a simple 2MB allocation per processing thread and is fully amortized at startup.

But either way I need to rewrite some code 😓

@LucasSte LucasSte dismissed Lichtso’s stale review June 23, 2026 21:16

The merge-base changed after approval.

LucasSte added a commit that referenced this pull request Jun 23, 2026
* Fix account mapping

* Add test and fix edge case

* Verify account owner for permissions

* Fix rebase problems

* Remove optimization

* Change condition

* @nagisa's review

* Update program-runtime/src/memory_context.rs

Co-authored-by: Simonas Kazlauskas <github@kazlauskas.me>

* Format file

---------

Co-authored-by: Simonas Kazlauskas <github@kazlauskas.me>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants