Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
b32c837
fix(sdk): refuse identity updates that disable the last valid authent…
lklimek Oct 28, 2026
1e12c36
fix(platform-wallet): keep received contact requests usable after a r…
lklimek Oct 28, 2026
65668db
fix: stop refusing received contact requests for the purpose of their…
lklimek Oct 28, 2026
22c6a4c
test: import test helpers at the top and name the merge test with should
lklimek Oct 28, 2026
8037b11
refactor: enforce the DIP-11 disable rule as a predicate, leaving upd…
lklimek Oct 28, 2026
3c313e8
fix(platform-wallet): log key warnings on accepted contact requests a…
lklimek Oct 28, 2026
f0b82ef
fix(platform-wallet): name the owner identity in the accept-path key …
lklimek Oct 28, 2026
cfbbd4c
refactor(platform-wallet): name contact-request key sides with an enum
lklimek Oct 28, 2026
0e66b75
refactor: enforce the DIP-11 last-key rule in dpp's identity update b…
lklimek Oct 28, 2026
1c3de13
Merge branch 'v5.1-dev' into fix/platform-wallet-dip11-key-rules
lklimek Oct 28, 2026
26aacc9
fix(dpp): count only unbudgeted keys with matching contract bounds as…
lklimek Oct 29, 2026
be4ae67
fix(sdk): refuse disabled sender and recipient keys when creating a c…
lklimek Oct 29, 2026
11f4dbc
refactor(platform-wallet): leave the send-side disabled-key refusal t…
lklimek Oct 29, 2026
c784766
fix(platform-wallet-ffi): report the DIP-11 last-key refusal as an in…
lklimek Oct 29, 2026
dfd660d
test(dpp): borrow the budgeted key as a slice instead of cloning it
lklimek Oct 29, 2026
1001dda
fix(dpp): count only key types that can sign as DIP-11 replacements
lklimek Oct 29, 2026
7e6fd8e
Merge remote-tracking branch 'origin/v5.1-dev' into fix/platform-wall…
lklimek Oct 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions docs/dashpay/INTEROP_DESK_CHECK.md
Original file line number Diff line number Diff line change
Expand Up @@ -471,17 +471,18 @@ The alignment recommendation above is superseded on the receive side by
contacts established through the legacy Android/dashj client had 27 inbound
requests that reference the recipient's AUTHENTICATION or TRANSFER key, and the
documents are immutable, so rejecting them left those contacts unpayable. The
rules now are (rs-sdk `platform/dashpay/contact_request.rs`):
rules now are:

- **Send (documents we create):** unchanged. The sender key must be ENCRYPTION
(`sender_key_purpose_is_valid`) and the recipient key DECRYPTION or ENCRYPTION
- **Send (documents we create; rs-sdk `platform/dashpay/contact_request.rs`):**
unchanged. The sender key must be ENCRYPTION (`sender_key_purpose_is_valid`)
and the recipient key DECRYPTION or ENCRYPTION
(`recipient_key_purpose_is_valid`).
- **Receive (documents already on chain):** the recipient key may be DECRYPTION,
ENCRYPTION, AUTHENTICATION or TRANSFER
(`recipient_key_purpose_is_acceptable_on_receive`), and the sender key
ENCRYPTION or AUTHENTICATION (`sender_key_purpose_is_acceptable_on_receive`).
Any other purpose is a mismatch that is skipped and retried, never a
permanently broken channel.
- **Receive (documents already on chain; rs-platform-wallet
`wallet/identity/crypto/validation.rs`, `validate_contact_request`):** key
purpose is not checked. Only the key type is: the sender key must be
ECDSA_SECP256K1, and the recipient key ECDSA_SECP256K1 or ECDSA_HASH160. A
key of another type is a permanent error; a key id absent from the identity
is retryable, since identities gain keys; a disabled key is only a warning.

## Re-checking against the reference clients

Expand Down
7 changes: 7 additions & 0 deletions packages/rs-dpp/src/errors/protocol_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::document::errors::*;
))]
use crate::state_transition::errors::InvalidIdentityPublicKeyTypeError;

use crate::identity::key_disable_rule::LastAuthenticationKeyError;
#[cfg(all(feature = "state-transitions", feature = "validation"))]
use crate::state_transition::errors::StateTransitionError;

Expand Down Expand Up @@ -324,6 +325,12 @@ pub enum ProtocolError {
using: u16,
msg: &'static str,
},

/// An identity update would disable the last valid authentication key of a security
/// level (DIP-11). Refused by the signing builder before anything is signed; this is
/// client-side policy, not a consensus rule, so it is never a `ConsensusError`.
#[error(transparent)]
LastAuthenticationKey(#[from] LastAuthenticationKeyError),
}

impl From<&str> for ProtocolError {
Expand Down
15 changes: 15 additions & 0 deletions packages/rs-dpp/src/identity/identity_public_key/key_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,21 @@ impl KeyType {
}
}

/// Can a key of this type sign an identity-signed state transition?
///
/// Mirrors the `SUPPORTED_KEY_TYPES` set drive-abci checks in
/// `validate_state_transition_identity_signed` (ECDSA_SECP256K1, BLS12_381 and
/// ECDSA_HASH160); `StateTransition::sign` refuses the other types. Keep the two in step.
pub fn can_sign_state_transitions(&self) -> bool {
match self {
KeyType::ECDSA_SECP256K1 => true,
KeyType::BLS12_381 => true,
KeyType::ECDSA_HASH160 => true,
KeyType::BIP13_SCRIPT_HASH => false,
KeyType::EDDSA_25519_HASH160 => false,
}
Comment thread
Claudius-Maginificent marked this conversation as resolved.
Resolved
}

/// Can this key type be understood as an address on the Core chain?
pub fn is_core_address_key_type(&self) -> bool {
match self {
Expand Down
Loading
Loading