diff --git a/README.md b/README.md index a94ba55a282..357a8b9ad06 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,10 @@ Schema-based specifications that describe the structure and validation rules for their application data. The network stores, indexes, and enforces these schemas directly. Applications interact with the platform through structured data reads and writes (called **state transitions**) rather than arbitrary code execution. -Smart contract support is planned for Platform v4.0 (targeted for mainnet in -2027). +Smart-contract execution (DashVM: Rust contracts compiled to WebAssembly and +run on Wasmtime) is in development for Platform 5.0. The plan and the design +decisions are tracked in +[dashpay/platform#4626](https://github.com/dashpay/platform/issues/4626). ### How Dash Platform compares @@ -60,7 +62,7 @@ Smart contract support is planned for Platform v4.0 (targeted for mainnet in | **State proofs** | Merkle-Patricia proofs | No native proofs | **GroveDB Merkle proofs for every query** | | **Light client trust** | Needs sync committee | Trusts RPC provider | **Cryptographic proof per response -- same security as a full node** | | **Data model** | Account / key-value | Account / key-value | **Structured documents with secondary indexes** | -| **Smart contracts** | **Yes (Solidity / Vyper on EVM)** | **Yes (Rust / C on SVM)** | Coming in v4.0 | +| **Smart contracts** | **Yes (Solidity / Vyper on EVM)** | **Yes (Rust / C on SVM)** | In development for 5.0 (Rust on WebAssembly) | The standout difference is light client verification. Most chains either offer no state proofs (Solana) or give proofs that are expensive to verify @@ -170,7 +172,9 @@ are located in the [packages](./packages) directory. Key packages include: - **rs-sdk** -- Rust SDK for building applications on Dash Platform - **wasm-sdk** / **wasm-dpp2** -- WebAssembly bindings for browser-based applications -- **rs-sdk-ffi** / **swift-sdk** -- FFI layer and iOS/Swift SDK +- **rs-sdk-ffi** / **rs-platform-wallet-ffi** / **rs-unified-sdk-ffi** / + **rs-unified-sdk-jni** -- FFI and JNI layers under the mobile SDKs +- **swift-sdk** / **kotlin-sdk** -- iOS/Swift SDK and Android/Kotlin SDK - **js-evo-sdk** -- JavaScript SDK - **dashmate** -- Node management and local development tool - **dapi** / **rs-dapi** -- Decentralized API server implementations @@ -181,8 +185,8 @@ are located in the [packages](./packages) directory. Key packages include: |-----|--------|---------| | **Rust** | Available now | [`rs-sdk`](./packages/rs-sdk) | | **JavaScript** | Available now | [`js-evo-sdk`](./packages/js-evo-sdk) | -| **iOS (Swift)** | Coming in v3.1 | [`swift-sdk`](./packages/swift-sdk) | -| **Android** | Coming in v3.2 | -- | +| **iOS (Swift)** | Available; built from source with `build_ios.sh` (Swift Package Manager, iOS 18+ / macOS 15+) | [`swift-sdk`](./packages/swift-sdk) | +| **Android (Kotlin)** | Available; shipped as an AAR asset on each platform GitHub release | [`kotlin-sdk`](./packages/kotlin-sdk) | For details on choosing an SDK and what each one provides, see the [SDK Support](https://dashpay.github.io/platform/sdk-support.html) chapter in diff --git a/book/src/architecture/overview.md b/book/src/architecture/overview.md index d001c411ec7..8f8c4135cc1 100644 --- a/book/src/architecture/overview.md +++ b/book/src/architecture/overview.md @@ -1,6 +1,6 @@ # Monorepo Overview -Dash Platform ships as a single Git repository containing 47 Rust crates, a +Dash Platform ships as a single Git repository containing 49 Rust crates, a handful of JavaScript/TypeScript packages, and supporting tooling. This chapter maps the territory: what each crate owns, how they depend on one another, and where the boundaries are drawn. @@ -17,8 +17,9 @@ a few critical external dependencies at the workspace level -- most notably dashcore = { git = "https://github.com/dashpay/rust-dashcore", rev = "53d699c..." } ``` -The workspace version (`4.2.0-dev` at time of writing, Rust edition 2021, MSRV -1.98) is shared by all member crates through `version.workspace = true`. +The workspace version (`4.2.0-beta.N` in the root `Cargo.toml` at the time of +writing; Rust edition 2021, MSRV 1.98) is shared by all member crates through +`version.workspace = true`. ## The Core Dependency Chain @@ -273,17 +274,18 @@ Here is a simplified view of every Rust workspace member, grouped by role: | Role | Crates | |------|--------| -| **Protocol types** | `dpp`, `platform-value`, `platform-serialization`, `platform-serialization-derive`, `platform-versioning`, `platform-value-convertible` | +| **Protocol types** | `dpp`, `platform-version`, `platform-value`, `platform-serialization`, `platform-serialization-derive`, `platform-versioning`, `platform-value-convertible`, `dpp-json-convertible-derive` | | **Storage** | `drive` | | **Application server** | `drive-abci` | -| **Client SDK** | `dash-sdk`, `rs-dapi-client`, `dash-context-provider`, `rs-sdk-trusted-context-provider` | +| **Client SDK** | `dash-sdk`, `rs-dapi-client`, `dash-context-provider`, `rs-sdk-trusted-context-provider`, `dash-async`, `dash-platform-queries` | | **Proof verification** | `drive-proof-verifier` | | **gRPC definitions** | `dapi-grpc` | | **WASM bindings** | `wasm-dpp`, `wasm-dpp2`, `wasm-sdk`, `wasm-drive-verify` | -| **iOS/FFI** | `rs-sdk-ffi` | -| **System contracts** | `dpns-contract`, `dashpay-contract`, `withdrawals-contract`, `masternode-reward-shares-contract`, `wallet-utils-contract`, `token-history-contract`, `keyword-search-contract`, `document-history-contract`, `app-connect-contract`, `moderation-charters-contract`, `data-contracts` | -| **Tooling** | `dashmate` (JS), `strategy-tests`, `simple-signer`, `check-features`, `json-schema-compatibility-validator` | -| **Other** | `dash-platform-macros`, `rs-dash-event-bus`, `rs-platform-wallet`, `dash-platform-balance-checker`, `rs-dapi` | +| **Wallet** | `platform-wallet`, `platform-wallet-storage`, `platform-encryption` | +| **Mobile/FFI** | `rs-sdk-ffi`, `platform-wallet-ffi`, `rs-unified-sdk-ffi` (C ABI consumed by `swift-sdk`), `rs-unified-sdk-jni` (JNI shim consumed by `kotlin-sdk`); the Swift and Kotlin SDKs themselves are non-Rust packages layered on these crates | +| **System contracts** | `dpns-contract`, `dashpay-contract`, `withdrawals-contract`, `masternode-reward-shares-contract`, `wallet-utils-contract`, `token-history-contract`, `document-history-contract`, `keyword-search-contract`, `app-connect-contract`, `moderation-charters-contract`, `data-contracts` | +| **Tooling** | `dashmate` (JS), `strategy-tests`, `simple-signer`, `check-features`, `json-schema-compatibility-validator`, `rs-scripts` | +| **Other** | `dash-platform-macros`, `rs-dash-event-bus`, `dash-platform-balance-checker`, `rs-dapi` | ## Rules diff --git a/book/src/error-handling/consensus-errors.md b/book/src/error-handling/consensus-errors.md index 8558c088e42..ef862813a7a 100644 --- a/book/src/error-handling/consensus-errors.md +++ b/book/src/error-handling/consensus-errors.md @@ -55,9 +55,9 @@ There are five things worth understanding here. Every consensus error falls into one of four categories: -- **BasicError** -- structural and syntactic validation failures. The state transition itself is malformed, references a nonexistent document type, has an invalid identifier, exceeds size limits, or fails schema validation. These are caught before the node ever checks persistent state. The `BasicError` enum in `packages/rs-dpp/src/errors/consensus/basic/basic_error.rs` contains over 130 variants organized into sub-groups: versioning errors, structure errors, data contract errors, group errors, document errors, token errors, identity errors, state transition errors, and address errors. +- **BasicError** -- structural and syntactic validation failures. The state transition itself is malformed, references a nonexistent document type, has an invalid identifier, exceeds size limits, or fails schema validation. These are caught before the node ever checks persistent state. The `BasicError` enum in `packages/rs-dpp/src/errors/consensus/basic/basic_error.rs` contains over 200 variants organized into sub-groups: versioning errors, structure errors, data contract errors, group errors, document errors, token errors, identity errors, state transition errors, and address errors. -- **StateError** -- the transition is structurally valid but conflicts with the current platform state. A document already exists, an identity nonce is wrong, a token account is frozen, a group action was already completed. The `StateError` enum in `packages/rs-dpp/src/errors/consensus/state/state_error.rs` contains roughly 80 variants covering data contracts, documents, identities, voting, tokens, groups, and address balances. +- **StateError** -- the transition is structurally valid but conflicts with the current platform state. A document already exists, an identity nonce is wrong, a token account is frozen, a group action was already completed. The `StateError` enum in `packages/rs-dpp/src/errors/consensus/state/state_error.rs` contains roughly 150 variants covering data contracts, documents, identities, voting, tokens, groups, and address balances. - **SignatureError** -- the cryptographic signature on the transition is invalid. The identity was not found, the key type is wrong, the key is disabled, the security level is insufficient, or the raw signature verification failed. diff --git a/book/src/introduction.md b/book/src/introduction.md index 72728a4e873..43109ca11fa 100644 --- a/book/src/introduction.md +++ b/book/src/introduction.md @@ -202,8 +202,8 @@ with `rs-` on disk but have shorter names in `Cargo.toml`: | `packages/rs-platform-serialization` | `platform-serialization` | | `packages/rs-drive-proof-verifier` | `drive-proof-verifier` | -The workspace currently targets Rust 1.98 and protocol version 14 (as of -4.2.0-dev). The workspace `Cargo.toml` lists 47 member crates, but the core +The workspace currently targets Rust 1.98 and protocol version 14 (the 4.2 +line). The workspace `Cargo.toml` lists 49 member crates, but the core platform logic lives in the first eight listed above. Let's begin with the architecture. diff --git a/book/src/platform-comparison.md b/book/src/platform-comparison.md index 1446db21f03..a637588bf3a 100644 --- a/book/src/platform-comparison.md +++ b/book/src/platform-comparison.md @@ -35,9 +35,9 @@ security guarantees as a full node. | | Bitcoin | Ethereum | Solana | Polkadot | NEAR | Cosmos SDK | Avalanche | Dash Platform | |---|---|---|---|---|---|---|---|---| -| **Smart contracts** | `-` Limited Script opcodes | `+++` Solidity / Vyper on EVM | `+++` Rust / C on SVM | `++` Per-parachain, typically Wasm | `++` Rust / JS / AssemblyScript on Wasm VM | `+` App-specific (Go) | `++` Solidity on EVM, Rust on Wasm | `-` Coming in v4.0 | -| **VM / execution** | `-` Script interpreter | `+++` EVM | `+++` SVM (eBPF) | `++` Wasm (per parachain) | `++` Wasm VM | `+` No VM (compiled Go) | `++` EVM + Wasm subnets | `-` No VM (data contracts; VM planned for v4.0) | -| **Developer languages** | `-` Script | `+++` Solidity, Vyper | `++` Rust, C | `++` Rust (Substrate) | `++` Rust, JS, AssemblyScript | `+` Go | `++` Solidity, Rust | `+` JSON Schema (data contracts), Rust/JS/Swift (SDKs) | +| **Smart contracts** | `-` Limited Script opcodes | `+++` Solidity / Vyper on EVM | `+++` Rust / C on SVM | `++` Per-parachain, typically Wasm | `++` Rust / JS / AssemblyScript on Wasm VM | `+` App-specific (Go) | `++` Solidity on EVM, Rust on Wasm | `-` In development for 5.0 (Rust on WebAssembly, DashVM) | +| **VM / execution** | `-` Script interpreter | `+++` EVM | `+++` SVM (eBPF) | `++` Wasm (per parachain) | `++` Wasm VM | `+` No VM (compiled Go) | `++` EVM + Wasm subnets | `-` No VM today (data contracts); DashVM (Wasmtime) in development for 5.0 | +| **Developer languages** | `-` Script | `+++` Solidity, Vyper | `++` Rust, C | `++` Rust (Substrate) | `++` Rust, JS, AssemblyScript | `+` Go | `++` Solidity, Rust | `+` JSON Schema (data contracts), Rust/JS/Swift/Kotlin (SDKs) | | **Smart contract security** | N/A | `+` Reentrancy, gas exploits | `++` No reentrancy, but complexity | `++` Sandboxed per parachain | `++` Wasm sandboxing | N/A | `+` Inherits EVM risks | N/A (data contracts are declarative) | Dash Platform takes a fundamentally different approach: instead of a VM that @@ -45,8 +45,12 @@ executes arbitrary code, developers define **data contracts** -- JSON Schema-based specifications that describe the structure and validation rules for their application data. The network stores, indexes, and enforces these schemas directly. This eliminates entire classes of smart contract vulnerabilities -(reentrancy, unchecked external calls, gas manipulation). Smart contract support -is planned for Platform v4.0 (targeted for mainnet in 2027). +(reentrancy, unchecked external calls, gas manipulation). Smart-contract +execution (DashVM: Rust contracts compiled to WebAssembly and run on Wasmtime) +is in development for Platform 5.0, tracked in +[dashpay/platform#4626](https://github.com/dashpay/platform/issues/4626). The +data-contract model stays: contracts compose with the existing native rules +rather than replacing them. ## Token Support @@ -70,7 +74,7 @@ enforced by the protocol itself. | **License** | MIT | Various (GPL, Apache, MIT) | Apache 2.0 | GPL 3.0 | Apache 2.0 / MIT | Apache 2.0 | BSD 3-Clause | MIT | | **Open source** | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | | **Core language** | C++ | Go, Rust | Rust | Rust | Rust | Go | Go | Rust | -| **Client SDKs** | `+` Multiple (community) | `+++` web3.js, ethers.js, viem | `++` @solana/web3.js | `+` Polkadot.js | `+` near-api-js | `+` CosmJS | `++` ethers.js (C-Chain) | `++` Rust, JavaScript, Swift (iOS), Android (coming) | +| **Client SDKs** | `+` Multiple (community) | `+++` web3.js, ethers.js, viem | `++` @solana/web3.js | `+` Polkadot.js | `+` near-api-js | `+` CosmJS | `++` ethers.js (C-Chain) | `++` Rust, JavaScript, Swift (iOS), Kotlin (Android) | | **Launched** | 2009 | 2015 | 2020 | 2020 | 2020 | 2019 (SDK) | 2020 | 2024 (v1.0 mainnet) | | **Ecosystem maturity** | `+++` Largest, most established | `+++` Largest smart contract ecosystem | `++` Fast-growing DeFi ecosystem | `+` Growing parachain ecosystem | `+` Growing dApp ecosystem | `++` Many sovereign chains | `++` Growing subnet ecosystem | `+` Early stage, growing | | **Identity system** | `-` Addresses only | `+` ENS (contract-based) | `-` No native identity | `-` No native identity | `+` Named accounts | `-` No native identity | `-` No native identity | `+++` Protocol-native identities with hierarchical keys and DPNS usernames | diff --git a/book/src/sdk-support.md b/book/src/sdk-support.md index 582ed0c2cca..69ae63835f6 100644 --- a/book/src/sdk-support.md +++ b/book/src/sdk-support.md @@ -9,14 +9,17 @@ developers can build applications on whatever stack they prefer. |-----|----------|--------|---------|----------| | **Rust SDK** | Rust | Available now | [`rs-sdk`](https://github.com/dashpay/platform/tree/master/packages/rs-sdk) | Server-side applications, full-node tooling, direct protocol access | | **JavaScript SDK** | JavaScript / TypeScript | Available now | [`js-evo-sdk`](https://github.com/dashpay/platform/tree/master/packages/js-evo-sdk) | Node.js backends, scripts, CLI tools | -| **iOS SDK** | Swift | Coming in v3.1 | [`swift-sdk`](https://github.com/dashpay/platform/tree/master/packages/swift-sdk) | iOS and macOS applications | -| **Android SDK** | Kotlin | Coming in v3.2 | -- | Android applications | +| **iOS SDK** | Swift | Available; iOS 18+ and macOS 15+ via Swift Package Manager. The `DashSDKFFI.xcframework` binary target is built locally by `build_ios.sh` | [`swift-sdk`](https://github.com/dashpay/platform/tree/master/packages/swift-sdk) | iOS and macOS applications | +| **Android SDK** | Kotlin | Available; an AAR is attached to every platform GitHub release. Maven coordinates `org.dashj:dash-sdk-android` are the publishing target described in the package's `PUBLISHING.md` | [`kotlin-sdk`](https://github.com/dashpay/platform/tree/master/packages/kotlin-sdk) | Android applications | ### Supporting packages | Package | Purpose | |---------|---------| | [`rs-sdk-ffi`](https://github.com/dashpay/platform/tree/master/packages/rs-sdk-ffi) | C FFI layer over the Rust SDK; used by the Swift SDK, the Android SDK, and any language that can call C | +| [`rs-platform-wallet-ffi`](https://github.com/dashpay/platform/tree/master/packages/rs-platform-wallet-ffi) | C FFI layer over the platform wallet (persistence, key management, shielded pool) | +| [`rs-unified-sdk-ffi`](https://github.com/dashpay/platform/tree/master/packages/rs-unified-sdk-ffi) | Unified C ABI combining the SDK, wallet and core wallet FFI crates; packaged as `DashSDKFFI.xcframework` for the Swift SDK | +| [`rs-unified-sdk-jni`](https://github.com/dashpay/platform/tree/master/packages/rs-unified-sdk-jni) | JNI shim over the same FFI crates, loaded by the Kotlin SDK as `libdash_sdk_jni.so` | ## Choosing an SDK @@ -24,11 +27,11 @@ developers can build applications on whatever stack they prefer. performance and direct access to all protocol features, or the **JavaScript SDK** if your stack is Node.js. -**Building an iOS or macOS app?** Use the **Swift SDK** (v3.1+), which wraps -the Rust SDK through an FFI layer and provides native Swift types. +**Building an iOS or macOS app?** Use the **Swift SDK**, which wraps the +Rust SDK through an FFI layer and provides native Swift types. -**Building an Android app?** The **Android SDK** (v3.2+) will wrap the same -FFI layer with native Kotlin types. +**Building an Android app?** Use the **Android SDK**, which wraps the same +FFI crates through a JNI shim with native Kotlin types. **Building for another language?** The **FFI layer** (`rs-sdk-ffi`) exposes a C-compatible interface that can be called from Python, C#, or any language diff --git a/book/src/state-transitions/lifecycle.md b/book/src/state-transitions/lifecycle.md index 1c5833f2e81..772471f6f92 100644 --- a/book/src/state-transitions/lifecycle.md +++ b/book/src/state-transitions/lifecycle.md @@ -18,7 +18,10 @@ This is fundamentally different from a smart contract model. There is no arbitra execution. Every possible mutation is one of a fixed set of state transition types, each with its own validation rules hardcoded into the platform. The benefit is predictability: you can reason about fees, security, and correctness without worrying about -Turing-complete execution. +Turing-complete execution. The smart-contract work in development for Platform +5.0 ([dashpay/platform#4626](https://github.com/dashpay/platform/issues/4626)) +adds contract execution as further members of this fixed, versioned set rather +than replacing the model. ## The StateTransition Enum @@ -55,6 +58,8 @@ pub enum StateTransition { ShieldFromIdentity(ShieldFromIdentityTransition), IdentityTopUpFromShieldedPool(IdentityTopUpFromShieldedPoolTransition), IdentityKeyLimitsUpdate(IdentityKeyLimitsUpdateTransition), + ContractUserModeration(ContractUserModerationTransition), + ContractFeeClaim(ContractFeeClaimTransition), } ``` @@ -77,19 +82,35 @@ These variants fall into natural groups: - `DataContractCreate` -- Register a new data contract (schema) - `DataContractUpdate` -- Update an existing data contract - `Batch` -- Create, replace, delete, or transfer documents; mint, burn, transfer, or freeze tokens +- `ContractUserModeration` -- Ban, suspend or warn an identity on a moderated contract + (protocol version 14 and later) +- `ContractFeeClaim` -- Pay out a contract's accumulated owner or moderator fee pot + (protocol version 14 and later) **Governance:** - `MasternodeVote` -- Cast a vote in a contested resource election -**Address-based (newer):** -- `IdentityCreateFromAddresses`, `IdentityTopUpFromAddresses`, `AddressFundsTransfer`, - `AddressFundingFromAssetLock`, `AddressCreditWithdrawal` -- Operations that use - platform addresses instead of (or in addition to) identity-based authentication - -**Shielded pool:** -- `Shield`, `ShieldedTransfer`, `Unshield`, `ShieldFromAssetLock`, `ShieldedWithdrawal`, - `IdentityCreateFromShieldedPool`, `ShieldFromIdentity`, `IdentityTopUpFromShieldedPool` -- - Operations that move credits into, inside, and out of the shielded pool +**Address-based (protocol version 11 and later):** +- `IdentityCreditTransferToAddresses`, `IdentityCreateFromAddresses`, + `IdentityTopUpFromAddresses`, `AddressFundsTransfer`, `AddressFundingFromAssetLock`, + `AddressCreditWithdrawal` -- Operations that use platform addresses instead of (or + in addition to) identity-based authentication + +**Shielded pool (protocol version 12 and later):** +- `Shield` -- Move credits from transparent platform addresses into the shielded pool +- `ShieldFromAssetLock` -- Fund the shielded pool directly from a core-chain asset lock +- `ShieldedTransfer` -- Move value inside the pool; only the fee leaves it +- `Unshield` -- Move credits from the pool back to a transparent platform address +- `ShieldedWithdrawal` -- Withdraw credits from the pool to the core chain +- `IdentityCreateFromShieldedPool` -- Create an identity funded from the pool with a + fixed denomination +- `ShieldFromIdentity` -- Move credits from an identity balance into the pool (protocol + version 14 and later) +- `IdentityTopUpFromShieldedPool` -- Top up an existing identity from the pool (protocol + version 14 and later) + +The [Shielded Transaction Fees](../fees/shielded-fees.md) chapter covers how each +of these is priced. Each variant has its own numeric discriminant, defined in `packages/rs-dpp/src/state_transition/state_transition_types.rs`: @@ -121,6 +142,8 @@ pub enum StateTransitionType { ShieldFromIdentity = 21, IdentityTopUpFromShieldedPool = 22, IdentityKeyLimitsUpdate = 23, + ContractUserModeration = 24, + ContractFeeClaim = 25, } ``` @@ -134,7 +157,8 @@ The `Batch` variant deserves special attention because it is the most complex. A `BatchTransition` can contain multiple sub-transitions, each operating on a different document or token. The sub-transitions include: -- **Document operations:** Create, Replace, Delete, Transfer, UpdatePrice, Purchase +- **Document operations:** Create, Replace, Delete, Transfer, UpdatePrice, Purchase, + IndexOnlyDelete - **Token operations:** Transfer, Mint, Burn, Freeze, Unfreeze, DestroyFrozenFunds, EmergencyAction, ConfigUpdate, Claim, DirectPurchase, SetPriceForDirectPurchase @@ -144,8 +168,8 @@ preventing partial replay attacks. ## Signatures and Authentication -State transitions carry cryptographic signatures that prove authorization. There are -two fundamentally different authentication models: +State transitions carry cryptographic signatures that prove authorization. Several +distinct authentication models exist: **Identity-signed transitions** -- The majority of transition types. The signer is an identity that already exists on the platform. The transition carries a @@ -161,6 +185,14 @@ chain. The signature proves ownership of the funds being locked. use platform address inputs with their own nonces and balances, rather than identity-based authentication. +**Shielded transitions** -- The shielded-pool transitions are authorized by the +zero-knowledge proof and the binding signature of their Orchard bundle. Two of them +also carry a transition-level signature. `ShieldFromIdentity` is identity-signed: it +spends an identity balance, so it carries `signature_public_key_id` and a `signature` +over the signable bytes, which binds the bundle to that identity and its nonce. +`ShieldFromAssetLock` carries an ECDSA signature made with the asset-lock key; it +commits to the optional surplus output. + The `sign` method on `StateTransition` handles this: ```rust @@ -271,8 +303,8 @@ version's logic. It is how the platform achieves hard-fork-free upgrades. ## The call_method Macro -Since `StateTransition` is an enum with 15 variants, dispatching a method call to -the inner type would require writing out a 15-arm match statement every time. The +Since `StateTransition` is an enum with 26 variants, dispatching a method call to +the inner type would require writing out a 26-arm match statement every time. The codebase solves this with a family of macros: ```rust @@ -282,7 +314,7 @@ macro_rules! call_method { StateTransition::DataContractCreate(st) => st.$method(), StateTransition::DataContractUpdate(st) => st.$method(), StateTransition::Batch(st) => st.$method(), - // ... all 15 variants + // ... all 26 variants } }; } @@ -305,9 +337,20 @@ an error for inapplicable variants). for the current protocol version. **Do not:** -- Assume all transitions have signatures. `IdentityCreateFromAddresses` and - `AddressFundsTransfer` return `None` from `signature()`. -- Assume all transitions have an `owner_id`. Address-based transitions do not. +- Assume all transitions have signatures. `signature()` returns `None` for + `IdentityCreateFromAddresses`, `IdentityTopUpFromAddresses`, `AddressFundsTransfer`, + `AddressCreditWithdrawal`, `Shield`, `ShieldedTransfer`, `Unshield`, + `ShieldedWithdrawal`, `IdentityCreateFromShieldedPool` and + `IdentityTopUpFromShieldedPool`. Of the transitions that spend from addresses or + the shielded pool only `AddressFundingFromAssetLock` and `ShieldFromAssetLock` are + signed. `IdentityCreditTransferToAddresses` and `ShieldFromIdentity` are the + exceptions in their groups: both are identity-signed like `IdentityCreditTransfer`, + because they spend an identity balance rather than address inputs or pool notes + (`inputs()` returns `None` for both). +- Assume all transitions have an `owner_id`. The transitions funded from address + inputs, asset locks into addresses, or the shielded pool return `None`; + `IdentityCreditTransferToAddresses` and `ShieldFromIdentity` keep their identity + owner. - Modify the `StateTransitionType` discriminant values -- they are part of the wire format and changing them would break all existing serialized data. - Add new variants without also updating every `call_method` macro and every diff --git a/book/src/state-transitions/validation-pipeline.md b/book/src/state-transitions/validation-pipeline.md index 859e4a31317..4cab38d1677 100644 --- a/book/src/state-transitions/validation-pipeline.md +++ b/book/src/state-transitions/validation-pipeline.md @@ -53,8 +53,10 @@ Let us walk through the full pipeline, stage by stage. Some state transition types are only available starting from a certain protocol version. For example, address-based transitions like `IdentityCreateFromAddresses` require -protocol version 11 or higher. The first check asks: is this transition type even -permitted on the current network? +protocol version 11 or higher, and the shielded-pool transitions require protocol +version 12 or higher (the constants live in +`packages/rs-platform-version/src/version/feature_initial_protocol_versions.rs`). +The first check asks: is this transition type even permitted on the current network? ```rust if state_transition.has_is_allowed_validation()? { diff --git a/book/src/versioning/platform-version.md b/book/src/versioning/platform-version.md index 32e7db207f5..f4caf6b7b52 100644 --- a/book/src/versioning/platform-version.md +++ b/book/src/versioning/platform-version.md @@ -125,7 +125,7 @@ pub const PLATFORM_V1: PlatformVersion = PlatformVersion { methods: DRIVE_ABCI_METHOD_VERSIONS_V1, validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V1, withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V1, - query: DRIVE_ABCI_QUERY_VERSIONS_V1, + query: DRIVE_ABCI_QUERY_VERSIONS_V0, checkpoints: DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1, }, dpp: DPPVersion { @@ -157,8 +157,8 @@ Now compare with `PLATFORM_V14`, the latest at the time of writing. By convention, each sub-constant slot that was bumped carries a trailing `// changed:` comment saying what changed. The `protocol_version` field is the snapshot's identity and is never annotated. One bumped slot in this snapshot, -`validation` (`DPP_VALIDATION_VERSIONS_V4` to `V5`), is missing its comment, -which is exactly the omission the convention exists to prevent: +`state_transitions` (`STATE_TRANSITION_VERSIONS_V3` to `V4`), is missing its +comment, which is exactly the omission the convention exists to prevent: ```rust // packages/rs-platform-version/src/version/v14.rs @@ -167,7 +167,7 @@ pub const PLATFORM_V14: PlatformVersion = PlatformVersion { protocol_version: PROTOCOL_VERSION_14, drive: DRIVE_VERSION_V9, // changed: drive document method versions v4 (v2 index walkers, detect_ranked_mode slot) drive_abci: DriveAbciVersion { - structs: DRIVE_ABCI_STRUCTURE_VERSIONS_V1, + structs: DRIVE_ABCI_STRUCTURE_VERSIONS_V2, // changed: saved platform state structure 1 keeps masternodes and validator sets as one aux entry each methods: DRIVE_ABCI_METHOD_VERSIONS_V10, // changed: records the per-block total credits history validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V10, // changed: contested-index cross-check + refersTo validation withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V3, // changed: prune bound for the total credits history @@ -176,22 +176,22 @@ pub const PLATFORM_V14: PlatformVersion = PlatformVersion { }, dpp: DPPVersion { costs: DPP_COSTS_VERSIONS_V1, - validation: DPP_VALIDATION_VERSIONS_V5, + validation: DPP_VALIDATION_VERSIONS_V5, // changed: validate_config_update 2 admits the contract moderation declaration of config V2 state_transition_serialization_versions: STATE_TRANSITION_SERIALIZATION_VERSIONS_V3, // changed: documentIndexOnlyDelete joins the wire state_transition_conversion_versions: STATE_TRANSITION_CONVERSION_VERSIONS_V2, - state_transition_method_versions: STATE_TRANSITION_METHOD_VERSIONS_V1, - state_transitions: STATE_TRANSITION_VERSIONS_V3, + state_transition_method_versions: STATE_TRANSITION_METHOD_VERSIONS_V2, // changed: public keys in creation may carry a budget or an expiry + state_transitions: STATE_TRANSITION_VERSIONS_V4, contract_versions: CONTRACT_VERSIONS_V6, // changed: v3 document meta-schema (ranked, refersTo, requiredSince, timeRange) document_versions: DOCUMENT_VERSIONS_V4, // changed: document serialization format 3 identity_versions: IDENTITY_VERSIONS_V1, voting_versions: VOTING_VERSION_V2, - token_versions: TOKEN_VERSIONS_V2, + token_versions: TOKEN_VERSIONS_V3, // changed: deterministic libm for token reward math; epoch claim cap no longer wraps asset_lock_versions: DPP_ASSET_LOCK_VERSIONS_V1, methods: DPP_METHOD_VERSIONS_V3, // changed: daily_withdrawal_limit v2 factory_versions: DPP_FACTORY_VERSIONS_V1, }, system_data_contracts: SYSTEM_DATA_CONTRACT_VERSIONS_V3, // changed: DashPay v2 profile payment address fields - fee_version: FEE_VERSION2, + fee_version: FEE_VERSION3, // changed: contested document contribution, masternode vote cost, moderation election fund, distribution surcharge system_limits: SYSTEM_LIMITS_V4, // changed: relative daily withdrawal limit + time-range overlap cap consensus: ConsensusVersions { tenderdash_consensus_version: 1, @@ -199,11 +199,13 @@ pub const PLATFORM_V14: PlatformVersion = PlatformVersion { }; ``` -Notice how only some subsystem versions change between V1 and V14. The ABCI -structure versions and checkpoint parameters are still at V1 because nothing -in them ever changed. The ABCI method versions, on the other hand, went from -V1 to V10 -- ten revisions of the block processing logic -- and the query -versions from V1 to V3. +Notice how only some subsystem versions change between V1 and V14. The +checkpoint parameters are still at V1 because nothing in them ever changed. The +ABCI structure versions stayed at V1 through V13 and moved to V2 at V14, when the +saved platform-state layout changed. The query versions stayed at V0 for the +first eleven protocol versions, moved to V1 at V12 and to V2 at V14. The ABCI +method versions, on the other hand, went from V1 to V10 -- ten revisions of the +block processing logic. This is the power of the snapshot model: **each subsystem version evolves at its own pace.** A new protocol version does not require bumping everything. You @@ -425,7 +427,7 @@ version 14 means. every node that was there at the time. - Never add a new field to `PlatformVersion` without also updating every `PLATFORM_V*` constant. The compiler will enforce this, but be aware that - the fix is updating fourteen files, not one. + the fix is updating every registered version file (fourteen today), not one. - Never use `PlatformVersion::latest()` in consensus-critical code paths. Always use the version from the current platform state, obtained via `platform_state.current_platform_version()`. The "latest" version is what diff --git a/book/src/versioning/versioned-dispatch.md b/book/src/versioning/versioned-dispatch.md index 7a59a994be1..4e6b9c89897 100644 --- a/book/src/versioning/versioned-dispatch.md +++ b/book/src/versioning/versioned-dispatch.md @@ -341,7 +341,12 @@ know that the binary is too old to handle the active protocol version. Let us walk through the exact steps to add a v1 implementation of a method that currently only has v0. We will use a fictional example: -`my_grove_operation`. +`my_grove_operation`; the method and its table slot do not exist. Of the version +constants in the excerpts below, `DRIVE_GROVE_METHOD_VERSIONS_V1`, +`DRIVE_VERSION_V9` and `PLATFORM_V14` are the ones in the tree today; +`DRIVE_GROVE_METHOD_VERSIONS_V2`, `DRIVE_VERSION_V10`, `PROTOCOL_VERSION_15` and +`PLATFORM_V15` are the hypothetical next generations the walkthrough would +create, not recorded history. ### Step 1: Write the new implementation @@ -530,7 +535,7 @@ meaningfully. This is a lot of steps, but each one is mechanical and the compiler guides you through most of it. If you add a field to a version struct and forget to set it -in one of the fourteen platform version constants, the build fails. +in one of the registered platform version constants (fourteen today), the build fails. ## Passing Version References diff --git a/docs/SDK_ARCHITECTURE.md b/docs/SDK_ARCHITECTURE.md index 6a0019d85e7..85ea3b1d990 100644 --- a/docs/SDK_ARCHITECTURE.md +++ b/docs/SDK_ARCHITECTURE.md @@ -159,20 +159,31 @@ graph TD - **Error Handling**: Swift Error protocol implementation - **Async/Await**: Native Swift concurrency support -#### 3.2 Kotlin SDK (Android/JVM) - Planned +#### 3.2 Kotlin SDK (Android) ``` ┌─────────────────────────────────────────┐ -│ kotlin-sdk (Planned) │ +│ kotlin-sdk │ ├─────────────────────────────────────────┤ -│ • JNI Bindings to rs-sdk-ffi │ -│ • Kotlin-first API │ -│ • Android-Specific Features │ -│ • Coroutine Support │ -│ • Type-Safe Builders │ +│ • Android library │ +│ (org.dashfoundation.dashsdk) │ +│ • JNI shim: rs-unified-sdk-jni over │ +│ rs-sdk-ffi, platform-wallet-ffi and │ +│ key-wallet-ffi │ +│ • Kotlin-first API, coroutine support │ +│ • KotlinExampleApp (Jetpack Compose) │ └─────────────────────────────────────────┘ ``` +**Components:** +- **Native layer**: `packages/rs-unified-sdk-jni` builds `libdash_sdk_jni.so` + with cargo-ndk; there is no C glue or generated header on Android +- **SDK module**: `packages/kotlin-sdk/sdk`, published as the + `dash-sdk-android` AAR attached to platform GitHub releases (see + `packages/kotlin-sdk/PUBLISHING.md`) +- **Example app**: `packages/kotlin-sdk/KotlinExampleApp`, a Compose port of + SwiftExampleApp + #### 3.3 Python SDK - Planned ``` @@ -326,20 +337,26 @@ Each SDK layer provides appropriate error handling: | Feature | Rust SDK | Swift SDK | Kotlin SDK | Python SDK | Go SDK | JS SDK | |---------|----------|-----------|------------|------------|--------|---------| -| Identity Management | ✅ | ✅ | ⏳ | ⏳ | ⏳ | ✅ | -| Data Contracts | ✅ | ✅ | ⏳ | ⏳ | ⏳ | ✅ | -| Documents | ✅ | ✅ | ⏳ | ⏳ | ⏳ | ✅ | -| Tokens | ✅ | ✅ | ⏳ | ⏳ | ⏳ | ⏳ | -| Proofs | ✅ | ✅ | ⏳ | ⏳ | ⏳ | 🚧 | -| State Transitions | ✅ | ✅ | ⏳ | ⏳ | ⏳ | ⏳ | -| Dashpay | ⏳ | ⏳ | ⏳ | ⏳ | ⏳ | ⏳ | -| Name Service (DPNS) | ⏳ | ⏳ | ⏳ | ⏳ | ⏳ | ⏳ | -| Core Types Support | ✅ | ✅ | ⏳ | ⏳ | ⏳ | ⏳ | -| Core Blockchain Sync | 🚧 | 🚧 | ⏳ | ⏳ | ⏳ | ⏳ | +| Identity Management | ✅ | ✅ | ✅ | ⏳ | ⏳ | ✅ | +| Data Contracts | ✅ | ✅ | ✅ | ⏳ | ⏳ | ✅ | +| Documents | ✅ | ✅ | ✅ | ⏳ | ⏳ | ✅ | +| Tokens | ✅ | ✅ | ✅ | ⏳ | ⏳ | ⏳ | +| Proofs | ✅ | ✅ | ✅ | ⏳ | ⏳ | 🚧 | +| State Transitions | ✅ | ✅ | ✅ | ⏳ | ⏳ | ⏳ | +| Dashpay | ⏳ | ⏳ | 🚧 | ⏳ | ⏳ | ⏳ | +| Name Service (DPNS) | ⏳ | ⏳ | 🚧 | ⏳ | ⏳ | ⏳ | +| Core Types Support | ✅ | ✅ | ✅ | ⏳ | ⏳ | ⏳ | +| Core Blockchain Sync | 🚧 | 🚧 | ✅ | ⏳ | ⏳ | ⏳ | | Core Deterministic Masternode List Sync | 🚧 | 🚧 | ⏳ | ⏳ | ⏳ | ⏳ | Legend: ✅ Fully Supported | 🚧 In Development | ⏳ Planned | ❌ Not Supported +The Kotlin column follows the feature list in `packages/kotlin-sdk/README.md`, +qualified by the generated parity audit in +`packages/kotlin-sdk/PARITY_SUMMARY.md`. Dashpay and DPNS are marked in +development there because that audit records `dashpay.deferred_contact_crypto` +and `dpns.contested_names_by_identity` as partial on Kotlin. + ## Development Considerations ### Performance diff --git a/packages/swift-sdk/README.md b/packages/swift-sdk/README.md index 1e7ceffd153..5f84e18d313 100644 --- a/packages/swift-sdk/README.md +++ b/packages/swift-sdk/README.md @@ -16,23 +16,30 @@ See also: iOS Simulator MCP usage and Codex config in [IOS_SIMULATOR_MCP.md](./I ### Requirements -- iOS 13.0+ -- Xcode 12.0+ -- Swift 5.3+ +- iOS 18.0+ or macOS 15.0+ (see `Package.swift`) +- Xcode with Swift 6 tools (`swift-tools-version: 6.0`) +- The Rust workspace toolchain, for building the native framework ### Building -1. Build the Rust library: +1. Build the native framework. The script builds the `rs-unified-sdk-ffi` crate + for the requested Apple targets and assembles `DashSDKFFI.xcframework` in + this directory: ```bash cd packages/swift-sdk -cargo build --release +./build_ios.sh --target sim # release profile is the default +./build_ios.sh --target all # device, simulator and macOS slices ``` -2. The build will generate a static library that can be linked with your iOS project. +2. The Swift package's `DashSDKFFI` binary target points at that xcframework. + The platform release workflow (`.github/workflows/release-swift-sdk.yml`) + builds and attaches versioned xcframework zips to platform GitHub releases + when it runs; building locally is the supported path today. ### Integration -1. Add the generated library to your Xcode project +1. Add this package (`packages/swift-sdk`) as a Swift Package Manager + dependency of your app or open it in Xcode 2. Import the Swift module: ```swift import SwiftDashSDK @@ -325,20 +332,25 @@ guard let identity = swift_dash_identity_fetch(sdk, identityId) else { ## Testing -The Swift SDK uses compilation verification and Swift integration testing: +`Package.swift` defines two test targets: `SwiftDashSDKTests` (offline, +hermetic) and `SwiftDashSDKIntegrationTests` (against a local dashmate devnet, +gated by `RUN_INTEGRATION_TESTS=1`). The package tests run on macOS, so the +xcframework needs the macOS slice: ```bash -# Verify compilation -cargo build -p swift-sdk +cd packages/swift-sdk -# Run unit tests -cargo test -p swift-sdk --lib +# Build the simulator and macOS slices, run the package tests and the +# SwiftExampleApp test bundle on a simulator (what CI runs) +./run_tests.sh -# Check symbol exports -nm -g target/debug/libswift_sdk.a | grep swift_dash_ -``` +# Or by hand +./build_ios.sh --target tests --profile dev +swift test -For comprehensive testing, integrate the compiled library into an iOS project with XCTest suites. +# Integration tests: restarts a local dashmate devnet, then runs the gated target +./run_integration_tests.sh +``` ## Example App @@ -422,20 +434,24 @@ enum DashError: Error { ## Building the Library -To build the library: +To build the native framework: ```bash -cargo build --release -p swift-sdk +cd packages/swift-sdk +./build_ios.sh --target sim ``` -This will generate both static and dynamic libraries that can be linked with iOS applications. +This builds `rs-unified-sdk-ffi` for the requested targets (`ios`, `sim`, `mac` +or `all`) and produces `DashSDKFFI.xcframework`, which the Swift package +consumes as a binary target. Use `--profile dev` only for local iteration; +debug assertions abort the host app. ## Integration with iOS Projects -1. Build the library using the command above -2. Include the generated header file in your Xcode project -3. Link against the generated library -4. Use the C functions directly from Swift +1. Build the framework using the command above +2. Add `packages/swift-sdk` as a Swift Package Manager dependency +3. `import SwiftDashSDK`; the package links the framework and exposes the C + symbols through its Swift wrappers, so no header copying is needed ## Thread Safety