Repository navigation
SDK: cost functions for document replace and delete, contract update, key operations and the admission requirement #5265
Description
documentCreateCost (#5159) lets an app price a document create from the contract alone, with Drive's own rules. We would like the same for the other writes apps make: replace, delete, contract update and identity key changes. We would also like a function for the admission requirement, meaning what the balance and the signing key's budget must cover before Drive accepts a write. Today an app can only learn that from refusals.
We hit this building Dash Forge, a git forge that runs on Platform.
Expected Behavior
Offline functions in the same style as documentCreateCost, computed by Drive's code in rs-drive and exposed through wasm-sdk / @dashevo/evo-sdk (and rs-sdk). Each would report both storage scenarios and flag which parts are exact. For example:
documentReplaceCost(contract, documentTypeName, options, platformVersion): the storage added or freed by changing given fields or sizes, the resulting refund, and the processing.documentDeleteCost(...): the processing of a delete and the net refund, including types withindexOnlyor ranked indexes.contractCreateCost/contractUpdateCost(oldContract, newContract, ...): the registration cost plus the storage and processing of the write.- Identity key operations: adding a key, disabling a key, and
IdentityKeyLimitsUpdate. admissionRequirement(...): for a given write, whatvalidate_fees_of_eventrequires of the identity's balance and of the signing key's remaining budget.
Current Behavior
- At
v5.0.0-beta.1the only cost function in the SDKs isdocumentCreateCost(wasm-sdk/src/document_create_cost.rs L187-L204, backed by rs-drive/src/drive/document/cost/mod.rs L276-L282). We searched wasm-sdk, wasm-dpp2 and rs-sdk at the tag for cost, fee and estimate functions and found nothing else of this kind. The default branch (v5.0-dev) has nothing more either. documentCreateCostcovers creates only:DataContract::registration_costexists in rs-dpp (registration_cost/mod.rs L28-L47) but is not exposed in wasm-sdk or wasm-dpp2. A contract update is charged that full cost again; the code says "The update cost pays for the whole contract again" (execution_event/mod.rs L375-L391). An app cannot easily guess that.calculate_min_required_fee(feat(platform)!: state transition minimum required balance for fees #2899) is a pre-check floor. For a document batch it is a flat minimum per sub-transition (L22-L33), not a cost or the admission requirement.- The admission requirement is computed from Drive's cost estimate (
apply_drive_operationswithapply = false), and that estimate is larger than the charge. The key budget must cover the removed balance, the estimated storage fee, fixed costs and the user fee increase (validate_fees_of_event/v1/mod.rs L26-L48, L229-L241). The balance must cover the whole estimated fee plus fixed costs (v0/mod.rs L118-L143). With budgeted authentication keys (feat(platform)!: allow authentication keys with a budget and an expiry #4798), an app has to know this number before signing, or the user gets a refusal they could not foresee.
What we observed:
- On a 4.2 beta devnet (protocol 14), Drive refused a 10-byte comment until the key had 79,623,000 credits of budget left and the identity had 193,644,600 credits of balance. The same write was charged about 52.2 M. We keep one admission table per document type, read from refusal messages (cost.ts L298-L316).
- Our delete, replace and key-operation previews are also hand-measured tables (cost.ts L231-L275, L528-L535). They miss in both directions. Deleting one document refunded 81.8 M credits where our table said 20 M. A replace is quoted at a 17 M upper bound, but we have seen it charged between 3.9 M and 17.0 M depending on how much text changed.
- These tables drift between Platform betas, and we re-measure them on each devnet. The same tables back our CLI (crates/dg/src/cost.rs).
Possible Solution
A suggestion:
- Extend
drive::document::costwith replace and delete. These are the same element walk as the create, plus the old document's elements and the refund rules that already pricerefund. - Expose
registration_costin wasm-sdk, and add a contract update cost that includes it. - Add
admissionRequirement, returning{ requiredBalance, requiredKeyBudget }per scenario. It would mirrorrequired_from_key_budgetand the balance check invalidate_fees_of_event. As far as we can tell, the estimate it uses (apply = false) is built from estimated layer information rather than from stored values, so it may be computable offline likedocumentCreateCost. If it is not, the node-side dry run requested in Add a read-only dry run for signed state transitions: verdict and fee breakdown without mempool admission #5264 would cover it. - Keep the
exactflags so apps know which numbers are quotes.
Alternatives Considered
- Measuring on a devnet (what we do now): costly, and it has to be redone on every beta.
- A node-side dry run of a signed transition. We filed that as Add a read-only dry run for signed state transitions: verdict and fee breakdown without mempool admission #5264. It answers more precisely because it sees state, but needs a signed transition and a network round trip. Offline functions remain useful for previews before anything is signed, and for contract design.
- Parsing refusals (
IdentityPublicKeyBudgetExceededError,IdentityInsufficientBalanceError) to learn the admission requirement. It works, but only after a failed attempt.
Additional Context
- Related: Add a read-only dry run for signed state transitions: verdict and fee breakdown without mempool admission #5264 (node-side dry run), feat(drive): compute what creating a document costs for the SDKs #5159 (the create function), feat(drive): compute a document type's GroveDB layout for the SDKs #5153 (
documentTypeLayout), Improve fee estimation API for state transition #3041 (open; unsigned fee estimation for address transitions), Feature Request: Estimate fee method for platform transactions #2807 (closed; fee estimation request). - Environment: Platform 5.0.0-beta.1 (protocol 14) on a devnet (sakura). Clients:
@dashevo/evo-sdkand@dashevo/wasm-sdk5.0.0-beta.1, anddash-sdk(rs-sdk) at tagv5.0.0-beta.1. The admission and table figures above were measured on earlier 4.2 beta devnets, also on protocol 14.
Activity
fix(dpns): show and enforce the balance a username registration reall…