Skip to content

Conversation

@lklimek
Copy link
Contributor

@lklimek lklimek commented Dec 5, 2025

Issue being fixed or feature implemented

Drive-ABCI does not verify apphash in FinalizeBlock, what can lead in some edge cases to corrupted data storage that is detected at next height. This means a node may get stuck, and need full platform reset.

What was done?

Added verification.

How Has This Been Tested?

GHA passing.
Mainnet fullnode resync (in progress).

Breaking Changes

None.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have added "!" to the title and described breaking changes in the corresponding section if my code contains any
  • I have made corresponding changes to the documentation if needed

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

Summary by CodeRabbit

  • Bug Fixes
    • Strengthened block finalization validation by incorporating app_hash verification.
    • Enhanced error messages with comprehensive diagnostic details when block validation mismatches occur.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 5, 2025

Walkthrough

The pull request adds app_hash validation to the block state information matching process. A new app_hash parameter is introduced to block finalization validation, with conversion handling and comparison against stored app_hash values throughout the execution pipeline.

Changes

Cohort / File(s) Summary
Block state info method signature updates
packages/rs-drive-abci/src/execution/types/block_state_info/mod.rs,
packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs
Added app_hash generic parameter to matches_expected_block_info method. Implements conversion from generic type I: TryInto<[u8; 32]> with BadRequestDataSize error handling. Extends validation to compare received app_hash against stored app_hash using unwrap_or_default.
Block finalization validation flow
packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs
Integrated app_hash into block finalization validation. Includes block_header.app_hash in initial block info comparison and propagates through WrongFinalizeBlockReceived error reporting with updated message formatting and hex-encoding.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Areas requiring extra attention:
    • App_hash conversion logic and BadRequestDataSize error construction in .../v0/mod.rs
    • Comparison logic using unwrap_or_default for app_hash matching
    • Error message formatting and hex-encoding in finalize_block_proposal error path

Poem

🐰 I hopped through bytes and fields so bright,
I found an app_hash hidden in the light,
I converted, checked, and kept it tight,
Now blocks and hashes all unite,
A rabbit cheers for matching right! 🎉

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(drive-abci): verify apphash in finalize_block' clearly and specifically describes the main change: adding app_hash verification to the finalize_block flow.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/verify-apphash-block-state-info

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@lklimek lklimek added this to the v2.2.0 milestone Dec 5, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs (1)

95-105: App hash validation logic looks correct; simplify Option checks for clarity

The extended matches_expected_block_info implementation does what you want: it converts app_hash with an appropriate BadRequestDataSize error, includes it in tracing, and requires both self.block_hash and self.app_hash to be present and equal to the received values.

Two minor clarity nits:

  1. Redundant is_some() + unwrap_or_default() pattern

You currently have:

Ok(self.height == height
    && self.round == round
    && self.core_chain_locked_height == core_block_height
    && self.proposer_pro_tx_hash == proposer_pro_tx_hash
    && self.block_hash.is_some()
    && self.block_hash.unwrap() == received_hash
    && self.app_hash.is_some()
    && self.app_hash.unwrap_or_default() == received_app_hash)

You can avoid the is_some() + unwrap* combo and make the intent “Some and equal” explicit with map_or:

-        Ok(self.height == height
-            && self.round == round
-            && self.core_chain_locked_height == core_block_height
-            && self.proposer_pro_tx_hash == proposer_pro_tx_hash
-            && self.block_hash.is_some()
-            && self.block_hash.unwrap() == received_hash
-            && self.app_hash.is_some()
-            && self.app_hash.unwrap_or_default() == received_app_hash)
+        Ok(self.height == height
+            && self.round == round
+            && self.core_chain_locked_height == core_block_height
+            && self.proposer_pro_tx_hash == proposer_pro_tx_hash
+            && self
+                .block_hash
+                .map_or(false, |hash| hash == received_hash)
+            && self
+                .app_hash
+                .map_or(false, |hash| hash == received_app_hash))

This keeps the semantics (must be Some and equal) while avoiding unwrap and making the Option handling a bit more idiomatic.

  1. Doc comment drift (optional)

The doc comment still says “Does this match a height and round?”, but the method now validates height, round, core height, proposer, block hash, and app hash. Consider updating the comment to reflect the full set of invariants when convenient.

Also applies to: 147-187

packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs (1)

100-122: Align expected app_hash logging with block_hash and avoid ambiguous default value

Including block_header.app_hash in matches_expected_block_info and in the error message is the right move.

For the expected side of the error message you currently do:

block_state_info.block_hash().map(hex::encode).unwrap_or("None".to_string()),
hex::encode(block_state_info.app_hash().unwrap_or_default()),

If block_state_info.app_hash() is None, this will log an all‑zero app_hash, which is ambiguous and inconsistent with how you format block_hash.

You can make this clearer and symmetric with block_hash:

-                block_state_info.block_hash().map(hex::encode).unwrap_or("None".to_string()),
-                hex::encode(block_state_info.app_hash().unwrap_or_default()),
+                block_state_info
+                    .block_hash()
+                    .map(hex::encode)
+                    .unwrap_or("None".to_string()),
+                block_state_info
+                    .app_hash()
+                    .map(hex::encode)
+                    .unwrap_or("None".to_string()),

Optionally, you might also tweak the nearby comment (“check the basics, height, round and hash”) to mention app_hash now that it’s part of the basic invariants.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bc2dd30 and 51892ef.

📒 Files selected for processing (3)
  • packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs (1 hunks)
  • packages/rs-drive-abci/src/execution/types/block_state_info/mod.rs (2 hunks)
  • packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.rs: Rust code must pass cargo clippy --workspace linter checks
Rust code must be formatted using cargo fmt --all

**/*.rs: Use 4-space indent for Rust files
Follow rustfmt defaults and keep code clippy-clean for Rust modules
Use snake_case for Rust module names
Use PascalCase for Rust type names
Use SCREAMING_SNAKE_CASE for Rust constants

Files:

  • packages/rs-drive-abci/src/execution/types/block_state_info/mod.rs
  • packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs
  • packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs
🧠 Learnings (9)
📓 Common learnings
Learnt from: shumkov
Repo: dashpay/platform PR: 2305
File: packages/rs-drive-abci/src/abci/handler/finalize_block.rs:81-0
Timestamp: 2024-11-03T10:39:11.242Z
Learning: In `packages/rs-drive-abci/src/abci/handler/finalize_block.rs`, the use of `.expect("commit transaction")` after `app.commit_transaction(platform_version)` is intentional due to the provided comment explaining its necessity. Do not flag this usage in future reviews.
📚 Learning: 2024-11-22T08:19:14.448Z
Learnt from: shumkov
Repo: dashpay/platform PR: 2345
File: packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs:93-99
Timestamp: 2024-11-22T08:19:14.448Z
Learning: In `packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs`, the `insert_contract` method requires an owned `BlockInfo`, so cloning `block_info` is necessary when calling it.

Applied to files:

  • packages/rs-drive-abci/src/execution/types/block_state_info/mod.rs
  • packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs
  • packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs
📚 Learning: 2024-10-06T16:18:07.994Z
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2215
File: packages/rs-drive-abci/src/execution/engine/run_block_proposal/mod.rs:119-120
Timestamp: 2024-10-06T16:18:07.994Z
Learning: In the `run_block_proposal` function in `packages/rs-drive-abci/src/execution/engine/run_block_proposal/mod.rs`, it's acceptable to pass `platform_state` to `perform_events_on_first_block_of_protocol_change`, even if `block_platform_state` has been updated.

Applied to files:

  • packages/rs-drive-abci/src/execution/types/block_state_info/mod.rs
  • packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs
  • packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs
📚 Learning: 2024-10-08T13:28:03.529Z
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2227
File: packages/rs-drive-abci/src/platform_types/platform_state/mod.rs:141-141
Timestamp: 2024-10-08T13:28:03.529Z
Learning: When converting `PlatformStateV0` to `PlatformStateForSavingV1` in `packages/rs-drive-abci/src/platform_types/platform_state/mod.rs`, only version `0` needs to be handled in the match on `platform_state_for_saving_structure_default` because the changes are retroactive.

Applied to files:

  • packages/rs-drive-abci/src/execution/types/block_state_info/mod.rs
  • packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs
📚 Learning: 2024-10-06T16:17:34.571Z
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2215
File: packages/rs-drive-abci/src/execution/engine/run_block_proposal/mod.rs:105-105
Timestamp: 2024-10-06T16:17:34.571Z
Learning: In `run_block_proposal` in `packages/rs-drive-abci/src/execution/engine/run_block_proposal/mod.rs`, when retrieving `last_block_time_ms`, it's acceptable to use `platform_state` instead of `block_platform_state`, even after updating the protocol version.

Applied to files:

  • packages/rs-drive-abci/src/execution/types/block_state_info/mod.rs
  • packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs
  • packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs
📚 Learning: 2024-11-03T10:39:11.242Z
Learnt from: shumkov
Repo: dashpay/platform PR: 2305
File: packages/rs-drive-abci/src/abci/handler/finalize_block.rs:81-0
Timestamp: 2024-11-03T10:39:11.242Z
Learning: In `packages/rs-drive-abci/src/abci/handler/finalize_block.rs`, the use of `.expect("commit transaction")` after `app.commit_transaction(platform_version)` is intentional due to the provided comment explaining its necessity. Do not flag this usage in future reviews.

Applied to files:

  • packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs
  • packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs
📚 Learning: 2025-10-09T15:59:28.329Z
Learnt from: lklimek
Repo: dashpay/platform PR: 2716
File: packages/rs-dapi/src/services/platform_service/broadcast_state_transition.rs:181-187
Timestamp: 2025-10-09T15:59:28.329Z
Learning: In `packages/rs-dapi/src/services/platform_service/broadcast_state_transition.rs`, the maintainer requires logging full state transition bytes (`tx_bytes = hex::encode(st_bytes)`) at debug level when a state transition passes CheckTx but is removed from the block by the proposer, to facilitate debugging of this rare edge case.

Applied to files:

  • packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs
📚 Learning: 2024-11-20T10:01:50.837Z
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2257
File: packages/rs-drive-abci/src/platform_types/platform_state/v0/old_structures/mod.rs:94-94
Timestamp: 2024-11-20T10:01:50.837Z
Learning: In `packages/rs-drive-abci/src/platform_types/platform_state/v0/old_structures/mod.rs`, when converting with `PublicKey::try_from`, it's acceptable to use `.expect()` to handle potential conversion errors.

Applied to files:

  • packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs
📚 Learning: 2024-10-18T15:43:32.447Z
Learnt from: lklimek
Repo: dashpay/platform PR: 2254
File: packages/rs-sdk/src/sdk.rs:654-658
Timestamp: 2024-10-18T15:43:32.447Z
Learning: In `packages/rs-sdk/src/sdk.rs`, within the `verify_metadata_height` function, when using `compare_exchange` on `last_seen_height`, it's acceptable to use `Ordering::Relaxed` for the failure ordering, as any inconsistency would only trigger an extra loop iteration without affecting correctness.

Applied to files:

  • packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs
🧬 Code graph analysis (3)
packages/rs-drive-abci/src/execution/types/block_state_info/mod.rs (1)
packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs (2)
  • app_hash (214-214)
  • app_hash (273-275)
packages/rs-drive-abci/src/execution/types/block_state_info/v0/mod.rs (1)
packages/rs-drive-abci/src/execution/types/block_state_info/mod.rs (4)
  • app_hash (63-67)
  • height (21-25)
  • round (27-31)
  • proposer_pro_tx_hash (45-49)
packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs (3)
packages/rs-drive-abci/src/execution/types/block_state_info/mod.rs (5)
  • height (21-25)
  • round (27-31)
  • app_hash (63-67)
  • core_chain_locked_height (51-55)
  • block_hash (57-61)
packages/rs-dpp/src/block/extended_block_info/mod.rs (2)
  • round (93-97)
  • app_hash (63-67)
packages/rs-dpp/src/block/extended_block_info/v0/mod.rs (4)
  • round (51-51)
  • round (105-107)
  • app_hash (38-38)
  • app_hash (85-87)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Rust packages (drive-abci) / Tests
  • GitHub Check: Rust packages (drive-abci) / Check each feature
  • GitHub Check: Rust packages (drive-abci) / Linting
  • GitHub Check: Build Docker images (RS-DAPI, rs-dapi, rs-dapi) / Build RS-DAPI image
  • GitHub Check: Build Docker images (Drive, drive, drive-abci) / Build Drive image
  • GitHub Check: Build JS packages / Build JS
  • GitHub Check: Rust crates security audit
🔇 Additional comments (1)
packages/rs-drive-abci/src/execution/types/block_state_info/mod.rs (1)

164-181: App hash is correctly threaded through the BlockStateInfo wrapper

The new app_hash: I parameter is cleanly added to matches_expected_block_info and correctly forwarded to the v0 implementation. As long as both hash and app_hash use the same concrete type at call sites (which appears to be the case in this PR), this change is sound and keeps the versioned enum API aligned with v0.

@github-actions
Copy link

github-actions bot commented Dec 5, 2025

✅ DashSDKFFI.xcframework built for this PR.

SwiftPM (host the zip at a stable URL, then use):

.binaryTarget(
  name: "DashSDKFFI",
  url: "https://your.cdn.example/DashSDKFFI.xcframework.zip",
  checksum: "a15a391b4986ffdb7cb1abc7ea345174193704819d68d6b4a9d6569cb0175a22"
)

Xcode manual integration:

  • Download 'DashSDKFFI.xcframework' artifact from the run link above.
  • Drag it into your app target (Frameworks, Libraries & Embedded Content) and set Embed & Sign.
  • If using the Swift wrapper package, point its binaryTarget to the xcframework location or add the package and place the xcframework at the expected path.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs (1)

110-123: Consider error message clarity for missing app_hash.

The error message enhancement is helpful for debugging. However, on line 120, using unwrap_or_default() will display all zeros ("000...") when the stored app_hash is None, which could be confused with an actual all-zeros app_hash. Consider using a more explicit representation like "None" for missing values to improve clarity.

Apply this diff to make the error message more explicit:

-                hex::encode(block_state_info.app_hash().unwrap_or_default()),
+                block_state_info.app_hash().map(hex::encode).unwrap_or("None".to_string()),

This matches the pattern already used for block_hash on line 119.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 51892ef and 6007308.

📒 Files selected for processing (1)
  • packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.rs: Rust code must pass cargo clippy --workspace linter checks
Rust code must be formatted using cargo fmt --all

**/*.rs: Use 4-space indent for Rust files
Follow rustfmt defaults and keep code clippy-clean for Rust modules
Use snake_case for Rust module names
Use PascalCase for Rust type names
Use SCREAMING_SNAKE_CASE for Rust constants

Files:

  • packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs
🧠 Learnings (6)
📓 Common learnings
Learnt from: shumkov
Repo: dashpay/platform PR: 2305
File: packages/rs-drive-abci/src/abci/handler/finalize_block.rs:81-0
Timestamp: 2024-11-03T10:39:11.242Z
Learning: In `packages/rs-drive-abci/src/abci/handler/finalize_block.rs`, the use of `.expect("commit transaction")` after `app.commit_transaction(platform_version)` is intentional due to the provided comment explaining its necessity. Do not flag this usage in future reviews.
📚 Learning: 2024-11-22T08:19:14.448Z
Learnt from: shumkov
Repo: dashpay/platform PR: 2345
File: packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs:93-99
Timestamp: 2024-11-22T08:19:14.448Z
Learning: In `packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs`, the `insert_contract` method requires an owned `BlockInfo`, so cloning `block_info` is necessary when calling it.

Applied to files:

  • packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs
📚 Learning: 2024-10-06T16:18:07.994Z
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2215
File: packages/rs-drive-abci/src/execution/engine/run_block_proposal/mod.rs:119-120
Timestamp: 2024-10-06T16:18:07.994Z
Learning: In the `run_block_proposal` function in `packages/rs-drive-abci/src/execution/engine/run_block_proposal/mod.rs`, it's acceptable to pass `platform_state` to `perform_events_on_first_block_of_protocol_change`, even if `block_platform_state` has been updated.

Applied to files:

  • packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs
📚 Learning: 2024-11-03T10:39:11.242Z
Learnt from: shumkov
Repo: dashpay/platform PR: 2305
File: packages/rs-drive-abci/src/abci/handler/finalize_block.rs:81-0
Timestamp: 2024-11-03T10:39:11.242Z
Learning: In `packages/rs-drive-abci/src/abci/handler/finalize_block.rs`, the use of `.expect("commit transaction")` after `app.commit_transaction(platform_version)` is intentional due to the provided comment explaining its necessity. Do not flag this usage in future reviews.

Applied to files:

  • packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs
📚 Learning: 2024-10-09T00:22:57.778Z
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2215
File: packages/rs-drive-abci/src/execution/engine/run_block_proposal/mod.rs:105-105
Timestamp: 2024-10-09T00:22:57.778Z
Learning: In `run_block_proposal` in `packages/rs-drive-abci/src/execution/engine/run_block_proposal/mod.rs`, when retrieving `last_block_time_ms`, it's acceptable to use `platform_state` instead of `block_platform_state`, even after updating the protocol version.

Applied to files:

  • packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs
📚 Learning: 2025-10-09T15:59:28.329Z
Learnt from: lklimek
Repo: dashpay/platform PR: 2716
File: packages/rs-dapi/src/services/platform_service/broadcast_state_transition.rs:181-187
Timestamp: 2025-10-09T15:59:28.329Z
Learning: In `packages/rs-dapi/src/services/platform_service/broadcast_state_transition.rs`, the maintainer requires logging full state transition bytes (`tx_bytes = hex::encode(st_bytes)`) at debug level when a state transition passes CheckTx but is removed from the block by the proposer, to facilitate debugging of this rare edge case.

Applied to files:

  • packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Rust packages (drive-abci) / Check each feature
  • GitHub Check: Build Docker images (Drive, drive, drive-abci) / Build Drive image
  • GitHub Check: Build Docker images (Dashmate helper, dashmate-helper, dashmate-helper) / Build Dashmate helper image
  • GitHub Check: Build Docker images (RS-DAPI, rs-dapi, rs-dapi) / Build RS-DAPI image
  • GitHub Check: Build JS packages / Build JS
  • GitHub Check: Rust crates security audit
  • GitHub Check: Swift SDK and Example build (warnings as errors)
🔇 Additional comments (2)
packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs (2)

101-108: LGTM! App hash validation correctly integrated.

The addition of block_header.app_hash as a parameter to matches_expected_block_info aligns with the PR objective of preventing corrupted data storage. The error handling via the ? operator appropriately propagates any conversion errors from the underlying type conversion.


217-226: LGTM! Validated app hash correctly propagated.

The ExtendedBlockInfoV0 construction correctly uses the validated block_header.app_hash, ensuring that only verified app hashes are committed to the extended block info.

@lklimek lklimek changed the base branch from v2.2-dev to v3.0-dev December 18, 2025 13:12
@lklimek lklimek modified the milestones: v2.2.0, v3.0 Dec 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants