Description
TrustedHttpContextProvider::get_quorum_public_key() in rs-sdk-trusted-context-provider/src/provider.rs (line ~626) calls futures::executor::block_on() when a quorum key is not found in cache and refetch_if_not_found is true. This call happens from within a tokio runtime context (the SDK's FFI layer enters the runtime via wrapper.runtime.block_on(async { ... })), which causes a deadlock.
Root Cause
The ContextProvider trait has a synchronous interface (fn get_quorum_public_key(...) -> Result<...>). When the quorum cache misses, the code falls back to:
futures::executor::block_on(self.find_quorum(...))
find_quorum makes HTTP requests via reqwest. Nesting futures::executor::block_on inside a tokio runtime context deadlocks on single-threaded runtimes or panics on multi-threaded runtimes.
Trigger Conditions
- SDK created via
dash_sdk_create_trusted — quorum prefetch is async and the SDK handle is returned immediately (race condition)
- App issues a query requiring proof verification before the prefetch completes
get_quorum_public_key is called, cache is empty
futures::executor::block_on called inside tokio → deadlock
Also triggered if a proof references a quorum hash not in the pre-fetched set.
Impact
- App hangs permanently (denial of service)
- Intermittent — depends on timing of prefetch vs first query
- Affects iOS SDK and any other FFI consumer using the trusted context provider
Suggested Fixes
- Use
tokio::task::block_in_place + Handle::current().block_on() for the synchronous fallback
- Or restructure
ContextProvider trait to support async operations
- Or block SDK creation until prefetch completes (ensure SDK is ready before returning handle)
- Or set
refetch_if_not_found = false when operating within a tokio context and rely solely on the prefetched cache
Related
dash_sdk_create_trusted returns SDK before prefetch completes (rs-sdk-ffi/src/sdk.rs:504-537)
- The diagnostic HTTP requests to google.com at lines 511-521 should also be removed
Found By
Security audit of v3.1-dev branch.
Description
TrustedHttpContextProvider::get_quorum_public_key()inrs-sdk-trusted-context-provider/src/provider.rs(line ~626) callsfutures::executor::block_on()when a quorum key is not found in cache andrefetch_if_not_foundis true. This call happens from within a tokio runtime context (the SDK's FFI layer enters the runtime viawrapper.runtime.block_on(async { ... })), which causes a deadlock.Root Cause
The
ContextProvidertrait has a synchronous interface (fn get_quorum_public_key(...) -> Result<...>). When the quorum cache misses, the code falls back to:find_quorummakes HTTP requests viareqwest. Nestingfutures::executor::block_oninside a tokio runtime context deadlocks on single-threaded runtimes or panics on multi-threaded runtimes.Trigger Conditions
dash_sdk_create_trusted— quorum prefetch is async and the SDK handle is returned immediately (race condition)get_quorum_public_keyis called, cache is emptyfutures::executor::block_oncalled inside tokio → deadlockAlso triggered if a proof references a quorum hash not in the pre-fetched set.
Impact
Suggested Fixes
tokio::task::block_in_place+Handle::current().block_on()for the synchronous fallbackContextProvidertrait to support async operationsrefetch_if_not_found = falsewhen operating within a tokio context and rely solely on the prefetched cacheRelated
dash_sdk_create_trustedreturns SDK before prefetch completes (rs-sdk-ffi/src/sdk.rs:504-537)Found By
Security audit of v3.1-dev branch.