Skip to content
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
30 changes: 30 additions & 0 deletions .github/actions/local-network/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,33 @@ runs:
run: yarn start
env:
DEBUG: 1

- name: Refresh local masternode discovery
shell: bash
run: |
set -euo pipefail

# The seed's discovery service starts before the DAPI nodes and can
# cache failed version checks for ten minutes. `yarn start` waits for
# DAPI readiness; restart discovery now so it checks the ready nodes.
quorum_discovery_container=$(docker ps -q \
--filter label=com.docker.compose.service=quorum_list \
--filter label=org.dashmate.config.name=local_seed)
if [[ -z "$quorum_discovery_container" || "$quorum_discovery_container" == *$'\n'* ]]; then
echo "::error::Expected exactly one local seed quorum discovery container"
exit 1
fi
docker restart "$quorum_discovery_container"

# Match the SDK's eligibility filter, not just HTTP readiness: a
# successful response can still contain only failed version checks.
quorum_discovery_deadline=$((SECONDS + 120))
until curl --fail --silent --show-error --connect-timeout 2 --max-time 5 \
http://127.0.0.1:22444/masternodes \
| jq -e '.success == true and any(.data[]?; .status == "ENABLED" and .versionCheck == "success")' > /dev/null; do
if (( SECONDS >= quorum_discovery_deadline )); then
echo "::error::Local masternode discovery did not return an eligible node within 120 seconds"
exit 1
fi
sleep 2
done
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ pub(super) fn verify_average_query(
platform_version: &PlatformVersion,
provider: &dyn ContextProvider,
) -> Result<(Option<Vec<AverageEntry>>, ResponseMetadata, Proof), drive_proof_verifier::Error> {
request.ensure_no_sub_queries()?;
let proof = response
.proof()
.or(Err(drive_proof_verifier::Error::NoProofInResult))?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ impl TryFromPlatformVersioned<ChainedDocumentQuery> for GetDocumentsRequest {
outer_document_type_name,
} = value;

inner
.ensure_no_sub_queries()
.map_err(|e| Error::Config(e.to_string()))?;
if inner.limit == 0 {
return Err(Error::Config(
"a chained document query requires an explicit non-zero inner limit: it \
Expand Down Expand Up @@ -125,6 +128,10 @@ impl<'a> TryFrom<&'a ChainedDocumentQuery> for DriveDocumentQuery<'a> {
type Error = Error;

fn try_from(request: &'a ChainedDocumentQuery) -> Result<Self, Self::Error> {
request
.inner
.ensure_no_sub_queries()
.map_err(|e| Error::Config(e.to_string()))?;
let inner: DriveDocumentQuery<'a> = (&request.inner).try_into()?;
let outer_document_type = request
.inner
Expand Down Expand Up @@ -289,31 +296,54 @@ mod tests {
assert_eq!(drive_query.limit, Some(10));
}

fn assert_plain_conversions_refuse(query: &DriveDocumentQuery) {
#[test]
fn should_reject_sub_queries_inside_a_chained_inner_query() {
use crate::documents::composite_document_query::CompositeSubQuery;

let mut query = posts_i_liked(10);
query.inner.sub_queries.push(
CompositeSubQuery::documents(query.inner.data_contract.clone(), "post")
.expect("post doctype exists")
.bound_to_page("postId", "$id"),
);
let refused =
GetDocumentsRequest::try_from_platform_versioned(query.clone(), platform_version());
assert!(matches!(refused, Err(Error::Config(message)) if message.contains("sub-queries")));
let refused = DriveDocumentQuery::try_from(&query);
assert!(matches!(refused, Err(Error::Config(message)) if message.contains("sub-queries")));
}

fn assert_conversions_preserve_sub_queries(query: &DriveDocumentQuery) {
for result in [
DocumentQuery::try_from(query),
DocumentQuery::try_from(query.clone()),
DocumentQuery::new_with_drive_query(query),
] {
assert!(
matches!(&result, Err(Error::Config(message)) if message.contains("sub-queries")),
"a plain conversion must refuse the composition, got {result:?}"
);
let sdk_query = result.expect("conversion preserves sub-queries");
let restored: DriveDocumentQuery = (&sdk_query).try_into().expect("converts back");
assert_eq!(&restored, query);
let request =
GetDocumentsRequest::try_from_platform_versioned(sdk_query, platform_version())
.expect("the composition encodes");
let Some(RequestVersion::V1(v1)) = request.version else {
panic!("expected V1");
};
assert_eq!(v1.sub_queries.len(), query.sub_queries.len());
}
}

#[test]
fn should_refuse_dropping_a_drive_join_during_plain_query_conversion() {
fn should_preserve_a_drive_join_during_query_conversion() {
let query = posts_i_liked(10);
let drive_query: DriveDocumentQuery = (&query).try_into().expect("drive query");
drive_query
.validate_chained(platform_version())
.expect("valid chained shape");
assert_plain_conversions_refuse(&drive_query);
assert_conversions_preserve_sub_queries(&drive_query);
}

#[test]
fn should_refuse_dropping_a_composite_count_during_plain_query_conversion() {
fn should_preserve_a_composite_count_during_query_conversion() {
let query = posts_i_liked(10);
let page: DriveDocumentQuery = (&query.inner).try_into().expect("drive page");
let count = DriveSubQuery {
Expand All @@ -333,7 +363,7 @@ mod tests {
composite
.validate_composite(platform_version())
.expect("valid count composition");
assert_plain_conversions_refuse(&composite);
assert_conversions_preserve_sub_queries(&composite);
}

#[test]
Expand Down
Loading
Loading