diff --git a/Cargo.lock b/Cargo.lock index 53c5b37cf..9d576d96e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2937,7 +2937,7 @@ dependencies = [ "magicblock-rpc-client", "rand 0.9.2", "solana-account", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-loader-v3-interface", "solana-loader-v4-interface", @@ -2963,7 +2963,7 @@ dependencies = [ "magicblock-committor-service", "magicblock-core", "magicblock-program", - "solana-hash", + "solana-hash 2.2.1", "solana-pubkey", "solana-transaction", "solana-transaction-error", @@ -3076,7 +3076,7 @@ dependencies = [ "solana-feature-set", "solana-fee-calculator", "solana-genesis-config", - "solana-hash", + "solana-hash 2.2.1", "solana-inline-spl", "solana-instruction", "solana-keypair", @@ -3086,7 +3086,7 @@ dependencies = [ "solana-pubkey", "solana-rent", "solana-rpc-client", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-signature", "solana-signer", "solana-system-program", @@ -3126,7 +3126,7 @@ dependencies = [ "solana-clock", "solana-commitment-config", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-loader-v3-interface", @@ -3192,7 +3192,7 @@ dependencies = [ "solana-address-lookup-table-interface", "solana-commitment-config", "solana-compute-budget-interface", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-message", @@ -3245,7 +3245,7 @@ dependencies = [ "magicblock-magic-program-api", "solana-account", "solana-account-decoder", - "solana-hash", + "solana-hash 2.2.1", "solana-program", "solana-pubkey", "solana-signature", @@ -3264,7 +3264,7 @@ dependencies = [ [[package]] name = "magicblock-delegation-program" version = "1.1.3" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372#2cb491032f372faa4cfdb55e3f05cefd7e07351d" +source = "git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fcommit-finalize-from-buffer#1347f31982a57762bd9321c91a021a3d32bebe05" dependencies = [ "bincode", "borsh 1.6.0", @@ -3279,6 +3279,7 @@ dependencies = [ "solana-curve25519", "solana-program", "solana-security-txt", + "solana-sha256-hasher 3.1.0", "static_assertions", "strum 0.27.2", "thiserror 2.0.17", @@ -3304,7 +3305,7 @@ dependencies = [ "serde", "solana-account-decoder", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-measure", @@ -3411,7 +3412,7 @@ dependencies = [ "solana-account-info", "solana-clock", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-log-collector", @@ -3437,7 +3438,7 @@ dependencies = [ "solana-address-lookup-table-interface", "solana-clock", "solana-commitment-config", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-pubkey", "solana-rpc-client", @@ -4351,7 +4352,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", - "heck 0.5.0", + "heck 0.4.1", "itertools 0.12.1", "log", "multimap", @@ -4371,7 +4372,7 @@ version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ - "heck 0.5.0", + "heck 0.4.1", "itertools 0.14.0", "log", "multimap", @@ -5641,7 +5642,7 @@ checksum = "75db7f2bbac3e62cfd139065d15bcda9e2428883ba61fc8d27ccb251081e7567" dependencies = [ "num-bigint 0.4.6", "num-traits", - "solana-define-syscall", + "solana-define-syscall 2.2.1", ] [[package]] @@ -5662,8 +5663,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1a0801e25a1b31a14494fc80882a036be0ffd290efc4c2d640bfcca120a4672" dependencies = [ "blake3", - "solana-define-syscall", - "solana-hash", + "solana-define-syscall 2.2.1", + "solana-hash 2.2.1", "solana-sanitize", ] @@ -5678,7 +5679,7 @@ dependencies = [ "ark-ff", "ark-serialize", "bytemuck", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "thiserror 2.0.17", ] @@ -5713,7 +5714,7 @@ dependencies = [ "solana-cpi", "solana-curve25519", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keccak-hasher", "solana-loader-v3-interface", @@ -5730,7 +5731,7 @@ dependencies = [ "solana-sbpf", "solana-sdk-ids", "solana-secp256k1-recover", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-stable-layout", "solana-system-interface", "solana-sysvar", @@ -5773,7 +5774,7 @@ dependencies = [ "solana-account", "solana-commitment-config", "solana-epoch-info", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-message", @@ -5806,7 +5807,7 @@ checksum = "7ace9fea2daa28354d107ea879cff107181d85cd4e0f78a2bedb10e1a428c97e" dependencies = [ "serde", "serde_derive", - "solana-hash", + "solana-hash 2.2.1", ] [[package]] @@ -5904,7 +5905,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8dc71126edddc2ba014622fc32d0f5e2e78ec6c5a1e0eb511b85618c09e9ea11" dependencies = [ "solana-account-info", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-instruction", "solana-program-error", "solana-pubkey", @@ -5920,7 +5921,7 @@ dependencies = [ "bytemuck", "bytemuck_derive", "curve25519-dalek 4.1.3", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "subtle", "thiserror 2.0.17", ] @@ -5940,6 +5941,12 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf784bb2cb3e02cac9801813c30187344228d2ae952534902108f6150573a33d" +[[package]] +name = "solana-define-syscall" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57e5b1c0bc1d4a4d10c88a4100499d954c09d3fecfae4912c1a074dff68b1738" + [[package]] name = "solana-derivation-path" version = "2.2.1" @@ -5984,7 +5991,7 @@ checksum = "86b575d3dd323b9ea10bb6fe89bf6bf93e249b215ba8ed7f68f1a3633f384db7" dependencies = [ "serde", "serde_derive", - "solana-hash", + "solana-hash 2.2.1", "solana-sdk-ids", "solana-sdk-macro", "solana-sysvar-id", @@ -5997,7 +6004,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c5fd2662ae7574810904585fd443545ed2b568dbd304b25a31e79ccc76e81b" dependencies = [ "siphasher", - "solana-hash", + "solana-hash 2.2.1", "solana-pubkey", ] @@ -6024,7 +6031,7 @@ dependencies = [ "serde_derive", "solana-address-lookup-table-interface", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keccak-hasher", "solana-message", @@ -6063,9 +6070,9 @@ dependencies = [ "ahash 0.8.12", "lazy_static", "solana-epoch-schedule", - "solana-hash", + "solana-hash 2.2.1", "solana-pubkey", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", ] [[package]] @@ -6129,7 +6136,7 @@ dependencies = [ "solana-cluster-type", "solana-epoch-schedule", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-inflation", "solana-keypair", "solana-logger", @@ -6138,7 +6145,7 @@ dependencies = [ "solana-pubkey", "solana-rent", "solana-sdk-ids", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-shred-version", "solana-signer", "solana-time-utils", @@ -6172,6 +6179,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "solana-hash" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5d48a6ee7b91fc7b998944ab026ed7b3e2fc8ee3bc58452644a86c2648152f" + [[package]] name = "solana-inflation" version = "2.2.1" @@ -6205,7 +6218,7 @@ dependencies = [ "num-traits", "serde", "serde_derive", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-pubkey", "wasm-bindgen", ] @@ -6234,8 +6247,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7aeb957fbd42a451b99235df4942d96db7ef678e8d5061ef34c9b34cae12f79" dependencies = [ "sha3", - "solana-define-syscall", - "solana-hash", + "solana-define-syscall 2.2.1", + "solana-hash 2.2.1", "solana-sanitize", ] @@ -6381,7 +6394,7 @@ dependencies = [ "serde", "serde_derive", "solana-bincode", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-pubkey", "solana-sanitize", @@ -6405,7 +6418,7 @@ dependencies = [ "reqwest", "solana-clock", "solana-cluster-type", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-time-utils", "thiserror 2.0.17", ] @@ -6416,7 +6429,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36a1a14399afaabc2781a1db09cb14ee4cc4ee5c7a5a3cfcc601811379a8092" dependencies = [ - "solana-define-syscall", + "solana-define-syscall 2.2.1", ] [[package]] @@ -6434,9 +6447,9 @@ dependencies = [ "serde", "serde_derive", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-pubkey", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", ] [[package]] @@ -6446,7 +6459,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cde971a20b8dbf60144d6a84439dda86b5466e00e2843091fe731083cda614da" dependencies = [ "solana-account", - "solana-hash", + "solana-hash 2.2.1", "solana-nonce", "solana-sdk-ids", ] @@ -6458,11 +6471,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b526398ade5dea37f1f147ce55dae49aa017a5d7326606359b0445ca8d946581" dependencies = [ "num_enum", - "solana-hash", + "solana-hash 2.2.1", "solana-packet", "solana-pubkey", "solana-sanitize", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-signature", "solana-signer", ] @@ -6499,7 +6512,7 @@ checksum = "8ad1ea160d08dc423c35021fa3e437a5783eb256f5ab8bc3024e27db913acf42" dependencies = [ "ark-bn254", "light-poseidon", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "thiserror 2.0.17", ] @@ -6576,13 +6589,13 @@ dependencies = [ "solana-clock", "solana-cpi", "solana-decode-error", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-epoch-rewards", "solana-epoch-schedule", "solana-example-mocks", "solana-feature-gate-interface", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-instructions-sysvar", "solana-keccak-hasher", @@ -6607,7 +6620,7 @@ dependencies = [ "solana-secp256k1-recover", "solana-serde-varint", "solana-serialize-utils", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-short-vec", "solana-slot-hashes", "solana-slot-history", @@ -6656,7 +6669,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b0268f6c89825fb634a34bd0c3b8fdaeaecfc3728be1d622a8ee6dd577b60d4" dependencies = [ "num-traits", - "solana-define-syscall", + "solana-define-syscall 2.2.1", ] [[package]] @@ -6694,7 +6707,7 @@ dependencies = [ "solana-epoch-rewards", "solana-epoch-schedule", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-last-restart-slot", "solana-log-collector", @@ -6736,9 +6749,9 @@ dependencies = [ "serde_derive", "solana-atomic-u64", "solana-decode-error", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-sanitize", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "wasm-bindgen", ] @@ -6865,7 +6878,7 @@ dependencies = [ "solana-epoch-info", "solana-epoch-schedule", "solana-feature-gate-interface", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-message", "solana-pubkey", @@ -7050,7 +7063,7 @@ checksum = "baa3120b6cdaa270f39444f5093a90a7b03d296d362878f7a6991d6de3bbe496" dependencies = [ "borsh 1.6.0", "libsecp256k1", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "thiserror 2.0.17", ] @@ -7133,8 +7146,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0037386961c0d633421f53560ad7c80675c0447cba4d1bb66d60974dd486c7ea" dependencies = [ "sha2 0.10.9", - "solana-define-syscall", - "solana-hash", + "solana-define-syscall 2.2.1", + "solana-hash 2.2.1", +] + +[[package]] +name = "solana-sha256-hasher" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db7dc3011ea4c0334aaaa7e7128cb390ecf546b28d412e9bf2064680f57f588f" +dependencies = [ + "solana-define-syscall 4.0.1", + "solana-hash 4.0.1", ] [[package]] @@ -7153,8 +7176,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afd3db0461089d1ad1a78d9ba3f15b563899ca2386351d38428faa5350c60a98" dependencies = [ "solana-hard-forks", - "solana-hash", - "solana-sha256-hasher", + "solana-hash 2.2.1", + "solana-sha256-hasher 2.2.1", ] [[package]] @@ -7191,7 +7214,7 @@ checksum = "0c8691982114513763e88d04094c9caa0376b867a29577939011331134c301ce" dependencies = [ "serde", "serde_derive", - "solana-hash", + "solana-hash 2.2.1", "solana-sdk-ids", "solana-sysvar-id", ] @@ -7280,7 +7303,7 @@ dependencies = [ "protobuf-src", "serde", "solana-account-decoder", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-message", "solana-pubkey", @@ -7310,7 +7333,7 @@ dependencies = [ "solana-compute-budget-instruction", "solana-feature-set", "solana-fee-structure", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-instructions-sysvar", "solana-loader-v4-program", @@ -7352,7 +7375,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fc4392f0eed412141a376e99dfb052069b96f13697a9abb335504babe29387a" dependencies = [ - "solana-hash", + "solana-hash 2.2.1", "solana-message", "solana-pubkey", "solana-sdk-ids", @@ -7408,7 +7431,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bd98a25e5bcba8b6be8bcbb7b84b24c2a6a8178d7fb0e3077a916855ceba91a" dependencies = [ - "solana-hash", + "solana-hash 2.2.1", "solana-keypair", "solana-message", "solana-pubkey", @@ -7432,11 +7455,11 @@ dependencies = [ "serde_derive", "solana-account-info", "solana-clock", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-epoch-rewards", "solana-epoch-schedule", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-instructions-sysvar", "solana-last-restart-slot", @@ -7492,7 +7515,7 @@ dependencies = [ "serde_derive", "solana-bincode", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-message", @@ -7555,7 +7578,7 @@ dependencies = [ "serde_json", "solana-account-decoder", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-loader-v2-interface", "solana-message", @@ -7644,7 +7667,7 @@ dependencies = [ "serde_derive", "solana-clock", "solana-decode-error", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-pubkey", "solana-rent", @@ -7672,7 +7695,7 @@ dependencies = [ "solana-clock", "solana-epoch-schedule", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-packet", @@ -7807,7 +7830,7 @@ checksum = "a7398da23554a31660f17718164e31d31900956054f54f52d5ec1be51cb4f4b3" dependencies = [ "bytemuck", "solana-program-error", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "spl-discriminator-derive", ] @@ -9677,7 +9700,7 @@ dependencies = [ "solana-account", "solana-account-decoder", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-message", "solana-pubkey", "solana-signature", diff --git a/Cargo.toml b/Cargo.toml index 8d47b19ba..d3dc1392f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -102,7 +102,7 @@ magicblock-committor-program = { path = "./magicblock-committor-program", featur magicblock-committor-service = { path = "./magicblock-committor-service" } magicblock-config = { path = "./magicblock-config" } magicblock-core = { path = "./magicblock-core" } -magicblock-delegation-program = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "2cb491032f372", features = [ +magicblock-delegation-program = { git = "https://github.com/magicblock-labs/delegation-program.git", branch = "snawaz/commit-finalize-from-buffer", features = [ "no-entrypoint", ] } magicblock-ledger = { path = "./magicblock-ledger" } diff --git a/magicblock-committor-service/src/intent_executor/mod.rs b/magicblock-committor-service/src/intent_executor/mod.rs index fb1426705..972ee0f13 100644 --- a/magicblock-committor-service/src/intent_executor/mod.rs +++ b/magicblock-committor-service/src/intent_executor/mod.rs @@ -83,6 +83,7 @@ impl metrics::LabelValue for ExecutionOutput { } } +#[derive(Debug)] pub struct IntentExecutionResult { /// Final result of Intent Execution pub inner: IntentExecutorResult, @@ -161,6 +162,8 @@ where if all_committed_pubkeys.is_empty() { // Build tasks for commit stage + // TODO (snawaz): it's actually MagicBaseIntent::BaseActions scenario, not Commit + // scenario, so the related code needs little bit of refactoring and proper renaming. let commit_tasks = TaskBuilderImpl::commit_tasks( &self.task_info_fetcher, &intent_bundle, diff --git a/magicblock-committor-service/src/persist/commit_persister.rs b/magicblock-committor-service/src/persist/commit_persister.rs index c9399bff9..5a006d84b 100644 --- a/magicblock-committor-service/src/persist/commit_persister.rs +++ b/magicblock-committor-service/src/persist/commit_persister.rs @@ -136,6 +136,12 @@ impl IntentPersisterImpl { [ (false, intent_bundle.get_commit_intent_accounts()), (true, intent_bundle.get_undelegate_intent_accounts()), + (false, intent_bundle.get_commit_finalize_intent_accounts()), + ( + true, + intent_bundle + .get_commit_finalize_and_undelegate_intent_accounts(), + ), ] .into_iter() .filter_map(|(undelegate, accounts)| { @@ -494,6 +500,8 @@ mod tests { MagicIntentBundle { commit: Some(CommitType::Standalone(test_accounts())), commit_and_undelegate: None, + commit_finalize: None, + commit_finalize_and_undelegate: None, standalone_actions: vec![], } } @@ -505,6 +513,8 @@ mod tests { commit_action: CommitType::Standalone(test_accounts()), undelegate_action: UndelegateType::Standalone, }), + commit_finalize: None, + commit_finalize_and_undelegate: None, standalone_actions: vec![], } } @@ -516,6 +526,8 @@ mod tests { commit_action: CommitType::Standalone(test_accounts()), undelegate_action: UndelegateType::Standalone, }), + commit_finalize: None, + commit_finalize_and_undelegate: None, standalone_actions: vec![], } } @@ -524,6 +536,8 @@ mod tests { MagicIntentBundle { commit: None, commit_and_undelegate: None, + commit_finalize: None, + commit_finalize_and_undelegate: None, standalone_actions: vec![], } } diff --git a/magicblock-committor-service/src/tasks/args_task.rs b/magicblock-committor-service/src/tasks/args_task.rs index 3f883fbbf..7c8a06de0 100644 --- a/magicblock-committor-service/src/tasks/args_task.rs +++ b/magicblock-committor-service/src/tasks/args_task.rs @@ -1,10 +1,10 @@ use dlp::{ - args::{CommitDiffArgs, CommitStateArgs}, + args::{CommitDiffArgs, CommitFinalizeArgs, CommitStateArgs}, compute_diff, instruction_builder::{ call_handler_size_budget, call_handler_v2_size_budget, - commit_diff_size_budget, commit_size_budget, finalize_size_budget, - undelegate_size_budget, + commit_diff_size_budget, commit_finalize_size_budget, + commit_size_budget, finalize_size_budget, undelegate_size_budget, }, AccountSizeClass, }; @@ -19,8 +19,8 @@ use crate::tasks::{ buffer_task::{BufferTask, BufferTaskType}, visitor::Visitor, BaseActionTask, BaseActionV2Task, BaseTask, BaseTaskError, BaseTaskResult, - CommitDiffTask, CommitTask, FinalizeTask, PreparationState, TaskType, - UndelegateTask, + CommitDiffTask, CommitFinalizeTask, CommitTask, FinalizeTask, + PreparationState, TaskType, UndelegateTask, }; /// Task that will be executed on Base layer via arguments @@ -28,6 +28,7 @@ use crate::tasks::{ pub enum ArgsTaskType { Commit(CommitTask), CommitDiff(CommitDiffTask), + CommitFinalize(CommitFinalizeTask), Finalize(FinalizeTask), Undelegate(UndelegateTask), // Special action really BaseAction(BaseActionTask), @@ -95,6 +96,38 @@ impl BaseTask for ArgsTask { args, ) } + ArgsTaskType::CommitFinalize(task) => { + let (data, data_is_diff) = + if let Some(base_account) = &task.base_account { + ( + compute_diff( + base_account.data(), + task.committed_account.account.data(), + ) + .to_vec(), + true, + ) + } else { + (task.committed_account.account.data.clone(), false) + }; + + let mut args = CommitFinalizeArgs { + commit_id: task.commit_id, + lamports: task.committed_account.account.lamports, + data_is_diff: data_is_diff.into(), + allow_undelegation: task.allow_undelegation.into(), + bumps: Default::default(), + reserved_padding: Default::default(), + }; + + dlp::instruction_builder::commit_finalize( + *validator, + task.committed_account.pubkey, + &mut args, + &data, + ) + .0 + } ArgsTaskType::Finalize(value) => { dlp::instruction_builder::finalize( *validator, @@ -111,6 +144,8 @@ impl BaseTask for ArgsTask { } ArgsTaskType::BaseAction(value) => { let action = &value.action; + + #[allow(deprecated)] dlp::instruction_builder::call_handler( *validator, action.destination_program, @@ -147,6 +182,11 @@ impl BaseTask for ArgsTask { BufferTaskType::CommitDiff(value), ))) } + ArgsTaskType::CommitFinalize(value) => { + Ok(Box::new(BufferTask::new_preparation_required( + BufferTaskType::CommitFinalize(value), + ))) + } ArgsTaskType::BaseAction(_) | ArgsTaskType::BaseActionV2(_) | ArgsTaskType::Finalize(_) @@ -175,6 +215,7 @@ impl BaseTask for ArgsTask { match &self.task_type { ArgsTaskType::Commit(_) => 70_000, ArgsTaskType::CommitDiff(_) => 70_000, + ArgsTaskType::CommitFinalize(_) => 70_000, ArgsTaskType::BaseAction(task) => task.action.compute_units, ArgsTaskType::BaseActionV2(task) => task.action.compute_units, ArgsTaskType::Undelegate(_) => 70_000, @@ -194,6 +235,11 @@ impl BaseTask for ArgsTask { task.committed_account.account.data.len() as u32, )) } + ArgsTaskType::CommitFinalize(task) => { + commit_finalize_size_budget(AccountSizeClass::Dynamic( + task.committed_account.account.data.len() as u32, + )) + } ArgsTaskType::BaseAction(task) => { // assume all other accounts are Small accounts. let other_accounts_budget = @@ -235,6 +281,7 @@ impl BaseTask for ArgsTask { match &self.task_type { ArgsTaskType::Commit(_) => TaskType::Commit, ArgsTaskType::CommitDiff(_) => TaskType::Commit, + ArgsTaskType::CommitFinalize(_) => TaskType::CommitFinalize, ArgsTaskType::BaseAction(_) | ArgsTaskType::BaseActionV2(_) => { TaskType::Action } @@ -256,6 +303,9 @@ impl BaseTask for ArgsTask { ArgsTaskType::CommitDiff(task) => { task.commit_id = commit_id; } + ArgsTaskType::CommitFinalize(task) => { + task.commit_id = commit_id; + } ArgsTaskType::BaseAction(_) | ArgsTaskType::BaseActionV2(_) | ArgsTaskType::Finalize(_) @@ -269,6 +319,7 @@ impl LabelValue for ArgsTask { match self.task_type { ArgsTaskType::Commit(_) => "args_commit", ArgsTaskType::CommitDiff(_) => "args_commit_diff", + ArgsTaskType::CommitFinalize(_) => "args_commit_finalize", ArgsTaskType::BaseAction(_) => "args_action", ArgsTaskType::BaseActionV2(_) => "args_action_v2", ArgsTaskType::Finalize(_) => "args_finalize", diff --git a/magicblock-committor-service/src/tasks/buffer_task.rs b/magicblock-committor-service/src/tasks/buffer_task.rs index fc8440a1a..72d2264ac 100644 --- a/magicblock-committor-service/src/tasks/buffer_task.rs +++ b/magicblock-committor-service/src/tasks/buffer_task.rs @@ -1,11 +1,15 @@ use dlp::{ - args::CommitStateFromBufferArgs, + args::{CommitFinalizeArgs, CommitStateFromBufferArgs}, compute_diff, - instruction_builder::{commit_diff_size_budget, commit_size_budget}, + instruction_builder::{ + commit_diff_size_budget, commit_finalize_from_buffer_size_budget, + commit_size_budget, + }, AccountSizeClass, }; use magicblock_committor_program::Chunks; use magicblock_metrics::metrics::LabelValue; +use solana_account::ReadableAccount; use solana_instruction::Instruction; use solana_pubkey::Pubkey; @@ -17,8 +21,8 @@ use crate::{ consts::MAX_WRITE_CHUNK_SIZE, tasks::{ visitor::Visitor, BaseTask, BaseTaskError, BaseTaskResult, - CommitDiffTask, CommitTask, PreparationState, PreparationTask, - TaskType, + CommitDiffTask, CommitFinalizeTask, CommitTask, PreparationState, + PreparationTask, TaskType, }, }; @@ -27,6 +31,7 @@ use crate::{ pub enum BufferTaskType { Commit(CommitTask), CommitDiff(CommitDiffTask), + CommitFinalize(CommitFinalizeTask), // Action in the future } @@ -85,6 +90,28 @@ impl BufferTask { chunks, }) } + + BufferTaskType::CommitFinalize(task) => { + let data = if let Some(base_account) = &task.base_account { + compute_diff( + base_account.data(), + task.committed_account.account.data(), + ) + .to_vec() + } else { + task.committed_account.account.data.clone() + }; + + let chunks = + Chunks::from_data_length(data.len(), MAX_WRITE_CHUNK_SIZE); + + PreparationState::Required(PreparationTask { + commit_id: task.commit_id, + pubkey: task.committed_account.pubkey, + committed_data: data, + chunks, + }) + } } } } @@ -151,6 +178,32 @@ impl BaseTask for BufferTask { }, ) } + + BufferTaskType::CommitFinalize(task) => { + let (data_buffer_pubkey, _) = + magicblock_committor_program::pdas::buffer_pda( + validator, + &task.committed_account.pubkey, + &task.commit_id.to_le_bytes(), + ); + + let mut args = CommitFinalizeArgs { + commit_id: task.commit_id, + lamports: task.committed_account.account.lamports, + data_is_diff: task.base_account.is_some().into(), + allow_undelegation: task.allow_undelegation.into(), + bumps: Default::default(), + reserved_padding: Default::default(), + }; + + dlp::instruction_builder::commit_finalize_from_buffer( + *validator, + task.committed_account.pubkey, + data_buffer_pubkey, + &mut args, + ) + .0 + } } } @@ -181,6 +234,7 @@ impl BaseTask for BufferTask { match self.task_type { BufferTaskType::Commit(_) => 70_000, BufferTaskType::CommitDiff(_) => 70_000, + BufferTaskType::CommitFinalize(_) => 70_000, } } @@ -192,6 +246,9 @@ impl BaseTask for BufferTask { BufferTaskType::CommitDiff(_) => { commit_diff_size_budget(AccountSizeClass::Huge) } + BufferTaskType::CommitFinalize(_) => { + commit_finalize_from_buffer_size_budget(AccountSizeClass::Huge) + } } } @@ -204,6 +261,7 @@ impl BaseTask for BufferTask { match self.task_type { BufferTaskType::Commit(_) => TaskType::Commit, BufferTaskType::CommitDiff(_) => TaskType::Commit, + BufferTaskType::CommitFinalize(_) => TaskType::CommitFinalize, } } @@ -220,6 +278,9 @@ impl BaseTask for BufferTask { BufferTaskType::CommitDiff(task) => { task.commit_id = commit_id; } + BufferTaskType::CommitFinalize(task) => { + task.commit_id = commit_id; + } }; self.preparation_state = Self::preparation_required(&self.task_type) @@ -231,6 +292,7 @@ impl LabelValue for BufferTask { match self.task_type { BufferTaskType::Commit(_) => "buffer_commit", BufferTaskType::CommitDiff(_) => "buffer_commit_diff", + BufferTaskType::CommitFinalize(_) => "buffer_commit_finalize", } } } diff --git a/magicblock-committor-service/src/tasks/mod.rs b/magicblock-committor-service/src/tasks/mod.rs index b4af90c58..bb845ab65 100644 --- a/magicblock-committor-service/src/tasks/mod.rs +++ b/magicblock-committor-service/src/tasks/mod.rs @@ -35,6 +35,7 @@ pub use task_builder::TaskBuilderImpl; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum TaskType { Commit, + CommitFinalize, Finalize, Undelegate, Action, @@ -123,6 +124,14 @@ pub struct CommitDiffTask { pub base_account: Account, } +#[derive(Clone, Debug)] +pub struct CommitFinalizeTask { + pub commit_id: u64, + pub allow_undelegation: bool, + pub base_account: Option, // None implies commit-full-bytes else commit-diff + pub committed_account: CommittedAccount, +} + #[derive(Clone, Debug)] pub struct UndelegateTask { pub delegated_account: Pubkey, diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index 507d7358b..c42c28adc 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -2,8 +2,8 @@ use std::{collections::HashMap, sync::Arc}; use async_trait::async_trait; use magicblock_program::magic_scheduled_base_intent::{ - BaseAction, CommitType, CommittedAccount, ScheduledIntentBundle, - UndelegateType, + BaseAction, CommitAndUndelegate, CommitType, CommittedAccount, + ScheduledIntentBundle, UndelegateType, }; use solana_account::Account; use solana_pubkey::Pubkey; @@ -18,8 +18,8 @@ use crate::{ persist::IntentPersister, tasks::{ args_task::{ArgsTask, ArgsTaskType}, - BaseActionTask, BaseActionV2Task, BaseTask, FinalizeTask, - UndelegateTask, + BaseActionTask, BaseActionV2Task, BaseTask, CommitFinalizeTask, + FinalizeTask, UndelegateTask, }, }; @@ -106,12 +106,12 @@ impl TaskBuilderImpl { async fn fetch_commit_nonces( task_info_fetcher: &Arc, - accounts: &[(bool, CommittedAccount)], + accounts: &[(bool, bool, CommittedAccount)], min_context_slot: u64, ) -> TaskInfoFetcherResult> { let committed_pubkeys = accounts .iter() - .map(|(_, account)| account.pubkey) + .map(|(_, _, account)| account.pubkey) .collect::>(); task_info_fetcher @@ -121,26 +121,48 @@ impl TaskBuilderImpl { async fn fetch_diffable_accounts( task_info_fetcher: &Arc, - accounts: &[(bool, CommittedAccount)], + accounts: &[(bool, bool, CommittedAccount)], min_context_slot: u64, ) -> TaskInfoFetcherResult> { let diffable_pubkeys = accounts .iter() - .filter(|(_, account)| { + .filter(|(_, _, account)| { account.account.data.len() > COMMIT_STATE_SIZE_THRESHOLD }) - .map(|(_, account)| account.pubkey) + .map(|(_, _, account)| account.pubkey) .collect::>(); task_info_fetcher .get_base_accounts(&diffable_pubkeys, min_context_slot) .await } + + pub fn create_commit_finalize_task( + commit_id: u64, + allow_undelegation: bool, + account: CommittedAccount, + base_account: Option, + ) -> ArgsTask { + let base_account = + if account.account.data.len() > COMMIT_STATE_SIZE_THRESHOLD { + base_account + } else { + None + }; + + ArgsTaskType::CommitFinalize(CommitFinalizeTask { + commit_id, + allow_undelegation, + committed_account: account, + base_account, + }) + .into() + } } #[async_trait] impl TasksBuilder for TaskBuilderImpl { - /// Returns [`Task`]s for Commit stage + /// Returns []s for Commit stage async fn commit_tasks( task_info_fetcher: &Arc, intent_bundle: &ScheduledIntentBundle, @@ -155,21 +177,31 @@ impl TasksBuilder for TaskBuilderImpl { intent_bundle.get_commit_intent_accounts().cloned(); let undelegated_accounts = intent_bundle.get_undelegate_intent_accounts().cloned(); - let flagged_accounts: Vec<_> = - [(false, committed_accounts), (true, undelegated_accounts)] + let commit_finalize_accounts = + intent_bundle.get_commit_finalize_intent_accounts().cloned(); + let commit_finalize_and_undelegate_accounts = intent_bundle + .get_commit_finalize_and_undelegate_intent_accounts() + .cloned(); + + let flagged_accounts: Vec<_> = [ + (false, false, committed_accounts), + (true, false, undelegated_accounts), + (false, true, commit_finalize_accounts), + (true, true, commit_finalize_and_undelegate_accounts), + ] + .into_iter() + .flat_map(|(allow_undelegation, finalize, accounts)| { + accounts .into_iter() - .flat_map(|(allow_undelegation, accounts)| { - accounts - .into_iter() - .flatten() - .map(move |account| (allow_undelegation, account)) - }) - .collect(); + .flatten() + .map(move |account| (allow_undelegation, finalize, account)) + }) + .collect(); // Get commit nonces and base accounts let min_context_slot = flagged_accounts .iter() - .map(|(_, account)| account.remote_slot) + .map(|(_, _, account)| account.remote_slot) .max() .unwrap_or(0); let (commit_ids, base_accounts) = tokio::join!( @@ -202,7 +234,7 @@ impl TasksBuilder for TaskBuilderImpl { // Create commit tasks let commit_tasks_iter = flagged_accounts.into_iter().map( - |(allow_undelegation, account)| { + |(allow_undelegation, finalize, account)| { let commit_id = commit_ids .get(&account.pubkey) .copied() @@ -215,16 +247,16 @@ impl TasksBuilder for TaskBuilderImpl { }); let base_account = base_accounts.remove(&account.pubkey); - Box::new(Self::create_commit_task( - commit_id, - allow_undelegation, - account.clone(), - base_account, - )) as Box + let task = if finalize { + Self::create_commit_finalize_task(commit_id, allow_undelegation, account.clone(), base_account) + } else { + Self::create_commit_task(commit_id, allow_undelegation, account.clone(), base_account) + }; + + Box::new(task) as Box }, ); tasks.extend(commit_tasks_iter); - Ok(tasks) } @@ -255,7 +287,9 @@ impl TasksBuilder for TaskBuilderImpl { } // Helper to process commit types - fn process_commit(commit: &CommitType) -> Vec> { + fn create_finalize_tasks( + commit: &CommitType, + ) -> Vec> { match commit { CommitType::Standalone(accounts) => { accounts.iter().map(finalize_task).collect() @@ -276,18 +310,12 @@ impl TasksBuilder for TaskBuilderImpl { } } - let mut tasks = Vec::new(); - if let Some(ref value) = intent_bundle.intent_bundle.commit { - tasks.extend(process_commit(value)); - } - - if let Some(ref value) = - intent_bundle.intent_bundle.commit_and_undelegate - { - tasks.extend(process_commit(&value.commit_action)); - + async fn create_undelegate_tasks( + commit_and_undelegate: &CommitAndUndelegate, + info_fetcher: &Arc, + ) -> TaskBuilderResult>> { // Get rent reimbursments for undelegated accounts - let accounts = value.get_committed_accounts(); + let accounts = commit_and_undelegate.get_committed_accounts(); let mut min_context_slot = 0; let pubkeys = accounts .iter() @@ -302,17 +330,39 @@ impl TasksBuilder for TaskBuilderImpl { .await .map_err(TaskBuilderError::FinalizedTasksBuildError)?; - tasks.extend(accounts.iter().zip(rent_reimbursements).map( - |(account, rent_reimbursement)| { + let mut tasks = accounts + .iter() + .zip(rent_reimbursements) + .map(|(account, rent_reimbursement)| { undelegate_task(account, &rent_reimbursement) - }, - )); + }) + .collect::>(); if let UndelegateType::WithBaseActions(actions) = - &value.undelegate_action + &commit_and_undelegate.undelegate_action { - tasks.extend(Self::create_action_tasks(actions)); + tasks.extend(TaskBuilderImpl::create_action_tasks(actions)); } + Ok(tasks) + } + + let mut tasks = Vec::new(); + + if let Some(ref value) = intent_bundle.intent_bundle.commit { + tasks.extend(create_finalize_tasks(value)); + } + + if let Some(ref value) = + intent_bundle.intent_bundle.commit_and_undelegate + { + tasks.extend(create_finalize_tasks(&value.commit_action)); + tasks.extend(create_undelegate_tasks(value, info_fetcher).await?); + }; + + if let Some(ref value) = + intent_bundle.intent_bundle.commit_finalize_and_undelegate + { + tasks.extend(create_undelegate_tasks(value, info_fetcher).await?); }; Ok(tasks) diff --git a/magicblock-committor-service/src/tasks/task_visitors/persistor_visitor.rs b/magicblock-committor-service/src/tasks/task_visitors/persistor_visitor.rs index 3976395a0..875cc1646 100644 --- a/magicblock-committor-service/src/tasks/task_visitors/persistor_visitor.rs +++ b/magicblock-committor-service/src/tasks/task_visitors/persistor_visitor.rs @@ -52,6 +52,11 @@ where &task.committed_account.pubkey, commit_strategy(true), ), + ArgsTaskType::CommitFinalize(task) => ( + task.commit_id, + &task.committed_account.pubkey, + commit_strategy(task.base_account.is_some()), + ), _ => return, }; @@ -101,6 +106,11 @@ where &task.committed_account.pubkey, commit_strategy(true), ), + BufferTaskType::CommitFinalize(task) => ( + task.commit_id, + &task.committed_account.pubkey, + commit_strategy(task.base_account.is_some()), + ), }; if let Err(err) = self.persistor.set_commit_strategy( diff --git a/magicblock-committor-service/src/tasks/task_visitors/utility_visitor.rs b/magicblock-committor-service/src/tasks/task_visitors/utility_visitor.rs index c0c62b966..1658a24ed 100644 --- a/magicblock-committor-service/src/tasks/task_visitors/utility_visitor.rs +++ b/magicblock-committor-service/src/tasks/task_visitors/utility_visitor.rs @@ -55,6 +55,13 @@ impl Visitor for TaskVisitorUtils { remote_slot: task.committed_account.remote_slot, }) } + ArgsTaskType::CommitFinalize(task) => { + *commit_meta = Some(CommitMeta { + committed_pubkey: task.committed_account.pubkey, + commit_id: task.commit_id, + remote_slot: task.committed_account.remote_slot, + }) + } _ => *commit_meta = None, } } @@ -77,6 +84,13 @@ impl Visitor for TaskVisitorUtils { remote_slot: task.committed_account.remote_slot, }) } + BufferTaskType::CommitFinalize(task) => { + *commit_meta = Some(CommitMeta { + committed_pubkey: task.committed_account.pubkey, + commit_id: task.commit_id, + remote_slot: task.committed_account.remote_slot, + }) + } } } } diff --git a/magicblock-committor-service/src/types.rs b/magicblock-committor-service/src/types.rs new file mode 100644 index 000000000..4a72a2242 --- /dev/null +++ b/magicblock-committor-service/src/types.rs @@ -0,0 +1,42 @@ +use std::ops::Deref; + +use magicblock_metrics::metrics; +use magicblock_program::magic_scheduled_base_intent::{ + MagicBaseIntent, ScheduledBaseIntent, +}; + +// TODO: should be removed once cranks are supported +// Ideally even now OffChain/"Manual" commits should be triggered via Tx +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum TriggerType { + OnChain, + OffChain, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct ScheduledBaseIntentWrapper { + pub inner: ScheduledBaseIntent, + pub trigger_type: TriggerType, +} + +impl metrics::LabelValue for ScheduledBaseIntentWrapper { + fn value(&self) -> &str { + match &self.inner.base_intent { + MagicBaseIntent::BaseActions(_) => "actions", + MagicBaseIntent::Commit(_) => "commit", + MagicBaseIntent::CommitAndUndelegate(_) => "commit_and_undelegate", + MagicBaseIntent::CommitFinalize(_) => "commit_finalize", + MagicBaseIntent::CommitFinalizeAndUndelegate(_) => { + "commit_finalize_and_undelegate" + } + } + } +} + +impl Deref for ScheduledBaseIntentWrapper { + type Target = ScheduledBaseIntent; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} diff --git a/programs/magicblock/src/magic_scheduled_base_intent.rs b/programs/magicblock/src/magic_scheduled_base_intent.rs index 08c63153e..2f90c6b4e 100644 --- a/programs/magicblock/src/magic_scheduled_base_intent.rs +++ b/programs/magicblock/src/magic_scheduled_base_intent.rs @@ -125,6 +125,21 @@ impl ScheduledIntentBundle { self.intent_bundle.get_commit_intent_accounts() } + /// Returns `[CommitFinalizeAndUndelegate]` intent's accounts + pub fn get_commit_finalize_and_undelegate_intent_accounts( + &self, + ) -> Option<&Vec> { + self.intent_bundle + .get_commit_finalize_and_undelegate_intent_accounts() + } + + /// Returns `CommitFinalize` intent's accounts + pub fn get_commit_finalize_intent_accounts( + &self, + ) -> Option<&Vec> { + self.intent_bundle.get_commit_finalize_intent_accounts() + } + /// Returns `Commit` intent's accounts pub fn get_commit_intent_accounts_mut( &mut self, @@ -160,6 +175,8 @@ pub enum MagicBaseIntent { BaseActions(Vec), Commit(CommitType), CommitAndUndelegate(CommitAndUndelegate), + CommitFinalize(CommitType), + CommitFinalizeAndUndelegate(CommitAndUndelegate), } // Bundle of BaseIntents @@ -167,6 +184,8 @@ pub enum MagicBaseIntent { pub struct MagicIntentBundle { pub commit: Option, pub commit_and_undelegate: Option, + pub commit_finalize: Option, + pub commit_finalize_and_undelegate: Option, pub standalone_actions: Vec, } @@ -181,6 +200,12 @@ impl From for MagicIntentBundle { MagicBaseIntent::CommitAndUndelegate(value) => { this.commit_and_undelegate = Some(value) } + MagicBaseIntent::CommitFinalize(value) => { + this.commit_finalize = Some(value) + } + MagicBaseIntent::CommitFinalizeAndUndelegate(value) => { + this.commit_finalize_and_undelegate = Some(value) + } } this @@ -198,10 +223,22 @@ impl MagicIntentBundle { .commit .map(|value| CommitType::try_from_args(value, context)) .transpose()?; + let commit_and_undelegate = args .commit_and_undelegate .map(|value| CommitAndUndelegate::try_from_args(value, context)) .transpose()?; + + let commit_finalize = args + .commit_finalize + .map(|value| CommitType::try_from_args(value, context)) + .transpose()?; + + let commit_finalize_and_undelegate = args + .commit_finalize_and_undelegate + .map(|value| CommitAndUndelegate::try_from_args(value, context)) + .transpose()?; + let actions = args .standalone_actions .into_iter() @@ -211,6 +248,8 @@ impl MagicIntentBundle { let this = Self { commit, commit_and_undelegate, + commit_finalize, + commit_finalize_and_undelegate, standalone_actions: actions, }; this.post_validation(context)?; @@ -291,12 +330,24 @@ impl MagicIntentBundle { if let Some(cau) = &self.commit_and_undelegate { check(cau.get_committed_accounts())?; } + if let Some(commit_finalize) = &self.commit_finalize { + check(commit_finalize.get_committed_accounts())?; + } + if let Some(commit_finalize_and_undelegate) = + &self.commit_finalize_and_undelegate + { + check(commit_finalize_and_undelegate.get_committed_accounts())?; + } Ok(()) } pub fn has_undelegate_intent(&self) -> bool { self.commit_and_undelegate.is_some() + + // TODO (snawaz): we need to add this as well? + // || + // self.commit_finalize_and_undelegate.is_some() } pub fn has_committed_accounts(&self) -> bool { @@ -308,8 +359,19 @@ impl MagicIntentBundle { .get_undelegate_intent_accounts() .map(|el| !el.is_empty()) .unwrap_or(false); + let has_commit_finalize_intent_accounts = self + .get_commit_finalize_intent_accounts() + .map(|el| !el.is_empty()) + .unwrap_or(false); + let has_commit_finalize_and_undelegate_intent_accounts = self + .get_commit_finalize_and_undelegate_intent_accounts() + .map(|el| !el.is_empty()) + .unwrap_or(false); - has_commit_intent_accounts || has_undelegate_intent_accounts + has_commit_intent_accounts + || has_undelegate_intent_accounts + || has_commit_finalize_intent_accounts + || has_commit_finalize_and_undelegate_intent_accounts } /// Returns `[CommitAndUndelegate]` intent's accounts @@ -328,6 +390,24 @@ impl MagicIntentBundle { Some(self.commit.as_ref()?.get_committed_accounts()) } + /// Returns `[CommitAndUndelegate]` intent's accounts + pub fn get_commit_finalize_and_undelegate_intent_accounts( + &self, + ) -> Option<&Vec> { + Some( + self.commit_finalize_and_undelegate + .as_ref()? + .get_committed_accounts(), + ) + } + + /// Returns `Commit` intent's accounts + pub fn get_commit_finalize_intent_accounts( + &self, + ) -> Option<&Vec> { + Some(self.commit_finalize.as_ref()?.get_committed_accounts()) + } + /// Returns `Commit` intent's accounts pub fn get_commit_intent_accounts_mut( &mut self, @@ -340,18 +420,29 @@ impl MagicIntentBundle { pub fn get_all_committed_accounts(&self) -> Vec { let committed = self.get_commit_intent_accounts(); let undelegated = self.get_undelegate_intent_accounts(); - [committed, undelegated] - .into_iter() - .flatten() - .flatten() - .cloned() - .collect() + let commit_finalize = self.get_commit_finalize_intent_accounts(); + let commit_finalize_and_undelegate = + self.get_commit_finalize_and_undelegate_intent_accounts(); + + [ + committed, + undelegated, + commit_finalize, + commit_finalize_and_undelegate, + ] + .into_iter() + .flatten() + .flatten() + .cloned() + .collect() } pub fn get_all_committed_pubkeys(&self) -> Vec { [ self.get_commit_intent_pubkeys(), self.get_undelegate_intent_pubkeys(), + self.get_commit_finalize_intent_pubkeys(), + self.get_commit_finalize_and_undelegate_intent_pubkeys(), ] .into_iter() .flatten() @@ -371,17 +462,49 @@ impl MagicIntentBundle { .map(|value| value.get_committed_pubkeys()) } + pub fn get_commit_finalize_intent_pubkeys(&self) -> Option> { + self.commit_finalize + .as_ref() + .map(|value| value.get_committed_pubkeys()) + } + + pub fn get_commit_finalize_and_undelegate_intent_pubkeys( + &self, + ) -> Option> { + self.commit_finalize_and_undelegate + .as_ref() + .map(|value| value.get_committed_pubkeys()) + } + pub fn is_empty(&self) -> bool { let no_committed = self.commit.as_ref().map(|el| el.is_empty()).unwrap_or(true); + let no_committed_and_undelegated = self .commit_and_undelegate .as_ref() .map(|el| el.is_empty()) .unwrap_or(true); + + let no_commit_finalize = self + .commit_finalize + .as_ref() + .map(|el| el.is_empty()) + .unwrap_or(true); + + let no_commit_finalize_and_undelegate = self + .commit_finalize_and_undelegate + .as_ref() + .map(|el| el.is_empty()) + .unwrap_or(true); + let no_actions = self.standalone_actions.is_empty(); - no_committed && no_committed_and_undelegated && no_actions + no_committed + && no_committed_and_undelegated + && no_commit_finalize + && no_commit_finalize_and_undelegate + && no_actions } } @@ -407,8 +530,17 @@ impl MagicBaseIntent { CommitAndUndelegate::try_from_args(type_, context)?; Ok(MagicBaseIntent::CommitAndUndelegate(commit_and_undelegate)) } - MagicBaseIntentArgs::CommitFinalize(_) => todo!(), - MagicBaseIntentArgs::CommitFinalizeAndUndelegate(_) => todo!(), + MagicBaseIntentArgs::CommitFinalize(type_) => { + let commit = CommitType::try_from_args(type_, context)?; + Ok(MagicBaseIntent::CommitFinalize(commit)) + } + MagicBaseIntentArgs::CommitFinalizeAndUndelegate(type_) => { + let commit_and_undelegate = + CommitAndUndelegate::try_from_args(type_, context)?; + Ok(MagicBaseIntent::CommitFinalizeAndUndelegate( + commit_and_undelegate, + )) + } } } @@ -417,6 +549,18 @@ impl MagicBaseIntent { MagicBaseIntent::BaseActions(_) => false, MagicBaseIntent::Commit(_) => false, MagicBaseIntent::CommitAndUndelegate(_) => true, + MagicBaseIntent::CommitFinalize(_) => false, + MagicBaseIntent::CommitFinalizeAndUndelegate(_) => true, + } + } + + pub fn is_commit_finalize(&self) -> bool { + match &self { + MagicBaseIntent::BaseActions(_) => false, + MagicBaseIntent::Commit(_) => false, + MagicBaseIntent::CommitAndUndelegate(_) => false, + MagicBaseIntent::CommitFinalize(_) => true, + MagicBaseIntent::CommitFinalizeAndUndelegate(_) => true, } } @@ -427,6 +571,12 @@ impl MagicBaseIntent { MagicBaseIntent::CommitAndUndelegate(t) => { Some(t.get_committed_accounts()) } + MagicBaseIntent::CommitFinalize(t) => { + Some(t.get_committed_accounts()) + } + MagicBaseIntent::CommitFinalizeAndUndelegate(t) => { + Some(t.get_committed_accounts()) + } } } @@ -439,6 +589,12 @@ impl MagicBaseIntent { MagicBaseIntent::CommitAndUndelegate(t) => { Some(t.get_committed_accounts_mut()) } + MagicBaseIntent::CommitFinalize(t) => { + Some(t.get_committed_accounts_mut()) + } + MagicBaseIntent::CommitFinalizeAndUndelegate(t) => { + Some(t.get_committed_accounts_mut()) + } } } @@ -453,6 +609,8 @@ impl MagicBaseIntent { MagicBaseIntent::BaseActions(actions) => actions.is_empty(), MagicBaseIntent::Commit(t) => t.is_empty(), MagicBaseIntent::CommitAndUndelegate(t) => t.is_empty(), + MagicBaseIntent::CommitFinalize(t) => t.is_empty(), + MagicBaseIntent::CommitFinalizeAndUndelegate(t) => t.is_empty(), } } } diff --git a/programs/magicblock/src/magicblock_processor.rs b/programs/magicblock/src/magicblock_processor.rs index 7070aadc4..d6a71c969 100644 --- a/programs/magicblock/src/magicblock_processor.rs +++ b/programs/magicblock/src/magicblock_processor.rs @@ -11,7 +11,8 @@ use crate::{ schedule_task::{process_cancel_task, process_schedule_task}, schedule_transactions::{ process_accept_scheduled_commits, process_schedule_commit, - process_schedule_intent_bundle, ProcessScheduleCommitOptions, + process_schedule_commit_finalize, process_schedule_intent_bundle, + ProcessScheduleCommitOptions, }, toggle_executable_check::process_toggle_executable_check, }; @@ -64,8 +65,14 @@ declare_process_instruction!( }, ), ScheduleCommitFinalize { - request_undelegation: _, - } => todo!(), + request_undelegation, + } => process_schedule_commit_finalize( + signers, + invoke_context, + ProcessScheduleCommitOptions { + request_undelegation, + }, + ), AcceptScheduleCommits => { process_accept_scheduled_commits(signers, invoke_context) } diff --git a/programs/magicblock/src/schedule_transactions/mod.rs b/programs/magicblock/src/schedule_transactions/mod.rs index 942a5991c..a8d30df03 100644 --- a/programs/magicblock/src/schedule_transactions/mod.rs +++ b/programs/magicblock/src/schedule_transactions/mod.rs @@ -1,5 +1,6 @@ mod process_accept_scheduled_commits; mod process_schedule_commit; +mod process_schedule_commit_finalize; #[cfg(test)] mod process_schedule_commit_tests; mod process_schedule_intent_bundle; @@ -9,6 +10,7 @@ pub(crate) mod transaction_scheduler; use magicblock_magic_program_api::MAGIC_CONTEXT_PUBKEY; pub(crate) use process_accept_scheduled_commits::*; pub(crate) use process_schedule_commit::*; +pub(crate) use process_schedule_commit_finalize::*; pub(crate) use process_schedule_intent_bundle::process_schedule_intent_bundle; pub use process_scheduled_commit_sent::{ process_scheduled_commit_sent, register_scheduled_commit_sent, SentCommit, diff --git a/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs b/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs new file mode 100644 index 000000000..832cf63e3 --- /dev/null +++ b/programs/magicblock/src/schedule_transactions/process_schedule_commit_finalize.rs @@ -0,0 +1,281 @@ +use std::collections::HashSet; + +// no direct token remap helpers needed here; handled in CommittedAccount builder +use solana_account::{state_traits::StateMut, ReadableAccount}; +use solana_instruction::error::InstructionError; +use solana_log_collector::ic_msg; +use solana_program_runtime::invoke_context::InvokeContext; +use solana_pubkey::Pubkey; + +use crate::{ + magic_scheduled_base_intent::{ + validate_commit_schedule_permissions, CommitAndUndelegate, CommitType, + CommittedAccount, MagicBaseIntent, ScheduledIntentBundle, + UndelegateType, + }, + schedule_transactions::{self, ProcessScheduleCommitOptions}, + utils::{ + account_actions::mark_account_as_undelegated, + accounts::{ + get_instruction_account_with_idx, get_instruction_pubkey_with_idx, + get_writable_with_idx, + }, + instruction_utils::InstructionUtils, + }, + MagicContext, +}; + +pub(crate) fn process_schedule_commit_finalize( + signers: HashSet, + invoke_context: &mut InvokeContext, + opts: ProcessScheduleCommitOptions, +) -> Result<(), InstructionError> { + const PAYER_IDX: u16 = 0; + const MAGIC_CONTEXT_IDX: u16 = PAYER_IDX + 1; + + schedule_transactions::check_magic_context_id( + invoke_context, + MAGIC_CONTEXT_IDX, + )?; + + let transaction_context = &invoke_context.transaction_context.clone(); + let ix_ctx = transaction_context.get_current_instruction_context()?; + let ix_accs_len = ix_ctx.get_number_of_instruction_accounts() as usize; + const COMMITTEES_START: usize = MAGIC_CONTEXT_IDX as usize + 1; + + // Assert MagicBlock program + ix_ctx + .find_index_of_program_account(transaction_context, &crate::id()) + .ok_or_else(|| { + ic_msg!( + invoke_context, + "ScheduleCommit ERR: Magic program account not found" + ); + InstructionError::UnsupportedProgramId + })?; + + // Assert enough accounts + if ix_accs_len <= COMMITTEES_START { + ic_msg!( + invoke_context, + "ScheduleCommit ERR: not enough accounts to schedule commit ({}), need payer, signing program an account for each pubkey to be committed", + ix_accs_len + ); + return Err(InstructionError::NotEnoughAccountKeys); + } + + // Assert Payer is signer + let payer_pubkey = + get_instruction_pubkey_with_idx(transaction_context, PAYER_IDX)?; + if !signers.contains(payer_pubkey) { + ic_msg!( + invoke_context, + "ScheduleCommit ERR: payer pubkey {} not in signers", + payer_pubkey + ); + return Err(InstructionError::MissingRequiredSignature); + } + + // + // Get the program_id of the parent instruction that invoked this one via CPI + // + + // We cannot easily simulate the transaction being invoked via CPI + // from the owning program during unit tests + // Instead the integration tests ensure that this works as expected + #[cfg(not(test))] + let frames = crate::utils::instruction_context_frames::InstructionContextFrames::try_from(transaction_context)?; + + // During unit tests we assume the first committee has the correct program ID + #[cfg(test)] + let first_committee_owner = { + *get_instruction_account_with_idx( + transaction_context, + COMMITTEES_START as u16, + )? + .borrow() + .owner() + }; + + #[cfg(not(test))] + let parent_program_id = { + let parent_program_id = + frames.find_program_id_of_parent_of_current_instruction(); + + ic_msg!( + invoke_context, + "ScheduleCommit: parent program id: {}", + parent_program_id + .map_or_else(|| "None".to_string(), |id| id.to_string()) + ); + + parent_program_id + }; + + #[cfg(test)] + let parent_program_id = Some(&first_committee_owner); + + // Assert all accounts are delegated, owned by invoking program OR are signers + // Also works if the validator authority is a signer + // NOTE: we don't require PDAs to be signers as in our case verifying that the + // program owning the PDAs invoked us directly via CPI is sufficient + // Thus we can be `invoke`d unsigned and no seeds need to be provided + let mut committed_accounts: Vec = Vec::new(); + for idx in COMMITTEES_START..ix_accs_len { + let acc_pubkey = + get_instruction_pubkey_with_idx(transaction_context, idx as u16)?; + let acc = + get_instruction_account_with_idx(transaction_context, idx as u16)?; + + if acc.borrow().confined() { + ic_msg!( + invoke_context, + "ScheduleCommit ERR: account {} is confined and cannot be committed", + acc_pubkey + ); + return Err(InstructionError::InvalidAccountData); + } + + { + let is_delegated = acc.borrow().delegated(); + + if opts.request_undelegation { + // Must be writable and delegated to avoid double-undelegation + let is_writable = + get_writable_with_idx(transaction_context, idx as u16)?; + if !is_writable || !is_delegated { + ic_msg!( + invoke_context, + "ScheduleCommit ERR: account {} is required to be writable and delegated in order to be undelegated", + acc_pubkey + ); + return Err(InstructionError::ReadonlyDataModified); + } + } else if !is_delegated { + ic_msg!( + invoke_context, + "ScheduleCommit ERR: account {} is required to be delegated to the current validator, in order to be committed", + acc_pubkey + ); + return Err(InstructionError::IllegalOwner); + } + + // Validate committed account was scheduled by valid authority + let acc_owner = *acc.borrow().owner(); + validate_commit_schedule_permissions( + &invoke_context, + &acc_owner, + acc_pubkey, + parent_program_id, + &signers, + )?; + + let committed = CommittedAccount::from_account_shared( + *acc_pubkey, + &acc.borrow(), + parent_program_id.cloned(), + ); + + if &committed.pubkey != acc_pubkey { + ic_msg!( + invoke_context, + "ScheduleCommit: remapping ATA {} -> eATA {}", + acc_pubkey, + committed.pubkey + ); + } + + committed_accounts.push(committed); + } + + if opts.request_undelegation { + // If the account is scheduled to be undelegated then we need to lock it + // immediately in order to prevent the following actions: + // - writes to the account + // - scheduling further commits for this account + // + // Setting the owner will prevent both, since in both cases the _actual_ + // owner program needs to sign for the account which is not possible at + // that point + // NOTE: this owner change only takes effect if the transaction which + // includes this instruction succeeds. + // + // We also set the undelegating flag on the account in order to detect + // undelegations for which we miss updates + mark_account_as_undelegated(acc); + ic_msg!( + invoke_context, + "ScheduleCommit: Marking account {} as undelegating", + acc_pubkey + ); + } + } + + // NOTE: this is only protected by all the above checks however if the + // instruction fails for other reasons detected afterward then the commit + // stays scheduled + let context_acc = get_instruction_account_with_idx( + transaction_context, + MAGIC_CONTEXT_IDX, + )?; + let context_data = &mut context_acc.borrow_mut(); + let mut context = + MagicContext::deserialize(context_data).map_err(|err| { + ic_msg!( + invoke_context, + "Failed to deserialize MagicContext: {}", + err + ); + InstructionError::GenericError + })?; + + // Get next intent id + let intent_id = context.next_intent_id(); + + // It appears that in builtin programs `Clock::get` doesn't work as expected, thus + // we have to get it directly from the sysvar cache. + let clock = + invoke_context + .get_sysvar_cache() + .get_clock() + .map_err(|err| { + ic_msg!(invoke_context, "Failed to get clock sysvar: {}", err); + InstructionError::UnsupportedSysvar + })?; + let blockhash = invoke_context.environment_config.blockhash; + let action_sent_transaction = + InstructionUtils::scheduled_commit_sent(intent_id, blockhash); + let commit_sent_sig = action_sent_transaction.signatures[0]; + + let base_intent = if opts.request_undelegation { + MagicBaseIntent::CommitFinalizeAndUndelegate(CommitAndUndelegate { + commit_action: CommitType::Standalone(committed_accounts), + undelegate_action: UndelegateType::Standalone, + }) + } else { + MagicBaseIntent::CommitFinalize(CommitType::Standalone( + committed_accounts, + )) + }; + + let scheduled_base_intent = ScheduledIntentBundle { + id: intent_id, + slot: clock.slot, + blockhash, + sent_transaction: action_sent_transaction, + payer: *payer_pubkey, + intent_bundle: base_intent.into(), + }; + + context.add_scheduled_action(scheduled_base_intent); + context_data.set_state(&context)?; + + ic_msg!(invoke_context, "Scheduled commit with ID: {}", intent_id); + ic_msg!( + invoke_context, + "ScheduledCommitSent signature: {}", + commit_sent_sig, + ); + + Ok(()) +} diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 2502ceb77..d703a03b6 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -83,7 +83,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aba2aec0682aa448f93db9b93df8fb331c119cb4d66fe9ba61d6b42dd3a91105" dependencies = [ - "solana-hash", + "solana-hash 2.2.1", "solana-message", "solana-packet", "solana-pubkey", @@ -1700,7 +1700,7 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk" version = "0.8.5" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=d6a81e25a80d78fea9adf3fb1342df9bc9b87ba6#d6a81e25a80d78fea9adf3fb1342df9bc9b87ba6" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=95bb6373a0f7c741a84030c8d0fdcb3e0359afb1#95bb6373a0f7c741a84030c8d0fdcb3e0359afb1" dependencies = [ "base64ct", "borsh 0.10.4", @@ -1710,7 +1710,7 @@ dependencies = [ "ephemeral-rollups-sdk-attribute-ephemeral", "getrandom 0.2.16", "magicblock-delegation-program 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "magicblock-magic-program-api 0.8.0 (git+https://github.com/magicblock-labs/magicblock-validator.git?branch=snawaz%2Fschedule-commit-finalize)", + "magicblock-magic-program-api 0.8.0 (git+https://github.com/magicblock-labs/magicblock-validator.git?rev=34585f091d1debbe19232d07d332afbeb5f93872)", "solana-account", "solana-account-info", "solana-cpi", @@ -1725,7 +1725,7 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk-attribute-action" version = "0.8.5" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=d6a81e25a80d78fea9adf3fb1342df9bc9b87ba6#d6a81e25a80d78fea9adf3fb1342df9bc9b87ba6" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=95bb6373a0f7c741a84030c8d0fdcb3e0359afb1#95bb6373a0f7c741a84030c8d0fdcb3e0359afb1" dependencies = [ "quote", "syn 1.0.109", @@ -1734,7 +1734,7 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk-attribute-commit" version = "0.8.5" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=d6a81e25a80d78fea9adf3fb1342df9bc9b87ba6#d6a81e25a80d78fea9adf3fb1342df9bc9b87ba6" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=95bb6373a0f7c741a84030c8d0fdcb3e0359afb1#95bb6373a0f7c741a84030c8d0fdcb3e0359afb1" dependencies = [ "quote", "syn 1.0.109", @@ -1743,7 +1743,7 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk-attribute-delegate" version = "0.8.5" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=d6a81e25a80d78fea9adf3fb1342df9bc9b87ba6#d6a81e25a80d78fea9adf3fb1342df9bc9b87ba6" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=95bb6373a0f7c741a84030c8d0fdcb3e0359afb1#95bb6373a0f7c741a84030c8d0fdcb3e0359afb1" dependencies = [ "proc-macro2", "quote", @@ -1753,7 +1753,7 @@ dependencies = [ [[package]] name = "ephemeral-rollups-sdk-attribute-ephemeral" version = "0.8.5" -source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=d6a81e25a80d78fea9adf3fb1342df9bc9b87ba6#d6a81e25a80d78fea9adf3fb1342df9bc9b87ba6" +source = "git+https://github.com/magicblock-labs/ephemeral-rollups-sdk.git?rev=95bb6373a0f7c741a84030c8d0fdcb3e0359afb1#95bb6373a0f7c741a84030c8d0fdcb3e0359afb1" dependencies = [ "proc-macro2", "quote", @@ -2894,7 +2894,7 @@ dependencies = [ "color-backtrace", "magicblock-config", "magicblock-core", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fcommit-finalize-from-buffer)", "random-port", "rayon", "serde", @@ -3288,7 +3288,7 @@ dependencies = [ "magicblock-rpc-client", "rand 0.9.2", "solana-account", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-loader-v3-interface 3.0.0", "solana-loader-v4-interface", @@ -3314,7 +3314,7 @@ dependencies = [ "magicblock-committor-service", "magicblock-core", "magicblock-program", - "solana-hash", + "solana-hash 2.2.1", "solana-pubkey", "solana-transaction", "solana-transaction-error", @@ -3420,7 +3420,7 @@ dependencies = [ "solana-feature-set", "solana-fee-calculator", "solana-genesis-config", - "solana-hash", + "solana-hash 2.2.1", "solana-inline-spl", "solana-instruction", "solana-keypair", @@ -3430,7 +3430,7 @@ dependencies = [ "solana-pubkey", "solana-rent", "solana-rpc-client", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-signature", "solana-signer", "solana-system-program", @@ -3456,7 +3456,7 @@ dependencies = [ "magicblock-accounts-db", "magicblock-config", "magicblock-core", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fcommit-finalize-from-buffer)", "magicblock-magic-program-api 0.8.0", "magicblock-metrics", "parking_lot", @@ -3468,7 +3468,7 @@ dependencies = [ "solana-clock", "solana-commitment-config", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-loader-v3-interface 3.0.0", @@ -3521,7 +3521,7 @@ dependencies = [ "futures-util", "lru", "magicblock-committor-program", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fcommit-finalize-from-buffer)", "magicblock-metrics", "magicblock-program", "magicblock-rpc-client", @@ -3532,7 +3532,7 @@ dependencies = [ "solana-address-lookup-table-interface", "solana-commitment-config", "solana-compute-budget-interface", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-message", @@ -3579,7 +3579,7 @@ dependencies = [ "magicblock-magic-program-api 0.8.0", "solana-account", "solana-account-decoder", - "solana-hash", + "solana-hash 2.2.1", "solana-program", "solana-pubkey", "solana-signature", @@ -3611,7 +3611,7 @@ dependencies = [ [[package]] name = "magicblock-delegation-program" version = "1.1.3" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372#2cb491032f372faa4cfdb55e3f05cefd7e07351d" +source = "git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fcommit-finalize-from-buffer#1347f31982a57762bd9321c91a021a3d32bebe05" dependencies = [ "bincode", "borsh 1.6.0", @@ -3626,6 +3626,7 @@ dependencies = [ "solana-curve25519", "solana-program", "solana-security-txt", + "solana-sha256-hasher 3.1.0", "static_assertions", "strum 0.27.2", "thiserror 2.0.17", @@ -3651,7 +3652,7 @@ dependencies = [ "serde", "solana-account-decoder", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-measure", @@ -3683,7 +3684,7 @@ dependencies = [ [[package]] name = "magicblock-magic-program-api" version = "0.8.0" -source = "git+https://github.com/magicblock-labs/magicblock-validator.git?branch=snawaz%2Fschedule-commit-finalize#33f3097e3ceb40538b2983ff89623c788469620e" +source = "git+https://github.com/magicblock-labs/magicblock-validator.git?rev=34585f091d1debbe19232d07d332afbeb5f93872#34585f091d1debbe19232d07d332afbeb5f93872" dependencies = [ "bincode", "serde", @@ -3756,7 +3757,7 @@ dependencies = [ "solana-account-info", "solana-clock", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-log-collector", @@ -3781,7 +3782,7 @@ dependencies = [ "solana-address-lookup-table-interface", "solana-clock", "solana-commitment-config", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-pubkey", "solana-rpc-client", @@ -3850,7 +3851,7 @@ dependencies = [ name = "magicblock-validator-admin" version = "0.8.0" dependencies = [ - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fcommit-finalize-from-buffer)", "magicblock-program", "magicblock-rpc-client", "solana-commitment-config", @@ -4788,7 +4789,7 @@ version = "0.0.0" dependencies = [ "borsh 1.6.0", "ephemeral-rollups-sdk", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fcommit-finalize-from-buffer)", "magicblock-magic-program-api 0.8.0", "rkyv 0.7.45", "solana-program", @@ -4879,7 +4880,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", - "heck 0.5.0", + "heck 0.4.1", "itertools 0.12.1", "log", "multimap", @@ -4899,7 +4900,7 @@ version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ - "heck 0.5.0", + "heck 0.4.1", "itertools 0.12.1", "log", "multimap", @@ -5780,7 +5781,7 @@ dependencies = [ "borsh 1.6.0", "integration-test-tools", "magicblock-core", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fcommit-finalize-from-buffer)", "program-schedulecommit", "solana-program", "solana-rpc-client", @@ -5798,7 +5799,7 @@ dependencies = [ "futures", "magicblock-committor-program", "magicblock-committor-service", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fcommit-finalize-from-buffer)", "magicblock-program", "magicblock-rpc-client", "magicblock-table-mania", @@ -6358,7 +6359,7 @@ dependencies = [ "smallvec", "solana-bucket-map", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-inline-spl", "solana-lattice-hash", "solana-measure", @@ -6484,7 +6485,7 @@ checksum = "75db7f2bbac3e62cfd139065d15bcda9e2428883ba61fc8d27ccb251081e7567" dependencies = [ "num-bigint 0.4.6", "num-traits", - "solana-define-syscall", + "solana-define-syscall 2.2.1", ] [[package]] @@ -6505,8 +6506,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1a0801e25a1b31a14494fc80882a036be0ffd290efc4c2d640bfcca120a4672" dependencies = [ "blake3", - "solana-define-syscall", - "solana-hash", + "solana-define-syscall 2.2.1", + "solana-hash 2.2.1", "solana-sanitize", ] @@ -6521,7 +6522,7 @@ dependencies = [ "ark-ff", "ark-serialize", "bytemuck", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "thiserror 2.0.17", ] @@ -6556,7 +6557,7 @@ dependencies = [ "solana-cpi", "solana-curve25519", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keccak-hasher", "solana-loader-v3-interface 3.0.0", @@ -6573,7 +6574,7 @@ dependencies = [ "solana-sbpf", "solana-sdk-ids", "solana-secp256k1-recover", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-stable-layout", "solana-system-interface", "solana-sysvar", @@ -6670,7 +6671,7 @@ dependencies = [ "solana-commitment-config", "solana-connection-cache", "solana-epoch-info", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-measure", @@ -6704,7 +6705,7 @@ dependencies = [ "solana-account", "solana-commitment-config", "solana-epoch-info", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-message", @@ -6737,7 +6738,7 @@ checksum = "7ace9fea2daa28354d107ea879cff107181d85cd4e0f78a2bedb10e1a428c97e" dependencies = [ "serde", "serde_derive", - "solana-hash", + "solana-hash 2.2.1", ] [[package]] @@ -6888,7 +6889,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8dc71126edddc2ba014622fc32d0f5e2e78ec6c5a1e0eb511b85618c09e9ea11" dependencies = [ "solana-account-info", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-instruction", "solana-program-error", "solana-pubkey", @@ -6904,7 +6905,7 @@ dependencies = [ "bytemuck", "bytemuck_derive", "curve25519-dalek 4.1.3", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "subtle", "thiserror 2.0.17", ] @@ -6924,6 +6925,12 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf784bb2cb3e02cac9801813c30187344228d2ae952534902108f6150573a33d" +[[package]] +name = "solana-define-syscall" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57e5b1c0bc1d4a4d10c88a4100499d954c09d3fecfae4912c1a074dff68b1738" + [[package]] name = "solana-derivation-path" version = "2.2.1" @@ -6968,7 +6975,7 @@ checksum = "86b575d3dd323b9ea10bb6fe89bf6bf93e249b215ba8ed7f68f1a3633f384db7" dependencies = [ "serde", "serde_derive", - "solana-hash", + "solana-hash 2.2.1", "solana-sdk-ids", "solana-sdk-macro", "solana-sysvar-id", @@ -6981,7 +6988,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c5fd2662ae7574810904585fd443545ed2b568dbd304b25a31e79ccc76e81b" dependencies = [ "siphasher 0.3.11", - "solana-hash", + "solana-hash 2.2.1", "solana-pubkey", ] @@ -7008,7 +7015,7 @@ dependencies = [ "serde_derive", "solana-address-lookup-table-interface", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keccak-hasher", "solana-message", @@ -7047,9 +7054,9 @@ dependencies = [ "ahash 0.8.12", "lazy_static", "solana-epoch-schedule", - "solana-hash", + "solana-hash 2.2.1", "solana-pubkey", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", ] [[package]] @@ -7113,7 +7120,7 @@ dependencies = [ "solana-cluster-type", "solana-epoch-schedule", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-inflation", "solana-keypair", "solana-logger", @@ -7122,7 +7129,7 @@ dependencies = [ "solana-pubkey", "solana-rent", "solana-sdk-ids", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-shred-version", "solana-signer", "solana-time-utils", @@ -7156,6 +7163,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "solana-hash" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5d48a6ee7b91fc7b998944ab026ed7b3e2fc8ee3bc58452644a86c2648152f" + [[package]] name = "solana-inflation" version = "2.2.1" @@ -7189,7 +7202,7 @@ dependencies = [ "num-traits", "serde", "serde_derive", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-pubkey", "wasm-bindgen", ] @@ -7218,8 +7231,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7aeb957fbd42a451b99235df4942d96db7ef678e8d5061ef34c9b34cae12f79" dependencies = [ "sha3", - "solana-define-syscall", - "solana-hash", + "solana-define-syscall 2.2.1", + "solana-hash 2.2.1", "solana-sanitize", ] @@ -7389,7 +7402,7 @@ dependencies = [ "serde", "serde_derive", "solana-bincode", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-pubkey", "solana-sanitize", @@ -7413,7 +7426,7 @@ dependencies = [ "reqwest", "solana-clock", "solana-cluster-type", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-time-utils", "thiserror 2.0.17", ] @@ -7424,7 +7437,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36a1a14399afaabc2781a1db09cb14ee4cc4ee5c7a5a3cfcc601811379a8092" dependencies = [ - "solana-define-syscall", + "solana-define-syscall 2.2.1", ] [[package]] @@ -7470,9 +7483,9 @@ dependencies = [ "serde", "serde_derive", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-pubkey", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", ] [[package]] @@ -7482,7 +7495,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cde971a20b8dbf60144d6a84439dda86b5466e00e2843091fe731083cda614da" dependencies = [ "solana-account", - "solana-hash", + "solana-hash 2.2.1", "solana-nonce", "solana-sdk-ids", ] @@ -7494,11 +7507,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b526398ade5dea37f1f147ce55dae49aa017a5d7326606359b0445ca8d946581" dependencies = [ "num_enum", - "solana-hash", + "solana-hash 2.2.1", "solana-packet", "solana-pubkey", "solana-sanitize", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-signature", "solana-signer", ] @@ -7537,7 +7550,7 @@ dependencies = [ "rand 0.8.5", "rayon", "serde", - "solana-hash", + "solana-hash 2.2.1", "solana-message", "solana-metrics", "solana-packet", @@ -7567,7 +7580,7 @@ checksum = "8ad1ea160d08dc423c35021fa3e437a5783eb256f5ab8bc3024e27db913acf42" dependencies = [ "ark-bn254", "light-poseidon", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "thiserror 2.0.17", ] @@ -7644,13 +7657,13 @@ dependencies = [ "solana-clock", "solana-cpi", "solana-decode-error", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-epoch-rewards", "solana-epoch-schedule", "solana-example-mocks", "solana-feature-gate-interface", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-instructions-sysvar", "solana-keccak-hasher", @@ -7675,7 +7688,7 @@ dependencies = [ "solana-secp256k1-recover", "solana-serde-varint", "solana-serialize-utils", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "solana-short-vec", "solana-slot-hashes", "solana-slot-history", @@ -7724,7 +7737,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b0268f6c89825fb634a34bd0c3b8fdaeaecfc3728be1d622a8ee6dd577b60d4" dependencies = [ "num-traits", - "solana-define-syscall", + "solana-define-syscall 2.2.1", ] [[package]] @@ -7762,7 +7775,7 @@ dependencies = [ "solana-epoch-rewards", "solana-epoch-schedule", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-last-restart-slot", "solana-log-collector", @@ -7841,9 +7854,9 @@ dependencies = [ "serde_derive", "solana-atomic-u64", "solana-decode-error", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-sanitize", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "wasm-bindgen", ] @@ -8011,7 +8024,7 @@ dependencies = [ "solana-epoch-info", "solana-epoch-schedule", "solana-feature-gate-interface", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-message", "solana-pubkey", @@ -8063,7 +8076,7 @@ checksum = "0244e2bf439ec424179414173cdc8b43e34371608752799c5610bf17430eee18" dependencies = [ "solana-account", "solana-commitment-config", - "solana-hash", + "solana-hash 2.2.1", "solana-message", "solana-nonce", "solana-pubkey", @@ -8168,7 +8181,7 @@ dependencies = [ "log", "solana-compute-budget", "solana-compute-budget-instruction", - "solana-hash", + "solana-hash 2.2.1", "solana-message", "solana-pubkey", "solana-sdk-ids", @@ -8320,7 +8333,7 @@ checksum = "baa3120b6cdaa270f39444f5093a90a7b03d296d362878f7a6991d6de3bbe496" dependencies = [ "borsh 1.6.0", "libsecp256k1", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "thiserror 2.0.17", ] @@ -8422,8 +8435,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0037386961c0d633421f53560ad7c80675c0447cba4d1bb66d60974dd486c7ea" dependencies = [ "sha2 0.10.9", - "solana-define-syscall", - "solana-hash", + "solana-define-syscall 2.2.1", + "solana-hash 2.2.1", +] + +[[package]] +name = "solana-sha256-hasher" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db7dc3011ea4c0334aaaa7e7128cb390ecf546b28d412e9bf2064680f57f588f" +dependencies = [ + "solana-define-syscall 4.0.1", + "solana-hash 4.0.1", ] [[package]] @@ -8442,8 +8465,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afd3db0461089d1ad1a78d9ba3f15b563899ca2386351d38428faa5350c60a98" dependencies = [ "solana-hard-forks", - "solana-hash", - "solana-sha256-hasher", + "solana-hash 2.2.1", + "solana-sha256-hasher 2.2.1", ] [[package]] @@ -8480,7 +8503,7 @@ checksum = "0c8691982114513763e88d04094c9caa0376b867a29577939011331134c301ce" dependencies = [ "serde", "serde_derive", - "solana-hash", + "solana-hash 2.2.1", "solana-sdk-ids", "solana-sysvar-id", ] @@ -8568,7 +8591,7 @@ dependencies = [ "protobuf-src", "serde", "solana-account-decoder", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-message", "solana-pubkey", @@ -8646,7 +8669,7 @@ dependencies = [ "solana-compute-budget-instruction", "solana-feature-set", "solana-fee-structure", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-instructions-sysvar", "solana-loader-v4-program", @@ -8690,7 +8713,7 @@ dependencies = [ "solana-compute-budget-instruction", "solana-feature-set", "solana-fee-structure", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-instructions-sysvar", "solana-loader-v4-program", @@ -8732,7 +8755,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fc4392f0eed412141a376e99dfb052069b96f13697a9abb335504babe29387a" dependencies = [ - "solana-hash", + "solana-hash 2.2.1", "solana-message", "solana-pubkey", "solana-sdk-ids", @@ -8788,7 +8811,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bd98a25e5bcba8b6be8bcbb7b84b24c2a6a8178d7fb0e3077a916855ceba91a" dependencies = [ - "solana-hash", + "solana-hash 2.2.1", "solana-keypair", "solana-message", "solana-pubkey", @@ -8812,11 +8835,11 @@ dependencies = [ "serde_derive", "solana-account-info", "solana-clock", - "solana-define-syscall", + "solana-define-syscall 2.2.1", "solana-epoch-rewards", "solana-epoch-schedule", "solana-fee-calculator", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-instructions-sysvar", "solana-last-restart-slot", @@ -8859,7 +8882,7 @@ dependencies = [ "solana-commitment-config", "solana-connection-cache", "solana-epoch-info", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-message", @@ -8948,7 +8971,7 @@ dependencies = [ "serde_derive", "solana-bincode", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-message", @@ -9028,7 +9051,7 @@ dependencies = [ "serde_json", "solana-account-decoder", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-loader-v2-interface", "solana-message", @@ -9146,7 +9169,7 @@ dependencies = [ "solana-account", "solana-bincode", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-packet", "solana-pubkey", @@ -9171,7 +9194,7 @@ dependencies = [ "serde_derive", "solana-clock", "solana-decode-error", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-pubkey", "solana-rent", @@ -9199,7 +9222,7 @@ dependencies = [ "solana-clock", "solana-epoch-schedule", "solana-feature-set", - "solana-hash", + "solana-hash 2.2.1", "solana-instruction", "solana-keypair", "solana-packet", @@ -9412,7 +9435,7 @@ checksum = "a7398da23554a31660f17718164e31d31900956054f54f52d5ec1be51cb4f4b3" dependencies = [ "bytemuck", "solana-program-error", - "solana-sha256-hasher", + "solana-sha256-hasher 2.2.1", "spl-discriminator-derive", ] @@ -10008,7 +10031,7 @@ dependencies = [ "integration-test-tools", "magicblock-chainlink", "magicblock-config", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fcommit-finalize-from-buffer)", "program-flexi-counter", "program-mini", "solana-account", @@ -10092,7 +10115,7 @@ dependencies = [ "integration-test-tools", "magicblock-accounts-db", "magicblock-config", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fcommit-finalize-from-buffer)", "program-flexi-counter", "solana-rpc-client", "solana-sdk", @@ -10113,7 +10136,7 @@ dependencies = [ "magic-domain-program", "magicblock-api", "magicblock-config", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fcommit-finalize-from-buffer)", "magicblock-program", "magicblock-validator-admin", "solana-rpc-client", @@ -10153,7 +10176,7 @@ name = "test-schedule-intent" version = "0.0.0" dependencies = [ "integration-test-tools", - "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=2cb491032f372)", + "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?branch=snawaz%2Fcommit-finalize-from-buffer)", "program-flexi-counter", "solana-rpc-client-api", "solana-sdk", @@ -11622,7 +11645,7 @@ dependencies = [ "solana-account", "solana-account-decoder", "solana-clock", - "solana-hash", + "solana-hash 2.2.1", "solana-message", "solana-pubkey", "solana-signature", diff --git a/test-integration/Cargo.toml b/test-integration/Cargo.toml index 3aeaaf5ed..eec04baab 100644 --- a/test-integration/Cargo.toml +++ b/test-integration/Cargo.toml @@ -36,7 +36,7 @@ chrono = "0.4" cleanass = "0.0.1" color-backtrace = { version = "0.7" } ctrlc = "3.4.7" -ephemeral-rollups-sdk = { git = "https://github.com/magicblock-labs/ephemeral-rollups-sdk.git", rev = "d6a81e25a80d78fea9adf3fb1342df9bc9b87ba6", default-features = false, features = [ +ephemeral-rollups-sdk = { git = "https://github.com/magicblock-labs/ephemeral-rollups-sdk.git", rev = "95bb6373a0f7c741a84030c8d0fdcb3e0359afb1", default-features = false, features = [ "modular-sdk", ] } futures = "0.3.31" @@ -60,7 +60,7 @@ magic-domain-program = { git = "https://github.com/magicblock-labs/magic-domain- "modular-sdk", ] } magicblock_magic_program_api = { package = "magicblock-magic-program-api", path = "../magicblock-magic-program-api" } -magicblock-delegation-program = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "2cb491032f372", features = [ +magicblock-delegation-program = { git = "https://github.com/magicblock-labs/delegation-program.git", branch = "snawaz/commit-finalize-from-buffer", features = [ "no-entrypoint", ] } magicblock-program = { path = "../programs/magicblock" } diff --git a/test-integration/programs/schedulecommit-security/src/lib.rs b/test-integration/programs/schedulecommit-security/src/lib.rs index 8236b40a7..a1e65c869 100644 --- a/test-integration/programs/schedulecommit-security/src/lib.rs +++ b/test-integration/programs/schedulecommit-security/src/lib.rs @@ -2,7 +2,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; use ephemeral_rollups_sdk::ephem::create_schedule_commit_ix; use program_schedulecommit::{ api::schedule_commit_cpi_instruction, process_schedulecommit_cpi, - ProcessSchedulecommitCpiArgs, + ProcessSchedulecommitCpiArgs, ScheduleCommitType, }; use solana_program::{ account_info::{next_account_info, AccountInfo}, @@ -82,9 +82,9 @@ pub fn process_instruction<'a>( &players, ProcessSchedulecommitCpiArgs { modify_accounts: false, - undelegate: false, commit_payer: false, }, + ScheduleCommitType::Commit, ), } } @@ -124,6 +124,7 @@ fn process_sibling_schedule_cpis( *magic_context.key, players, &pdas, + ScheduleCommitType::Commit, ); let mut account_infos = account_infos .clone() diff --git a/test-integration/programs/schedulecommit/src/api.rs b/test-integration/programs/schedulecommit/src/api.rs index 8f359a56c..606097b04 100644 --- a/test-integration/programs/schedulecommit/src/api.rs +++ b/test-integration/programs/schedulecommit/src/api.rs @@ -10,7 +10,7 @@ use solana_program::{ use crate::{ BookUpdate, DelegateCpiArgs, DelegateOrderBookArgs, ScheduleCommitCpiArgs, - ScheduleCommitInstruction, + ScheduleCommitInstruction, ScheduleCommitType, }; #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -180,6 +180,7 @@ pub fn schedule_commit_cpi_instruction( magic_context_id: Pubkey, players: &[Pubkey], committees: &[Pubkey], + commit_type: ScheduleCommitType, ) -> Instruction { schedule_commit_cpi_instruction_impl( payer, @@ -187,10 +188,8 @@ pub fn schedule_commit_cpi_instruction( magic_context_id, players, committees, - ScheduleCommitCpiInstructionImplArgs { - undelegate: false, - commit_payer: false, - }, + false, + commit_type, ) } @@ -212,11 +211,12 @@ pub fn update_order_book_instruction( ) } -pub fn schedule_commit_diff_instruction_for_order_book( +pub fn schedule_commit_instruction_for_order_book( payer: Pubkey, order_book: Pubkey, magic_program_id: Pubkey, magic_context_id: Pubkey, + commit_type: ScheduleCommitType, ) -> Instruction { let program_id = crate::id(); let account_metas = vec![ @@ -228,7 +228,7 @@ pub fn schedule_commit_diff_instruction_for_order_book( Instruction::new_with_borsh( program_id, - &ScheduleCommitInstruction::ScheduleCommitForOrderBook, + &ScheduleCommitInstruction::ScheduleCommitForOrderBook(commit_type), account_metas, ) } @@ -246,10 +246,8 @@ pub fn schedule_commit_with_payer_cpi_instruction( magic_context_id, players, committees, - ScheduleCommitCpiInstructionImplArgs { - undelegate: false, - commit_payer: true, - }, + true, + ScheduleCommitType::Commit, ) } @@ -266,25 +264,19 @@ pub fn schedule_commit_and_undelegate_cpi_instruction( magic_context_id, players, committees, - ScheduleCommitCpiInstructionImplArgs { - undelegate: true, - commit_payer: false, - }, + false, + ScheduleCommitType::CommitAndUndelegate, ) } -struct ScheduleCommitCpiInstructionImplArgs { - undelegate: bool, - commit_payer: bool, -} - fn schedule_commit_cpi_instruction_impl( payer: Pubkey, magic_program_id: Pubkey, magic_context_id: Pubkey, players: &[Pubkey], committees: &[Pubkey], - args: ScheduleCommitCpiInstructionImplArgs, + commit_payer: bool, + commit_type: ScheduleCommitType, ) -> Instruction { let program_id = crate::id(); let mut account_metas = vec![ @@ -299,10 +291,10 @@ fn schedule_commit_cpi_instruction_impl( let cpi_args = ScheduleCommitCpiArgs { players: players.to_vec(), modify_accounts: true, - undelegate: args.undelegate, - commit_payer: args.commit_payer, + commit_payer, }; - let ix = ScheduleCommitInstruction::ScheduleCommitCpi(cpi_args); + let ix = + ScheduleCommitInstruction::ScheduleCommitCpi(cpi_args, commit_type); Instruction::new_with_borsh(program_id, &ix, account_metas) } diff --git a/test-integration/programs/schedulecommit/src/lib.rs b/test-integration/programs/schedulecommit/src/lib.rs index 32d2e39f5..72a71ea16 100644 --- a/test-integration/programs/schedulecommit/src/lib.rs +++ b/test-integration/programs/schedulecommit/src/lib.rs @@ -6,7 +6,10 @@ use ephemeral_rollups_sdk::{ cpi::{ delegate_account, undelegate_account, DelegateAccounts, DelegateConfig, }, - ephem::{commit_accounts, commit_and_undelegate_accounts}, + ephem::{ + commit_accounts, commit_and_undelegate_accounts, + commit_finalize_accounts, commit_finalize_and_undelegate_accounts, + }, }; use magicblock_magic_program_api::instruction::MagicBlockInstruction; use solana_program::{ @@ -66,8 +69,6 @@ pub struct ScheduleCommitCpiArgs { pub players: Vec, /// If true, the accounts will be modified after the commit pub modify_accounts: bool, - /// If true, the accounts will be undelegated after the commit - pub undelegate: bool, /// If true, also commit the payer account pub commit_payer: bool, } @@ -96,7 +97,7 @@ pub enum ScheduleCommitInstruction { /// - **1** `[]` MagicContext (used to record scheduled commit) /// - **2** `[]` MagicBlock Program (used to schedule commit) /// - **3..n** `[]` PDA accounts to be committed - ScheduleCommitCpi(ScheduleCommitCpiArgs), + ScheduleCommitCpi(ScheduleCommitCpiArgs, ScheduleCommitType), /// Same instruction input like [ScheduleCommitInstruction::ScheduleCommitCpi]. /// Behavior differs that it will modify the accounts after it @@ -157,7 +158,53 @@ pub enum ScheduleCommitInstruction { UpdateOrderBook(BookUpdate), /// ScheduleCommitDiffCpi - ScheduleCommitForOrderBook, + ScheduleCommitForOrderBook(ScheduleCommitType), +} + +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, Copy)] +pub enum ScheduleCommitType { + Commit, + CommitAndUndelegate, + CommitFinalize, + CommitFinalizeAndUndelegate, +} + +impl ScheduleCommitType { + fn invoke_commit<'a, 'info>( + self, + payer: &'a AccountInfo<'info>, + accounts: Vec<&'a AccountInfo<'info>>, + magic_context: &'a AccountInfo<'info>, + magic_program: &'a AccountInfo<'info>, + ) -> ProgramResult { + match self { + ScheduleCommitType::Commit => { + commit_accounts(payer, accounts, magic_context, magic_program) + } + ScheduleCommitType::CommitAndUndelegate => { + commit_and_undelegate_accounts( + payer, + accounts, + magic_context, + magic_program, + ) + } + ScheduleCommitType::CommitFinalize => commit_finalize_accounts( + payer, + accounts, + magic_context, + magic_program, + ), + ScheduleCommitType::CommitFinalizeAndUndelegate => { + commit_finalize_and_undelegate_accounts( + payer, + accounts, + magic_context, + magic_program, + ) + } + } + } } pub fn process_instruction<'a>( @@ -187,14 +234,14 @@ pub fn process_instruction<'a>( match ix { Init => process_init(program_id, accounts), DelegateCpi(args) => process_delegate_cpi(accounts, args), - ScheduleCommitCpi(args) => process_schedulecommit_cpi( + ScheduleCommitCpi(args, commit_type) => process_schedulecommit_cpi( accounts, &args.players, ProcessSchedulecommitCpiArgs { modify_accounts: args.modify_accounts, - undelegate: args.undelegate, commit_payer: args.commit_payer, }, + commit_type, ), ScheduleCommitAndUndelegateCpiModAfter(players) => { process_schedulecommit_and_undelegation_cpi_with_mod_after( @@ -214,8 +261,8 @@ pub fn process_instruction<'a>( } DelegateOrderBook(args) => process_delegate_order_book(accounts, args), UpdateOrderBook(args) => process_update_order_book(accounts, args), - ScheduleCommitForOrderBook => { - process_schedulecommit_for_orderbook(accounts) + ScheduleCommitForOrderBook(commit_type) => { + process_schedulecommit_for_orderbook(accounts, commit_type) } } } @@ -448,6 +495,7 @@ fn process_update_order_book<'a>( // ----------------- pub fn process_schedulecommit_for_orderbook( accounts: &[AccountInfo], + commit_type: ScheduleCommitType, ) -> Result<(), ProgramError> { msg!("Processing schedulecommit (for orderbook) instruction"); @@ -458,7 +506,7 @@ pub fn process_schedulecommit_for_orderbook( assert_is_signer(payer, "payer")?; - commit_and_undelegate_accounts( + commit_type.invoke_commit( payer, vec![order_book_account], magic_context, @@ -510,7 +558,6 @@ pub fn process_delegate_cpi( pub struct ProcessSchedulecommitCpiArgs { pub modify_accounts: bool, - pub undelegate: bool, pub commit_payer: bool, } @@ -521,6 +568,7 @@ pub fn process_schedulecommit_cpi( accounts: &[AccountInfo], player_pubkeys: &[Pubkey], args: ProcessSchedulecommitCpiArgs, + commit_type: ScheduleCommitType, ) -> Result<(), ProgramError> { msg!("Processing schedulecommit_cpi instruction"); @@ -573,16 +621,12 @@ pub fn process_schedulecommit_cpi( committees.iter().map(|x| x.key).collect::>() ); - if args.undelegate { - commit_and_undelegate_accounts( - payer, - committees, - magic_context, - magic_program, - )?; - } else { - commit_accounts(payer, committees, magic_context, magic_program)?; - } + commit_type.invoke_commit( + payer, + committees, + magic_context, + magic_program, + )?; Ok(()) } diff --git a/test-integration/schedulecommit/elfs/dlp.so b/test-integration/schedulecommit/elfs/dlp.so index 0a9abca45..b085aa10f 100755 Binary files a/test-integration/schedulecommit/elfs/dlp.so and b/test-integration/schedulecommit/elfs/dlp.so differ diff --git a/test-integration/schedulecommit/test-scenarios/tests/01_commits.rs b/test-integration/schedulecommit/test-scenarios/tests/01_commits.rs index cd9ab6490..58c0c7f7a 100644 --- a/test-integration/schedulecommit/test-scenarios/tests/01_commits.rs +++ b/test-integration/schedulecommit/test-scenarios/tests/01_commits.rs @@ -6,7 +6,7 @@ use program_schedulecommit::{ delegate_account_cpi_instruction, init_account_instruction, pda_and_bump, schedule_commit_cpi_instruction, UserSeeds, }, - ScheduleCommitCpiArgs, ScheduleCommitInstruction, + ScheduleCommitCpiArgs, ScheduleCommitInstruction, ScheduleCommitType, }; use schedulecommit_client::{verify, ScheduleCommitTestContextFields}; use solana_rpc_client::rpc_client::SerializableTransaction; @@ -69,6 +69,7 @@ fn test_committing_one_account() { .map(|(player, _)| player.pubkey()) .collect::>(), &committees.iter().map(|(_, pda)| *pda).collect::>(), + program_schedulecommit::ScheduleCommitType::Commit, ); let ephem_blockhash = ephem_client.get_latest_blockhash().unwrap(); @@ -123,6 +124,7 @@ fn test_committing_two_accounts() { .map(|(player, _)| player.pubkey()) .collect::>(), &committees.iter().map(|(_, pda)| *pda).collect::>(), + program_schedulecommit::ScheduleCommitType::Commit, ); let ephem_blockhash = ephem_client.get_latest_blockhash().unwrap(); @@ -319,9 +321,15 @@ fn schedule_commit_cpi_illegal_owner( let cpi_args = ScheduleCommitCpiArgs { players: players.to_vec(), modify_accounts: false, - undelegate: is_undelegate, commit_payer: true, }; - let ix = ScheduleCommitInstruction::ScheduleCommitCpi(cpi_args); + let ix = ScheduleCommitInstruction::ScheduleCommitCpi( + cpi_args, + if is_undelegate { + ScheduleCommitType::CommitAndUndelegate + } else { + ScheduleCommitType::Commit + }, + ); Instruction::new_with_borsh(program_id, &ix, account_metas) } diff --git a/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs b/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs index 5973b34a6..8e330d5bd 100644 --- a/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs +++ b/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs @@ -9,10 +9,10 @@ use program_schedulecommit::{ schedule_commit_and_undelegate_cpi_instruction, schedule_commit_and_undelegate_cpi_twice, schedule_commit_and_undelegate_cpi_with_mod_after_instruction, - schedule_commit_diff_instruction_for_order_book, set_count_instruction, + schedule_commit_instruction_for_order_book, set_count_instruction, update_order_book_instruction, UserSeeds, }, - BookUpdate, OrderLevel, FAIL_UNDELEGATION_COUNT, + BookUpdate, OrderLevel, ScheduleCommitType, FAIL_UNDELEGATION_COUNT, }; use rand::{RngCore, SeedableRng}; use schedulecommit_client::{ @@ -42,7 +42,10 @@ use utils::{ get_context_with_delegated_committees, }; -use crate::utils::assert_is_one_of_instruction_errors; +use crate::utils::{ + assert_is_one_of_instruction_errors, + assert_one_committee_account_was_not_undelegated_on_chain, +}; mod utils; @@ -110,8 +113,9 @@ fn commit_and_undelegate_one_account( (ctx, *sig, tx_res) } -fn commit_and_undelegate_order_book_account( +fn commit_order_book_account( update: BookUpdate, + commit_type: ScheduleCommitType, ) -> ( ScheduleCommitTestContext, Signature, @@ -134,11 +138,12 @@ fn commit_and_undelegate_order_book_account( committees[0].1, update, ), - schedule_commit_diff_instruction_for_order_book( + schedule_commit_instruction_for_order_book( payer_ephem.pubkey(), committees[0].1, magicblock_magic_program_api::id(), magicblock_magic_program_api::MAGIC_CONTEXT_PUBKEY, + commit_type, ), ]; @@ -298,7 +303,34 @@ fn test_committing_and_undelegating_one_account() { } #[test] -fn test_committing_and_undelegating_huge_order_book_account() { +fn test_commit_huge_order_book_account() { + run_test_for_commit_huge_order_book_account(ScheduleCommitType::Commit); +} + +#[test] +fn test_commit_and_undelegate_huge_order_book_account() { + run_test_for_commit_huge_order_book_account( + ScheduleCommitType::CommitAndUndelegate, + ); +} + +#[test] +fn test_commit_finalize_huge_order_book_account() { + run_test_for_commit_huge_order_book_account( + ScheduleCommitType::CommitFinalize, + ); +} + +#[test] +fn test_commit_finalize_and_undelegate_huge_order_book_account() { + run_test_for_commit_huge_order_book_account( + ScheduleCommitType::CommitFinalizeAndUndelegate, + ); +} + +fn run_test_for_commit_huge_order_book_account( + commit_type: ScheduleCommitType, +) { run_test!({ let (rng_seed, update) = { use rand::{ @@ -324,8 +356,11 @@ fn test_committing_and_undelegating_huge_order_book_account() { (rng_seed, update) }; let (ctx, sig, tx_res) = - commit_and_undelegate_order_book_account(update.clone()); - info!("'{}' {:?}", sig, tx_res); + commit_order_book_account(update.clone(), commit_type); + println!( + "run_test_for_commit_huge_order_book_account: '{}' {:?}", + sig, tx_res + ); let res = verify::fetch_and_verify_order_book_commit_result_from_logs( &ctx, sig, @@ -357,7 +392,15 @@ fn test_committing_and_undelegating_huge_order_book_account() { ); assert_one_committee_was_committed(&ctx, &res, true); - assert_one_committee_account_was_undelegated_on_chain(&ctx); + match commit_type { + ScheduleCommitType::Commit | ScheduleCommitType::CommitFinalize => { + assert_one_committee_account_was_not_undelegated_on_chain(&ctx); + } + ScheduleCommitType::CommitAndUndelegate + | ScheduleCommitType::CommitFinalizeAndUndelegate => { + assert_one_committee_account_was_undelegated_on_chain(&ctx); + } + } }); } diff --git a/test-integration/schedulecommit/test-scenarios/tests/utils/mod.rs b/test-integration/schedulecommit/test-scenarios/tests/utils/mod.rs index 342f94ed2..d2a49417a 100644 --- a/test-integration/schedulecommit/test-scenarios/tests/utils/mod.rs +++ b/test-integration/schedulecommit/test-scenarios/tests/utils/mod.rs @@ -28,9 +28,13 @@ pub fn get_context_with_delegated_committees( let txhash = ctx.init_committees().unwrap(); println!("txhash (init_committees): {}", txhash); + ctx.dump_chain_logs(txhash); + let txhash = ctx.delegate_committees().unwrap(); println!("txhash (delegate_committees): {}", txhash); + ctx.dump_chain_logs(txhash); + ctx } @@ -53,6 +57,13 @@ pub fn assert_one_committee_was_committed( let commit = res.included.get(&pda); assert!(commit.is_some(), "should have committed pda"); + println!( + "PDA:{}, included: {:#?}, sigs: {:#?}", + pda, + res.included.keys(), + res.sigs + ); + // SingleStage Commit & Finalize result in 1 tx // TwoStage results in 2 signatures on base layer let sig_len = if is_single_stage { 1 } else { 2 }; @@ -195,6 +206,15 @@ pub fn assert_one_committee_account_was_undelegated_on_chain( assert_account_was_undelegated_on_chain(ctx, pda, id); } +#[allow(dead_code)] // used in 02_commit_and_undelegate.rs +pub fn assert_one_committee_account_was_not_undelegated_on_chain( + ctx: &ScheduleCommitTestContext, +) { + let pda = ctx.committees[0].1; + let id = program_schedulecommit::id(); + assert_account_was_not_undelegated_on_chain(ctx, pda, id); +} + #[allow(dead_code)] // used in 02_commit_and_undelegate.rs pub fn assert_two_committee_accounts_were_undelegated_on_chain( ctx: &ScheduleCommitTestContext, @@ -221,6 +241,25 @@ pub fn assert_account_was_undelegated_on_chain( assert_eq!(owner, new_owner, "{} has new owner", pda); } +#[allow(dead_code)] // used in 02_commit_and_undelegate.rs +pub fn assert_account_was_not_undelegated_on_chain( + ctx: &ScheduleCommitTestContext, + pda: Pubkey, + program_id: Pubkey, +) { + let owner = ctx.fetch_chain_account_owner(pda).unwrap(); + assert_ne!( + owner, program_id, + "{} should not be owned by {} as it is delegated", + pda, program_id + ); + assert_eq!( + owner, DELEGATION_PROGRAM_ID, + "{} should be owned by delegation program", + pda + ); +} + #[allow(dead_code)] // used in tests pub fn assert_is_instruction_error( tx_err: TransactionError, diff --git a/test-integration/schedulecommit/test-security/tests/01_invocations.rs b/test-integration/schedulecommit/test-security/tests/01_invocations.rs index 8fa8ed255..3b3babfb1 100644 --- a/test-integration/schedulecommit/test-security/tests/01_invocations.rs +++ b/test-integration/schedulecommit/test-security/tests/01_invocations.rs @@ -1,4 +1,7 @@ -use program_schedulecommit::api::{schedule_commit_cpi_instruction, UserSeeds}; +use program_schedulecommit::{ + api::{schedule_commit_cpi_instruction, UserSeeds}, + ScheduleCommitType, +}; use schedulecommit_client::{ ScheduleCommitTestContext, ScheduleCommitTestContextFields, }; @@ -296,6 +299,7 @@ fn test_schedule_commit_via_direct_and_from_other_program_indirect_cpi_including magicblock_magic_program_api::MAGIC_CONTEXT_PUBKEY, players, pdas, + ScheduleCommitType::Commit, ); let nested_cpi_ix = diff --git a/test-integration/test-committor-service/tests/test_ix_commit_local.rs b/test-integration/test-committor-service/tests/test_ix_commit_local.rs index 0a0417fce..f4276ec86 100644 --- a/test-integration/test-committor-service/tests/test_ix_commit_local.rs +++ b/test-integration/test-committor-service/tests/test_ix_commit_local.rs @@ -18,6 +18,7 @@ use magicblock_program::magic_scheduled_base_intent::{ }; use magicblock_rpc_client::MagicblockRpcClient; use program_flexi_counter::state::FlexiCounter; +use program_schedulecommit::ScheduleCommitType; use solana_account::{Account, ReadableAccount}; use solana_pubkey::Pubkey; use solana_rpc_client::nonblocking::rpc_client::RpcClient; @@ -66,62 +67,122 @@ fn expect_strategies( #[tokio::test] async fn test_ix_commit_single_account_100_bytes() { - commit_single_account(100, CommitStrategy::StateArgs, false).await; + commit_single_account( + 100, + CommitStrategy::StateArgs, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_100_bytes_and_undelegate() { - commit_single_account(100, CommitStrategy::StateArgs, true).await; + commit_single_account( + 100, + CommitStrategy::StateArgs, + ScheduleCommitType::CommitAndUndelegate, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_256_bytes() { - commit_single_account(256, CommitStrategy::StateArgs, false).await; + commit_single_account( + 256, + CommitStrategy::StateArgs, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_257_bytes() { - commit_single_account(257, CommitStrategy::DiffArgs, false).await; + commit_single_account( + 257, + CommitStrategy::DiffArgs, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_256_bytes_and_undelegate() { - commit_single_account(256, CommitStrategy::StateArgs, true).await; + commit_single_account( + 256, + CommitStrategy::StateArgs, + ScheduleCommitType::CommitAndUndelegate, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_257_bytes_and_undelegate() { - commit_single_account(257, CommitStrategy::DiffArgs, true).await; + commit_single_account( + 257, + CommitStrategy::DiffArgs, + ScheduleCommitType::CommitAndUndelegate, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_800_bytes() { - commit_single_account(800, CommitStrategy::DiffArgs, false).await; + commit_single_account( + 800, + CommitStrategy::DiffArgs, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_800_bytes_and_undelegate() { - commit_single_account(800, CommitStrategy::DiffArgs, true).await; + commit_single_account( + 800, + CommitStrategy::DiffArgs, + ScheduleCommitType::CommitAndUndelegate, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_one_kb() { - commit_single_account(1024, CommitStrategy::DiffArgs, false).await; + commit_single_account( + 1024, + CommitStrategy::DiffArgs, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] async fn test_ix_commit_single_account_ten_kb() { - commit_single_account(10 * 1024, CommitStrategy::DiffArgs, false).await; + commit_single_account( + 10 * 1024, + CommitStrategy::DiffArgs, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] async fn test_ix_commit_order_book_change_100_bytes() { - commit_book_order_account(100, CommitStrategy::DiffArgs, false).await; + commit_book_order_account( + 100, + CommitStrategy::DiffArgs, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] async fn test_ix_commit_order_book_change_671_bytes() { - commit_book_order_account(671, CommitStrategy::DiffArgs, false).await; + commit_book_order_account( + 671, + CommitStrategy::DiffArgs, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] @@ -130,19 +191,38 @@ async fn test_ix_commit_order_book_change_681_bytes() { // of size 1644 (which is the max limit), but while the size of raw bytes for 680 is within // 1232 limit, the size for 681 exceeds by 1 (1233). That is why we used // 681 as changed_len where CommitStrategy goes from Args to FromBuffer. - commit_book_order_account(681, CommitStrategy::DiffBuffer, false).await; + commit_book_order_account( + 681, + CommitStrategy::DiffBuffer, + ScheduleCommitType::Commit, + ) + .await; } #[tokio::test] async fn test_ix_commit_order_book_change_10k_bytes() { - commit_book_order_account(10 * 1024, CommitStrategy::DiffBuffer, false) - .await; + commit_book_order_account( + 10 * 1024, + CommitStrategy::DiffBuffer, + ScheduleCommitType::CommitAndUndelegate, + ) + .await; +} + +#[tokio::test] +async fn test_ix_commit_finalize_order_book_change_10k_bytes() { + commit_book_order_account( + 10 * 1024, + CommitStrategy::DiffBuffer, + ScheduleCommitType::CommitFinalize, + ) + .await; } async fn commit_single_account( bytes: usize, expected_strategy: CommitStrategy, - undelegate: bool, + commit_type: ScheduleCommitType, ) { init_logger!(); @@ -178,13 +258,27 @@ async fn commit_single_account( account, remote_slot: Default::default(), }; - let base_intent = if undelegate { - MagicBaseIntent::CommitAndUndelegate(CommitAndUndelegate { - commit_action: CommitType::Standalone(vec![account]), - undelegate_action: UndelegateType::Standalone, - }) - } else { - MagicBaseIntent::Commit(CommitType::Standalone(vec![account])) + let base_intent = match commit_type { + ScheduleCommitType::Commit => { + MagicBaseIntent::Commit(CommitType::Standalone(vec![account])) + } + ScheduleCommitType::CommitAndUndelegate => { + MagicBaseIntent::CommitAndUndelegate(CommitAndUndelegate { + commit_action: CommitType::Standalone(vec![account]), + undelegate_action: UndelegateType::Standalone, + }) + } + ScheduleCommitType::CommitFinalize => { + MagicBaseIntent::CommitFinalize(CommitType::Standalone(vec![ + account, + ])) + } + ScheduleCommitType::CommitFinalizeAndUndelegate => { + MagicBaseIntent::CommitFinalizeAndUndelegate(CommitAndUndelegate { + commit_action: CommitType::Standalone(vec![account]), + undelegate_action: UndelegateType::Standalone, + }) + } }; let intent = ScheduledIntentBundle { @@ -201,6 +295,7 @@ async fn commit_single_account( service, vec![intent], expect_strategies(&[(expected_strategy, 1)]), + program_flexi_counter::ID, ) .await; } @@ -208,7 +303,7 @@ async fn commit_single_account( async fn commit_book_order_account( changed_len: usize, expected_strategy: CommitStrategy, - undelegate: bool, + commit_type: ScheduleCommitType, ) { init_logger!(); @@ -242,13 +337,27 @@ async fn commit_book_order_account( account: order_book_ac, remote_slot: Default::default(), }; - let base_intent = if undelegate { - MagicBaseIntent::CommitAndUndelegate(CommitAndUndelegate { - commit_action: CommitType::Standalone(vec![account]), - undelegate_action: UndelegateType::Standalone, - }) - } else { - MagicBaseIntent::Commit(CommitType::Standalone(vec![account])) + let base_intent = match commit_type { + ScheduleCommitType::Commit => { + MagicBaseIntent::Commit(CommitType::Standalone(vec![account])) + } + ScheduleCommitType::CommitAndUndelegate => { + MagicBaseIntent::CommitAndUndelegate(CommitAndUndelegate { + commit_action: CommitType::Standalone(vec![account]), + undelegate_action: UndelegateType::Standalone, + }) + } + ScheduleCommitType::CommitFinalize => { + MagicBaseIntent::CommitFinalize(CommitType::Standalone(vec![ + account, + ])) + } + ScheduleCommitType::CommitFinalizeAndUndelegate => { + MagicBaseIntent::CommitFinalizeAndUndelegate(CommitAndUndelegate { + commit_action: CommitType::Standalone(vec![account]), + undelegate_action: UndelegateType::Standalone, + }) + } }; let intent = ScheduledIntentBundle { @@ -264,6 +373,7 @@ async fn commit_book_order_account( service, vec![intent], expect_strategies(&[(expected_strategy, 1)]), + program_schedulecommit::ID, ) .await; } @@ -621,7 +731,13 @@ async fn commit_multiple_accounts( }) .collect::>(); - ix_commit_local(service, intents, expected_strategies).await; + ix_commit_local( + service, + intents, + expected_strategies, + program_flexi_counter::ID, + ) + .await; } async fn execute_intent_bundle( @@ -667,7 +783,13 @@ async fn execute_intent_bundle( payer: Pubkey::new_unique(), intent_bundle, }; - ix_commit_local(service, vec![intent_bundle], expected_strategies).await; + ix_commit_local( + service, + vec![intent_bundle], + expected_strategies, + program_flexi_counter::id(), + ) + .await; } // TODO(thlorenz/snawaz): once delegation program supports larger commits add the following @@ -701,6 +823,7 @@ async fn ix_commit_local( service: CommittorServiceExt, intent_bundles: Vec, expected_strategies: ExpectedStrategies, + program_id: Pubkey, ) { let execution_outputs = service .schedule_intent_bundles_waiting(intent_bundles.clone()) @@ -751,16 +874,28 @@ async fn ix_commit_local( } let committed_accounts = base_intent.get_commit_intent_accounts(); + + let committed_finalize_accounts = + base_intent.get_commit_finalize_intent_accounts(); + let undelegated_accounts = base_intent.get_undelegate_intent_accounts(); - let mut committed_accounts: HashMap = - [(false, committed_accounts), (true, undelegated_accounts)] - .into_iter() - .flat_map(|(allow_undelegation, accounts)| { - accounts.into_iter().flatten().map(move |account| { - (account.pubkey, (allow_undelegation, account)) - }) - }) - .collect(); + + let commit_finalized_and_undelegated_accounts = + base_intent.get_commit_finalize_and_undelegate_intent_accounts(); + + let mut committed_accounts: HashMap = [ + (false, committed_accounts), + (true, undelegated_accounts), + (false, committed_finalize_accounts), + (true, commit_finalized_and_undelegated_accounts), + ] + .into_iter() + .flat_map(|(allow_undelegation, accounts)| { + accounts.into_iter().flatten().map(move |account| { + (account.pubkey, (allow_undelegation, account)) + }) + }) + .collect(); let statuses = service .get_commit_statuses(base_intent.id) @@ -777,17 +912,15 @@ async fn ix_commit_local( ); assert_eq!(statuses.len(), committed_accounts.len()); + for commit_status in statuses { let (is_undelegate, account) = committed_accounts .remove(&commit_status.pubkey) .expect("Account should be persisted"); // When we finalize it is possible to also undelegate the account - let expected_owner = if is_undelegate { - program_flexi_counter::id() - } else { - dlp::id() - }; + let expected_owner = + if is_undelegate { program_id } else { dlp::id() }; let lamports = account.account.lamports; get_account!( diff --git a/test-integration/test-committor-service/tests/utils/transactions.rs b/test-integration/test-committor-service/tests/utils/transactions.rs index b1f44e209..886c6ca8f 100644 --- a/test-integration/test-committor-service/tests/utils/transactions.rs +++ b/test-integration/test-committor-service/tests/utils/transactions.rs @@ -141,7 +141,9 @@ pub async fn tx_logs_contain( // in the logs when needle == CommitState. It's easier to make this little adjustment here than computing // the decision and passing either CommitState or CommitDiff from the tests themselves. if needle == "CommitState" { - log.contains(needle) || log.contains("CommitDiff") + log.contains(needle) + || log.contains("CommitDiff") + || log.contains("CommitFinalize") } else { log.contains(needle) }