Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strip metadata fix #1774

Merged
merged 20 commits into from
Oct 21, 2024
Merged

Strip metadata fix #1774

merged 20 commits into from
Oct 21, 2024

Conversation

pkhry
Copy link
Contributor

@pkhry pkhry commented Sep 18, 2024

Description:

See #1659

This fixes the error described inside the issue, however it will strip types in a bit different way which will result in slightly less savings on average.

Biggest difference between the new and old approaches is that:

  • we always keep full outerenum enums, unless there are some variants that do not reference any types we intend to retain.
  • we dont immediately drop pallets that the user is not interested in, instead we strip them to contain only types that are relevant and if it ends up empty -> it is being dropped.
  • outer enums and pallet types are now traversed fully to collect all the types and their deps.

Size comparison with the previous stripping approach:

size reduction Comparison:

  • using `./artifacts/polkadot_metadata_full.scale"
Comparison for old and new stripping methods. be warned, it's 1K lines
[
    DebugInfo {
        pallets_list: "System",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 502,
            num_pallets: 7,
            encoded_size: 133756,
            codegen_size: 598771,
        },
        old_retaining_algo: Info {
            num_types: 418,
            num_pallets: 1,
            encoded_size: 80216,
            codegen_size: 461382,
        },
    },
    DebugInfo {
        pallets_list: "Babe",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 411,
            num_pallets: 11,
            encoded_size: 80680,
            codegen_size: 442897,
        },
        old_retaining_algo: Info {
            num_types: 411,
            num_pallets: 1,
            encoded_size: 78437,
            codegen_size: 429077,
        },
    },
    DebugInfo {
        pallets_list: "Timestamp",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 395,
            num_pallets: 13,
            encoded_size: 75779,
            codegen_size: 416354,
        },
        old_retaining_algo: Info {
            num_types: 395,
            num_pallets: 1,
            encoded_size: 73003,
            codegen_size: 398718,
        },
    },
    DebugInfo {
        pallets_list: "Indices",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 398,
            num_pallets: 9,
            encoded_size: 76784,
            codegen_size: 428982,
        },
        old_retaining_algo: Info {
            num_types: 398,
            num_pallets: 1,
            encoded_size: 74575,
            codegen_size: 415427,
        },
    },
    DebugInfo {
        pallets_list: "Balances",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 419,
            num_pallets: 9,
            encoded_size: 84407,
            codegen_size: 487783,
        },
        old_retaining_algo: Info {
            num_types: 419,
            num_pallets: 1,
            encoded_size: 82198,
            codegen_size: 474216,
        },
    },
    DebugInfo {
        pallets_list: "Parameters",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 413,
            num_pallets: 12,
            encoded_size: 76925,
            codegen_size: 426018,
        },
        old_retaining_algo: Info {
            num_types: 413,
            num_pallets: 1,
            encoded_size: 74168,
            codegen_size: 408409,
        },
    },
    DebugInfo {
        pallets_list: "TransactionPayment",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 397,
            num_pallets: 11,
            encoded_size: 75533,
            codegen_size: 414861,
        },
        old_retaining_algo: Info {
            num_types: 397,
            num_pallets: 1,
            encoded_size: 72801,
            codegen_size: 397551,
        },
    },
    DebugInfo {
        pallets_list: "Authorship",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 394,
            num_pallets: 12,
            encoded_size: 74160,
            codegen_size: 408939,
        },
        old_retaining_algo: Info {
            num_types: 394,
            num_pallets: 1,
            encoded_size: 71342,
            codegen_size: 390790,
        },
    },
    DebugInfo {
        pallets_list: "Offences",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 399,
            num_pallets: 10,
            encoded_size: 74334,
            codegen_size: 414022,
        },
        old_retaining_algo: Info {
            num_types: 399,
            num_pallets: 1,
            encoded_size: 71984,
            codegen_size: 398824,
        },
    },
    DebugInfo {
        pallets_list: "Historical",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 396,
            num_pallets: 13,
            encoded_size: 74258,
            codegen_size: 410475,
        },
        old_retaining_algo: Info {
            num_types: 396,
            num_pallets: 1,
            encoded_size: 71516,
            codegen_size: 392805,
        },
    },
    DebugInfo {
        pallets_list: "Session",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 402,
            num_pallets: 10,
            encoded_size: 76815,
            codegen_size: 425948,
        },
        old_retaining_algo: Info {
            num_types: 402,
            num_pallets: 1,
            encoded_size: 74456,
            codegen_size: 411628,
        },
    },
    DebugInfo {
        pallets_list: "Grandpa",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 402,
            num_pallets: 11,
            encoded_size: 78756,
            codegen_size: 436131,
        },
        old_retaining_algo: Info {
            num_types: 402,
            num_pallets: 1,
            encoded_size: 76444,
            codegen_size: 421462,
        },
    },
    DebugInfo {
        pallets_list: "AuthorityDiscovery",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 395,
            num_pallets: 13,
            encoded_size: 74382,
            codegen_size: 411048,
        },
        old_retaining_algo: Info {
            num_types: 395,
            num_pallets: 1,
            encoded_size: 71495,
            codegen_size: 391843,
        },
    },
    DebugInfo {
        pallets_list: "Treasury",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 404,
            num_pallets: 7,
            encoded_size: 81164,
            codegen_size: 459627,
        },
        old_retaining_algo: Info {
            num_types: 404,
            num_pallets: 1,
            encoded_size: 79538,
            codegen_size: 448852,
        },
    },
    DebugInfo {
        pallets_list: "ConvictionVoting",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 414,
            num_pallets: 9,
            encoded_size: 82661,
            codegen_size: 455934,
        },
        old_retaining_algo: Info {
            num_types: 414,
            num_pallets: 1,
            encoded_size: 80387,
            codegen_size: 441568,
        },
    },
    DebugInfo {
        pallets_list: "Referenda",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 423,
            num_pallets: 9,
            encoded_size: 86419,
            codegen_size: 476546,
        },
        old_retaining_algo: Info {
            num_types: 423,
            num_pallets: 1,
            encoded_size: 84335,
            codegen_size: 464801,
        },
    },
    DebugInfo {
        pallets_list: "FellowshipCollective",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 405,
            num_pallets: 10,
            encoded_size: 78791,
            codegen_size: 452499,
        },
        old_retaining_algo: Info {
            num_types: 405,
            num_pallets: 1,
            encoded_size: 76496,
            codegen_size: 438100,
        },
    },
    DebugInfo {
        pallets_list: "FellowshipReferenda",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 422,
            num_pallets: 9,
            encoded_size: 85893,
            codegen_size: 476641,
        },
        old_retaining_algo: Info {
            num_types: 422,
            num_pallets: 1,
            encoded_size: 83809,
            codegen_size: 464909,
        },
    },
    DebugInfo {
        pallets_list: "Origins",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 394,
            num_pallets: 13,
            encoded_size: 74175,
            codegen_size: 409028,
        },
        old_retaining_algo: Info {
            num_types: 394,
            num_pallets: 1,
            encoded_size: 71288,
            codegen_size: 389811,
        },
    },
    DebugInfo {
        pallets_list: "Whitelist",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 563,
            num_pallets: 7,
            encoded_size: 232060,
            codegen_size: 699070,
        },
        old_retaining_algo: Info {
            num_types: 397,
            num_pallets: 1,
            encoded_size: 72631,
            codegen_size: 406658,
        },
    },
    DebugInfo {
        pallets_list: "Claims",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 404,
            num_pallets: 10,
            encoded_size: 78848,
            codegen_size: 442670,
        },
        old_retaining_algo: Info {
            num_types: 404,
            num_pallets: 1,
            encoded_size: 76238,
            codegen_size: 426953,
        },
    },
    DebugInfo {
        pallets_list: "Utility",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 563,
            num_pallets: 7,
            encoded_size: 232114,
            codegen_size: 710366,
        },
        old_retaining_algo: Info {
            num_types: 399,
            num_pallets: 1,
            encoded_size: 75701,
            codegen_size: 422136,
        },
    },
    DebugInfo {
        pallets_list: "Identity",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 451,
            num_pallets: 9,
            encoded_size: 90133,
            codegen_size: 523383,
        },
        old_retaining_algo: Info {
            num_types: 451,
            num_pallets: 1,
            encoded_size: 87985,
            codegen_size: 510544,
        },
    },
    DebugInfo {
        pallets_list: "Society",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 419,
            num_pallets: 9,
            encoded_size: 88999,
            codegen_size: 526480,
        },
        old_retaining_algo: Info {
            num_types: 419,
            num_pallets: 1,
            encoded_size: 86875,
            codegen_size: 513932,
        },
    },
    DebugInfo {
        pallets_list: "Recovery",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 567,
            num_pallets: 7,
            encoded_size: 235321,
            codegen_size: 733453,
        },
        old_retaining_algo: Info {
            num_types: 403,
            num_pallets: 1,
            encoded_size: 80171,
            codegen_size: 447311,
        },
    },
    DebugInfo {
        pallets_list: "Vesting",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 401,
            num_pallets: 9,
            encoded_size: 78445,
            codegen_size: 438034,
        },
        old_retaining_algo: Info {
            num_types: 401,
            num_pallets: 1,
            encoded_size: 76171,
            codegen_size: 423657,
        },
    },
    DebugInfo {
        pallets_list: "Scheduler",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 568,
            num_pallets: 6,
            encoded_size: 233977,
            codegen_size: 731145,
        },
        old_retaining_algo: Info {
            num_types: 407,
            num_pallets: 1,
            encoded_size: 77612,
            codegen_size: 445470,
        },
    },
    DebugInfo {
        pallets_list: "Proxy",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 571,
            num_pallets: 7,
            encoded_size: 234609,
            codegen_size: 734882,
        },
        old_retaining_algo: Info {
            num_types: 408,
            num_pallets: 1,
            encoded_size: 80803,
            codegen_size: 451419,
        },
    },
    DebugInfo {
        pallets_list: "Multisig",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 566,
            num_pallets: 7,
            encoded_size: 234170,
            codegen_size: 721871,
        },
        old_retaining_algo: Info {
            num_types: 404,
            num_pallets: 1,
            encoded_size: 80096,
            codegen_size: 437136,
        },
    },
    DebugInfo {
        pallets_list: "Preimage",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 406,
            num_pallets: 9,
            encoded_size: 76746,
            codegen_size: 431555,
        },
        old_retaining_algo: Info {
            num_types: 406,
            num_pallets: 1,
            encoded_size: 74544,
            codegen_size: 418020,
        },
    },
    DebugInfo {
        pallets_list: "AssetRate",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 399,
            num_pallets: 12,
            encoded_size: 75807,
            codegen_size: 425186,
        },
        old_retaining_algo: Info {
            num_types: 399,
            num_pallets: 1,
            encoded_size: 73118,
            codegen_size: 408334,
        },
    },
    DebugInfo {
        pallets_list: "Bounties",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 403,
            num_pallets: 8,
            encoded_size: 80792,
            codegen_size: 460794,
        },
        old_retaining_algo: Info {
            num_types: 403,
            num_pallets: 1,
            encoded_size: 78790,
            codegen_size: 447849,
        },
    },
    DebugInfo {
        pallets_list: "ChildBounties",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 401,
            num_pallets: 9,
            encoded_size: 81941,
            codegen_size: 461812,
        },
        old_retaining_algo: Info {
            num_types: 401,
            num_pallets: 1,
            encoded_size: 79667,
            codegen_size: 447431,
        },
    },
    DebugInfo {
        pallets_list: "Nis",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 411,
            num_pallets: 10,
            encoded_size: 87484,
            codegen_size: 452193,
        },
        old_retaining_algo: Info {
            num_types: 411,
            num_pallets: 1,
            encoded_size: 85056,
            codegen_size: 438127,
        },
    },
    DebugInfo {
        pallets_list: "NisCounterpartBalances",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 419,
            num_pallets: 9,
            encoded_size: 84547,
            codegen_size: 488784,
        },
        old_retaining_algo: Info {
            num_types: 419,
            num_pallets: 1,
            encoded_size: 82338,
            codegen_size: 475221,
        },
    },
    DebugInfo {
        pallets_list: "ParachainsOrigin",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 394,
            num_pallets: 13,
            encoded_size: 74389,
            codegen_size: 409047,
        },
        old_retaining_algo: Info {
            num_types: 394,
            num_pallets: 1,
            encoded_size: 71502,
            codegen_size: 389830,
        },
    },
    DebugInfo {
        pallets_list: "Configuration",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 401,
            num_pallets: 11,
            encoded_size: 82178,
            codegen_size: 507561,
        },
        old_retaining_algo: Info {
            num_types: 401,
            num_pallets: 1,
            encoded_size: 79884,
            codegen_size: 492936,
        },
    },
    DebugInfo {
        pallets_list: "ParasShared",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 398,
            num_pallets: 12,
            encoded_size: 74569,
            codegen_size: 411275,
        },
        old_retaining_algo: Info {
            num_types: 398,
            num_pallets: 1,
            encoded_size: 72189,
            codegen_size: 396041,
        },
    },
    DebugInfo {
        pallets_list: "ParaInclusion",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 399,
            num_pallets: 12,
            encoded_size: 77253,
            codegen_size: 422753,
        },
        old_retaining_algo: Info {
            num_types: 399,
            num_pallets: 1,
            encoded_size: 74565,
            codegen_size: 405916,
        },
    },
    DebugInfo {
        pallets_list: "ParaInherent",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 403,
            num_pallets: 11,
            encoded_size: 75833,
            codegen_size: 416278,
        },
        old_retaining_algo: Info {
            num_types: 403,
            num_pallets: 1,
            encoded_size: 73481,
            codegen_size: 400791,
        },
    },
    DebugInfo {
        pallets_list: "ParaScheduler",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 402,
            num_pallets: 13,
            encoded_size: 76002,
            codegen_size: 415314,
        },
        old_retaining_algo: Info {
            num_types: 402,
            num_pallets: 1,
            encoded_size: 73326,
            codegen_size: 397895,
        },
    },
    DebugInfo {
        pallets_list: "Paras",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 409,
            num_pallets: 10,
            encoded_size: 84043,
            codegen_size: 489674,
        },
        old_retaining_algo: Info {
            num_types: 409,
            num_pallets: 1,
            encoded_size: 81928,
            codegen_size: 477328,
        },
    },
    DebugInfo {
        pallets_list: "Initializer",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 397,
            num_pallets: 12,
            encoded_size: 75143,
            codegen_size: 413268,
        },
        old_retaining_algo: Info {
            num_types: 397,
            num_pallets: 1,
            encoded_size: 72846,
            codegen_size: 397237,
        },
    },
    DebugInfo {
        pallets_list: "Dmp",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 395,
            num_pallets: 11,
            encoded_size: 74519,
            codegen_size: 413520,
        },
        old_retaining_algo: Info {
            num_types: 395,
            num_pallets: 1,
            encoded_size: 71919,
            codegen_size: 397515,
        },
    },
    DebugInfo {
        pallets_list: "Hrmp",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 404,
            num_pallets: 10,
            encoded_size: 84211,
            codegen_size: 484166,
        },
        old_retaining_algo: Info {
            num_types: 404,
            num_pallets: 1,
            encoded_size: 82019,
            codegen_size: 470555,
        },
    },
    DebugInfo {
        pallets_list: "ParaSessionInfo",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 395,
            num_pallets: 11,
            encoded_size: 74404,
            codegen_size: 412193,
        },
        old_retaining_algo: Info {
            num_types: 395,
            num_pallets: 1,
            encoded_size: 72062,
            codegen_size: 397981,
        },
    },
    DebugInfo {
        pallets_list: "ParasDisputes",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 401,
            num_pallets: 12,
            encoded_size: 76379,
            codegen_size: 428147,
        },
        old_retaining_algo: Info {
            num_types: 401,
            num_pallets: 1,
            encoded_size: 74108,
            codegen_size: 412914,
        },
    },
    DebugInfo {
        pallets_list: "ParasSlashing",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 398,
            num_pallets: 12,
            encoded_size: 75264,
            codegen_size: 418095,
        },
        old_retaining_algo: Info {
            num_types: 398,
            num_pallets: 1,
            encoded_size: 72576,
            codegen_size: 401262,
        },
    },
    DebugInfo {
        pallets_list: "MessageQueue",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 406,
            num_pallets: 11,
            encoded_size: 79786,
            codegen_size: 435568,
        },
        old_retaining_algo: Info {
            num_types: 406,
            num_pallets: 1,
            encoded_size: 77343,
            codegen_size: 421441,
        },
    },
    DebugInfo {
        pallets_list: "OnDemandAssignmentProvider",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 410,
            num_pallets: 11,
            encoded_size: 78015,
            codegen_size: 435642,
        },
        old_retaining_algo: Info {
            num_types: 410,
            num_pallets: 1,
            encoded_size: 75350,
            codegen_size: 419089,
        },
    },
    DebugInfo {
        pallets_list: "CoretimeAssignmentProvider",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 410,
            num_pallets: 12,
            encoded_size: 75833,
            codegen_size: 419616,
        },
        old_retaining_algo: Info {
            num_types: 410,
            num_pallets: 1,
            encoded_size: 73340,
            codegen_size: 402579,
        },
    },
    DebugInfo {
        pallets_list: "Registrar",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 399,
            num_pallets: 10,
            encoded_size: 80476,
            codegen_size: 451649,
        },
        old_retaining_algo: Info {
            num_types: 399,
            num_pallets: 1,
            encoded_size: 77931,
            codegen_size: 436736,
        },
    },
    DebugInfo {
        pallets_list: "Slots",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 400,
            num_pallets: 11,
            encoded_size: 76992,
            codegen_size: 426605,
        },
        old_retaining_algo: Info {
            num_types: 400,
            num_pallets: 1,
            encoded_size: 74327,
            codegen_size: 410057,
        },
    },
    DebugInfo {
        pallets_list: "Auctions",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 403,
            num_pallets: 11,
            encoded_size: 78797,
            codegen_size: 441003,
        },
        old_retaining_algo: Info {
            num_types: 403,
            num_pallets: 1,
            encoded_size: 76132,
            codegen_size: 424453,
        },
    },
    DebugInfo {
        pallets_list: "Crowdloan",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 404,
            num_pallets: 9,
            encoded_size: 80930,
            codegen_size: 457966,
        },
        old_retaining_algo: Info {
            num_types: 404,
            num_pallets: 1,
            encoded_size: 78656,
            codegen_size: 443593,
        },
    },
    DebugInfo {
        pallets_list: "Coretime",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 402,
            num_pallets: 11,
            encoded_size: 76251,
            codegen_size: 423311,
        },
        old_retaining_algo: Info {
            num_types: 402,
            num_pallets: 1,
            encoded_size: 73892,
            codegen_size: 407866,
        },
    },
    DebugInfo {
        pallets_list: "XcmPallet",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 417,
            num_pallets: 7,
            encoded_size: 98939,
            codegen_size: 559130,
        },
        old_retaining_algo: Info {
            num_types: 417,
            num_pallets: 1,
            encoded_size: 97317,
            codegen_size: 549670,
        },
    },
    DebugInfo {
        pallets_list: "Beefy",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 402,
            num_pallets: 11,
            encoded_size: 79859,
            codegen_size: 443341,
        },
        old_retaining_algo: Info {
            num_types: 402,
            num_pallets: 1,
            encoded_size: 77547,
            codegen_size: 428671,
        },
    },
    DebugInfo {
        pallets_list: "Mmr",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 394,
            num_pallets: 13,
            encoded_size: 74369,
            codegen_size: 411191,
        },
        old_retaining_algo: Info {
            num_types: 394,
            num_pallets: 1,
            encoded_size: 71605,
            codegen_size: 393515,
        },
    },
    DebugInfo {
        pallets_list: "MmrLeaf",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 394,
            num_pallets: 12,
            encoded_size: 74165,
            codegen_size: 407670,
        },
        old_retaining_algo: Info {
            num_types: 394,
            num_pallets: 1,
            encoded_size: 71601,
            codegen_size: 391981,
        },
    },
    DebugInfo {
        pallets_list: "IdentityMigrator",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 396,
            num_pallets: 11,
            encoded_size: 75128,
            codegen_size: 416436,
        },
        old_retaining_algo: Info {
            num_types: 396,
            num_pallets: 1,
            encoded_size: 72396,
            codegen_size: 399132,
        },
    },
    DebugInfo {
        pallets_list: "ParasSudoWrapper",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 397,
            num_pallets: 10,
            encoded_size: 76190,
            codegen_size: 423531,
        },
        old_retaining_algo: Info {
            num_types: 397,
            num_pallets: 1,
            encoded_size: 73740,
            codegen_size: 409225,
        },
    },
    DebugInfo {
        pallets_list: "AssignedSlots",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 400,
            num_pallets: 11,
            encoded_size: 77104,
            codegen_size: 436959,
        },
        old_retaining_algo: Info {
            num_types: 400,
            num_pallets: 1,
            encoded_size: 74683,
            codegen_size: 420984,
        },
    },
    DebugInfo {
        pallets_list: "ValidatorManager",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 397,
            num_pallets: 12,
            encoded_size: 75227,
            codegen_size: 419450,
        },
        old_retaining_algo: Info {
            num_types: 397,
            num_pallets: 1,
            encoded_size: 72408,
            codegen_size: 401297,
        },
    },
    DebugInfo {
        pallets_list: "StateTrieMigration",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 403,
            num_pallets: 10,
            encoded_size: 80409,
            codegen_size: 443344,
        },
        old_retaining_algo: Info {
            num_types: 403,
            num_pallets: 1,
            encoded_size: 77799,
            codegen_size: 427618,
        },
    },
    DebugInfo {
        pallets_list: "RootTesting",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 397,
            num_pallets: 13,
            encoded_size: 74767,
            codegen_size: 415329,
        },
        old_retaining_algo: Info {
            num_types: 397,
            num_pallets: 1,
            encoded_size: 71947,
            codegen_size: 396895,
        },
    },
    DebugInfo {
        pallets_list: "Sudo",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 563,
            num_pallets: 7,
            encoded_size: 231999,
            codegen_size: 700755,
        },
        old_retaining_algo: Info {
            num_types: 398,
            num_pallets: 1,
            encoded_size: 73263,
            codegen_size: 409387,
        },
    },
    DebugInfo {
        pallets_list: "System,Balances,Configuration,XcmPallet,Timestamp",
        default: Info {
            num_types: 942,
            num_pallets: 67,
            encoded_size: 420397,
            codegen_size: 2812530,
        },
        new_retaining_algo: Info {
            num_types: 552,
            num_pallets: 10,
            encoded_size: 172372,
            codegen_size: 936371,
        },
        old_retaining_algo: Info {
            num_types: 472,
            num_pallets: 5,
            encoded_size: 127358,
            codegen_size: 816513,
        },
    },
]

@pkhry pkhry requested a review from a team as a code owner September 18, 2024 16:28
@pkhry pkhry marked this pull request as draft September 18, 2024 16:29
@pkhry pkhry marked this pull request as ready for review September 24, 2024 11:49
@pkhry pkhry changed the title WIP: Strip metadata fix Strip metadata fix Sep 24, 2024
}
}

fn collect_types(&mut self, metadata: &Metadata, t: &PortableType) {
Copy link
Collaborator

@jsdw jsdw Oct 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this logic is basically recursing through all of the types linked from some type and adding them to the set. But this is the same thing that we do in PortableRegistry::retain here https://github.com/paritytech/scale-info/blob/master/src/portable.rs#L104; is it necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, retain is called dead last before updating types, but we need to collect types ourselves to determine which outer type variants are safe to drop/which pallets can be stripped or dropped completetely.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how I feel about this function, because it duplicates the logic in scale_info's retain.

a) On the one hand, we could also remove this function entirely (ie no longer recurse and building this type Ids map when we collect up our pallet/runtime etc types), and instead have a function which has the specific goal of searching through the metadata to look for the runtime types (and in that way, it doesn't need to allocate/collect anything).

b) On the other hand, keeping this function is "easier" because you need to recurse anyway to do the above searching, so maybe you end up with fewer lines of code by just keeping it around.

Personally I'd try (a) and see whether doing so makes things easier to follow or not, but not sure!

Comment on lines 437 to 446
|| !matches!(
pallet,
PalletMetadataInner {
storage: None,
call_ty: None,
event_ty: None,
error_ty: None,
constants: map,
..
} if map.is_empty()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this make any difference? I can't see why a pallet would exist that had nothing meaningful in it, but even if it did, is there any harm in leaving it there?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I am starting to see why this is kept but not understanding it yet; you are turning things to None above in some cases

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

codegen size

@@ -588,7 +584,7 @@ impl<'a> MetadataHasher<'a> {

// Get the hashes of outer enums, considering only `specific_pallets` (if any are set).
// If any of the typed that represent outer enums are encountered later, hashes from `top_level_enum_hashes` can be substituted.
let outer_enum_hashes = OuterEnumHashes::new(metadata, self.specific_pallets.as_deref());
let outer_enum_hashes = OuterEnumHashes::new(metadata);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So here we no logner care about the possibility of the enums like RuntimeCall etc being changed, but how can we avoid caring about this?

(either the variants and all of their types still exist, so the hashes are the same, or we have stripped some types and/or variants and then the hashes owuld be different unless we ignore them, wouldn't they?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

list of pallets/variants types is completely dependant on the given set of pallets for a particular pallet or unpredictable

Copy link
Member

@niklasad1 niklasad1 Oct 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand,

So what happens if Call::Balances(pallet_system::AccountData) variant exist and I only want retain the system pallet, does the Call::Balances get filtered out?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aight, I think this was opinionated and removed variants without checking that it was actually referenced by pallets, runtime apis?

We now only rely on TypeSet::retain_metadata(..) to achieve this

metadata/src/utils/retain.rs Outdated Show resolved Hide resolved
Comment on lines 94 to 119
fn collect_extrinsic_types(&mut self, extrinsic: &ExtrinsicMetadata) {
let mut ids = Vec::from([
extrinsic.address_ty,
extrinsic.call_ty,
extrinsic.signature_ty,
extrinsic.extra_ty,
]);

for signed in &extrinsic.signed_extensions {
ids.push(signed.extra_ty);
ids.push(signed.additional_ty);
}
for id in ids {
self.seen_ids.insert(id);
}
}

if let Some(ty) = pallet.event_ty {
type_ids.insert(ty);
/// Collect all type IDs needed to represent the runtime APIs.
fn collect_runtime_api_types(&mut self, api: &RuntimeApiMetadataInner) {
for method in api.methods.values() {
for input in &method.inputs {
self.seen_ids.insert(input.ty);
}
self.seen_ids.insert(method.output_ty);
}
}
Copy link
Collaborator

@jsdw jsdw Oct 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two functions don't recurse through any sub types. While I don't think anything should, if we did decide we wanted to recurse here then I guess these should, too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pushed a change that does traverse, a few more types added to retained set on average.

Comment on lines 420 to 426
let mut retained_set = TypeSet {
seen_ids: type_set
.seen_ids
.difference(&retained_set.seen_ids)
.copied()
.collect(),
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it looks like you are:

  • building a set of types to keep based on the pallets we want to keep (retained_set)
  • cloning that set and then adding all of the other types we want to keep (runtime APIs etc) too (type_set)
  • taking the difference between those (ie type_set - retained_set? So just the other types without the pallet ones, which we could get by just not cloning above?). This difference is now retained_set.
  • for pallets we want to filter, run update_filtered_pallet, which roughly seems to keep things in the pallet if they reference types we've collected outside of the pallet stuff, and remove things if not. We then only discard pallets if no types that they directly reference are used elsewhere outside of pallets.

I might be wrong, but I don't really understand the reason for doing this? since you collected the outer enums, I can see that the first pallet we see that references those would actually be kept (which I guess has the effect of keeping the variant too?), but it feels like quite a long winded way to go about avoiding getting rid of variants if the outer enums are used somewhere, and I don't know if there is any other benefit :D

I also see that update_filtered_pallet calls retained_set.remove() each time it checks, so only the first pallet referencing eg RuntimeCall would end up having bits kept I think, and other pallets that reference RuntimeCall would be removed. Is that intentional?

Overall, I feel like we can remove a lot of this logic and rely on scale_info::PortableRegistry::retain for the recursive retaining of IDs we care about (because either that works ok already, or doesn't work and should be fixed). Then the logic can be something like:

  • Add all of the type IDs from the pallets etc that we want to keep to a set
  • For any return types or storage types in these things we are keeping, do a deep scan to see if we find the RuntimeCall, RutimeEvent or RuntimeError outer enums. If we find one, we can't strip any variants out of it
  • Now, call PortableRegistry::retain to keep all of the type Ids we need (which will vary depending on whether those enums had variants stripped out of them or not and thus fewer IDs to recurse through).

All of that said though, if there is some value I'm not understanding in the way that we are keeping pallets etc here, then probably I'd need to be walked through it and we'd want to add a comment or two somewhere here to explain the approach and reasoning for it for our future selves :)

Copy link
Contributor Author

@pkhry pkhry Oct 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

taking the difference between those (ie type_set - retained_set? So just the other types without the pallet ones, which we could get by just not cloning above?). This difference is now retained_set.

The difference is the types present in the type_set and absent in retained_set. retained_set is not interesting in this case as types were already present in retained pallet. But i feel like we are talking about the same thing

but it feels like quite a long winded way to go about avoiding getting rid of variants if the outer enums are used somewhere, and I don't know if there is any other benefit :D

Its more about getting rid of pallets and outer enums, but only if they are not referenced anywhere. Its about stripping types that are not interesting to user without accidentally removing something that is required.

I also see that update_filtered_pallet calls retained_set.remove() each time it checks, so only the first pallet referencing eg RuntimeCall would end up having bits kept I think, and other pallets that reference RuntimeCall would be removed. Is that intentional?

I guess i'm misunderstanding something, shouldn't only one pallet with the type be enough or we can safely ignore those refs to runtime call/runtime error/runtime event and remove pallet based purely on storage/constant types? My intuition was to keep them as they might be referencing inner types inside outerenum variant, ie pallet.event_ty = 365 and metadata.outer_enum.event_ty = 22

All of that said though, if there is some value I'm not understanding in the way that we are keeping pallets etc here, then probably I'd need to be walked through it and we'd want to add a comment or two somewhere here to explain the approach and reasoning for it for our future selves :)

as above: My intuition was to keep them as they might be referencing inner types inside outerenum variant, ie pallet.event_ty = 365 and metadata.outer_enum.event_ty = 22

@jsdw
Copy link
Collaborator

jsdw commented Oct 3, 2024

I had a look over and think I'm starting to understand the code more, though I still think that it's more complex than we need (but let's chat tomorrow and look at the code more to confirm).

Essentially, scale_info::PortableRegistry::retain() should already do the recursive retaining stuff, and then the one thing that we do that can cause issues is that we dumbly strip variants from the outer enums without checking if they are returned anywhere. The goal then is to work out whether we can strip the outer enums in this way or whether we need to leave them as is.

So, the approach I'd lean towards with this is more like:

  1. Traverse all of the type IDs we see in the pallets and runtime APIs that we want to keep (not recursively), adding them to a set of IDs we want to keep.
  2. While doing this or as a separate step, do a recursive search over this pallets and runtime APIs — on the pallet errors, events, and storage, and the runtime API return type IDs (hope I'm not missing something!) — to see if we find any of the outer enum IDs. See the example function below for a way to search for outer enum IDs given some starting ID.
  3. For any outer enum IDs still in the set (ie not found), strip them to only contain the pallet variants we are keeping. Add the outer enum IDs to the set of IDs we want to keep.
  4. Call scale_info::PortableReigstry::retain() passing all of the IDs we want to keep. This will handle recursively keeping Ids etc, and will get rid of any now-unneeded IDs if we stripped any enum variants too.
  5. Filter all of the pallets and runtime APIs that we don't want to keep from the metadata (we could do this right at the beginning if we want; we always filter them).

For working out whether some type contains an outer enum, you might end up with a recursive check which is a simplified version of yours, and doesn't need to allocate anything like:

fn find_tys_in_id(id: u32, types: &PortableRegistry, unseen: &mut BTreeSet<u32>) {
    unseen.remove(id)

    let ty = types.resolve(id);
    match ty.type_def {
        TypeDef::Composite(TypeDefComposite { fields }) => {
            for field in fields {
                find_tys_in_id(field.ty.id, types, unseen)
            }
        }
        TypeDef::Variant(TypeDefVariant { variants }) => {
            for variant in variants {
                for field in &variant.fields {
                    find_tys_in_id(field.ty.id, types, unseen)
                }
            }
        }
        TypeDef::Array(TypeDefArray { len: _, type_param })
        | TypeDef::Sequence(TypeDefSequence { type_param })
        | TypeDef::Compact(TypeDefCompact { type_param }) => {
            find_tys_in_id(type_param.id, types, unseen)
        }
        TypeDef::Tuple(TypeDefTuple { fields }) => {
            for field in fields {
                find_tys_in_id(field.id, types, unseen)
            }
        }
        TypeDef::Primitive(_) | TypeDef::BitSequence(_) => {
            // End of recursion.
        }
    }
}

I def think that the existing code can be made clearer w.r.t what steps it takes, and hopefully this extra check to see if we can strip outer enum types handles the edge case we've faced where we strip variants even though we need the fully types to decode something in Subxt.

Note: If the outer enum types are inputs to some runtime API etc, we can still strip them I think. All this means is that users won't be able to express things about pallets that have been stripped when constructing such inputs. Everything should still encode ok.

@pkhry
Copy link
Contributor Author

pkhry commented Oct 9, 2024

I had a look over and think I'm starting to understand the code more, though I still think that it's more complex than we need (but let's chat tomorrow and look at the code more to confirm).

Essentially, scale_info::PortableRegistry::retain() should already do the recursive retaining stuff, and then the one thing that we do that can cause issues is that we dumbly strip variants from the outer enums without checking if they are returned anywhere. The goal then is to work out whether we can strip the outer enums in this way or whether we need to leave them as is.

So, the approach I'd lean towards with this is more like:

  1. Traverse all of the type IDs we see in the pallets and runtime APIs that we want to keep (not recursively), adding them to a set of IDs we want to keep.
  2. While doing this or as a separate step, do a recursive search over this pallets and runtime APIs — on the pallet errors, events, and storage, and the runtime API return type IDs (hope I'm not missing something!) — to see if we find any of the outer enum IDs. See the example function below for a way to search for outer enum IDs given some starting ID.
  3. For any outer enum IDs still in the set (ie not found), strip them to only contain the pallet variants we are keeping. Add the outer enum IDs to the set of IDs we want to keep.
  4. Call scale_info::PortableReigstry::retain() passing all of the IDs we want to keep. This will handle recursively keeping Ids etc, and will get rid of any now-unneeded IDs if we stripped any enum variants too.
  5. Filter all of the pallets and runtime APIs that we don't want to keep from the metadata (we could do this right at the beginning if we want; we always filter them).

For working out whether some type contains an outer enum, you might end up with a recursive check which is a simplified version of yours, and doesn't need to allocate anything like:

fn find_tys_in_id(id: u32, types: &PortableRegistry, unseen: &mut BTreeSet<u32>) {
    unseen.remove(id)

    let ty = types.resolve(id);
    match ty.type_def {
        TypeDef::Composite(TypeDefComposite { fields }) => {
            for field in fields {
                find_tys_in_id(field.ty.id, types, unseen)
            }
        }
        TypeDef::Variant(TypeDefVariant { variants }) => {
            for variant in variants {
                for field in &variant.fields {
                    find_tys_in_id(field.ty.id, types, unseen)
                }
            }
        }
        TypeDef::Array(TypeDefArray { len: _, type_param })
        | TypeDef::Sequence(TypeDefSequence { type_param })
        | TypeDef::Compact(TypeDefCompact { type_param }) => {
            find_tys_in_id(type_param.id, types, unseen)
        }
        TypeDef::Tuple(TypeDefTuple { fields }) => {
            for field in fields {
                find_tys_in_id(field.id, types, unseen)
            }
        }
        TypeDef::Primitive(_) | TypeDef::BitSequence(_) => {
            // End of recursion.
        }
    }
}

I def think that the existing code can be made clearer w.r.t what steps it takes, and hopefully this extra check to see if we can strip outer enum types handles the edge case we've faced where we strip variants even though we need the fully types to decode something in Subxt.

Note: If the outer enum types are inputs to some runtime API etc, we can still strip them I think. All this means is that users won't be able to express things about pallets that have been stripped when constructing such inputs. Everything should still encode ok.

ok, so after fiddling this a bit more i think this suggested approach is the way to go.
With the conditional outerenum variant removal the biggest factor in the amount of types retained is always the runtime_api

click me, wall of text `pallet_filter` - the pallet we want to keep. `name` - approach to traversal that was taken. `count` - amount of types retained in the registry after stripping.

as visible from set below its the runtime_api that plays the biggest whether or not the outer_enums would be stripped down.

Note however that amount of types on average will increase compared to the old approach, e.g. for a dataset of 943 types it will be 644 instead of the 411 in the past.

[
    Collected {
        pallets_filter: "System",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 581,
            },
            Info {
                name: "traverse pallets",
                count: 644,
            },
            Info {
                name: "traverse extrinsics",
                count: 581,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 644,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 644,
            },
        ],
    },
    Collected {
        pallets_filter: "Babe",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 575,
            },
            Info {
                name: "traverse pallets",
                count: 575,
            },
            Info {
                name: "traverse extrinsics",
                count: 575,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 575,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 640,
            },
        ],
    },
    Collected {
        pallets_filter: "Timestamp",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 562,
            },
            Info {
                name: "traverse pallets",
                count: 562,
            },
            Info {
                name: "traverse extrinsics",
                count: 562,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 562,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 627,
            },
        ],
    },
    Collected {
        pallets_filter: "Indices",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 565,
            },
            Info {
                name: "traverse pallets",
                count: 565,
            },
            Info {
                name: "traverse extrinsics",
                count: 565,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 565,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 629,
            },
        ],
    },
    Collected {
        pallets_filter: "Balances",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 584,
            },
            Info {
                name: "traverse pallets",
                count: 584,
            },
            Info {
                name: "traverse extrinsics",
                count: 584,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 584,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 647,
            },
        ],
    },
    Collected {
        pallets_filter: "Parameters",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 570,
            },
            Info {
                name: "traverse pallets",
                count: 570,
            },
            Info {
                name: "traverse extrinsics",
                count: 570,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 570,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 627,
            },
        ],
    },
    Collected {
        pallets_filter: "TransactionPayment",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 564,
            },
            Info {
                name: "traverse pallets",
                count: 564,
            },
            Info {
                name: "traverse extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 628,
            },
        ],
    },
    Collected {
        pallets_filter: "Authorship",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 562,
            },
            Info {
                name: "traverse pallets",
                count: 562,
            },
            Info {
                name: "traverse extrinsics",
                count: 562,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 562,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 627,
            },
        ],
    },
    Collected {
        pallets_filter: "Offences",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 566,
            },
            Info {
                name: "traverse pallets",
                count: 566,
            },
            Info {
                name: "traverse extrinsics",
                count: 566,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 566,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 630,
            },
        ],
    },
    Collected {
        pallets_filter: "Historical",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 563,
            },
            Info {
                name: "traverse pallets",
                count: 563,
            },
            Info {
                name: "traverse extrinsics",
                count: 563,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 563,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 628,
            },
        ],
    },
    Collected {
        pallets_filter: "Session",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 567,
            },
            Info {
                name: "traverse pallets",
                count: 567,
            },
            Info {
                name: "traverse extrinsics",
                count: 567,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 567,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 631,
            },
        ],
    },
    Collected {
        pallets_filter: "Grandpa",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 567,
            },
            Info {
                name: "traverse pallets",
                count: 567,
            },
            Info {
                name: "traverse extrinsics",
                count: 567,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 567,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 631,
            },
        ],
    },
    Collected {
        pallets_filter: "AuthorityDiscovery",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 563,
            },
            Info {
                name: "traverse pallets",
                count: 563,
            },
            Info {
                name: "traverse extrinsics",
                count: 563,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 563,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 628,
            },
        ],
    },
    Collected {
        pallets_filter: "Treasury",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 570,
            },
            Info {
                name: "traverse pallets",
                count: 570,
            },
            Info {
                name: "traverse extrinsics",
                count: 570,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 570,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 634,
            },
        ],
    },
    Collected {
        pallets_filter: "ConvictionVoting",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 576,
            },
            Info {
                name: "traverse pallets",
                count: 576,
            },
            Info {
                name: "traverse extrinsics",
                count: 576,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 576,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 640,
            },
        ],
    },
    Collected {
        pallets_filter: "Referenda",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 582,
            },
            Info {
                name: "traverse pallets",
                count: 582,
            },
            Info {
                name: "traverse extrinsics",
                count: 582,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 582,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 645,
            },
        ],
    },
    Collected {
        pallets_filter: "FellowshipCollective",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 571,
            },
            Info {
                name: "traverse pallets",
                count: 571,
            },
            Info {
                name: "traverse extrinsics",
                count: 571,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 571,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 633,
            },
        ],
    },
    Collected {
        pallets_filter: "FellowshipReferenda",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 581,
            },
            Info {
                name: "traverse pallets",
                count: 581,
            },
            Info {
                name: "traverse extrinsics",
                count: 581,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 581,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 644,
            },
        ],
    },
    Collected {
        pallets_filter: "Origins",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 562,
            },
            Info {
                name: "traverse pallets",
                count: 562,
            },
            Info {
                name: "traverse extrinsics",
                count: 562,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 562,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 627,
            },
        ],
    },
    Collected {
        pallets_filter: "Whitelist",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 564,
            },
            Info {
                name: "traverse pallets",
                count: 564,
            },
            Info {
                name: "traverse extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 628,
            },
        ],
    },
    Collected {
        pallets_filter: "Claims",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 564,
            },
            Info {
                name: "traverse pallets",
                count: 564,
            },
            Info {
                name: "traverse extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 628,
            },
        ],
    },
    Collected {
        pallets_filter: "Utility",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 564,
            },
            Info {
                name: "traverse pallets",
                count: 564,
            },
            Info {
                name: "traverse extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 628,
            },
        ],
    },
    Collected {
        pallets_filter: "Identity",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 579,
            },
            Info {
                name: "traverse pallets",
                count: 579,
            },
            Info {
                name: "traverse extrinsics",
                count: 579,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 579,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 643,
            },
        ],
    },
    Collected {
        pallets_filter: "Society",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 585,
            },
            Info {
                name: "traverse pallets",
                count: 585,
            },
            Info {
                name: "traverse extrinsics",
                count: 585,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 585,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 648,
            },
        ],
    },
    Collected {
        pallets_filter: "Recovery",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 568,
            },
            Info {
                name: "traverse pallets",
                count: 568,
            },
            Info {
                name: "traverse extrinsics",
                count: 568,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 568,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 632,
            },
        ],
    },
    Collected {
        pallets_filter: "Vesting",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 567,
            },
            Info {
                name: "traverse pallets",
                count: 567,
            },
            Info {
                name: "traverse extrinsics",
                count: 567,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 567,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 631,
            },
        ],
    },
    Collected {
        pallets_filter: "Scheduler",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 569,
            },
            Info {
                name: "traverse pallets",
                count: 569,
            },
            Info {
                name: "traverse extrinsics",
                count: 569,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 569,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 633,
            },
        ],
    },
    Collected {
        pallets_filter: "Proxy",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 572,
            },
            Info {
                name: "traverse pallets",
                count: 572,
            },
            Info {
                name: "traverse extrinsics",
                count: 572,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 572,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 636,
            },
        ],
    },
    Collected {
        pallets_filter: "Multisig",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 567,
            },
            Info {
                name: "traverse pallets",
                count: 567,
            },
            Info {
                name: "traverse extrinsics",
                count: 567,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 567,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 631,
            },
        ],
    },
    Collected {
        pallets_filter: "Preimage",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 573,
            },
            Info {
                name: "traverse pallets",
                count: 573,
            },
            Info {
                name: "traverse extrinsics",
                count: 573,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 573,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 637,
            },
        ],
    },
    Collected {
        pallets_filter: "AssetRate",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 564,
            },
            Info {
                name: "traverse pallets",
                count: 564,
            },
            Info {
                name: "traverse extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 628,
            },
        ],
    },
    Collected {
        pallets_filter: "Bounties",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 569,
            },
            Info {
                name: "traverse pallets",
                count: 569,
            },
            Info {
                name: "traverse extrinsics",
                count: 569,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 569,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 633,
            },
        ],
    },
    Collected {
        pallets_filter: "ChildBounties",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 567,
            },
            Info {
                name: "traverse pallets",
                count: 567,
            },
            Info {
                name: "traverse extrinsics",
                count: 567,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 567,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 631,
            },
        ],
    },
    Collected {
        pallets_filter: "Nis",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 576,
            },
            Info {
                name: "traverse pallets",
                count: 576,
            },
            Info {
                name: "traverse extrinsics",
                count: 576,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 576,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 640,
            },
        ],
    },
    Collected {
        pallets_filter: "NisCounterpartBalances",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 584,
            },
            Info {
                name: "traverse pallets",
                count: 584,
            },
            Info {
                name: "traverse extrinsics",
                count: 584,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 584,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 647,
            },
        ],
    },
    Collected {
        pallets_filter: "ParachainsOrigin",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 562,
            },
            Info {
                name: "traverse pallets",
                count: 562,
            },
            Info {
                name: "traverse extrinsics",
                count: 562,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 562,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 627,
            },
        ],
    },
    Collected {
        pallets_filter: "Configuration",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 566,
            },
            Info {
                name: "traverse pallets",
                count: 566,
            },
            Info {
                name: "traverse extrinsics",
                count: 566,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 566,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 631,
            },
        ],
    },
    Collected {
        pallets_filter: "ParasShared",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 565,
            },
            Info {
                name: "traverse pallets",
                count: 565,
            },
            Info {
                name: "traverse extrinsics",
                count: 565,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 565,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 630,
            },
        ],
    },
    Collected {
        pallets_filter: "ParaInclusion",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 566,
            },
            Info {
                name: "traverse pallets",
                count: 566,
            },
            Info {
                name: "traverse extrinsics",
                count: 566,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 566,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 630,
            },
        ],
    },
    Collected {
        pallets_filter: "ParaInherent",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 563,
            },
            Info {
                name: "traverse pallets",
                count: 563,
            },
            Info {
                name: "traverse extrinsics",
                count: 563,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 563,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 628,
            },
        ],
    },
    Collected {
        pallets_filter: "ParaScheduler",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 570,
            },
            Info {
                name: "traverse pallets",
                count: 570,
            },
            Info {
                name: "traverse extrinsics",
                count: 570,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 570,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 635,
            },
        ],
    },
    Collected {
        pallets_filter: "Paras",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 575,
            },
            Info {
                name: "traverse pallets",
                count: 575,
            },
            Info {
                name: "traverse extrinsics",
                count: 575,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 575,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 639,
            },
        ],
    },
    Collected {
        pallets_filter: "Initializer",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 564,
            },
            Info {
                name: "traverse pallets",
                count: 564,
            },
            Info {
                name: "traverse extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 629,
            },
        ],
    },
    Collected {
        pallets_filter: "Dmp",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 562,
            },
            Info {
                name: "traverse pallets",
                count: 562,
            },
            Info {
                name: "traverse extrinsics",
                count: 562,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 562,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 627,
            },
        ],
    },
    Collected {
        pallets_filter: "Hrmp",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 569,
            },
            Info {
                name: "traverse pallets",
                count: 569,
            },
            Info {
                name: "traverse extrinsics",
                count: 569,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 569,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 633,
            },
        ],
    },
    Collected {
        pallets_filter: "ParaSessionInfo",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 562,
            },
            Info {
                name: "traverse pallets",
                count: 562,
            },
            Info {
                name: "traverse extrinsics",
                count: 562,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 562,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 627,
            },
        ],
    },
    Collected {
        pallets_filter: "ParasDisputes",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 568,
            },
            Info {
                name: "traverse pallets",
                count: 568,
            },
            Info {
                name: "traverse extrinsics",
                count: 568,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 568,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 630,
            },
        ],
    },
    Collected {
        pallets_filter: "ParasSlashing",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 564,
            },
            Info {
                name: "traverse pallets",
                count: 564,
            },
            Info {
                name: "traverse extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 629,
            },
        ],
    },
    Collected {
        pallets_filter: "MessageQueue",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 571,
            },
            Info {
                name: "traverse pallets",
                count: 571,
            },
            Info {
                name: "traverse extrinsics",
                count: 571,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 571,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 634,
            },
        ],
    },
    Collected {
        pallets_filter: "OnDemandAssignmentProvider",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 576,
            },
            Info {
                name: "traverse pallets",
                count: 576,
            },
            Info {
                name: "traverse extrinsics",
                count: 576,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 576,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 640,
            },
        ],
    },
    Collected {
        pallets_filter: "CoretimeAssignmentProvider",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 573,
            },
            Info {
                name: "traverse pallets",
                count: 573,
            },
            Info {
                name: "traverse extrinsics",
                count: 573,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 573,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 638,
            },
        ],
    },
    Collected {
        pallets_filter: "Registrar",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 566,
            },
            Info {
                name: "traverse pallets",
                count: 566,
            },
            Info {
                name: "traverse extrinsics",
                count: 566,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 566,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 630,
            },
        ],
    },
    Collected {
        pallets_filter: "Slots",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 567,
            },
            Info {
                name: "traverse pallets",
                count: 567,
            },
            Info {
                name: "traverse extrinsics",
                count: 567,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 567,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 631,
            },
        ],
    },
    Collected {
        pallets_filter: "Auctions",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 568,
            },
            Info {
                name: "traverse pallets",
                count: 568,
            },
            Info {
                name: "traverse extrinsics",
                count: 568,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 568,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 632,
            },
        ],
    },
    Collected {
        pallets_filter: "Crowdloan",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 567,
            },
            Info {
                name: "traverse pallets",
                count: 567,
            },
            Info {
                name: "traverse extrinsics",
                count: 567,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 567,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 631,
            },
        ],
    },
    Collected {
        pallets_filter: "Coretime",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 564,
            },
            Info {
                name: "traverse pallets",
                count: 564,
            },
            Info {
                name: "traverse extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 628,
            },
        ],
    },
    Collected {
        pallets_filter: "XcmPallet",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 583,
            },
            Info {
                name: "traverse pallets",
                count: 583,
            },
            Info {
                name: "traverse extrinsics",
                count: 583,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 583,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 647,
            },
        ],
    },
    Collected {
        pallets_filter: "Beefy",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 564,
            },
            Info {
                name: "traverse pallets",
                count: 564,
            },
            Info {
                name: "traverse extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 629,
            },
        ],
    },
    Collected {
        pallets_filter: "Mmr",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 562,
            },
            Info {
                name: "traverse pallets",
                count: 562,
            },
            Info {
                name: "traverse extrinsics",
                count: 562,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 562,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 627,
            },
        ],
    },
    Collected {
        pallets_filter: "MmrLeaf",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 562,
            },
            Info {
                name: "traverse pallets",
                count: 562,
            },
            Info {
                name: "traverse extrinsics",
                count: 562,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 562,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 627,
            },
        ],
    },
    Collected {
        pallets_filter: "IdentityMigrator",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 563,
            },
            Info {
                name: "traverse pallets",
                count: 563,
            },
            Info {
                name: "traverse extrinsics",
                count: 563,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 563,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 627,
            },
        ],
    },
    Collected {
        pallets_filter: "ParasSudoWrapper",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 563,
            },
            Info {
                name: "traverse pallets",
                count: 563,
            },
            Info {
                name: "traverse extrinsics",
                count: 563,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 563,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 628,
            },
        ],
    },
    Collected {
        pallets_filter: "AssignedSlots",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 565,
            },
            Info {
                name: "traverse pallets",
                count: 565,
            },
            Info {
                name: "traverse extrinsics",
                count: 565,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 565,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 629,
            },
        ],
    },
    Collected {
        pallets_filter: "ValidatorManager",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 563,
            },
            Info {
                name: "traverse pallets",
                count: 563,
            },
            Info {
                name: "traverse extrinsics",
                count: 563,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 563,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 627,
            },
        ],
    },
    Collected {
        pallets_filter: "StateTrieMigration",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 565,
            },
            Info {
                name: "traverse pallets",
                count: 565,
            },
            Info {
                name: "traverse extrinsics",
                count: 565,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 565,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 627,
            },
        ],
    },
    Collected {
        pallets_filter: "RootTesting",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 563,
            },
            Info {
                name: "traverse pallets",
                count: 563,
            },
            Info {
                name: "traverse extrinsics",
                count: 563,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 563,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 627,
            },
        ],
    },
    Collected {
        pallets_filter: "Sudo",
        results: [
            Info {
                name: "no stripping",
                count: 943,
            },
            Info {
                name: "no deep traversal",
                count: 564,
            },
            Info {
                name: "traverse pallets",
                count: 564,
            },
            Info {
                name: "traverse extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets & extrinsics",
                count: 564,
            },
            Info {
                name: "traverse pallets, extrinsics & runtime",
                count: 628,
            },
        ],
    },
]

@@ -214,7 +214,10 @@ impl Metadata {
MetadataHasher::new(self)
}

/// Filter out any pallets that we don't want to keep, retaining only those that we do.
/// Filter out any pallets and/or runtime_apis that we don't want to keep, retaining only those that we do.
/// Note:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather create a dev-note using // to avoid this to end-up in the API docs

/// Filter out any pallets that we don't want to keep, retaining only those that we do.
/// Filter out any pallets and/or runtime_apis that we don't want to keep, retaining only those that we do.
/// Note:
/// without also filtering out irrelevant runtime_api's in addition to pallets one should not expect significant metadata size reduction.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// without also filtering out irrelevant runtime_api's in addition to pallets one should not expect significant metadata size reduction.
/// runtime api filtering will not lead to significant metadata size reduction because the return types are kept to ensure that those can be decoded.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

runtimeApi filtering will lead to significant metadata size reductions.
If a runtimeApi returns an outerEnum type we no longer can strip the enum, because we don't know which variants are used.

/// Filter out any pallets and/or runtime_apis that we don't want to keep, retaining only those that we do.
/// Note:
/// without also filtering out irrelevant runtime_api's in addition to pallets one should not expect significant metadata size reduction.
/// This happens because we will keep the types returned by runtime_api methods to guarantee that we can safely decode them.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need to keep the return types if those are not used/trimmed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can never know if they are used fully or partially, therefore we always keep the full type

metadata/src/lib.rs Outdated Show resolved Hide resolved
match entry.entry_type {
StorageEntryType::Plain(ty) => {
type_ids.insert(ty);
use alloc::collections::{BTreeMap, BTreeSet, VecDeque};
Copy link
Member

@niklasad1 niklasad1 Oct 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mind document the algorithm we use to filter out pallets/runtime APIs as top-level docs in this module?
Such as the tree/types, outer enums etc are traversed and in which order...

// test that the hashes are the same:
let hash = MetadataHasher::new(&metadata)
.only_these_pallets(&["First"])
.only_these_pallets(&name_set)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we can revert this to "First" now to simplify?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed the test completetely as the behaviour in OuterEnumHashes relied on the fact that some of the variants in outernums are removed unconditionally.

Comment on lines +440 to +445
{
let set = "Balances,Timestamp,Contracts,ContractsEvm,System"
.split(",")
.collect::<BTreeSet<&str>>();
move |s| set.contains(&s)
},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd simplify this to just |s| ["Balances","Timestamp","Contracts","ContractsEVM","System"].contains(s); no need for the set etc really (and with so few items it's prob not even slower anyways, but being a test it's not a big deal)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i written it like this only because repro command is a string and i was lazy to type


#[test]
fn issue_1659() {
let metadata_cache = load_metadata("../artifacts/regressions/1659.scale");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: rename to full_metadata?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which full_metadata? maybe we can name it 1659.full_metadata.scale?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I wasn't clear at all! I meant to rename metadata_cache to full_metadata :)

}
}

#[test]
fn retain_one_runtime_api() {
let metadata_cache = load_metadata();
let metadata_cache = load_metadata_polkadot();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I'd call this just metadata too (not really this PR but hey :))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renamed load_metadata_polkadot to load_metadata and introduced load_metadata_custom to load different files

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I wasn't clear at all there! I was referring to the variable metadata_cache; it's not really a cache or anything ,it is just the metadata :)

@pkhry pkhry requested a review from jsdw October 15, 2024 09:50
@jsdw
Copy link
Collaborator

jsdw commented Oct 15, 2024

One of the things that was bugging me a bit in this code prior to this PR is that we have separate collect_x and update_x functions, and we need to ensure that the logic for finding each type Id is identical across them.

Something that I find a bit hard to do still in this PR is following exactly the steps that we take to strip types. I think this was also a bit messy before the PR too.

Anyway, I got to wondering whether something like the following would be ultimately much clearer and easier to follow, while avoiding duplicating the logc around collect vs update:

pub fn retain_metadata<F, G>(
    metadata: &mut Metadata,
    mut pallets_filter: F,
    mut runtime_apis_filter: G,
) where
    F: FnMut(&str) -> bool,
    G: FnMut(&str) -> bool,
{
    // 1. Delete pallets we don't want to keep.
    metadata.pallets.retain(|pallet| pallets_filter(&pallet.name));
    metadata.pallets_by_index = metadata
        .pallets
        .values()
        .iter()
        .enumerate()
        .map(|(pos, p)| (p.index, pos))
        .collect();

    // 2. Delete runtime APIs we don't want to keep.
    metadata.apis.retain(|api| runtime_apis_filter(&api.name));

    // 3. For each outer enum type, strip it if possible, ie if it is not returned by any
    // of the things we're keeping (because if it is, we need to keep all of it so that we
    // can still decode values into it).
    let outer_enums = metadata.outer_enums();
    for outer_enum_ty_id in [outer_enums.call_enum_ty(), outer_enums.error_enum_ty(), outer_enums.event_enum_ty()] {
        if !find_type_id_in_return_pos(metadata, outer_enum_ty_id) {
            retain_variants_in_enum_type(metadata, &pallets_filter); 
            // ^ prob clearer renamed to "strip_variants_in_enum_type"
        }
    }

    // 4. Collect all of the type IDs we still want to keep after deleting.
    let mut keep_these_type_ids: BTreeSet<u32> = iterate_metadata_types(metadata).map(|id| *id).collect();

    // 5. Additionally, subxt depends on the `DispatchError` type existing; we use the same
    // logic here that is used when building our `Metadata` to ensure we keep it too.
    let dispatch_error_ty = metadata
        .types
        .types
        .iter()
        .find(|ty| ty.ty.path.segments == ["sp_runtime", "DispatchError"])
        .expect("Metadata must contain sp_runtime::DispatchError");
    keep_these_type_ids.insert(dispatch_error_ty.id);

    // 5. Strip all of the type IDs we no longer need, based on the above set.
    let map_ids = metadata.types.retain(|id| keep_these_type_ids.contains(&id));

    // 6. Now, update the type IDs referenced in our metadata to reflect this.
    for id in iterate_metadata_types(metadata) {
        if let Some(new_id) = map_ids.get(id) {
            *id = *new_id;
        } else {
            panic!("Type id {id} was not retained. This is a bug");
        }
    }
}

/// return an iterator handing back a mutable reference to each type ID seen in the metadata (not recursively).
/// This will iterate over every type referenced in the metadata outside of `metadata.types`.
fn iterate_metadata_types(metadata: &mut Metadata) -> impl Iterator<Item = &mut u32> {
    unimplemented!()
}

/// Look for a type ID anywhere that we can be given back, ie in constants, storage or runtime API return types.
/// This will recurse deeply into those type IDs to find them (but doesn't need to allocate).
fn find_type_id_in_return_pos(metadata: &mut Metadata, type_id: u32) -> bool {
    unimplemented!()
}

I think this would be something like my "north star" for a readable and hopefullyfairly easy to follow implementation of stripping pallets/runtime APIs.

That all said, I think we can aim to get this PR merged and havea go as a follow up step to do something like this.

metadata/src/lib.rs Outdated Show resolved Hide resolved
@pkhry pkhry requested a review from jsdw October 15, 2024 10:45
@pkhry pkhry requested a review from jsdw October 17, 2024 14:17

/// return an Vec handing back a mutable reference to each type ID seen in the metadata (not recursively).
/// This will iterate over every type referenced in the metadata outside of `metadata.types`.
fn iterate_metadata_types(metadata: &mut Metadata) -> alloc::vec::Vec<&mut u32> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good for now, as actually iterating is much more ocmplicated and requires you to keep an internal state machine etc!

One thing I'd be tempted to do, since it's called iterate_metadata_types and only needed for iterating is to change the return type to -> impl Iterator<Item=&mut u32> and then call types.into_iter() at the end ofthe body to make that work.

(That way we can also optimise. the internals at some point without caring about anything else)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

metadata/src/utils/retain.rs Outdated Show resolved Hide resolved
@pkhry pkhry requested a review from jsdw October 21, 2024 11:21

/// Look for a type ID anywhere that we can be given back, ie in constants, storage, extrinsics or runtime API return types.
/// This will recurse deeply into those type IDs to find them.
pub fn collect_return_types<F, G>(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: rename to something like keep_outer_enum_type (because it's specifically handing back a function for that)?

Also all of the TypeSet stuff above is only used in here now I think? Personally I'd prob move the functions from there into here so we end up with something like:

fn collect_return_types(..) {
    fn collect_types_recursively(&mut set: BTreeSet, metadata, id) {
        // TypeSet::collect_types impl
    }
    fn collect_extrinsic_types(&mut set: BTreeSet, extrinsic) {
        // TypeSet::collect_extrinsic_types impl
    }
    // same for collect_runtime_api_types and collect_pallet_types

    // Gather all of the types that could contain an outer enum:
    let mut types = BTreeSet::new();
    for pallet in metadata.pallets.values() {
        if pallets_filter(&pallet.name) {
            collect_pallet_types(&mut types, pallet, metadata);
        }
    }
    for api in metadata.apis.values() {
        if runtime_apis_filter(&api.name) {
            collect_runtime_api_types(&mut types, metadata, api);
        }
    }
    type_set.collect_extrinsic_types(&mut types, &metadata.extrinsic);
    
    // Return a function to check whether some outer enum type is seen
    move |type_id| types.contains(type_id)
}

Bit "messier" but it hides all of the "internal" logic of how we do it away behind your nice function signature, and thus lets us tweak it in the future without any fear that anything else will break.

Copy link
Collaborator

@jsdw jsdw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me; nice one!

I left just a couple of small comments which I think will make it a touch easier to modify in the future :)

fn new() -> Self {
Self {
seen_ids: BTreeSet::new(),
work_set: VecDeque::with_capacity(22),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why 22?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No particular reason besides that the biggest struct I've seen in the wild had ~20 fields

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth a comment about this perhaps!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, would be good with a comment because I will ask the same everytime I see that :D

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a comment, also simplified a bit to keep workset size smaller, now its usually around 30-50 elements

Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com>

/// Returns an iterator that allows modifying each type ID seen in the metadata (not recursively).
/// This will iterate over every type referenced in the metadata outside of `metadata.types`.
fn iterate_metadata_types(metadata: &mut Metadata) -> impl Iterator<Item = &mut u32> {
Copy link
Member

@niklasad1 niklasad1 Oct 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether we can name this function to something better to explain that you get a mutable iterator to modify the metadata.

What I can come up with is iter_mut(&mut Metadata), metadata_types_iter_mut(&mut Metadata) 🤷

Copy link
Member

@niklasad1 niklasad1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, I appreciate the extra comments in the code which makes easier for me to follow

@pkhry pkhry merged commit ae0fce8 into master Oct 21, 2024
13 checks passed
@pkhry pkhry deleted the pkhry/metadata_stripping branch October 21, 2024 20:41
@jsdw jsdw mentioned this pull request Oct 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants