feat(platform)!: contract references may require a minimum age of, and time since the last update to, the referenced contract - #4913
Conversation
… referenced contract A `contract` refersTo declaration's `contractRequirements` gains `minimumAgeSeconds`: the referenced contract's recorded creation time plus that many seconds must not be after the block time of the write. It gives a contract's creation a delay before a charter can be posted against it, so a moderation team cannot be seated before anyone has seen the contract. A contract without a recorded creation time (the V0 format) never meets it. Checked in the document reference validation against the contract already fetched for the existence check, so it costs no further read; an unmet requirement refuses the write with the existing ReferencedContractRequirementNotMetError (40135), field `minimumAgeSeconds`, required = the number. Meta-schema v3 and the parser bound the value to 1..=4294967295; a changed value is an incompatible schema change on update. wasm-dpp2 reports it on the reference surface. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Warning Review limit reachedNext included review available in 37 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 (15)
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-22T15:29:00.747Z |
|
|
… the referenced contract's last update `contractRequirements` gains `minimumSecondsSinceUpdate`, measured from the later of the referenced contract's recorded creation and last update times to the block time of the write. It closes the gap the creation delay leaves: an old contract updated to declare elected moderation would otherwise take its owner's charter in the next block. Any update restarts the clock; a contract never updated counts from its creation; one without a recorded creation time never meets it. Same declaration bounds (1..=u32::MAX), the same 40135 error with the field naming the requirement, and the same wasm-dpp2 surface. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…s old The charter's `targetContractId` reference now also carries `minimumAgeSeconds: 432000` (#4913), so a charter for a contract created less than five days before the block is refused with `ReferencedContractRequirementNotMetError` (40135), like one whose target does not declare elected moderation. The network gets notice of a contract before any team can apply to moderate it. `MINIMUM_TARGET_CONTRACT_AGE_SECONDS` in rs-dpp pins the schema's number through the system contract test, which also gains the two requirement fields #4913 added to `ContractReferenceRequirements`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Issue being fixed or feature implemented
The moderation charters contract (#4898) lets a team apply to moderate a contract the moment that contract exists. A team that also created the target could seat itself before anyone had seen the contract. The charter's
targetContractIdalready requires the target to declare elected moderation throughrefersTo: { "type": "contract", "contractRequirements": { "moderation": "elected" } }(#4909); this adds two duration requirements so a reference can demand a delay between the referenced contract's creation, or its last update, and the referring document. The second closes the gap the first leaves: an old contract updated to declare elected moderation would otherwise take its owner's charter in the next block.What was done?
contractRequirementsgainsminimumAgeSecondsandminimumSecondsSinceUpdate, following the grammar of #4909 (each key an aspect of the referenced contract, its value the requirement):minimumAgeSeconds: the referenced contract's recorded creation time plus that many seconds must not be after the block time of the write.minimumSecondsSinceUpdate: the same, from the later of its recorded creation and last update times, so any update restarts the clock (updated_atis set on every contract update; a contract never updated counts from its creation). The block time is used rather than the document's$createdAt: it is what "post" means, the writer cannot shift it, and the referring type need not carry$createdAt. A contract without a recorded creation time (the V0 format, created before contracts recorded it) is of unknown age and never meets either.ContractReferenceRequirements::first_unmet_bynow takes the block time; the document reference validation v0 passesblock_info.time_ms. The check runs against the contract already fetched for the existence check, so it costs no further read. An unmet requirement refuses the write, paid, with the existingReferencedContractRequirementNotMetError(40135) withfieldnaming the requirement (minimumAgeSecondsorminimumSecondsSinceUpdate) andrequired= the number as text. No new error code orStateErrordiscriminant. The error message was reworded from "does not declare" to "does not meet the reference's requirement" so it reads for both keys.apply_property_referencev0 accept, for each, an integer from 1 to 4294967295 (u32) and refuse zero, negatives, non-integers and strings. A changed value is an incompatible schema change on update, like the rest ofrefersTo.ContractReferenceRequirements.minimum_age_secondsand.minimum_seconds_since_update: Option<u32>,ContractReferenceRequirement::MinimumAgeSecondsand::MinimumSecondsSinceUpdate,ContractReferenceRequirement::is_met_by, the pureminimum_age_is_met(saturating arithmetic) andlast_change_time.required()returns aStringnow.Displayappends "at least N seconds old" and "unchanged for at least N seconds".contractRequirements?: { moderation?: 'elected'; minimumAgeSeconds?: number; minimumSecondsSinceUpdate?: number }.Follow-up: add
minimumAgeSecondsandminimumSecondsSinceUpdateto the charter'stargetContractIdin #4898 once the delays are chosen.How Has This Been Tested?
moderation, up tou32::MAX; zero, negative, too large, float and string refused, the error naming the key), meta-schema v3 tests (accepted values; malformed values, unknown keys andcontractRequirementson an identity reference refused),Display, the update-compatibility test (a changed value reports/properties/toUserId/refersTo/contractRequirements/<key>), a unit test of the duration arithmetic (one millisecond short, exact boundary, no recorded time, saturation) and one oflast_change_time(neither, creation only, both, update only).reference-validation-contract-aged-contract-ref.json(minimumAgeSeconds: 3600) andreference-validation-contract-updated-contract-ref.json(minimumSecondsSinceUpdate: 3600); the reference-validation helper now takes aBlockInfo. Six new creation tests: referenced contract created one millisecond less than the minimum before the block (40135, fieldminimumAgeSeconds, required3600), without a creation time (40135), created exactly the minimum before the block (success); created long ago but updated one millisecond too recently (40135, fieldminimumSecondsSinceUpdate), updated exactly the minimum before the block (success), never updated and created exactly the minimum before the block (success). The four existing contract-reference tests still pass.cargo check -p wasm-dpp2 --target wasm32-unknown-unknown, clippy on dpp and drive-abci, rustfmt.Breaking Changes
Consensus: a
contractreference may now refuse a document write that the previous rules accepted, under protocol version 14 (unreleased), by the same code 40135 as an unmet moderation requirement. TheDocumentPropertyReferenceTarget::Contractencoding gains a field, in place at the unreleased version.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 ·
2aaa60c/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.