Repository navigation
fix: stop decoding UMP signals as XCM - #420
Merged
Merged
Conversation
Since elastic scaling, a candidate's upward message list is the XCM it sent, then UMP_SEPARATOR (an empty message), then UMP signals. We decoded every entry as XCM, so the signals came back as raw hex, indistinguishable from an XCM message that genuinely failed to decode. They are not corrupt XCM, they are well formed SCALE that is not XCM: a 3 byte SelectCore(CoreSelector, ClaimQueueOffset), and a 40 byte variant carrying a libp2p PeerId. Every parachain emits them, Asset Hub included, so on a recent relay block 46 of 46 upward messages were signals and none were XCM. Reads only up to the separator now. A raw hex `data` in the response therefore means one thing: XCM we could not decode. The separator was already invisible: it arrives as an empty JSON array and the old `msg.as_str()` check skipped it, which is why the signals looked like part of the list.
bee344
previously approved these changes
Sep 30, 2026
Review nits on #420. The doc comment for decode_xcm_message ended up above upward_xcm_messages when that helper was inserted, so it read as part of the wrong function and decode_xcm_message had none. Moved back. is_ump_separator now says why Value::Null is not a separator, with a test. Null means we failed to read that entry, not that the runtime marked a boundary, so treating it as one would truncate the list and drop the XCM after it. Anything that is not a string is skipped by the caller instead.
bee344
approved these changes
Sep 30, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes: #298
Description
Since elastic scaling, a candidate's
upward_messagesis the XCM it sent, thenUMP_SEPARATOR(an empty message), then UMP signals:We decoded every entry as
VersionedXcm, so the signals came back as raw hex with no way to tell them from an XCM message that genuinely failed to decode, which is what #298 asks for.They are not corrupt XCM. They are well formed SCALE that simply is not XCM:
Every parachain emits them, not just SORA as the issue supposed. On relay block 33216511 the senders were 1000, 1001, 1002, 1004, 1005, 1010, 2006, 2030, 3367, 3377, 3388, 3417 and 3428.
Changes
upward_xcm_messagesreads the list only up to the separator. Everything from the separator onwards is dropped, so a raw hexdatain the response now means exactly one thing: XCM we could not decode. A list with no separator is treated as all XCM, which is what pre signal runtimes emit.The separator was already invisible to us. It arrives as an empty JSON array and the old
msg.as_str()check skipped it, which is why the signals looked like part of the same list.Verified
Against live Polkadot relay, this branch versus the deployed build, counting messages in
decodedXcmMsgs:That last one is the control. It is a genuine V5 message from para 1000 that still decodes to
unpaidExecution,transactandsetTopic, so XCM ahead of the separator is untouched.Four unit tests cover the shape seen on chain, XCM before the separator, a list with no separator, and the separator arriving as an empty hex string rather than an empty array.
Note
This drops the signals rather than surfacing them. They are not XCM and the field is
decodedXcmMsgs, so that seemed right, but returning them under their own key would be an easy follow up if anyone wants them.