-
Notifications
You must be signed in to change notification settings - Fork 161
Description
Description
On parachains like Asset Hub, the block author is incorrectly determined because extractAuthor only checks the first PreRuntime digest log, which may not be the Aura digest containing the slot number.
Root Cause
In packages/api-derive/src/type/util.ts, the extractAuthor function uses:
const [pitem] = digest.logs.filter((e) => e.isPreRuntime);This destructuring takes only the first PreRuntime log. On Asset Hub (and likely other Cumulus-based parachains), the digest contains multiple PreRuntime logs:
PreRuntime CMLS(Cumulus parachain data) ← this is checkedPreRuntime aura(actual slot number) ← this is skipped!
Since CMLS is not recognized as an Aura engine (isAura = false), the code falls through to check the Seal log, which contains the Aura signature (64 bytes). The first 8 bytes of this signature are then incorrectly interpreted as a
slot number.
Example: Asset Hub Polkadot Block 12273189
Digest logs:
log[0] PreRuntime: engine=CMLS data=0x01010114
log[1] PreRuntime: engine=aura data=0x0b67cc0800000000 ← actual slot
log[2] Consensus: engine=RPSR data=0x1817f286...
log[3] Seal: engine=aura data=0x1091091abd0bb9f6... ← signature
Current (incorrect) behavior:
- Checks
log[0]PreRuntime CMLS →isAura = false, no author - Skips
log[1]PreRuntime aura (never checked!) - Checks
log[2]Consensus RPSR →isAura = false, no author - Checks
log[3]Seal aura → interprets signature bytes as slot - Slot from signature:
17778253910835302672(first 8 bytes of signature as u64 LE) - Index:
17778253910835302672 % 18 = 14 - Returns:
12owmS8Sobqxfx6KK9vk9e67FqnGpZdmxCFCRFptzZdsoujC
Correct behavior:
- Should check
log[1]PreRuntime aura - Actual slot:
147613451(0x0b67cc0800000000 as u64 LE) - Index:
147613451 % 18 = 5 - Should return:
14wQoaBqk718MgNxp3qdpqHnEgmTTmTkcVnYuxMWWvYr3DXb
Substrate SDK Reference
From substrate/client/consensus/aura/src/standalone.rs:
/// Get the slot author for given block along with authorities.
pub fn slot_author<P: Pair>(slot: Slot, authorities: &[AuthorityId<P>]) -> Option<&AuthorityId<P>> {
let idx = *slot % (authorities.len() as u64);
// ...
Some(current_author)
}From substrate/primitives/consensus/aura/src/digests.rs:
- The PreRuntime digest contains the slot number
- The Seal digest contains the signature
Suggested Fix
Instead of taking only the first PreRuntime log, check all PreRuntime logs for a supported consensus engine:
// Current (buggy):
const [pitem] = digest.logs.filter((e) => e.isPreRuntime);
// Suggested fix - find a PreRuntime with a supported engine:
const pitem = digest.logs.find((e) => {
if (!e.isPreRuntime) return false;
const [engine] = e.asPreRuntime;
return engine.isAura || engine.isBabe;
});Or alternatively, iterate through all PreRuntime logs in the extraction logic rather than just the first one.
Impact
- Affects all Cumulus-based parachains that have multiple PreRuntime digest logs
- The
authorIdfield in block responses contains an incorrect validator address - While this doesn't affect transaction processing, it provides incorrect information to API consumers
Environment
- Observed on: Asset Hub Polkadot (statemint)
- polkadot-js/api version: (affects current versions)
- Also affects substrate-api-sidecar which uses polkadot-js for author extraction