Skip to content
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

fix: contested resources query fixes #1896

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,7 @@ impl DocumentPropertyType {
Ok(Value::Text(String::from_utf8(value.to_vec()).map_err(
|_| {
ProtocolError::DecodingError(
"could not decode ut8 bytes into string".to_string(),
"could not decode utf8 bytes into string".to_string(),
)
},
)?))
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -142,18 +142,39 @@ impl<C> Platform<C> {
format!("limit greater than max limit {}", config.max_query_limit),
)))?;

let result = start_at_value_info
.map(|start_at_value_info| {
let start = bincode::decode_from_slice(
start_at_value_info.start_value.as_slice(),
bincode_config,
)
.map_err(|_| {
QueryError::InvalidArgument(format!(
"could not convert {:?} to a value for start at",
start_at_value_info.start_value
))
})?
.0;

Ok::<(dpp::platform_value::Value, bool), QueryError>((
start,
start_at_value_info.start_value_included,
))
})
.transpose();

let start_at_value_info = match result {
Ok(start_at_value_info) => start_at_value_info,
Err(e) => return Ok(QueryValidationResult::new_with_error(e)),
};

let query = VotePollsByDocumentTypeQuery {
contract_id,
document_type_name,
index_name,
start_index_values,
end_index_values,
start_at_value: start_at_value_info.map(|start_at_value_info| {
(
start_at_value_info.start_value,
start_at_value_info.start_value_included,
)
}),
start_at_value: start_at_value_info,
limit: Some(limit),
order_ascending,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ use dpp::fee::fee_result::FeeResult;
use dpp::data_contract::document_type::methods::DocumentTypeV0Methods;
use dpp::serialization::PlatformSerializableWithPlatformVersion;

use crate::drive::votes::paths::{
CONTESTED_DOCUMENT_INDEXES_TREE_KEY, CONTESTED_DOCUMENT_STORAGE_TREE_KEY,
};
use crate::error::contract::DataContractError;
use dpp::version::PlatformVersion;
use grovedb::batch::KeyInfoPath;
Expand Down Expand Up @@ -236,34 +239,24 @@ impl Drive {
];

// primary key tree
let key_info = Key(vec![0]);
let key_info_storage = Key(vec![CONTESTED_DOCUMENT_STORAGE_TREE_KEY]);
self.batch_insert_empty_tree(
type_path,
key_info,
key_info_storage,
storage_flags.as_ref(),
&mut batch_operations,
&platform_version.drive,
)?;

let mut index_cache: HashSet<&[u8]> = HashSet::new();
// for each type we should insert the indices that are top level
for index in document_type
.as_ref()
.top_level_indices_of_contested_unique_indexes()
{
// toDo: change this to be a reference by index
let index_bytes = index.name.as_bytes();
if !index_cache.contains(index_bytes) {
self.batch_insert_empty_tree(
type_path,
KeyRef(index_bytes),
storage_flags.as_ref(),
&mut batch_operations,
&platform_version.drive,
)?;
index_cache.insert(index_bytes);
}
}
// index key tree
let key_info_indexes = Key(vec![CONTESTED_DOCUMENT_INDEXES_TREE_KEY]);
self.batch_insert_empty_tree(
type_path,
key_info_indexes,
storage_flags.as_ref(),
&mut batch_operations,
&platform_version.drive,
)?;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters;
use crate::drive::defaults::DEFAULT_HASH_SIZE_U8;
use crate::drive::votes::paths::{
vote_contested_resource_active_polls_contract_document_tree_path_vec,
RESOURCE_ABSTAIN_VOTE_TREE_KEY, RESOURCE_LOCK_VOTE_TREE_KEY,
vote_contested_resource_contract_documents_indexes_path_vec, RESOURCE_ABSTAIN_VOTE_TREE_KEY,
RESOURCE_LOCK_VOTE_TREE_KEY,
};
use crate::error::drive::DriveError;
use dpp::data_contract::document_type::IndexProperty;
Expand Down Expand Up @@ -65,7 +66,7 @@ impl Drive {
// * DataContract ID recovered from document
// * 0 to signify Documents and notDataContract
let contract_document_type_path =
vote_contested_resource_active_polls_contract_document_tree_path_vec(
vote_contested_resource_contract_documents_indexes_path_vec(
document_and_contract_info.contract.id_ref().as_bytes(),
document_and_contract_info.document_type.name(),
);
Expand Down
6 changes: 5 additions & 1 deletion packages/rs-drive/src/drive/document/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#[cfg(feature = "server")]
use crate::drive::flags::StorageFlags;
use crate::drive::votes::paths::CONTESTED_DOCUMENT_STORAGE_TREE_KEY;
use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters;
#[cfg(any(feature = "server", feature = "verify"))]
use dpp::data_contract::document_type::DocumentTypeRef;
Expand Down Expand Up @@ -82,7 +83,10 @@ fn make_document_contested_reference(
// 0 represents document storage
// Then we add document id
// Then we add 0 if the document type keys history
let reference_path = vec![vec![0], document.id().to_vec()];
let reference_path = vec![
vec![CONTESTED_DOCUMENT_STORAGE_TREE_KEY],
document.id().to_vec(),
];
let max_reference_hops = 1;
// 2 because the contract could allow for history
// 5 because
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ use grovedb::EstimatedLayerSizes::AllSubtrees;
use crate::drive::votes::paths::{
vote_contested_resource_active_polls_contract_document_tree_path,
vote_contested_resource_active_polls_contract_tree_path,
vote_contested_resource_active_polls_tree_path, vote_contested_resource_tree_path,
vote_contested_resource_active_polls_tree_path,
vote_contested_resource_contract_documents_indexes_path, vote_contested_resource_tree_path,
vote_root_path,
};
use dpp::data_contract::accessors::v0::DataContractV0Getters;
Expand Down Expand Up @@ -130,7 +131,25 @@ impl Drive {
),
EstimatedLayerInformation {
is_sum_tree: false,
estimated_layer_count: ApproximateElements(document_type_count),
estimated_layer_count: ApproximateElements(2),
estimated_layer_sizes: AllSubtrees(
ESTIMATED_AVERAGE_INDEX_NAME_SIZE,
NoSumTrees,
None,
),
},
);

estimated_costs_only_with_layer_info.insert(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you insert estimated_costs_only_with_layer_info twice for purpose?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, they are not the same

KeyInfoPath::from_known_path(
vote_contested_resource_contract_documents_indexes_path(
contract.id_ref().as_bytes(),
document_type.name().as_str(),
),
),
EstimatedLayerInformation {
is_sum_tree: false,
estimated_layer_count: ApproximateElements(1024), //Just a guess
estimated_layer_sizes: AllSubtrees(
ESTIMATED_AVERAGE_INDEX_NAME_SIZE,
NoSumTrees,
Expand Down
46 changes: 41 additions & 5 deletions packages/rs-drive/src/drive/votes/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ pub const RESOURCE_STORED_INFO_KEY: char = 'b'; // 62 hex 98 decimal
/// The finished info
pub const RESOURCE_STORED_INFO_KEY_U8: u8 = b'b'; // 62 hex 98 decimal

/// The tree key for storage of contested documents
pub const CONTESTED_DOCUMENT_STORAGE_TREE_KEY: u8 = 0;

/// The tree key for the indexes of contested documents
pub const CONTESTED_DOCUMENT_INDEXES_TREE_KEY: u8 = 1;

/// The tree key for storage
pub const VOTING_STORAGE_TREE_KEY: u8 = 1;

Expand Down Expand Up @@ -141,7 +147,7 @@ impl VotePollPaths for ContestedDocumentResourceVotePollWithContractInfo {
}

fn contenders_path(&self, platform_version: &PlatformVersion) -> Result<Vec<Vec<u8>>, Error> {
let mut root = vote_contested_resource_active_polls_contract_document_tree_path_vec(
let mut root = vote_contested_resource_contract_documents_indexes_path_vec(
self.contract.as_ref().id_ref().as_slice(),
self.document_type_name.as_str(),
);
Expand Down Expand Up @@ -227,7 +233,7 @@ impl<'a> VotePollPaths for ContestedDocumentResourceVotePollWithContractInfoAllo
}

fn contenders_path(&self, platform_version: &PlatformVersion) -> Result<Vec<Vec<u8>>, Error> {
let mut root = vote_contested_resource_active_polls_contract_document_tree_path_vec(
let mut root = vote_contested_resource_contract_documents_indexes_path_vec(
self.contract.as_ref().id_ref().as_slice(),
self.document_type_name.as_str(),
);
Expand Down Expand Up @@ -266,7 +272,7 @@ impl<'a> VotePollPaths for ContestedDocumentResourceVotePollWithContractInfoAllo
let key = vote_choice.to_key();
let mut contender_voting_path = self.contenders_path(platform_version)?;
contender_voting_path.push(key);
contender_voting_path.push(vec![1]);
contender_voting_path.push(vec![VOTING_STORAGE_TREE_KEY]);
Ok(contender_voting_path)
}
}
Expand Down Expand Up @@ -408,7 +414,7 @@ pub fn vote_contested_resource_contract_documents_storage_path<'a>(
&[ACTIVE_POLLS_TREE_KEY as u8], // 1
contract_id, // 32
document_type_name.as_bytes(),
&[0], // 1
&[CONTESTED_DOCUMENT_STORAGE_TREE_KEY], // 1
]
}

Expand All @@ -423,7 +429,37 @@ pub fn vote_contested_resource_contract_documents_storage_path_vec(
vec![ACTIVE_POLLS_TREE_KEY as u8],
contract_id.to_vec(),
document_type_name.as_bytes().to_vec(),
vec![0],
vec![CONTESTED_DOCUMENT_STORAGE_TREE_KEY],
]
}

/// Returns the path to the primary keys of a contract document type.
pub fn vote_contested_resource_contract_documents_indexes_path<'a>(
contract_id: &'a [u8],
document_type_name: &'a str,
) -> [&'a [u8]; 6] {
[
Into::<&[u8; 1]>::into(RootTree::Votes), // 1
&[CONTESTED_RESOURCE_TREE_KEY as u8], // 1
&[ACTIVE_POLLS_TREE_KEY as u8], // 1
contract_id, // 32
document_type_name.as_bytes(),
&[CONTESTED_DOCUMENT_INDEXES_TREE_KEY], // 1
]
}

/// Returns the path to the primary keys of a contract document type as a vec.
pub fn vote_contested_resource_contract_documents_indexes_path_vec(
contract_id: &[u8],
document_type_name: &str,
) -> Vec<Vec<u8>> {
vec![
vec![RootTree::Votes as u8],
vec![CONTESTED_RESOURCE_TREE_KEY as u8],
vec![ACTIVE_POLLS_TREE_KEY as u8],
contract_id.to_vec(),
document_type_name.as_bytes().to_vec(),
vec![CONTESTED_DOCUMENT_INDEXES_TREE_KEY],
]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ impl TreePathStorageForm for ContestedDocumentResourceVoteStorageForm {
where
Self: Sized,
{
if path.len() < 9 {
if path.len() < 10 {
return Err(ProtocolError::VoteError(format!(
"path {} is not long enough to construct vote information",
path.into_iter()
Expand Down Expand Up @@ -174,8 +174,8 @@ impl TreePathStorageForm for ContestedDocumentResourceVoteStorageForm {
return Err(ProtocolError::VoteError(format!("path {} 2 before last element must be an identifier or RESOURCE_ABSTAIN_VOTE_TREE_KEY/RESOURCE_LOCK_VOTE_TREE_KEY", path.into_iter().map(hex::encode).collect::<Vec<_>>().join("/"))));
};

// 5 is the first index value, then we have 2 at the end that are not index values
let index_values = path.drain(5..path.len() - 3).collect::<Vec<_>>();
// 6 is the first index value, then we have 2 at the end that are not index values
let index_values = path.drain(6..path.len() - 3).collect::<Vec<_>>();

Ok(ContestedDocumentResourceVoteStorageForm {
contract_id,
Expand Down
Loading
Loading