Skip to content
Closed
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8445e18
feat: add the dash-sdk-contract declaration model, grammar and diagno…
DCG-Claude Sep 13, 2026
cf98654
build: wire dash-sdk-contract into CI and document the author API
DCG-Claude Sep 13, 2026
fd0071a
refactor: merge declarations through an identified-spec trait
DCG-Claude Sep 13, 2026
182a2f8
fix: make declaration merging order independent and bound interface w…
DCG-Claude Sep 13, 2026
6ecf308
fix: keep aggregate options explicit and canonicalize order-insensiti…
DCG-Claude Sep 15, 2026
6ef0251
build: refresh the lock after rebasing onto v4.3-dev and satisfy clip…
DCG-Claude Sep 15, 2026
fb37fac
feat: declare required system properties and sharpen wire and ranked …
DCG-Claude Sep 16, 2026
1b0040d
feat: carry the time-range ttl and canonicalize enum values
DCG-Claude Sep 16, 2026
7a79e56
build: refresh the lock for the 4.2.0-beta.3 workspace version
DCG-Claude Sep 22, 2026
6565750
feat: declare no-locking contests, composite terminals and count unde…
DCG-Claude Sep 27, 2026
909aa5e
build: refresh the lock for the 4.2.0-beta.4 workspace version
DCG-Claude Sep 27, 2026
26d83fe
feat: flat index-only indexes, entry payloads and the native property…
DCG-Claude Sep 27, 2026
69cfdd0
feat: implicit owner terminal, range-count countability, optional tok…
DCG-Claude Sep 29, 2026
5ace03a
build: refresh the lock for the 5.0.1 workspace version
DCG-Claude Oct 30, 2026
e5c3a9d
fix: natively valid score sketch, entry payload in the index-only dia…
DCG-Claude Oct 30, 2026
4d4779b
feat: integer ranges, skip sets on any index, level rankings for sums…
DCG-Claude Oct 30, 2026
afdf0d3
feat: deletion only when consumed, a type-level time to live and the …
DCG-Claude Oct 30, 2026
0eaaacb
test: align the score fixture with the natively valid sketch
DCG-Claude Oct 30, 2026
ae85f57
docs: typed-array indexes outside the model and the native prefix ran…
DCG-Claude Oct 30, 2026
cd5e9da
fix: report the own faults of declarations set aside by deduplication
DCG-Claude Oct 30, 2026
c2da2c0
fix: refuse a disabled interface requested by any collection declaration
DCG-Claude Oct 30, 2026
fc0820e
fix: check a repeated attribute option's value as well as reporting t…
DCG-Claude Nov 2, 2026
455f48d
fix: report every malformed entry of an attribute map
DCG-Claude Nov 2, 2026
05821ad
fix: every invalid list choice, one check per equivalence class, and …
DCG-Claude Nov 2, 2026
183dea8
docs: the count promotions as a mirrored exception and codes assigned…
DCG-Claude Nov 2, 2026
34b0698
fix: check module imports as a set and align the rustdoc with count n…
DCG-Claude Nov 2, 2026
2fdadc4
fix: leave the bucket source position to DPP and list the private doc…
DCG-Claude Nov 2, 2026
20176e9
fix: leave system-property terminal eligibility to DPP
DCG-Claude Nov 2, 2026
a8b839b
test: fail the book table test on an unreadable chapter inside the re…
DCG-Claude Nov 2, 2026
407d980
fix: leave index-only layout compatibility to DPP
DCG-Claude Nov 2, 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
4 changes: 4 additions & 0 deletions .github/package-filters/rs-packages-no-workflows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ rs-sdk-trusted-context-provider: &sdk_trusted_context_provider
- *context_provider
- *dpp

dash-sdk-contract:
- packages/rs-dash-sdk-contract/**
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
- book/src/dashvm/contract-declarations.md

dapi-grpc: &dapi_grpc
- packages/rs-platform-version/**
- packages/rs-dash-platform-macros/**
Expand Down
5 changes: 5 additions & 0 deletions .github/package-filters/rs-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ rs-sdk-trusted-context-provider: &sdk_trusted_context_provider
- *context_provider
- *dpp

dash-sdk-contract:
- .github/workflows/tests*
- packages/rs-dash-sdk-contract/**
- book/src/dashvm/contract-declarations.md

dapi-grpc: &dapi_grpc
- .github/workflows/tests*
- packages/rs-platform-version/**
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/tests-rs-workspace.yml
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,17 @@ jobs:
- name: Link dash-sdk-cxx from C++
run: packages/rs-sdk-cxx/scripts/cxx-smoke.sh

# The contract-author declaration crate is a guest dependency: contract
# packages compile it for WebAssembly without std. Whole-workspace
# builds unify features and would hide a std leak, so check the
# standalone no-std graph on the no-std-library wasm target and run the
# crate's tests without default features.
- name: Check guest declaration cut
run: |
rustup target add wasm32v1-none
cargo check -p dash-sdk-contract --no-default-features --target wasm32v1-none --locked
cargo test -p dash-sdk-contract --no-default-features --locked

- name: Detect immutable structure changes
if: github.event_name == 'pull_request'
run: |
Expand Down Expand Up @@ -506,6 +517,7 @@ jobs:
--package app-connect-contract \
--package moderation-charters-contract \
--package decision-proposals-contract \
--package dash-sdk-contract \
--all-features \
--locked \
-E '(not test(~shield) or (package(=platform-wallet-storage) and not test(~wallet::shielded::))) and (not binary_id(=drive-abci::strategy_tests) or test(~comprehensive_mixed_operations) or test(~process_proposal_collision))'
Expand Down
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ resolver = "2"
members = [
"packages/dapi-grpc",
"packages/rs-dash-platform-macros",
"packages/rs-dash-sdk-contract",
"packages/rs-dpp",
"packages/rs-drive",
"packages/rs-platform-value",
Expand Down
4 changes: 4 additions & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@
- [Binding Patterns](wasm/binding-patterns.md)
- [Error Macros](wasm/error-macros.md)

# DashVM

- [Contract Declarations and the Author API](dashvm/contract-declarations.md)

---

# Appendix
Expand Down
1 change: 1 addition & 0 deletions book/src/contributing/coding-conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ crate that has what the change needs, and no lower.
| A client API | `packages/rs-sdk` | Follow the query checklist in `packages/rs-sdk/README.md`. |
| A JavaScript binding | `packages/wasm-dpp2`, `packages/wasm-sdk` | Mirror the Rust shape; never validate. See `packages/wasm-dpp2/CONVENTIONS.md`. |
| Mobile orchestration (sync, identity registration, DashPay) | `packages/rs-platform-wallet` | The FFI crates and the Swift and Kotlin SDKs marshal; they do not decide. |
| A contract-author declaration or diagnostic | `packages/rs-dash-sdk-contract` | Builds for `wasm32v1-none` with `--no-default-features`; native limits are not duplicated there, they surface through `dash-contract-build`. See [Contract Declarations](../dashvm/contract-declarations.md). |

Three boundaries are enforced by CI and worth knowing by name:

Expand Down
414 changes: 414 additions & 0 deletions book/src/dashvm/contract-declarations.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/check-features/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ fn main() {
("rs-drive-proof-verifier", vec![]),
("rs-platform-wallet", vec![]),
("dash-platform-queries", vec![]),
("rs-dash-sdk-contract", vec![]),
];

for (specific_crate, to_ignore) in crates {
Expand Down
15 changes: 15 additions & 0 deletions packages/rs-dash-sdk-contract/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "dash-sdk-contract"
version.workspace = true
edition = "2021"
rust-version.workspace = true
authors = ["Dash Core Team"]
license = "MIT"
description = "Contract-author SDK for DashVM: declaration model, attribute grammar, diagnostics and canonical manifest"

[dependencies]
thiserror = { version = "2.0.17", default-features = false }

[features]
default = ["std"]
std = ["thiserror/std"]
24 changes: 24 additions & 0 deletions packages/rs-dash-sdk-contract/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# dash-sdk-contract

Contract-author SDK for DashVM: the declaration model behind `#[persistent]`,
`#[index]`, `#[rule]` and `#[entry]`, the attribute grammar those macros
implement, the diagnostics they report, and the canonical manifest a contract
package publishes.

```rust
use dash_sdk_contract::prelude::*;
```

This crate specifies the author-facing model. It carries no proc macros, no
host context and no runtime. It compiles without `std` on `wasm32v1-none`:

```bash
cargo check -p dash-sdk-contract --no-default-features --target wasm32v1-none
cargo test -p dash-sdk-contract
cargo test -p dash-sdk-contract --no-default-features
```

The chapter [Contract Declarations and the Author API](../../book/src/dashvm/contract-declarations.md)
in the Dash Platform Book describes the grammar, the identity rules, the
persistence semantics and what the validator checks versus what native
validation enforces.
136 changes: 136 additions & 0 deletions packages/rs-dash-sdk-contract/src/declare/capability.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
//! The capability catalogue: what a contract may require, and whether the
//! native host supports it today.

use core::fmt;

use super::collections::TypedCollectionKind;

/// Support status of a capability in the native host.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum CapabilityStatus {
/// Supported by the native host today; a manifest requesting it can be
/// deployed.
Native,
/// Specified, declarable, but without a native implementation yet. The
/// validator accepts the declaration; the build crate reports it as a
/// native gap and refuses to call the manifest deployable.
PendingNative,
/// Catalogued but disabled: the declaration is rejected until the
/// capability's semantics are specified. Today only the private document
/// store, whose encryption, key control, query visibility and proof
/// behaviour are not yet specified.
InterfaceDisabled,
}

/// A capability a contract requires, either explicitly (`requires = [...]`)
/// or derived from its declarations.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum CapabilityRequirement {
/// The native access-control primitive. Explicit.
Acl,
/// The native randomness primitive. Explicit.
Randomness,
/// `write = "contract"`: only the contract's own code may create
/// documents. Derived.
ContractWrites,
/// A rule with a native guard expression. Derived.
NativeGuards,
/// A rule with a read-only WASM predicate. Derived.
WasmPredicates,
/// A typed specialized collection of the given kind. Derived.
TypedCollections(TypedCollectionKind),
/// `store = "private"`. Derived.
PrivateStore,
/// Stored receipts (the default policy). Derived.
StoredReceipts,
/// At least one entry, which needs the DashVM runtime. Derived.
Entries,
/// More than one module, which needs bundle linking. Derived.
Modules,
}

impl CapabilityRequirement {
/// Whether the author writes this requirement (as opposed to the validator
/// deriving it).
pub fn is_explicit(&self) -> bool {
matches!(
self,
CapabilityRequirement::Acl | CapabilityRequirement::Randomness
)
}

/// The catalogue status of the requirement.
pub fn status(&self) -> CapabilityStatus {
match self {
CapabilityRequirement::PrivateStore => CapabilityStatus::InterfaceDisabled,
CapabilityRequirement::Acl
| CapabilityRequirement::Randomness
| CapabilityRequirement::ContractWrites
| CapabilityRequirement::NativeGuards
| CapabilityRequirement::WasmPredicates
| CapabilityRequirement::TypedCollections(_)
| CapabilityRequirement::StoredReceipts
| CapabilityRequirement::Entries
| CapabilityRequirement::Modules => CapabilityStatus::PendingNative,
}
}
}

impl fmt::Display for CapabilityRequirement {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CapabilityRequirement::Acl => f.write_str("acl"),
CapabilityRequirement::Randomness => f.write_str("randomness"),
CapabilityRequirement::ContractWrites => f.write_str("contract writes"),
CapabilityRequirement::NativeGuards => f.write_str("native guards"),
CapabilityRequirement::WasmPredicates => f.write_str("wasm predicates"),
CapabilityRequirement::TypedCollections(kind) => {
write!(f, "typed collections ({kind})")
}
CapabilityRequirement::PrivateStore => f.write_str("private store"),
CapabilityRequirement::StoredReceipts => f.write_str("stored receipts"),
CapabilityRequirement::Entries => f.write_str("entries"),
CapabilityRequirement::Modules => f.write_str("modules"),
}
}
}

/// Whether the host stores a receipt for every outer invocation.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ReceiptPolicy {
/// One bounded receipt per outer invocation, the default.
#[default]
Stored,
/// No receipts.
Disabled,
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn should_keep_the_private_store_catalogued_but_disabled() {
assert_eq!(
CapabilityRequirement::PrivateStore.status(),
CapabilityStatus::InterfaceDisabled
);
assert!(!CapabilityRequirement::PrivateStore.is_explicit());
}

#[test]
fn should_mark_acl_and_randomness_explicit_and_pending() {
for capability in [
CapabilityRequirement::Acl,
CapabilityRequirement::Randomness,
] {
assert!(capability.is_explicit());
assert_eq!(capability.status(), CapabilityStatus::PendingNative);
}
}

#[test]
fn should_default_receipts_to_stored() {
assert_eq!(ReceiptPolicy::default(), ReceiptPolicy::Stored);
}
}
Loading
Loading