fix(dpp)!: propertyConstraints compare identifier properties that declare refersTo (PV14) - #5073
Conversation
…lare refersTo (PV14) An identifier property with `refersTo` parses to `DocumentPropertyType::IdentifierWithReference`, but `apply_property_constraints_v0` recognized only the plain `Identifier` type: the parser took a const or a listed value beside such a property for a string, and two such properties or one and `$ownerId` for integers, so every identifier comparison of it was refused at registration. The property kind closure, the identifier read check and the hint for an identifier read as a number now match both variants, as the rest of the file does. Evaluation already reads identifiers with `Value::to_identifier` whatever the declared type, so it is unchanged. Extended in place: `parse_property_constraints` 0 is selected only by protocol version 14, which has not shipped, and the change only widens what registers; every previously valid declaration parses and evaluates as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedNext included review available in 22 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Repository: dashpay/platform/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (6)
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. Comment |
|
📖 Book Preview built successfully. Download the preview from the workflow artifacts. Updated at 2026-09-27T18:01:52.377Z |
|
🕓 Queued for automated review — 3rd in line, estimated start in ~10 min (commit f6b5f3f)
|
- `DocumentPropertyType::is_identifier()` names identifier-ness once, for a plain identifier and one carrying a reference; the three matches in `apply_property_constraints_v0` use it. - The dpp test sees `buyerIsNotSeller` fail when buyer and seller are the same identity. - A drive-abci test judges a const, an `in` and a property pair over identifier properties that declare `refersTo` an identity, on real creates whose referenced identities exist. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Basic explanation
What this does: A data contract can declare rules (
propertyConstraints) that compare a document's identifier fields: "the payment token is this one", "the buyer is not the seller", "the author is the owner". An identifier field can also say what it points at withrefersTo(for example "this is an existing identity"). Until now a field that declaredrefersTocould not appear in any of those comparisons: the contract was refused at registration with a confusing message claiming the field was a string or a number. This makes such a field compare exactly like any other identifier field.Value: Contract authors can use both keywords on the same field, which is the natural thing to want: a
buyerIdthat must point at an existing identity and must also differ fromsellerId. Before, there was no workaround: droppingrefersToloses the existence check, and dropping the rule loses the comparison.Risks: Low. The change only accepts declarations that were refused before; every contract that registered before parses and behaves exactly as it did. Protocol version 14 has not been released, so no production network runs it. A devnet already running a 4.2 prerelease at protocol version 14 (for example one on 4.2.0-beta.4) does see a consensus change: an upgraded node accepts such a contract where an older node refuses it, so upgrade that devnet all at once, or reset it, rather than node by node. Checking a document against the rules is unchanged: it already read identifiers the same way whatever the field declared.
Issue being fixed or feature implemented
propertyConstraintsgained identifier comparisons in #5047 and$ownerIdin #5048. An identifier property that declaresrefersToparses toDocumentPropertyType::IdentifierWithReference(_), butapply_property_constraints_v0matched onlyDocumentPropertyType::Identifier:property_kindclosure, which tells the parser whether a path names a string, an identifier or neither, returnedNonefor it, so the parser read aconstor aninlist beside it as strings, and a comparison with another identifier property or$ownerIdas integer arithmetic; both were then refused;PropertyRead::Identifiercheck would have refused it too, with "compares "buyerId" with an identifier, but it has type identifier, not identifier" (DocumentPropertyType::name()names both variants "identifier"). The closure hid this one; fixing the closure alone would have exposed it.Everywhere else in that file the pattern
Identifier | IdentifierWithReference(_)was already used.What was done?
DocumentPropertyType::is_identifier()(next tois_integer()): true forIdentifierandIdentifierWithReference(_), false for a typed array of identifiers.apply_property_constraints_v0(packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/mod.rs): three matches that named onlyIdentifiernow testis_identifier():property_kindclosure, so the parser classifies such a path as an identifier;PropertyRead::Identifiercheck, so it accepts it;refersToproperty used in arithmetic gets the same explanation as a plain one (still refused, only the message changes).KeyIdWithReference(au32key id withrefersTo) already reads as an integer throughis_integer().refersToon its items, is an array, which no comparison reads, so nothing changes there.identifier_valuereads withValue::to_identifier()whatever the declared type.v14.rsnow say that identifier properties declaringrefersToare included.Before / after
An
ordertype whosebuyerIdpoints at an identity (sellerIdis a plain identifier):Each rule below, on both parse paths (registration with full validation, and reading a stored contract):
Still refused, now with the same hint a plain identifier gets:
The "before" messages were captured by running the new test against the unfixed parser.
How Has This Been Tested?
should_compare_identifier_properties_that_declare_refers_to(try_from_schema/v3/property_constraints_tests.rs): withrefersTo: { "type": "identity" }onbuyerId, onsellerId, and on both, aconstcomparison, a comparison of the two properties, a$ownerIdcomparison and aninall register on both paths (full validation on and off), read their paths as identifier reads, and judge documents as they would for plain identifiers, each rule seen both holding and failing. Reading such a property as a number, comparing it with a string property, and ordering identifiers stay refused. Before the fix the test failed at the first registration with the "compares "buyerId" with a string" message above.should_compare_an_identifier_property_that_declares_refers_to(batch/tests/document/property_constraints.rs): the owned offer type withsellerIddeclaringrefersTo: { "type": "identity" }registers. A create naming another existing identity as seller is refused withDocumentPropertyConstraintViolatedError(10422, rulesellerIsOwner), one naming the owner is accepted, and a transfer to another identity is refused.should_judge_const_in_and_pair_rules_over_refers_to_identifiers:payerId,refundToandpaymentTokenall declarerefersTo: { "type": "identity" }, and every identity the rules name exists. A create paying in an unlisted identity (in), one naming the banned payer (notEqualwith aconst) and one refunding someone other than the payer (two properties) are each refused with 10422 naming their rule; a create meeting all three, and all three references, is accepted.cargo test -p dpp --lib property_constraints: 59 passedcargo test -p dpp --lib try_from_schema: 477 passedcargo test -p drive-abci --lib property_constraints: 20 passedcargo clippy -p dpp --all-features --all-targets -- -D warnings: cleanBreaking Changes
Consensus, from protocol version 14 (not yet released): contracts whose
propertyConstraintscompare an identifier property that declaresrefersToare now accepted at registration instead of refused. Nodes on either side of the change would disagree on such a registration, hence the!. Nothing changes before protocol version 14, and no contract that registered before is affected. A devnet already running a 4.2 prerelease at protocol version 14 should upgrade all its nodes together.In-place changes
apply_property_constraints_v0is edited in place rather than copied into a new generation, which is safe because:parse_property_constraints: Some(0), which onlyCONTRACT_VERSIONS_V6(protocol version 14) sets. Every earlier table hasNone, which skips the keyword entirely. Protocol version 14 has not shipped, so this generation is not frozen.IdentifierWithReferencepath as an identifier was refused, so no registered contract holds one. Every declaration that parsed before takes the same branch of each widened match and parses to the same rules, and the evaluation code is untouched, so every document is judged as before.Checklist:
structure.rs, regeneratedgrovedb-structure.json, and checked the structure viewer link posted on this pull requestFor repository code-owners and collaborators only
🤖 Generated with Claude Code
PR Hygiene ·
f6b5f3f/skip-botsproceeds without the ones not yet reported/self-reviewedonce the bots are doneWhen every box is checked the
PR Hygienecheck passes and this can merge.