polkadot-js / api

Promise and RxJS APIs around Polkadot and Substrate based chains via RPC calls. It is dynamically generated based on what the Substrate runtime provides in terms of metadata.
Apache License 2.0
1.06k stars 342 forks source link

Block with more than u16 events fails to be decoded #5782

Open Leouarz opened 5 months ago

Leouarz commented 5 months ago

When a block has more than 64 * 1024 events, it fails to be decoded by the api and makes other component panic (like the polkadot UI). To reproduce, I connected to a local polkadot node 1.0.0 and sent 4 batch of 8500 remark with events all in the same block. The node will process it correctly, but on the api side, if i try to decode the events, i will get an error : Error: Unable to decode storage system.events:: createType(Vec<FrameSystemEventRecord>):: Vec length 72264 exceeds 65536 This is coming from this file. Here's also my initial question on Stack exchange.

With the rise of new types of chain, rollups and even inscriptions, block can definitely contain a lot of events and polkadot api is the main library to interract with such chains. This issue is not reproduced in subxt for example. If it's a choice, I would be interested to know the motivations.

jamesbayly commented 1 month ago

Hi @IkerAlus is there an update here? It's starting to impact us

TarikGul commented 1 month ago

I am happy to start taking a look at this, but that being said, I am hesitant to just change the MAX_LENGTH for Vec's without some heavy testing.

Not sure what the residual affects could be, but I am sure Jaco put that there for good reason (I hope).

TarikGul commented 4 weeks ago

Pushing this issue to the top of the queue, I'll be expediting this today and tomorrow.

TarikGul commented 4 weeks ago

The source of the changes above: https://github.com/polkadot-js/api/pull/2670

TarikGul commented 4 weeks ago

This is also the first time it was introduced: https://github.com/polkadot-js/api/commit/7b04ea0bfeea7b3fc23abde32fe46fe8c0676bc3#diff-0d925a4fc950736275a23f6d43d19c518deab3978a724752c54ad22202f7454f

valentunn commented 4 weeks ago

Hey @TarikGul regarding the new value - would be ideal to increase it at least to 256k as we have seen chains with 144k events in a single block already in production I am thinking about maybe 512k as a safe ground that will allow this problem to not be brought up in the near future (hopefully). What do you think?

TarikGul commented 4 weeks ago

Hey @TarikGul regarding the new value - would be ideal to increase it at least to 256k as we have seen chains with 144k events in a single block already in production I am thinking about maybe 512k as a safe ground that will allow this problem to not be brought up in the near future (hopefully). What do you think?

That would be ideal and I hope it's that straight forward: I am looking into the feasibility right now. Currently it uses compactFromU8aLim which has limitations attached to it which is where I think the original MAX_VALUE comes from.

TarikGul commented 3 weeks ago

Made some local scripts to test, and work on this. Will post some of the workthrough I've done tomorrow. But for now its getting late!

TarikGul commented 3 weeks ago

This is the script I am currrently using:

require('@polkadot/api-augment');

const { ApiPromise, WsProvider } = require('@polkadot/api');
const { Keyring } = require('@polkadot/keyring');
const { cryptoWaitReady } = require('@polkadot/util-crypto');

const main = async () => {
    await cryptoWaitReady();

    const keyring = new Keyring();
    const alice = keyring.addFromUri('//Alice', { name: 'Alice' }, 'sr25519');

    const api = await ApiPromise.create({
        provider: new WsProvider('ws://127.0.0.1:9944')
    });

    const txs = [];
    for (let i = 0; i < 8500; i++) {
        txs.push(api.tx.system.remark('0x00'))
    };

    const batches = [
        api.tx.utility.batch(txs),
        api.tx.utility.batch(txs),
        api.tx.utility.batch(txs),
        api.tx.utility.batch(txs)
    ]

    await api.tx.utility.batchAll(batches).signAndSend(alice);
};

main().finally(() => process.exit());
TarikGul commented 3 weeks ago

So i created a successful transaction, and submitted it with 34k events.

Screenshot 2024-06-11 at 7 56 09 PM

Then using sidecar (just a RESTful wrapper around pjs to query and see if I would get any errors querying it, and I didnt).

Screenshot 2024-06-11 at 7 57 14 PM

Next: I'll try to decode by scratch, and also increase the amount of data in each remark.

valentunn commented 3 weeks ago

Hey @TarikGul you can use this block: https://bittensor.com/scan/block/3014340 to test decoding of 144k events

TarikGul commented 3 weeks ago

@valentunn What chain is that for?

KarimJedda commented 3 weeks ago

@TarikGul it's for Bittensor, sending you some RPC endpoints to try out.