Skip to content
Open
Show file tree
Hide file tree
Changes from 66 commits
Commits
Show all changes
143 commits
Select commit Hold shift + click to select a range
5fa4714
test(sdk): open an entry with the first of a wallet's prepared keys
QuantumExplorer Nov 8, 2026
1549627
feat(sdk): send, scan and read private contact requests
QuantumExplorer Nov 8, 2026
a6ca844
feat(sdk): name the sender key of a recovered private contact request
QuantumExplorer Nov 8, 2026
74c0d7d
feat(platform-wallet): send, read and accept DashPay private contact …
QuantumExplorer Nov 8, 2026
c3f1b0d
feat(sdk): sign private contact requests with the sender's signing key
QuantumExplorer Nov 8, 2026
f556feb
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 8, 2026
63e1f69
fix(platform-wallet): sign private contact requests and keep them pri…
QuantumExplorer Nov 8, 2026
6db333e
fix(sdk): bind the recipient key into a private request's signature
QuantumExplorer Nov 8, 2026
e12cb96
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 8, 2026
3d510b8
fix(sdk): export private_contact_request_signing_keys
QuantumExplorer Nov 8, 2026
197ca08
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 8, 2026
f248319
fix(platform-wallet): sign private requests only with keys the SDK al…
QuantumExplorer Nov 8, 2026
cc2c7bc
feat(platform-wallet): accept a contact request replying the way it came
QuantumExplorer Nov 8, 2026
d4efa2e
fix(sdk): validate private requests with dpp and check proved identit…
QuantumExplorer Nov 8, 2026
009747a
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 8, 2026
7bd302a
fix(platform-wallet): keep paid private replies and pay a reply lazily
QuantumExplorer Nov 8, 2026
473a440
fix(sdk): refuse expired signing keys and refresh a DashPay without t…
QuantumExplorer Nov 8, 2026
f518421
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 8, 2026
d0db59f
fix(platform-wallet): record a private request only once read back, o…
QuantumExplorer Nov 8, 2026
4a4826a
fix(sdk): keep encryption keys inside their contract bounds and check…
QuantumExplorer Nov 8, 2026
ff59d59
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 8, 2026
9a4ca7f
fix(platform-wallet): refuse a public request while a private one is …
QuantumExplorer Nov 8, 2026
f83284e
fix(platform-wallet): tie each pending private request to its attempt…
QuantumExplorer Nov 8, 2026
f8e20bb
fix(platform-wallet): refuse a contact request once every rotation ve…
QuantumExplorer Nov 8, 2026
785e493
fix(sdk): give an empty context provider the DashPay it fetches, and …
QuantumExplorer Nov 8, 2026
b95c212
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 8, 2026
8c5968c
fix(platform-wallet): fence a private contact request payment against…
QuantumExplorer Nov 8, 2026
9f5db04
fix(platform-wallet): read the private store before an identity's fir…
QuantumExplorer Nov 8, 2026
b3a0ad3
fix(wasm-dpp2): key the constructor's tokens by position as text, and…
QuantumExplorer Nov 8, 2026
875326b
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 8, 2026
f5dde30
fix(wasm-dpp2): refuse tokens for a contract that cannot hold them
QuantumExplorer Nov 8, 2026
77e943e
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 8, 2026
410b38c
fix(sdk): refuse a scan of another store as DashPay private contact r…
QuantumExplorer Nov 8, 2026
6b54d0d
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 8, 2026
9ea2325
fix(platform-wallet): restore an unconfirmed rotation over the reques…
QuantumExplorer Nov 8, 2026
ab68754
refactor(dpp): give the document signing levels of a security require…
QuantumExplorer Nov 8, 2026
1bd3788
fix(sdk): read a private contact request only through a key it could …
QuantumExplorer Nov 8, 2026
609f529
fix(sdk): wipe the outgoing viewing key a private contact request is …
QuantumExplorer Nov 8, 2026
5839100
fix(sdk): give a private page reader's context provider the contract …
QuantumExplorer Nov 8, 2026
be7fba8
feat(sdk): stream a private document store's pages, many fetched at once
QuantumExplorer Nov 8, 2026
b5e2eb2
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 8, 2026
f479c94
perf(platform-wallet): read the private contact request store many pa…
QuantumExplorer Nov 8, 2026
76c5418
feat(platform-wallet): keep the private contact request read position…
QuantumExplorer Nov 8, 2026
d5db080
fix(platform-wallet): claim a contact pair for a public request as a …
QuantumExplorer Nov 8, 2026
3698f6a
fix(platform-wallet): read the private store again when an identity's…
QuantumExplorer Nov 8, 2026
f7761d0
fix(platform-wallet): release a private reservation until its payment…
QuantumExplorer Nov 8, 2026
1ebd255
fix(platform-wallet): release a private reservation once its payment …
QuantumExplorer Nov 8, 2026
3012b4e
fix(platform-wallet): save a private payment's signed transition befo…
QuantumExplorer Nov 8, 2026
0a3b859
fix(platform-wallet): adopt a reply another accept recorded once the …
QuantumExplorer Nov 8, 2026
b8e41ab
fix(sdk): refuse a private document read below protocol version 15 as…
QuantumExplorer Nov 8, 2026
8950232
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 8, 2026
afc6b7e
fix(platform-wallet): hold a contact pair across a restart before any…
QuantumExplorer Nov 8, 2026
d91c1c6
fix(sdk): name the SDK's protocol version when building a private doc…
QuantumExplorer Nov 8, 2026
0e3f521
fix(wasm-dpp2): refuse tokens set on a data contract that holds none
QuantumExplorer Nov 8, 2026
3f546c0
docs(dpp): say at the batch signing levels why the in-place change ke…
QuantumExplorer Nov 8, 2026
e710dd7
docs(sdk): say what the private contact request parser and signing le…
QuantumExplorer Nov 8, 2026
454f25c
test(sdk): check a recipient key holding another point is refused by …
QuantumExplorer Nov 8, 2026
3b68903
test(sdk): pin a private page stream's order and its cursor under a g…
QuantumExplorer Nov 8, 2026
898e8fc
fix(sdk): keep the store a private document scan was read from, and r…
QuantumExplorer Nov 8, 2026
fa18256
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 8, 2026
91d8782
fix(sdk): send a private document transition only once the network is…
QuantumExplorer Nov 9, 2026
19ab417
fix(sdk): keep each outgoing viewing key in place as scan senders are…
QuantumExplorer Nov 9, 2026
75cd978
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 9, 2026
59e047a
fix(sdk): learn a private store's chunk size only from a page that en…
QuantumExplorer Nov 9, 2026
314d957
fix(sdk): refuse a private contact request scan of a contract whose t…
QuantumExplorer Nov 9, 2026
f98c1bd
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 9, 2026
dcc0b15
fix(platform-wallet): mark a private payment started only once its re…
QuantumExplorer Nov 9, 2026
d15c5c9
fix(platform-wallet): release a dropped spend's notes until the spend…
QuantumExplorer Nov 9, 2026
0dc72a0
fix(platform-wallet): take private payment rejection notices only und…
QuantumExplorer Nov 9, 2026
757474b
fix(platform-wallet): skip the private store read only on a network v…
QuantumExplorer Nov 9, 2026
ea2a66b
feat(platform-wallet-ffi): scan the private contact request store thr…
QuantumExplorer Nov 9, 2026
df8cba5
fix(platform-wallet): release a public request's claim only by the at…
QuantumExplorer Nov 9, 2026
6c3abe0
fix(platform-wallet): drop a private contact request association with…
QuantumExplorer Nov 9, 2026
e11ef7c
fix(sdk): keep a newer contract over a registered older one
QuantumExplorer Nov 9, 2026
856fd6b
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 9, 2026
c33583a
fix(platform-wallet): read the private store again before a send once…
QuantumExplorer Nov 9, 2026
efa0fc8
fix(sdk): complete a private store chunk an older snapshot ended part…
QuantumExplorer Nov 9, 2026
baa3092
fix(sdk): gate every type 29 broadcast and refuse it with the structu…
QuantumExplorer Nov 9, 2026
40e4f57
fix(sdk): keep a newer contract in the gRPC context provider, and say…
QuantumExplorer Nov 9, 2026
f7fcc44
fix(sdk): report an identity proved before its entry as a retryable s…
QuantumExplorer Nov 9, 2026
a35fe84
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 9, 2026
b065ca3
fix(sdk): read a private contact request under an eligible alias of i…
QuantumExplorer Nov 9, 2026
4712db7
fix(sdk): fetch again a private page an older snapshot left empty, th…
QuantumExplorer Nov 9, 2026
8558e83
feat(sdk): schedule a private store's page walk from the chunk size i…
QuantumExplorer Nov 9, 2026
fdc50a2
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 9, 2026
8079cb8
feat(platform-wallet-ffi): give the private contact request outcomes …
QuantumExplorer Nov 9, 2026
e3654c2
fix(platform-wallet): wipe a private request's sealing seed when its …
QuantumExplorer Nov 9, 2026
8f7088b
docs(platform-wallet): note the ShieldedStore 'static bound in the AP…
QuantumExplorer Nov 9, 2026
e37af8e
fix(platform-wallet): keep a failed spend's notes in its guard until …
QuantumExplorer Nov 9, 2026
d768705
fix(platform-wallet): keep a private payment's rejection for the sess…
QuantumExplorer Nov 9, 2026
cc6fef5
fix(platform-wallet): hold a reloaded wallet's public contact request…
QuantumExplorer Nov 9, 2026
a3a7fc4
fix(platform-wallet): refuse a private contact request pass whose pro…
QuantumExplorer Nov 9, 2026
4386ec0
docs(sdk): say that a private request's key expiry is the identity's …
QuantumExplorer Nov 9, 2026
2b5e86f
Merge remote-tracking branch 'origin/feat/sdk-private-documents-send-…
QuantumExplorer Nov 9, 2026
f9d669f
fix(sdk-trusted-context-provider): keep a newer known contract over a…
QuantumExplorer Nov 9, 2026
311ae62
fix(sdk): keep a failed refresh as the cause of a private document se…
QuantumExplorer Nov 9, 2026
4e75e27
fix(sdk): read a private page against a newer contract with the type …
QuantumExplorer Nov 9, 2026
235a4f8
fix(sdk): take the network as proven below a version only on a curren…
QuantumExplorer Nov 9, 2026
03cea26
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 9, 2026
5a91dc7
fix(platform-wallet-ffi): keep a missing mnemonic as key-unavailable …
QuantumExplorer Nov 9, 2026
4c81017
fix(platform-wallet): hold an identity reloaded with an unresolved pr…
QuantumExplorer Nov 9, 2026
91678f5
feat(platform-wallet-ffi): report unrestored private payments by thei…
QuantumExplorer Nov 9, 2026
ecf621d
docs(wasm-sdk): say that a registration keeps a held contract of a hi…
QuantumExplorer Nov 9, 2026
0dc274c
fix(sdk): ask the protocol gate before refusing a private document send
QuantumExplorer Nov 9, 2026
9b8589a
test(drive-abci): export a protocol 15 epoch probe for the SDK's gate…
QuantumExplorer Nov 9, 2026
50658b5
fix(sdk): establish protocol 15 through the gate for DashPay's privat…
QuantumExplorer Nov 9, 2026
c7502c4
Merge branch 'feat/sdk-private-documents-send-and-scan' into feat/pla…
QuantumExplorer Nov 9, 2026
3deebd5
fix(platform-wallet): fail a private payment restore closed on a save…
QuantumExplorer Nov 9, 2026
8cdeadf
fix(platform-wallet): match a recovered private request's recipient k…
QuantumExplorer Nov 9, 2026
8260a1c
fix(platform-wallet): keep a private payment's hold durable, required…
QuantumExplorer Nov 9, 2026
84c2b96
feat(platform-version): double a private document store's chunk targe…
QuantumExplorer Nov 9, 2026
b2af518
Merge remote-tracking branch 'origin/feat/sdk-private-documents-send-…
QuantumExplorer Nov 9, 2026
27e4173
fix(platform-wallet): fail a private payment restore on a saved trans…
QuantumExplorer Nov 9, 2026
f2b9c7d
fix(platform-wallet): keep a private contact payment reserved through…
QuantumExplorer Nov 9, 2026
d6279b0
fix(platform-wallet-ffi): report an unsupported private recovery by i…
QuantumExplorer Nov 9, 2026
acb98eb
fix(platform-wallet): free a pair rejected for good on the next priva…
QuantumExplorer Nov 9, 2026
194acb9
Merge remote-tracking branch 'origin/v5.1-dev' into feat/platform-wal…
QuantumExplorer Nov 9, 2026
f7a1204
test(drive-abci): expect DashPay v3's private store at chunk power 10…
QuantumExplorer Nov 9, 2026
b4b976f
Merge remote-tracking branch 'origin/v5.1-dev' into feat/platform-wal…
QuantumExplorer Nov 9, 2026
4f3bd84
fix(platform-wallet): hold private contact request pairs from a durab…
QuantumExplorer Nov 9, 2026
1fb46dd
fix(platform-wallet-ffi): report a broadcast that may have been deliv…
QuantumExplorer Nov 9, 2026
3ad51a3
docs(platform-wallet): describe the private payment journal and maybe…
QuantumExplorer Nov 9, 2026
e312365
fix(platform-wallet): own note reservations by attempt, and save a pr…
QuantumExplorer Nov 9, 2026
a1748d9
fix(platform-wallet): replay the last private payment marker, and flu…
QuantumExplorer Nov 9, 2026
94b4c83
fix(platform-wallet-ffi): keep code 70 for genuine protocol-version r…
QuantumExplorer Nov 9, 2026
360fb00
test(platform-wallet): restore a saved private payment in both startu…
QuantumExplorer Nov 9, 2026
c16c01b
Merge remote-tracking branch 'origin/v5.1-dev' into feat/platform-wal…
QuantumExplorer Nov 9, 2026
26de923
fix(drive): drop the argument #5798 removed from add_document_for_con…
QuantumExplorer Nov 9, 2026
8728bcd
test(platform-wallet): rebind identically while a scan holds the shie…
QuantumExplorer Nov 9, 2026
1b3a37b
Merge branch 'v5.1-dev' into feat/platform-wallet-private-contact-req…
QuantumExplorer Nov 9, 2026
5c99f46
fix(platform-wallet): count no endpoint verdict as proof a shielded s…
QuantumExplorer Nov 9, 2026
94452e6
fix(platform-wallet): keep a stale restoration from reserving a disch…
QuantumExplorer Nov 9, 2026
2197ec6
fix(platform-wallet): bind a public contact request to its wallet gen…
QuantumExplorer Nov 9, 2026
8ede791
fix(platform-wallet): discharge a private payment proven expired and …
QuantumExplorer Nov 9, 2026
ac4459a
feat(sdk): stream private document pages with their proved heights
QuantumExplorer Nov 9, 2026
d0d337b
fix(sdk): give a completed private document page the lowest height of…
QuantumExplorer Nov 9, 2026
0996db2
feat(sdk): let the mock SDK report a chosen response height
QuantumExplorer Nov 9, 2026
ad25184
fix(platform-wallet): prove a private payment expired only on evidenc…
QuantumExplorer Nov 9, 2026
c81424f
fix(platform-wallet): restore a private payment's reservation through…
QuantumExplorer Nov 9, 2026
f7510b4
fix(platform-wallet): retire a never-delivered payment's record and j…
QuantumExplorer Nov 9, 2026
0e24035
fix(platform-wallet): discharge an expired private payment whose inpu…
QuantumExplorer Nov 9, 2026
92569e7
feat(sdk): let the mock SDK prove each response type at its own height
QuantumExplorer Nov 9, 2026
e5f8ed9
fix(platform-wallet): release a stranded note only on height-pinned p…
QuantumExplorer Nov 9, 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
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,21 @@ pub enum BatchedTransitionBoundsCheck {
},
}

/// Whether a key carrying contract bounds may be used with the documents of one document type.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DocumentTypeBoundsCheck {
/// The document type lies inside the bounds.
Allowed,
/// The document type lies outside the bounds.
Denied,
/// The bounds name a contract group. The type lies inside them when its contract holds it,
/// or is a whole-contract member, of the group: only state can answer that.
RequiresContractGroupMembership {
/// The group the bounds name.
contract_group_id: Identifier,
},
}

impl ContractBounds {
/// Creates a new contract bounds for the key
pub fn new_from_type(
Expand Down Expand Up @@ -175,6 +190,33 @@ impl ContractBounds {
}
}

/// Whether a key carrying these bounds may be used with the documents of the type
/// `document_type_name` of the contract `contract_id`. Clients scope their ENCRYPTION and
/// DECRYPTION keys with this, as the bounds ask. A contract group bound is answered by the
/// group's members, which only state holds: a client that does not read them treats the
/// type as outside the bounds.
pub fn check_document_type(
&self,
contract_id: &Identifier,
document_type_name: &str,
) -> DocumentTypeBoundsCheck {
match self {
SingleContract { id } if id == contract_id => DocumentTypeBoundsCheck::Allowed,
SingleContractDocumentType {
id,
document_type_name: bound_document_type_name,
} if id == contract_id && bound_document_type_name == document_type_name => {
DocumentTypeBoundsCheck::Allowed
}
SingleContract { .. } | SingleContractDocumentType { .. } => {
DocumentTypeBoundsCheck::Denied
}
ContractGroup { id } => DocumentTypeBoundsCheck::RequiresContractGroupMembership {
contract_group_id: *id,
},
}
}

/// What authorizing `transition` with a key carrying these bounds needs. Consensus uses this
/// to authorize a batch signed by a contract-bound AUTHENTICATION key. Token operations are
/// contract-wide, so a document-type bound never covers them. A contract group bound is
Expand Down Expand Up @@ -376,6 +418,85 @@ mod core_tests {
}
}

#[cfg(test)]
mod document_type_tests {
use super::{ContractBounds, DocumentTypeBoundsCheck};
use crate::identifier::Identifier;

#[test]
fn should_allow_only_the_bound_contract_or_document_type() {
let contract_id = Identifier::from([1; 32]);
let other_id = Identifier::from([2; 32]);
let contract = ContractBounds::SingleContract { id: contract_id };
let document_type = ContractBounds::SingleContractDocumentType {
id: contract_id,
document_type_name: "note".to_string(),
};
for (case, bounds, checked_contract, checked_type, expected) in [
(
"a contract bound, a type of it",
&contract,
contract_id,
"note",
DocumentTypeBoundsCheck::Allowed,
),
(
"a contract bound, another type of it",
&contract,
contract_id,
"other",
DocumentTypeBoundsCheck::Allowed,
),
(
"a contract bound, another contract",
&contract,
other_id,
"note",
DocumentTypeBoundsCheck::Denied,
),
(
"a type bound, that type",
&document_type,
contract_id,
"note",
DocumentTypeBoundsCheck::Allowed,
),
(
"a type bound, another type",
&document_type,
contract_id,
"other",
DocumentTypeBoundsCheck::Denied,
),
(
"a type bound, that type's name in another contract",
&document_type,
other_id,
"note",
DocumentTypeBoundsCheck::Denied,
),
] {
assert_eq!(
bounds.check_document_type(&checked_contract, checked_type),
expected,
"{case}"
);
}
}

#[test]
fn should_leave_a_contract_group_bound_to_its_members() {
let contract_group_id = Identifier::from([3; 32]);
let bounds = ContractBounds::ContractGroup {
id: contract_group_id,
};
assert_eq!(
bounds.check_document_type(&Identifier::from([1; 32]), "note"),
DocumentTypeBoundsCheck::RequiresContractGroupMembership { contract_group_id }
);
}
}

#[cfg(all(test, feature = "json-conversion"))]
mod tests {
use super::*;
Expand Down
43 changes: 43 additions & 0 deletions packages/rs-dpp/src/identity/identity_public_key/security_level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,21 @@ impl SecurityLevel {
pub fn stronger_or_equal_security_than(self: SecurityLevel, rhs: SecurityLevel) -> bool {
(self as u8) <= (rhs as u8)
}

/// The security levels a key may sign a document at when the document's type requires
/// `self` (its `security_level_requirement`): `MASTER` alone when the requirement is
/// `MASTER`, otherwise every level from `CRITICAL` to the requirement, strongest first. A
/// batch takes the levels of the strongest requirement among its documents
/// (`DocumentsBatchTransitionMethodsV0::combined_security_level_requirement`).
pub fn document_signing_levels(self) -> Vec<SecurityLevel> {
if self == Self::MASTER {
return vec![Self::MASTER];
}
Self::full_range()
.into_iter()
.filter(|level| *level != Self::MASTER && (*level as u8) <= (self as u8))
.collect()
}
}

impl std::fmt::Display for SecurityLevel {
Expand All @@ -117,6 +132,34 @@ impl std::fmt::Display for SecurityLevel {
mod tests {
use super::*;

/// Each requirement admits `MASTER` alone, or `CRITICAL` to itself, as a document batch
/// has always computed it.
#[test]
fn should_give_the_levels_each_document_requirement_admits() {
use SecurityLevel::*;
assert_eq!(MASTER.document_signing_levels(), vec![MASTER]);
assert_eq!(CRITICAL.document_signing_levels(), vec![CRITICAL]);
assert_eq!(HIGH.document_signing_levels(), vec![CRITICAL, HIGH]);
assert_eq!(
MEDIUM.document_signing_levels(),
vec![CRITICAL, HIGH, MEDIUM]
);
for requirement in SecurityLevel::full_range() {
let range: Vec<SecurityLevel> = if requirement == MASTER {
vec![MASTER]
} else {
(CRITICAL as u8..=requirement as u8)
.map(|level| SecurityLevel::try_from(level).expect("a security level"))
.collect()
};
assert_eq!(
requirement.document_signing_levels(),
range,
"{requirement}"
);
}
}

// -- TryFrom<u8> valid --
#[test]
fn test_security_level_try_from_u8_all_valid() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use crate::ProtocolError;
use platform_value::Identifier;
#[cfg(feature = "state-transition-signing")]
use platform_version::version::PlatformVersion;
use std::convert::TryFrom;
use crate::state_transition::batch_transition::batched_transition::{BatchedTransition, BatchedTransitionRef};
#[cfg(feature = "state-transition-signing")]
use crate::state_transition::batch_transition::methods::StateTransitionCreationOptions;
Expand Down Expand Up @@ -165,14 +164,12 @@ pub trait DocumentsBatchTransitionMethodsV0: DocumentsBatchTransitionAccessorsV0
}
};

Ok(if highest_security_level == SecurityLevel::MASTER {
vec![SecurityLevel::MASTER]
} else {
// this might seem wrong until you realize that master is 0, critical 1, etc
(SecurityLevel::CRITICAL as u8..=highest_security_level as u8)
.map(|security_level| SecurityLevel::try_from(security_level).unwrap())
.collect()
})
// Edited in place in a shipped generation: `document_signing_levels` returns what the
// code it replaced did for every requirement (MASTER alone for MASTER, otherwise
// CRITICAL through the requirement, strongest first), without its `unwrap`. Its tests
// and the batch tests pin each output, so no protocol version that signs or checks a
// batch through this method can see another result.
Ok(highest_security_level.document_signing_levels())
}

fn set_transitions(&mut self, transitions: Vec<BatchedTransition>);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,69 @@ mod batch_transition_tests {
assert_eq!(purposes, vec![Purpose::AUTHENTICATION]);
}

// -----------------------------------------------------------------------
// combined_security_level_requirement
// -----------------------------------------------------------------------

/// The levels a batch may be signed at, pinned for each document requirement, for the
/// strongest of two requirements, for a token transition and for an empty batch: they
/// come from `SecurityLevel::document_signing_levels` and must not change.
#[test]
fn should_keep_the_levels_a_batch_may_be_signed_at() {
use SecurityLevel::*;
let documents = make_batch_v1(vec![
BatchedTransition::Document(make_delete_transition(1)),
BatchedTransition::Document(make_delete_transition(2)),
]);
for (requirement, expected) in [
(MASTER, vec![MASTER]),
(CRITICAL, vec![CRITICAL]),
(HIGH, vec![CRITICAL, HIGH]),
(MEDIUM, vec![CRITICAL, HIGH, MEDIUM]),
] {
let levels = documents
.combined_security_level_requirement(Some(
move |_: Identifier, _: String| -> Result<SecurityLevel, ProtocolError> {
Ok(requirement)
},
))
.expect("the levels");
assert_eq!(levels, expected, "{requirement}");
}

// The strongest requirement among the batch's documents wins.
let calls = std::cell::Cell::new(0);
let mixed = documents
.combined_security_level_requirement(Some(
|_: Identifier, _: String| -> Result<SecurityLevel, ProtocolError> {
calls.set(calls.get() + 1);
Ok(if calls.get() == 1 { MEDIUM } else { HIGH })
},
))
.expect("the levels");
assert_eq!(mixed, vec![CRITICAL, HIGH]);

let token = make_batch_v1(vec![BatchedTransition::Token(make_token_burn_transition(
1, 10,
))]);
assert_eq!(
token
.combined_security_level_requirement(
None::<fn(Identifier, String) -> Result<SecurityLevel, ProtocolError>>
)
.expect("the levels"),
vec![CRITICAL]
);
assert_eq!(
make_batch_v1(vec![])
.combined_security_level_requirement(
None::<fn(Identifier, String) -> Result<SecurityLevel, ProtocolError>>
)
.expect("the levels"),
vec![CRITICAL, HIGH, MEDIUM]
);
}

// -----------------------------------------------------------------------
// get_security_level_requirement function
// -----------------------------------------------------------------------
Expand Down
12 changes: 7 additions & 5 deletions packages/rs-platform-encryption/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ pub use ecdh::derive_shared_key_ecdh;
pub use error::CryptoError;
pub use private_document_envelope::{
open_private_document_entry, private_document_outgoing_viewing_key,
recover_sent_private_document_entry, seal_private_document_entry, OpenedPrivateDocumentEntry,
PrivateDocumentAuthMode, PrivateDocumentEnvelopeError, PrivateDocumentRecipient,
PrivateDocumentRecipientKeys, PrivateDocumentSender, PrivateDocumentTarget,
PRIVATE_DOCUMENT_ENVELOPE_BODY_HEADER_LEN, PRIVATE_DOCUMENT_ENVELOPE_OVERHEAD_LEN,
PRIVATE_DOCUMENT_ENVELOPE_VERSION, PRIVATE_DOCUMENT_ENVELOPE_WRAPPER_LEN,
private_document_signing_data, recover_private_document_signer,
recover_sent_private_document_entry, seal_private_document_entry,
sign_private_document_signing_data, OpenedPrivateDocumentEntry, PrivateDocumentAuthMode,
PrivateDocumentEnvelopeError, PrivateDocumentRecipient, PrivateDocumentRecipientKeys,
PrivateDocumentSender, PrivateDocumentTarget, PRIVATE_DOCUMENT_ENVELOPE_BODY_HEADER_LEN,
PRIVATE_DOCUMENT_ENVELOPE_OVERHEAD_LEN, PRIVATE_DOCUMENT_ENVELOPE_VERSION,
PRIVATE_DOCUMENT_ENVELOPE_WRAPPER_LEN,
};
Loading
Loading