-
Notifications
You must be signed in to change notification settings - Fork 23
feat: Execute CommitDiff as BufferTask #616
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: snawaz/commit-diff
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| use std::sync::Arc; | ||
|
|
||
| use dlp::{ | ||
| args::{CommitDiffArgs, CommitStateArgs}, | ||
| args::{CommitDiffArgs, CommitStateArgs, CommitStateFromBufferArgs}, | ||
| compute_diff, | ||
| }; | ||
| use dyn_clone::DynClone; | ||
|
|
@@ -52,7 +52,6 @@ pub enum PreparationState { | |
| Cleanup(CleanupTask), | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| #[derive(Copy, Clone, PartialEq, Eq, Debug)] | ||
| pub enum TaskStrategy { | ||
| Args, | ||
|
|
@@ -152,7 +151,7 @@ impl CommitTaskBuilder { | |
| allow_undelegation, | ||
| committed_account, | ||
| base_account, | ||
| force_commit_state: false, | ||
| strategy: TaskStrategy::Args, | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -163,29 +162,46 @@ pub struct CommitTask { | |
| pub allow_undelegation: bool, | ||
| pub committed_account: CommittedAccount, | ||
| base_account: Option<Account>, | ||
| force_commit_state: bool, | ||
| strategy: TaskStrategy, | ||
| } | ||
|
|
||
| impl CommitTask { | ||
| pub fn is_commit_diff(&self) -> bool { | ||
| !self.force_commit_state | ||
| && self.committed_account.account.data.len() | ||
| > CommitTaskBuilder::COMMIT_STATE_SIZE_THRESHOLD | ||
| && self.base_account.is_some() | ||
| } | ||
|
|
||
| pub fn force_commit_state(&mut self) { | ||
| self.force_commit_state = true; | ||
| pub fn switch_to_buffer_strategy(mut self) -> Self { | ||
| self.strategy = TaskStrategy::Buffer; | ||
| self | ||
| } | ||
|
|
||
| pub fn create_commit_ix(&self, validator: &Pubkey) -> Instruction { | ||
| if let Some(fetched_account) = self.base_account.as_ref() { | ||
| self.create_commit_diff_ix(validator, fetched_account) | ||
| } else { | ||
| self.create_commit_state_ix(validator) | ||
| match self.strategy { | ||
| TaskStrategy::Args => { | ||
| if let Some(base_account) = self.base_account.as_ref() { | ||
| self.create_commit_diff_ix(validator, base_account) | ||
| } else { | ||
| self.create_commit_state_ix(validator) | ||
| } | ||
| } | ||
| TaskStrategy::Buffer => { | ||
| if let Some(base_account) = self.base_account.as_ref() { | ||
| self.create_commit_diff_from_buffer_ix( | ||
| validator, | ||
| base_account, | ||
| ) | ||
| } else { | ||
| self.create_commit_state_from_buffer_ix(validator) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| pub fn compute_diff(&self) -> Option<dlp::rkyv::AlignedVec> { | ||
| self.base_account.as_ref().map(|base_account| { | ||
| compute_diff( | ||
| base_account.data(), | ||
| self.committed_account.account.data(), | ||
| ) | ||
| }) | ||
| } | ||
|
|
||
|
Comment on lines
+196
to
+204
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Reuse
Not a bug, but you could slightly simplify and DRY this by delegating to let diff = self
.compute_diff()
.expect("base_account must be Some when using CommitDiff");before constructing Also applies to: 220-232 🤖 Prompt for AI Agents |
||
| fn create_commit_state_ix(&self, validator: &Pubkey) -> Instruction { | ||
| let args = CommitStateArgs { | ||
| nonce: self.commit_id, | ||
|
|
@@ -204,17 +220,13 @@ impl CommitTask { | |
| fn create_commit_diff_ix( | ||
| &self, | ||
| validator: &Pubkey, | ||
| fetched_account: &Account, | ||
| base_account: &Account, | ||
| ) -> Instruction { | ||
| if self.force_commit_state { | ||
| return self.create_commit_state_ix(validator); | ||
| } | ||
|
|
||
| let args = CommitDiffArgs { | ||
| nonce: self.commit_id, | ||
| lamports: self.committed_account.account.lamports, | ||
| diff: compute_diff( | ||
| fetched_account.data(), | ||
| base_account.data(), | ||
| self.committed_account.account.data(), | ||
| ) | ||
| .to_vec(), | ||
|
Comment on lines
220
to
232
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial ❓ Verification inconclusiveBuffer-based commit instruction builders are consistent with PreparationTask PDAs but currently untested The new
This is structurally sound and lines up with how One gap is tests: the
That would give direct coverage of the new buffer commit paths. Also applies to: 244-268, 269-293 🏁 Script executed: #!/bin/bash
# Inspect existing tests that mention commit_*from_buffer and BufferTask usage
rg -n "commit_.*from_buffer" magicblock-committor-service
rg -n "BufferTask::new_preparation_required" magicblock-committor-serviceLength of output: 1114 I need to locate and inspect the test files to verify the coverage claim. Let me search for tests related to buffer tasks and instruction serialization. Length of output: 195 Let me fix the command syntax: Length of output: 109 Now let me inspect the actual test implementation to verify the review's claim: Length of output: 3040 Let me inspect the CommitTaskBuilder and BufferTask instruction method to understand the dispatch logic: Length of output: 1417 Let me get more of the create_commit_task implementation and locate the instruction method: Length of output: 2056 Now let me see the complete create_commit_ix match statement and the BufferTask::instruction() method: Length of output: 2419 Let me search more specifically for the BufferTask instruction method: Length of output: 1871 Let me search across all files for BufferTask definition: Length of output: 155 Now let me examine the BufferTask implementation: Length of output: 3557 Add tests for buffer instruction builders to ensure coverage of new The To cover these paths, either:
🤖 Prompt for AI Agents |
||
|
|
@@ -228,6 +240,57 @@ impl CommitTask { | |
| args, | ||
| ) | ||
| } | ||
|
|
||
| fn create_commit_state_from_buffer_ix( | ||
| &self, | ||
| validator: &Pubkey, | ||
| ) -> Instruction { | ||
| let commit_id_slice = self.commit_id.to_le_bytes(); | ||
| let (commit_buffer_pubkey, _) = | ||
| magicblock_committor_program::pdas::buffer_pda( | ||
| validator, | ||
| &self.committed_account.pubkey, | ||
| &commit_id_slice, | ||
| ); | ||
|
|
||
| dlp::instruction_builder::commit_state_from_buffer( | ||
| *validator, | ||
| self.committed_account.pubkey, | ||
| self.committed_account.account.owner, | ||
| commit_buffer_pubkey, | ||
| CommitStateFromBufferArgs { | ||
| nonce: self.commit_id, | ||
| lamports: self.committed_account.account.lamports, | ||
| allow_undelegation: self.allow_undelegation, | ||
| }, | ||
| ) | ||
| } | ||
|
|
||
| fn create_commit_diff_from_buffer_ix( | ||
| &self, | ||
| validator: &Pubkey, | ||
| _fetched_account: &Account, | ||
| ) -> Instruction { | ||
| let commit_id_slice = self.commit_id.to_le_bytes(); | ||
| let (commit_buffer_pubkey, _) = | ||
| magicblock_committor_program::pdas::buffer_pda( | ||
| validator, | ||
| &self.committed_account.pubkey, | ||
| &commit_id_slice, | ||
| ); | ||
|
|
||
| dlp::instruction_builder::commit_diff_from_buffer( | ||
| *validator, | ||
| self.committed_account.pubkey, | ||
| self.committed_account.account.owner, | ||
| commit_buffer_pubkey, | ||
| CommitStateFromBufferArgs { | ||
| nonce: self.commit_id, | ||
| lamports: self.committed_account.account.lamports, | ||
| allow_undelegation: self.allow_undelegation, | ||
| }, | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| #[derive(Clone)] | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
BufferTask now writes diff-or-state into buffer; ensure CommitTask is always in Buffer strategy when used here
Using
commit_task.compute_diff()to decide whether to write a diff or full state intoPreparationTask.committed_data, and derivingChunksfrom that length, is the right behavior for committing via buffers: buffer contents and chunking will match what*_from_bufferinstructions expect.One subtle requirement, though, is that the embedded
CommitTaskmust havestrategy == TaskStrategy::Buffer; otherwiseinstruction()will still emit the args-based commit instruction and completely ignore the prepared buffer, wasting the prep work and potentially re‑hitting tx-size limits.Since
ArgsTask::optimizealready callsvalue.switch_to_buffer_strategy()before wrapping inBufferTaskType::Commit, this is satisfied for the main flow, but any other construction ofBufferTask::Commit(including the tests) currently relies on the caller remembering to switch strategies.Consider tightening this by either:
BufferTask::new_preparation_required(orpreparation_required) assert in debug builds that the innerCommitTaskhasTaskStrategy::Buffer, and/orswitch_to_buffer_strategy()call into theBufferTaskconstruction path so callers cannot accidentally pass an Args‑strategy commit task.That would make BufferTask semantics self-contained and prevent silent misuse.
Also applies to: 65-77
🤖 Prompt for AI Agents