From 5f017216d996aaed4be7a8535c91b1e0003bd0b3 Mon Sep 17 00:00:00 2001 From: bkchr Date: Thu, 7 Mar 2024 00:39:50 +0000 Subject: [PATCH] deploy: 99e179cbc1432b7a3655d40b940cbdde92ed016d --- print.html | 65 ++++++++++++-------------- proposed/0078-merkleized-metadata.html | 65 ++++++++++++-------------- searchindex.js | 2 +- searchindex.json | 2 +- 4 files changed, 62 insertions(+), 72 deletions(-) diff --git a/print.html b/print.html index 54a1c27..c871a1f 100644 --- a/print.html +++ b/print.html @@ -2485,7 +2485,7 @@ Implement call filters. This will allow multisig accounts to only accept certain

The FRAME metadata provides a wide range of information about a FRAME based runtime. It contains information about the pallets, the calls per pallet, the storage entries per pallet, runtime APIs, and type information about most of the types that are used in the runtime. For decoding extrinsics on an offline wallet, what is mainly required is type information. Most of the other information in the FRAME metadata is actually not required for decoding extrinsics and thus it can be removed. Therefore, the following is a proposal on a custom representation of the metadata and how this custom metadata is chunked, ensuring that only the needed chunks required for decoding a particular extrinsic are sent to the offline wallet. The necessary information to transform the FRAME metadata type information into the type information presented in this RFC will be provided. However, not every single detail on how to convert from FRAME metadata into the RFC type information is described.

First, the MetadataDigest is introduced. After that, ExtrinsicMetadata is covered and finally the actual format of the type information. Then pruning of unrelated type information is covered and how to generate the TypeRefs. In the latest step, merkle tree calculation is explained.

Metadata digest

-

The metadata digest is the compact representation of the metadata. The hash of this digest is the metadata hash. Below the type declaration of the Hash type and the MetadatDigest itself can be found:

+

The metadata digest is the compact representation of the metadata. The hash of this digest is the metadata hash. Below the type declaration of the Hash type and the MetadataDigest itself can be found:

#![allow(unused)]
 fn main() {
 type Hash = [u8; 32];
@@ -2506,11 +2506,11 @@ enum MetadataDigest {
 

The Hash is 32 bytes long and blake3 is used for calculating it. The hash of the MetadataDigest is calculated by blake3(SCALE(MetadataDigest)). Therefore, MetadataDigest is at first SCALE encoded, and then those bytes are hashed.

The MetadataDigest itself is represented as an enum. This is done to make it future proof, because a SCALE encoded enum is prefixed by the index of the variant. This index represents the version of the digest. As seen above, there is no index zero and it starts directly with one. Version one of the digest contains the following elements:

    -
  • type_information_tree_root: The root of the Merkleized type information tree.
  • -
  • extrinsic_metadata_hash: The hash of the Extrinsic metadata.
  • +
  • type_information_tree_root: The root of the merkleized type information tree.
  • +
  • extrinsic_metadata_hash: The hash of the extrinsic metadata.
  • spec_version: The spec_version of the runtime as found in the RuntimeVersion when generating the metadata. While this information can also be found in the metadata, it is hidden in a big blob of data. To avoid transferring this big blob of data, we directly add this information here.
  • spec_name: Similar to spec_version, but being the spec_name found in the RuntimeVersion.
  • -
  • base58_prefix: The base58 prefix used for addresses.
  • +
  • ss58_prefix: The SS58 prefix used for address encoding.
  • decimals: The number of decimals for the token.
  • token_symbol: The symbol of the token.
@@ -2532,7 +2532,7 @@ struct SignedExtensionMetadata { included_in_signed_data: TypeRef, } }
-

To begin with, TypeRef. This is a unique identifier for a type as found in the type information. Using this TypeRef, it is possible to look up the type in the type information tree. More details on this process can be found in the section Merkleizing type information.

+

To begin with, TypeRef. This is a unique identifier for a type as found in the type information. Using this TypeRef, it is possible to look up the type in the type information tree. More details on this process can be found in the section Generating TypeRef.

The actual ExtrinsicMetadata contains the following information:

-

Every Type is composed of multiple different types. Each of these "sub types" can reference either a full Type again or reference one of the primitive types. This is where TypeRef comes into play as the type referencing information. To reference a Type in the type information a unique identifier is used. As primitive types can be represented using a single byte, they are not put as separate types into the type information. Instead the primitive types are directly part of TypeRef to not require the overhead of referencing them in an extra Type. The special primitive type Void represents a type that encodes to nothing and can be decoded from nothing. As FRAME doesn't support Compact as primitive type it requires a little bit more involved implementation to convert a FRAME type to a Compact primitive type. SCALE only supports u8, u16, u32, u64 and u128 as Compact which maps onto the primitive type declaration in the RFC. One special case is a Compact that wraps an empty Tuple which is expressed as primitive type Void.

+

Every Type is composed of multiple different types. Each of these "sub types" can reference either a full Type again or reference one of the primitive types. This is where TypeRef becomes relevant as the type referencing information. To reference a Type in the type information, a unique identifier is used. As primitive types can be represented using a single byte, they are not put as separate types into the type information. Instead the primitive types are directly part of TypeRef to not require the overhead of referencing them in an extra Type. The special primitive type Void represents a type that encodes to nothing and can be decoded from nothing. As FRAME doesn't support Compact as primitive type it requires a more involved implementation to convert a FRAME type to a Compact primitive type. SCALE only supports u8, u16, u32, u64 and u128 as Compact which maps onto the primitive type declaration in the RFC. One special case is a Compact that wraps an empty Tuple which is expressed as primitive type Void.

The TypeDef variants have the following meaning: