Skip to content

Conversation

notdanilo
Copy link
Contributor

@notdanilo notdanilo commented Aug 6, 2025

Status Type ⚠️ Core Change Issue
Ready Feature Yes #194

Problem

Systems serializes and returns the components data with a limit of 1024kb so the component program can take the data and write it back.

Solution

Change the whole execution logic.

  1. Component program gives ownership of the component to the system program.
  2. System program executes and changes it.
  3. System program gives ownership back to the component program.
  4. World program checks if the system program gave the ownership back.

Breaking changes:

  1. This requires an intermediate Buffer account to hold the data while we change ownership and the clients needs to be updated to add the Buffer account to the transaction. The API is the same, but everyone has to update the client code.
  2. The execute function signature changed. We no longer return the serialized data.
  3. BoltMetadata was moved to the top of the component structure

CU report:

Small bar is CPI cost
Big bar is total cost

Previous

%%{init: {"xyChart": {"width": 1200, "height": 400, "xAxis": {}}}}%%
xychart
    title "Bolt Apply System Cost"
    x-axis ["1C-CPIs:2","2C-CPIs:3","3C-CPIs:4","4C-CPIs:5","5C-CPIs:6","6C-CPIs:7","7C-CPIs:8","8C-CPIs:9","9C-CPIs:10","10C-CPIs:11"]
    y-axis "CU" 5000 --> 200000
    bar [15254,24352,33653,43017,52358,61568,71006,80482,89958,99299]
    bar [6162,11236,16305,21374,26443,31516,36608,41892,46984,52077]
Loading

Using Anchor CPI code

%%{init: {"xyChart": {"width": 1200, "height": 400, "xAxis": {}}}}%%
xychart
    title "Bolt Apply System Cost"
    x-axis ["1C-CPIs:5","2C-CPIs:9","3C-CPIs:13","4C-CPIs:17","5C-CPIs:21","6C-CPIs:25","7C-CPIs:29","8C-CPIs:33","9C-CPIs:0","10C-CPIs:0"]
    y-axis "CU" 5000 --> 200000
    bar [24092,41860,59800,77799,95615,113456,131593,149581,0,0]
    bar [6920,12931,18925,24915,30909,36900,42977,49059,0,0]
Loading

Using Solana CPI code

%%{init: {"xyChart": {"width": 1200, "height": 400, "xAxis": {}}}}%%
xychart
    title "Bolt Apply System Cost"
    x-axis ["1C-CPIs:5","2C-CPIs:9","3C-CPIs:13","4C-CPIs:17","5C-CPIs:21","6C-CPIs:25","7C-CPIs:29","8C-CPIs:33","9C-CPIs:37","10C-CPIs:40"]
    y-axis "CU" 5000 --> 200000
    bar [20119,34196,48290,62402,76546,90715,104998,119314,133655,0]
    bar [6919,12930,18924,24914,30908,36899,42976,49058,55137,59718]
Loading

Greptile Summary

This PR implements a fundamental architectural redesign of the Bolt ECS framework to eliminate a critical 1024-byte limitation in component data serialization. Previously, systems would serialize component data and return it to component programs for storage, creating both size constraints and performance bottlenecks. The new execution model implements an ownership transfer pattern that allows systems to directly modify components of any size.

The core workflow changes from data serialization to ownership transfer: (1) Component programs transfer ownership of component accounts to system programs via a Buffer account, (2) System programs execute and directly modify component data in-place, (3) System programs return ownership back to component programs, and (4) World programs validate that ownership was properly restored. This eliminates the serialization step entirely while maintaining the ECS paradigm.

Key architectural changes include:

  • Function signatures: System execute functions now return Result<()> instead of Result<Components>, removing the serialization requirement
  • New instructions: Added set_owner and set_data instructions for ownership manipulation and data copying from buffer accounts
  • BoltMetadata positioning: Moved to the top of component structures to support the ownership transfer protocol
  • Buffer accounts: Introduction of intermediate Buffer PDAs derived from authority keys to hold data during ownership transitions
  • CPI authentication: Enhanced cross-program invocation security through FindCpiAuthPda() for ownership transfer authorization
  • Client API changes: All apply operations now require buffer accounts, breaking existing client implementations

The implementation spans multiple language clients (TypeScript, C#) and removes multi-component apply instructions (apply2-apply5) in favor of the new unified ownership-based approach. The BoltAccount wrapper enables dynamic ownership validation during deserialization using const generics. While this change addresses the size limitation and improves performance, it requires comprehensive client code updates to include Buffer accounts in transactions.

Confidence score: 2/5

  • This PR has significant implementation gaps and critical bugs that make it unsafe to merge in its current state
  • Score reflects incomplete implementations in core system programs, infinite recursion bugs in C# client code, and placeholder functions that don't perform required operations
  • Pay close attention to crates/programs/bolt-system/src/lib.rs, crates/programs/bolt-component/src/lib.rs, and clients/csharp/Solana.Unity.Bolt/WorldProgram/World.cs which contain empty implementations and serious bugs

@notdanilo notdanilo self-assigned this Aug 6, 2025
@notdanilo notdanilo force-pushed the feature/system-updates-components branch from ea29cb2 to 3aee912 Compare August 14, 2025 14:06
@notdanilo notdanilo marked this pull request as ready for review August 14, 2025 20:00
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

58 files reviewed, 10 comments

Edit Code Review Bot Settings | Greptile

@notdanilo notdanilo changed the title 🚧 WIP - System directly updates components ✨ System directly updates components Aug 14, 2025
@notdanilo notdanilo force-pushed the feature/system-updates-components branch from 4df93f7 to 0fee5dc Compare August 14, 2025 20:10
@GabrielePicco GabrielePicco requested a review from Copilot August 18, 2025 12:18
Copy link

@Copilot Copilot AI left a comment

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 implements a fundamental architectural redesign of the Bolt ECS framework to address the 1024-byte limitation in component data serialization. The system transitions from a serialization-based approach to an ownership transfer pattern, allowing systems to directly modify components of any size without serialization bottlenecks.

Key changes include:

  • Complete overhaul of the execution flow where component programs transfer ownership to system programs via buffer accounts
  • Replacement of component data serialization with direct ownership manipulation through new set_owner and set_data instructions
  • Introduction of buffer PDAs and enhanced CPI authentication for secure ownership transfers

Reviewed Changes

Copilot reviewed 48 out of 61 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
scripts/test.sh Deleted entire test script file
examples/system-*/src/lib.rs Updated system execute functions to return Result<()> instead of Result<Components>
crates/programs/world/src/lib.rs Major refactor implementing ownership transfer pattern with buffer accounts and new CPI instructions
crates/programs/bolt-system/src/lib.rs Added placeholder implementations for set_data and set_owner instructions
crates/programs/bolt-component/src/lib.rs Replaced update functions with set_owner and set_data instructions
crates/bolt-lang/src/account.rs New BoltAccount wrapper for dynamic ownership validation using const generics
crates/bolt-lang/attribute/component-deserialize/src/lib.rs Enhanced component deserialization with proper Anchor discriminator calculation
clients/typescript/src/world/transactions.ts Updated client code to include buffer accounts in all apply operations
clients/csharp/Solana.Unity.Bolt/WorldProgram/World.cs Added buffer PDA support and updated apply system calls

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

Copy link
Contributor

@GabrielePicco GabrielePicco left a comment

Choose a reason for hiding this comment

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

Thanks @notdanilo for the PR. Overall, I think the implementation is a good idea.
It raises the limit from 1KB total component size per system apply to 10KB per component (limited by buffer creation), which should cover most use cases.

The only issue I see is the increased number of CPIs. To summarize, this was the previous flow:

sequenceDiagram
    participant WP as World Program
    participant SYS as System
    participant COMP as Component

    WP->>SYS: execute_system()
    SYS-->>WP: return_data
    WP->>COMP: set_component_data(return_data)
Loading

New flow:

sequenceDiagram
    participant WP as World Program
    participant COMP as Component
    participant SYS as System

    Note over WP: Copy component data to buffer
    WP->>COMP: set_owner(system)
    WP->>SYS: set_data(buffer)
    WP->>SYS: execute()

    Note over WP: Copy component data to buffer
    WP->>SYS: set_owner(component)
    WP->>COMP: set_data(buffer)
Loading

This results in 4×N + 1 CPIs (where N is the number of components) vs. N + 1 CPIs in the previous flow.

We should report a table of CU consumption with varying numbers of components (e.g., 1 to 5) to understand whether the CU increase is acceptable.

The Pinocchio reimplementation of the world program would improve this, but we should also consider alternatives if consumption increases too much, such as:

  • Having components directly owned by the world program
  • Using an account as a scratch pad to replace the return_data

@notdanilo notdanilo force-pushed the feature/system-updates-components branch 2 times, most recently from 0f83bd9 to 50355ed Compare August 28, 2025 14:07
@notdanilo notdanilo force-pushed the feature/system-updates-components branch from 50355ed to 598678a Compare August 29, 2025 10:01
@notdanilo notdanilo force-pushed the feature/system-updates-components branch from 520e6e5 to 3645bcb Compare September 8, 2025 15:10
@notdanilo notdanilo force-pushed the feature/system-updates-components branch from d806260 to b0d65fa Compare September 9, 2025 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants