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 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,279 @@ mod tests {

assert_eq!(contests.len(), 2);
}

#[test]
fn test_empty_string_start_index_value() {
let platform_version = PlatformVersion::latest();
let mut platform = TestPlatformBuilder::new()
.build_with_mock_rpc()
.set_genesis_state();

let platform_state = platform.state.load();

let (_contender_1, _contender_2, dpns_contract) = create_dpns_name_contest(
&mut platform,
&platform_state,
7,
"quantum",
platform_version,
);

let domain = dpns_contract
.document_type_for_name("domain")
.expect("expected a profile document type");

let index_name = "parentNameAndLabel".to_string();

let config = bincode::config::standard()
.with_big_endian()
.with_no_limit();

let empty_encoded = bincode::encode_to_vec(Value::Text("".to_string()), config)
.expect("expected to encode value");

{
let query_validation_result = platform
.query_contested_resources(
GetContestedResourcesRequest {
version: Some(get_contested_resources_request::Version::V0(
GetContestedResourcesRequestV0 {
contract_id: dpns_contract.id().to_vec(),
document_type_name: domain.name().clone(),
index_name: index_name.clone(),
start_index_values: vec![empty_encoded.clone()],
end_index_values: vec![],
start_at_value_info: None,
count: None,
order_ascending: true,
prove: false,
},
)),
},
&platform_state,
platform_version,
)
.expect("expected to execute query")
.into_data()
.expect("expected query to be valid");

let get_contested_resources_response::Version::V0(
GetContestedResourcesResponseV0 {
metadata: _,
result,
},
) = query_validation_result.version.expect("expected a version");

let Some(get_contested_resources_response_v0::Result::ContestedResourceValues(
get_contested_resources_response_v0::ContestedResourceValues {
contested_resource_values,
},
)) = result
else {
panic!("expected contested resources")
};

assert_eq!(contested_resource_values.len(), 0);
}

{
let query_validation_result = platform
.query_contested_resources(
GetContestedResourcesRequest {
version: Some(get_contested_resources_request::Version::V0(
GetContestedResourcesRequestV0 {
contract_id: dpns_contract.id().to_vec(),
document_type_name: domain.name().clone(),
index_name: index_name.clone(),
start_index_values: vec![empty_encoded],
end_index_values: vec![],
start_at_value_info: None,
count: None,
order_ascending: true,
prove: true,
},
)),
},
&platform_state,
platform_version,
)
.expect("expected to execute query")
.into_data()
.expect("expected query to be valid");

let get_contested_resources_response::Version::V0(
GetContestedResourcesResponseV0 {
metadata: _,
result,
},
) = query_validation_result.version.expect("expected a version");

let Some(get_contested_resources_response_v0::Result::Proof(proof)) = result
else {
panic!("expected proof")
};

let resolved_contested_document_vote_poll_drive_query =
ResolvedVotePollsByDocumentTypeQuery {
contract: DataContractResolvedInfo::BorrowedDataContract(
dpns_contract.as_ref(),
),
document_type_name: domain.name(),
index_name: &index_name,
start_index_values: &vec!["".into()],
end_index_values: &vec![],
limit: None,
order_ascending: true,
start_at_value: &None,
};

let (_, contests) = resolved_contested_document_vote_poll_drive_query
.verify_contests_proof(proof.grovedb_proof.as_ref(), platform_version)
.expect("expected to verify proof");

assert_eq!(contests.len(), 0);
}
}

#[test]
fn test_no_start_index_value() {
let platform_version = PlatformVersion::latest();
let mut platform = TestPlatformBuilder::new()
.build_with_mock_rpc()
.set_genesis_state();

let platform_state = platform.state.load();

let (_contender_1, _contender_2, dpns_contract) = create_dpns_name_contest(
&mut platform,
&platform_state,
7,
"quantum",
platform_version,
);

let domain = dpns_contract
.document_type_for_name("domain")
.expect("expected a profile document type");

let index_name = "parentNameAndLabel".to_string();

let config = bincode::config::standard()
.with_big_endian()
.with_no_limit();

{
let query_validation_result = platform
.query_contested_resources(
GetContestedResourcesRequest {
version: Some(get_contested_resources_request::Version::V0(
GetContestedResourcesRequestV0 {
contract_id: dpns_contract.id().to_vec(),
document_type_name: domain.name().clone(),
index_name: index_name.clone(),
start_index_values: vec![],
end_index_values: vec![],
start_at_value_info: None,
count: None,
order_ascending: true,
prove: false,
},
)),
},
&platform_state,
platform_version,
)
.expect("expected to execute query")
.into_data()
.expect("expected query to be valid");

let get_contested_resources_response::Version::V0(
GetContestedResourcesResponseV0 {
metadata: _,
result,
},
) = query_validation_result.version.expect("expected a version");

let Some(get_contested_resources_response_v0::Result::ContestedResourceValues(
get_contested_resources_response_v0::ContestedResourceValues {
contested_resource_values,
},
)) = result
else {
panic!("expected contested resources")
};

let dash_encoded =
bincode::encode_to_vec(Value::Text("dash".to_string()), config)
.expect("expected to encode the word dash");

assert_eq!(
contested_resource_values.first(),
Some(dash_encoded).as_ref()
);
}

{
let query_validation_result = platform
.query_contested_resources(
GetContestedResourcesRequest {
version: Some(get_contested_resources_request::Version::V0(
GetContestedResourcesRequestV0 {
contract_id: dpns_contract.id().to_vec(),
document_type_name: domain.name().clone(),
index_name: index_name.clone(),
start_index_values: vec![],
end_index_values: vec![],
start_at_value_info: None,
count: None,
order_ascending: true,
prove: true,
},
)),
},
&platform_state,
platform_version,
)
.expect("expected to execute query")
.into_data()
.expect("expected query to be valid");

let get_contested_resources_response::Version::V0(
GetContestedResourcesResponseV0 {
metadata: _,
result,
},
) = query_validation_result.version.expect("expected a version");

let Some(get_contested_resources_response_v0::Result::Proof(proof)) = result
else {
panic!("expected proof")
};

let resolved_contested_document_vote_poll_drive_query =
ResolvedVotePollsByDocumentTypeQuery {
contract: DataContractResolvedInfo::BorrowedDataContract(
dpns_contract.as_ref(),
),
document_type_name: domain.name(),
index_name: &index_name,
start_index_values: &vec![],
end_index_values: &vec![],
limit: None,
order_ascending: true,
start_at_value: &None,
};

let (_, contests) = resolved_contested_document_vote_poll_drive_query
.verify_contests_proof(proof.grovedb_proof.as_ref(), platform_version)
.expect("expected to verify proof");

assert_eq!(
contests.first(),
Some(Value::Text("dash".to_string())).as_ref()
);
}
}
}

mod vote_state_query {
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
Loading