Repository navigation
perf(platform)!: delete a consumed document from what its lookup read (PV15) #5360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
45 commits
Select commit
Hold shift + click to select a range
9de6dac
feat(platform)!: dpns contract v3 checks name registration with schem…
QuantumExplorer 08a5679
fix(platform): a pre-upgrade preorder meets only a one-block minimum age
QuantumExplorer 7fa7b0a
Merge remote-tracking branch 'origin/v5.0-dev' into claude/wizardly-d…
QuantumExplorer 521761b
test(sdk): pin the dpns preorder hash of a mixed-case parent domain name
QuantumExplorer bdc9d9e
Merge remote-tracking branch 'origin/v5.0-dev' into claude/wizardly-d…
QuantumExplorer d3518c7
chore(contract): shorten the dpns v3 schema descriptions
QuantumExplorer d93f498
feat(platform)!: dpns v3 preorders are unique per owner and hash the …
QuantumExplorer e6c1911
Merge remote-tracking branch 'origin/v5.0-dev' into claude/wizardly-d…
QuantumExplorer b66668f
fix(sdk): hash DPNS preorders against the contract the network stores
QuantumExplorer fbd02c9
fix(sdk): take the DPNS contract only from a response proved at the p…
QuantumExplorer b720af0
fix(drive): seed the block cache with the contract a rebuild stores
QuantumExplorer 51403d3
fix(sdk): skip a DPNS contract response when the SDK version moved me…
QuantumExplorer 4905cf3
Merge remote-tracking branch 'origin/v5.0-dev' into claude/wizardly-d…
QuantumExplorer 1f1a8b0
feat(contract): write the DPNS v3 byte arrays with the type shorthands
QuantumExplorer 45309b9
fix(platform): DPNS v3 review fixes
QuantumExplorer a9b1ee5
refactor(dpp): read a reference's findBy hash key through one accessor
QuantumExplorer cec6d0a
perf(drive): delete a consumed document from what its lookup read
QuantumExplorer 0e3ae00
test(sdk): give the records.identity refusal spec two distinct identi…
QuantumExplorer c2d30d9
docs(book): the findBy function exception for $ownerId; DPNS preorder…
QuantumExplorer b43fcec
test(drive): run the protocol 13 halves of three tests on DPNS v2
QuantumExplorer c158a7d
fix(sdk): parse a proof the SDK's version can not read under the vers…
QuantumExplorer 3961808
Merge branch 'v5.0-dev' into claude/wizardly-driscoll-44c981
QuantumExplorer 521bfa2
test(sdk): cover the protocol version fallback through the quorum key…
QuantumExplorer 193c42f
test(sdk): fetch a missing quorum key and read the proof again throug…
QuantumExplorer 35696a2
Merge remote-tracking branch 'origin/v5.0-dev' into claude/wizardly-d…
QuantumExplorer 4be5d8c
Merge remote-tracking branch 'origin/v5.0-dev' into claude/wizardly-d…
QuantumExplorer 759d679
feat(platform)!: dpns v3 preorders hash the owner and the name, witho…
QuantumExplorer aaa0bb7
fix(sdk): dpns registration decodes under the contract it built again…
QuantumExplorer b1ae90f
fix(wasm-sdk): the trusted context forwards a registered contract to …
QuantumExplorer ec975f7
Merge branch 'v5.0-dev' into claude/wizardly-driscoll-44c981
QuantumExplorer 8a35b1a
Merge branch 'v5.0-dev' into claude/wizardly-driscoll-44c981
QuantumExplorer a7e6bf7
Merge v5.1-dev (with v5.0-dev) into the DPNS v3 branch
QuantumExplorer 1cfe150
feat(platform)!: move DPNS v3 to protocol version 15 and choose the f…
QuantumExplorer 4146766
fix(drive-abci): keep DPNS v3 for its rebuild on an upgrade that skip…
QuantumExplorer 13b2ffb
Merge the DPNS v3 branch, retargeted to protocol version 15
QuantumExplorer f338eb1
feat(platform)!: delete a consumed document from its lookup's read fr…
QuantumExplorer f86ba2f
Merge v5.1-dev into the consume single-read branch
QuantumExplorer a87e37e
fix(drive): move consumed documents instead of copying them, and test…
QuantumExplorer d21b385
Merge v5.1-dev (yes/no vote polls) into the consume single-read branch
QuantumExplorer dccfbaf
Merge v5.1-dev into the consume single-read branch
QuantumExplorer 6628b77
refactor(platform)!: give the consume single read its own reference v…
QuantumExplorer 49488c5
Merge v5.1-dev into the consume single-read branch
QuantumExplorer 656c547
refactor(platform): read storage flags only for a consuming lookup
QuantumExplorer ac18c33
test(platform): pin consuming lookup misses and the consumed read exa…
QuantumExplorer e319d43
test(platform): pin that a consuming lookup reads the create's own co…
QuantumExplorer File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
177 changes: 177 additions & 0 deletions
177
...e_transitions/batch/action_validation/document/document_reference_validation/v1/lookup.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,177 @@ | ||
| //! The `refersTo` lookup of document reference validation 1 (protocol version 15). | ||
|
|
||
| use crate::error::Error; | ||
| use crate::execution::types::execution_operation::ValidationOperation; | ||
| use crate::execution::types::state_transition_execution_context::{ | ||
| StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0, | ||
| }; | ||
| use crate::execution::validation::state_transition::batch::state::v0::fetch_documents::{ | ||
| fetch_document_through_lookup, hash_lookup_key, holds_key_part, BilledLookupKey, | ||
| }; | ||
| use dpp::block::epoch::Epoch; | ||
| use dpp::data_contract::document_type::methods::DocumentTypeV0Methods; | ||
| use dpp::data_contract::document_type::{DocumentReferenceLookup, DocumentTypeRef}; | ||
| use dpp::data_contract::DataContract; | ||
| use dpp::document::Document; | ||
| use dpp::fee::fee_result::FeeResult; | ||
| use dpp::platform_value::{Identifier, Value}; | ||
| use dpp::version::PlatformVersion; | ||
| use drive::drive::document::query::QueryDocumentsWithFlagsOutcomeV0Methods; | ||
| use drive::drive::Drive; | ||
| use drive::grovedb::TransactionArg; | ||
| use drive::query::{DriveDocumentQuery, InternalClauses, WhereClause, WhereOperator}; | ||
| use drive::util::storage_flags::StorageFlags; | ||
| use std::collections::BTreeMap; | ||
|
|
||
| /// What `fetch_document_through_lookup` (batch state 0) finds. For a lookup declaring `consume`, | ||
| /// it also returns the storage flags of the document's stored element. That is the same path | ||
| /// query, read through `query_documents_with_flags` instead of `query_documents` and billed the | ||
| /// same way, and the create that consumes the document deletes it from this read without | ||
| /// reading it again. | ||
| /// | ||
| /// The two GroveDB calls behind those queries part ways only past a layer a query item misses: | ||
| /// `query` goes on with the next item, `query_item_value` stops. A lookup fixes every property | ||
| /// of a unique index, one key a layer, so a consuming lookup that finds nothing stops at the | ||
| /// same layer either way and pays what generation 0's pays | ||
| /// (`should_bill_a_consuming_lookup_that_finds_nothing_the_same_at_protocol_versions_14_and_15`). | ||
| /// A lookup that does not consume needs no flags, so it calls generation 0's read itself. | ||
| #[allow(clippy::too_many_arguments)] | ||
| pub(super) fn fetch_document_with_flags_through_lookup( | ||
| drive: &Drive, | ||
| contract: &DataContract, | ||
| document_type: DocumentTypeRef, | ||
| declaring_document_type: DocumentTypeRef, | ||
| lookup: &DocumentReferenceLookup, | ||
| reference_value: &Value, | ||
| document_data: &BTreeMap<String, Value>, | ||
| owner_id: Identifier, | ||
| billed_key: Option<BilledLookupKey>, | ||
| epoch: &Epoch, | ||
| execution_context: &mut StateTransitionExecutionContext, | ||
| transaction: TransactionArg, | ||
| platform_version: &PlatformVersion, | ||
| ) -> Result<Option<(Document, Option<StorageFlags>)>, Error> { | ||
| if !lookup.consume { | ||
| return Ok(fetch_document_through_lookup( | ||
| drive, | ||
| contract, | ||
| document_type, | ||
| declaring_document_type, | ||
| lookup, | ||
| reference_value, | ||
| document_data, | ||
| owner_id, | ||
| billed_key, | ||
| epoch, | ||
| execution_context, | ||
| transaction, | ||
| platform_version, | ||
| )? | ||
| .map(|document| (document, None))); | ||
| } | ||
| // Registration resolved the index its `findBy` names, and a type's indexes | ||
| // never change, so this only guards a declaration no registration admits: | ||
| // one naming no unique index finds no document | ||
| if lookup.resolve_index(document_type).is_err() { | ||
| return Ok(None); | ||
| } | ||
| // A function's `"."` param reads an identifier (an element, the writer or | ||
| // the creator); a property carrying the reference is named by its path. | ||
| // The writer is passed in place, inert before protocol version 14: only | ||
| // meta-schema v3 admits a computed key, and the `"$ownerId"` param that | ||
| // reads the writer | ||
| let reference_id = match reference_value { | ||
| Value::Identifier(id) => Some(Identifier::from(*id)), | ||
| _ => None, | ||
| }; | ||
| let billed_key = billed_key.or_else(|| { | ||
| lookup.hash_key().and_then(|(_, key)| { | ||
| hash_lookup_key( | ||
| key, | ||
| declaring_document_type, | ||
| reference_id, | ||
| owner_id, | ||
| document_data, | ||
| execution_context, | ||
| ) | ||
| }) | ||
| }); | ||
| let computed_key = billed_key.map(|key| Value::Bytes32(key.digest())); | ||
| let Some(key_values) = lookup.key_values( | ||
| reference_value, | ||
| document_data, | ||
| owner_id, | ||
| computed_key.as_ref(), | ||
| ) else { | ||
| return Ok(None); | ||
| }; | ||
| // A key part no index entry can hold finds no document. Serializing it is | ||
| // what the query does first, and its failure is the value's, not the state's | ||
| if key_values.iter().any(|(index_property, value)| { | ||
| document_type | ||
| .serialize_value_for_key(index_property, value, platform_version) | ||
| .is_err() | ||
| }) { | ||
| return Ok(None); | ||
| } | ||
| let equal_clauses = key_values | ||
| .iter() | ||
| .map(|(field, value)| { | ||
| ( | ||
| field.clone(), | ||
| WhereClause { | ||
| field: field.clone(), | ||
| operator: WhereOperator::Equal, | ||
| value: value.clone(), | ||
| }, | ||
| ) | ||
| }) | ||
| .collect(); | ||
|
|
||
| let drive_query = DriveDocumentQuery { | ||
| contract, | ||
| document_type, | ||
| internal_clauses: InternalClauses { | ||
| primary_key_in_clause: None, | ||
| primary_key_equal_clause: None, | ||
| in_clauses: Vec::new(), | ||
| range_clause: None, | ||
| equal_clauses, | ||
| }, | ||
| offset: None, | ||
| // The index is unique and every one of its properties is fixed, so at | ||
| // most one document matches | ||
| limit: Some(1), | ||
| order_by: Default::default(), | ||
| start_at: None, | ||
| start_at_included: false, | ||
| block_time_ms: None, | ||
| resolved_time_ranges: vec![], | ||
| sub_queries: vec![], | ||
| }; | ||
|
|
||
| let documents_outcome = drive.query_documents_with_flags( | ||
| drive_query, | ||
| Some(epoch), | ||
| false, | ||
| transaction, | ||
| Some(platform_version.protocol_version), | ||
| )?; | ||
|
QuantumExplorer marked this conversation as resolved.
Resolved
|
||
| execution_context.add_operation(ValidationOperation::PrecalculatedOperation(FeeResult { | ||
| storage_fee: 0, | ||
| processing_fee: documents_outcome.cost(), | ||
| fee_refunds: Default::default(), | ||
| removed_bytes_from_system: 0, | ||
| lifetime_storage_fees: Default::default(), | ||
| })); | ||
|
|
||
| Ok(documents_outcome | ||
| .documents_owned() | ||
| .into_iter() | ||
| .next() | ||
| .filter(|(document, _)| { | ||
| key_values.iter().all(|(index_property, value)| { | ||
| holds_key_part(document_type, document, index_property, value) | ||
| }) | ||
| })) | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.