polkadot-js / apps

Basic Polkadot/Substrate UI for interacting with a Polkadot and Substrate node. This is the main user-facing application, allowing access to all features available on Substrate chains.
https://dotapps.io
Apache License 2.0
1.75k stars 1.55k forks source link

Preimage tab has some preimages showing `Unable to decode preimage bytes into a valid Call` #10313

Closed TarikGul closed 4 months ago

TarikGul commented 8 months ago

Currently in the Preimages tab under Governance some Preimages are coming back as Unable to decode preimage bytes into a valid Call, this might be an upstream issue coming from the /polkadot-js/api (most likely), but his requires some investigation.

Screenshot 2024-02-29 at 8 52 22 PM Screenshot 2024-02-29 at 8 53 24 PM

Apps version v0.133.2-105

ryanleecode commented 8 months ago

taking this one @TarikGul

ggwpez commented 7 months ago

Are you sure that it is a valid call?
There is a case that when a pallet is removed from the runtime or someone notes a non-call, then it wont decode for sure.

KarimJedda commented 5 months ago

Hitting the same problem today :)

Both these extrinsics (Westend) decode in the extrinsics tab:

0x630004000100a50f04082f000006030300286bee42420f00510249020428001049044a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc171949054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc1719010049054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc1719020049054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc17190300

0xbd0204630004000100a50f04082f000006030300286bee42420f00510249020428001049044a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc171949054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc1719010049054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc1719020049054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc17190300

But the preimage of the second one doesn't decode in the PreImage view.

Screenshot from 2024-06-13 10-58-33

https://westend.subscan.io/extrinsic/21243687-2

KarimJedda commented 5 months ago

I read the code a bit and it boils down to this function:

// werks
const callTypeA = api.registry.createType('Call', '0x630004000100a50f04082f000006030300105e5f828b0800b47265706c616365206d6520776974682074686520636f6c6c6563746976657320707265696d6167652064617461');
console.log(callTypeA)

// werks (same as below, without the 0xbd0204 prefix)
const callTypeC = api.registry.createType('Call', '0x630004000100a50f04082f000006030300286bee42420f00510249020428001049044a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc171949054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc1719010049054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc1719020049054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc17190300');
console.log(callTypeC)

// fails
const callTypeB = api.registry.createType('Call', '0xbd0204630004000100a50f04082f000006030300286bee42420f00510249020428001049044a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc171949054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc1719010049054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc1719020049054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc17190300');
console.log(callTypeB)

Pasting this in the polkadot JS APPS developer tab and running it will show that the first two decode successfully, but the lats one not.

KarimJedda commented 5 months ago

Perhaps related: https://github.com/polkadot-js/apps/issues/8837#issuecomment-1387037378

I believe this: https://github.com/polkadot-js/apps/pull/8840/files#diff-856afd45749b2d4d60995d5a8f7a6e65024ab7d3de562658543372f70de653c8R81-R102

Would fix the decoding issue.

KarimJedda commented 5 months ago

Here is functioning (but messy) code that you can drop as is in Polkadot JS Apps / Javascript console that will resolve this:

async function decodeExtrinsic(hexData) {
    try {
        let extrinsicCall = null;

        // First attempt: Try to decode hexData as an extrinsic call directly
        try {
            extrinsicCall = api.createType('Call', hexData);
            const callHex = extrinsicCall.toHex();

            if (callHex === hexData) {
                return extrinsicCall;
            } else if (hexData.startsWith(callHex)) {
                // If hexData is a prefixed payload, attempt to decode it
                const prefixed = util.u8aConcat(util.compactToU8a(extrinsicCall.encodedLength), hexData);
                const extrinsicPayload = api.createType('ExtrinsicPayload', prefixed);

                util.assert(util.u8aEq(extrinsicPayload.toU8a(), prefixed), 'Unable to decode data as un-prefixed ExtrinsicPayload');

                extrinsicCall = api.createType('Call', extrinsicPayload.method.toHex());
                return extrinsicCall;
            } else {
                throw new Error('Unable to decode data as Call, length mismatch in supplied data');
            }
        } catch (error) {
            // Second attempt: Try to create a transaction and decode from it
            try {
                const tx = api.tx(hexData);
                util.assert(tx.toHex() === hexData, 'Cannot decode data as extrinsic, length mismatch');
                extrinsicCall = api.createType('Call', tx.method);
                return extrinsicCall;
            } catch (error) {
                // Third attempt: Try to decode hexData as a prefixed payload directly
                const extrinsicPayload = api.createType('ExtrinsicPayload', hexData);
                util.assert(extrinsicPayload.toHex() === hexData, 'Unable to decode input data as Call, Extrinsic or ExtrinsicPayload');

                extrinsicCall = api.createType('Call', extrinsicPayload.method.toHex());
                return extrinsicCall;
            }
        }
    } catch (error) {
        console.error('Error decoding extrinsic:', error.message);
        return null;
    }
}

// Example usage:
const hexData = '0xbd0204630004000100a50f04082f000006030300286bee42420f00510249020428001049044a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc171949054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc1719010049054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc1719020049054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc17190300';

decodeExtrinsic(hexData).then(extrinsic => {
    if (extrinsic) {
        const success = api.registry.createType('Call', extrinsic);
        console.log('Decoded extrinsic:', success);
        // outputs
        // Decoded extrinsic: {callIndex: 0x6300, args: {dest: {"v4":{"parents":0,"interior":{"x1":[{"parachain":1001}]}}}, message: {"v4":[{"unpaidExecution":{"weightLimit":{"unlimited":null},"checkOrigin":null}},{"transact":{"originKind":"Xcm","requireWeightAtMost":{"refTime":4000000000,"proofSize":250000},"call":{"encoded":"0x49020428001049044a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc171949054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc1719010049054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc1719020049054a0fde15a111eda94aba678170fd212dbe70f26c3b38cd89d67ad327aacc17190300"}}}]}}}
    } else {
        console.log('Failed to decode extrinsic.');
    }
}).catch(err => {
    console.error('Error decoding extrinsic:', err);
});
TarikGul commented 5 months ago

Thank you for doing the leg work and looking into this! I'll tag onto to this, and pick up on your work thanks :)

TarikGul commented 5 months ago

Cool, so I think this is a 2 prong issue:

  1. https://github.com/polkadot-js/apps/blob/master/packages/react-hooks/src/usePreimage.ts#L117-L140

This needs to resolve to the correct proposalLength, which means the callData needs to be succesfully created here.

  1. Then as mentioned above the decoding of the extrinsic then needs to be fixed.
rzadp commented 4 months ago

I've been looking into this issue.

I proposed a PR - it does fix the preimage 0xe67ffc628c8a9c43d2e134ae6c1d5d197af2e06d08d6e632795d46670a835abc mentioned above. (It doesn't exist on Westend anymore but I tested locally)

I didn't include the attempt with api.createType('ExtrinsicPayload', hexData) - it didn't help with any preimage - not on Rococo, Westend, Kusama or Polkadot.

polkadot-js-bot commented 3 months ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue if you think you have a related problem or query.