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
36 changes: 32 additions & 4 deletions rust/crates/truapi-host-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,9 @@ async fn run_pgas_check(
let asset_hub_state = alloc::fetch_chain_state(&asset_hub_rpc)
.await
.map_err(anyhow::Error::msg)?;
let network_suffix = alloc::slot::read_network_suffix(&asset_hub_rpc)
.await
.map_err(anyhow::Error::msg)?;
println!(
"asset hub: metadata V{} specVersion={} txVersion={} genesis=0x{}",
asset_hub_metadata.metadata_version(),
Expand Down Expand Up @@ -715,6 +718,7 @@ async fn run_pgas_check(
&asset_hub_metadata,
ring.collection,
membership.entropy,
&network_suffix,
day,
&[],
)
Expand All @@ -738,6 +742,7 @@ async fn run_pgas_check(
people_rpc: &people_rpc,
people_metadata: &people_metadata,
entropy: membership.entropy,
network_suffix: &network_suffix,
target: &target,
ring: &membership.ring,
})
Expand Down Expand Up @@ -795,6 +800,9 @@ async fn run_alloc_check(
let chain_state = alloc::fetch_chain_state(&rpc)
.await
.map_err(anyhow::Error::msg)?;
let network_suffix = alloc::slot::read_network_suffix(&rpc)
.await
.map_err(anyhow::Error::msg)?;
println!(
"chain: specVersion={} txVersion={} genesis=0x{}",
chain_state.spec_version,
Expand Down Expand Up @@ -841,16 +849,33 @@ async fn run_alloc_check(
continue;
}
print!("{}: ", candidate.collection);
report_slot_scan(&rpc, &metadata, *candidate, period, &target, now).await?;
report_slot_scan(
&rpc,
&metadata,
*candidate,
&network_suffix,
period,
&target,
now,
)
.await?;
}

if submit {
if memberships.is_empty() {
bail!("cannot submit: member not in any ring");
}
let scans = alloc::scan_collections(&rpc, &metadata, &candidates, period, &target, true)
.await
.map_err(anyhow::Error::msg)?;
let scans = alloc::scan_collections(
&rpc,
&metadata,
&candidates,
&network_suffix,
period,
&target,
true,
)
.await
.map_err(anyhow::Error::msg)?;
match alloc::register_statement_account_pooled(
&rpc,
&metadata,
Expand All @@ -860,6 +885,7 @@ async fn run_alloc_check(
alloc::PooledRegistrationParams {
target: &target,
period,
network_suffix: &network_suffix,
reuse_existing: true,
// A diagnostic that submits behaves as it did before pooling,
// where a full table was replaced rather than reported.
Expand Down Expand Up @@ -893,6 +919,7 @@ async fn report_slot_scan(
rpc: &alloc::rpc::RpcClient,
metadata: &alloc::extension::Metadata,
candidate: alloc::CollectionCandidate,
network_suffix: &[u8],
period: u32,
target: &[u8; 32],
now: u64,
Expand All @@ -903,6 +930,7 @@ async fn report_slot_scan(
alloc::slot::SlotScan {
collection: candidate.collection,
entropy: candidate.entropy,
network_suffix,
period,
target,
excluded: &[],
Expand Down
18 changes: 16 additions & 2 deletions rust/crates/truapi-host-cli/tests/live_asset_hub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ fn asset_hub_ws() -> String {
}
const PEOPLE_WS: &str = "wss://paseo-people-next-system-rpc.polkadot.io";

/// The ring our onboarded test identity sits in.
const RING_INDEX: u32 = 2;
/// Must stay active so the ignored live tests can resolve its mirrored roots.
const RING_INDEX: u32 = 1;
/// The ring this fixture's index belongs to.
const COLLECTION: PersonhoodCollection = PersonhoodCollection::LitePeople;

Expand All @@ -37,6 +37,20 @@ async fn asset_hub() -> (alloc::rpc::RpcClient, alloc::extension::Metadata) {
(rpc, metadata)
}

#[tokio::test]
#[ignore = "needs network access to a live Asset Hub"]
async fn live_asset_hub_reports_the_product_context_suffix() {
let (rpc, _metadata) = asset_hub().await;
let expected = std::env::var("LIVE_TLD").unwrap_or_else(|_| "paseo".to_string());

assert_eq!(
alloc::slot::read_network_suffix(&rpc)
.await
.expect("read Asset Hub NetworkSuffix"),
expected.as_bytes(),
);
}

/// The claim encodes five fields for `AsPgas::Claim`. A short payload is accepted
/// locally and then panics the runtime inside `validate_transaction`, which is how
/// the missing `revision` on the statement-store claim went unnoticed.
Expand Down
4 changes: 4 additions & 0 deletions rust/crates/truapi-host-cli/tests/live_people_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ async fn scanning_a_live_period_answers_without_erroring() {
.await
.expect("read the live chain context");
let period = current_period();
let network_suffix = alloc::slot::read_network_suffix(&rpc)
.await
.expect("read the live network suffix");

// Entropy and target are throwaway: no alias derived from them owns a slot,
// so the scan must offer a free one or report the table full — never error.
Expand All @@ -112,6 +115,7 @@ async fn scanning_a_live_period_answers_without_erroring() {
alloc::slot::SlotScan {
collection: PersonhoodCollection::LitePeople,
entropy: [0x11; 32],
network_suffix: &network_suffix,
period,
target: &[0x22; 32],
excluded: &[],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,9 @@ pub(super) async fn renew_now(
let chain_state = fetch_chain_state(&rpc)
.await
.map_err(|err| err.to_string())?;
let network_suffix = statement_allowance::slot::read_network_suffix(&rpc)
.await
.map_err(|err| err.to_string())?;
// Every ring back to index 0, because a membership that stopped being
// re-included still proves against the ring that holds it.
let memberships = find_including_rings(&rpc, &metadata, &candidates, u32::MAX)
Expand All @@ -426,6 +429,7 @@ pub(super) async fn renew_now(
rpc: &rpc,
metadata: &metadata,
chain_state: &chain_state,
network_suffix: &network_suffix,
candidates: &candidates,
memberships: &memberships,
};
Expand Down
33 changes: 22 additions & 11 deletions rust/crates/truapi-server/src/runtime/signing_host/sso_responder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,7 @@ pub(super) async fn allocate_statement_store_allowance(
.await?;
let rpc = client.rpc();
let chain = services.chain_context.get(&client).await?;
let network_suffix = statement_allowance::slot::read_network_suffix(rpc).await?;
let period = statement_allowance::slot::current_period(current_unix_secs()?);
let reuse_existing = matches!(policy, OnExistingAllowancePolicy::Ignore);

Expand All @@ -1087,6 +1088,7 @@ pub(super) async fn allocate_statement_store_allowance(
rpc,
&chain.metadata,
&candidates,
&network_suffix,
period,
&target,
reuse_existing,
Expand Down Expand Up @@ -1120,6 +1122,7 @@ pub(super) async fn allocate_statement_store_allowance(
PooledRegistrationParams {
target: &target,
period,
network_suffix: &network_suffix,
reuse_existing,
// Connecting a product must not revoke another product's allowance.
// A full period is reported as exhaustion; reclaiming space is the
Expand Down Expand Up @@ -1207,6 +1210,7 @@ pub(super) async fn allocate_bulletin_allowance(
.await?;
let people_rpc = people_client.rpc();
let chain = services.chain_context.get(&people_client).await?;
let network_suffix = statement_allowance::slot::read_network_suffix(people_rpc).await?;
let session = signing_host
.current_session()
.ok_or(AuthorityError::Disconnected)?;
Expand Down Expand Up @@ -1234,15 +1238,16 @@ pub(super) async fn allocate_bulletin_allowance(
current_unix_secs()?,
period_duration,
)?;
let outcome = claim_long_term_storage(
people_rpc,
&chain.metadata,
&chain.state,
membership.entropy,
&target,
let outcome = claim_long_term_storage(statement_allowance::LongTermStorageClaim {
rpc: people_rpc,
metadata: &chain.metadata,
chain_state: &chain.state,
entropy: membership.entropy,
network_suffix: &network_suffix,
target: &target,
period,
&membership.ring,
)
ring: &membership.ring,
})
.await?;
let statement_allowance::LongTermStorageOutcome::Claimed {
block_hash,
Expand Down Expand Up @@ -1350,6 +1355,8 @@ pub(super) async fn allocate_smart_contract_allowance(
debug!(%product_id, "PGAS allowance already funded; leaving it alone");
return Ok(());
}
let network_suffix =
statement_allowance::slot::read_network_suffix(asset_hub_client.rpc()).await?;

let people_client = services
.statement_store
Expand All @@ -1373,6 +1380,7 @@ pub(super) async fn allocate_smart_contract_allowance(
people_rpc,
people_metadata: &people.metadata,
entropy: membership.entropy,
network_suffix: &network_suffix,
target: &target,
ring: &membership.ring,
})
Expand Down Expand Up @@ -1773,6 +1781,10 @@ mod tests {
"state_getMetadata",
format!(r#""0x{}""#, hex::encode(PEOPLE_METADATA)),
),
(
"state_getStorage",
format!(r#""0x{}""#, hex::encode(b"paseo".to_vec().encode())),
),
(
"state_getStorage",
format!(r#""0x{}""#, hex::encode(&slot_entry)),
Expand Down Expand Up @@ -1829,14 +1841,13 @@ mod tests {
.any(|method| method.starts_with("author_submit")),
"an extrinsic was submitted for an allowance already in place: {methods:?}"
);
// One slot read answered it; the scan stopped at the first match.
assert_eq!(
methods
.iter()
.filter(|method| *method == "state_getStorage")
.count(),
1,
"expected a single slot read: {methods:?}"
2,
"expected one suffix and one slot read: {methods:?}"
);
}

Expand Down
Loading