Skip to content

Latest commit

 

History

History
231 lines (155 loc) · 10.6 KB

id-extrinsics.md

File metadata and controls

231 lines (155 loc) · 10.6 KB
title
-chap-num- Extrinsics

import Pseudocode from '@site/src/components/Pseudocode'; import encodeMortality from '!!raw-loader!@site/src/algorithms/encodeMortality.tex'; import decodeMortality from '!!raw-loader!@site/src/algorithms/decodeMortality.tex';

-sec-num- Introduction {#id-introduction-5}

An extrinsic is a SCALE encoded array consisting of a version number, signature, and varying data types indicating the resulting Runtime function to be called, including the parameters required for that function to be executed.

-sec-num- Preliminaries {#id-preliminaries-3}

Definition -def-num- Extrinsic {#defn-extrinsic}

:::definition

An extrinsic , ${t}{x}$, is a tuple consisting of the extrinsic version, ${T}{{v}}$ (Definition -def-num-ref-), and the body of the extrinsic, ${T}{{b}}$.

$$ {t}{x}:={\left({T}{{v}},{T}{{b}}\right)} $$

The value of ${T}_{{b}}$ varies for each version. The current version 4 is described in Section -sec-num-ref-.

:::

Definition -def-num- Extrinsic Version {#defn-extrinsic-version}

:::definition

${T}{{v}}$ is a 8-bit bitfield and defines the extrinsic version. The required format of an extrinsic body, ${T}{{b}}$, is dictated by the Runtime. Older or unsupported versions are rejected.

The most significant bit of ${T}{{v}}$ indicates whether the transaction is signed (${1}$) or unsigned (${0}$). The remaining 7-bits represent the version number. As an example, for extrinsic format version 4, a signed extrinsic represents ${T}{{v}}$ as 132 while an unsigned extrinsic represents it as 4.

:::

-sec-num- Extrinsics Body {#id-extrinsics-body}

-sec-num- Version 4 {#sect-version-four}

Version 4 of the Polkadot extrinsic format is defined as follows:

$$ {T}{{b}}:={\left({A}{{i}},{Sig},{E},{M}{{i}},{F}{{i}}{\left({m}\right)}\right)} $$

where

Definition -def-num- Extrinsic Address {#defn-extrinsic-address}

:::definition

Account Id, ${A}_{{i}}$, is the 32-byte address of the sender of the extrinsic as described in the external SS58 address format.

:::

Definition -def-num- Extrinsic Signature {#defn-extrinsic-signature}

:::definition

The signature, ${Sig}$, is a varying data type indicating the used signature type, followed by the signature created by the extrinsic author. The following types are supported:

$$ Sig := \begin{cases} 0, & \text{Ed25519, followed by: } (b_0, \ldots,b_{63}) \\ 1, & \text{Sr25519, followed by: } (b_0, \ldots,b_{63}) \\ 2, & \text{Ecdsa, followed by: } (b_0, \ldots,b_{64}) \end{cases} $$

Signature types vary in size, but each individual type is always fixed-size and therefore does not contain a length prefix. Ed25519 and Sr25519 signatures are 512-bit while Ecdsa is 520-bit, where the last 8 bits are the recovery ID.

The signature is created by signing payload ${P}$.

$$ \begin{aligned} P &:= \begin{cases} Raw, & \text{if } |Raw| \leq 256 \\ \text{Blake2}(Raw), & \text{if } |Raw| > 256 \\ \end{cases} \\ Raw &:= (M_i, F_i(m), E, R_v, F_v, H_h(G), H_h(B)) \end{aligned} $$

where

  • ${M}_{{i}}$: the module indicator (Definition -def-num-ref-).

  • ${F}_{{i}}{\left({m}\right)}$: the function indicator of the module (Definition -def-num-ref-).

  • ${E}$: the extra data (Definition -def-num-ref-).

  • ${R}_{{v}}$: a UINT32 containing the specification version (spec_version) of the Runtime (Section -sec-num-ref-), which can be updated and is therefore subject to change.

  • ${F}_{{v}}$: a UINT32 containing the transaction version (transaction_version) of the Runtime (Section -sec-num-ref-), which can be updated and is therefore subject to change.

  • ${H}_{{h}}{\left({G}\right)}$: a 32-byte array containing the genesis hash.

  • ${H}_{{h}}{\left({B}\right)}$: a 32-byte array containing the hash of the block which starts the mortality period, as described in Definition -def-num-ref-.

:::

Definition -def-num- Extra Data {#defn-extra-data}

:::definition

Extra data, ${E}$, is a tuple containing additional metadata about the extrinsic and the system it is meant to be executed in.

$$ {E}:={\left({T}{mor},{N},{P}{{t}}\right)} $$

where

  • ${T}_{mor}$: contains the SCALE encoded mortality of the extrinsic (Definition -def-num-ref-).

  • ${N}$: a compact integer containing the nonce of the sender. The nonce must be incremented by one for each extrinsic created, otherwise, the Polkadot network will reject the extrinsic.

  • ${P}_{{t}}$: a compact integer containing the transactor pay including tip.

:::

Definition -def-num- Module Indicator {#defn-module-indicator}

:::definition

${M}_{{i}}$ is an indicator for the Runtime to which Polkadot module, ${m}$, the extrinsic should be forwarded to.

${M}_{{i}}$ is a varying data type pointing to every module exposed to the network.

$$ M_i := \begin{cases} 0, & \text{System} \\ 1, & \text{Utility} \\ \ldots & \\ 7, & \text{Balances} \\ \ldots & \end{cases} $$

:::

Definition -def-num- Function Indicator {#defn-function-indicator}

:::definition

${F}{{i}}{\left({m}\right)}$ is a tuple which contains an indicator, ${m}{{i}}$, for the Runtime to which function within the Polkadot module, ${m}$, the extrinsic should be forwarded to. This indicator is followed by the concatenated and SCALE encoded parameters of the corresponding function, ${p}{a}{r}{a}{m}{s}$.

$$ {F}{{i}}{\left({m}\right)}:={\left({m}{{i}},{p}{a}{r}{a}{m}{s}\right)} $$

The value of ${m}_{{i}}$ varies for each Polkadot module since every module offers different functions. As an example, the Balances module has the following functions:

$$ Balances_i := \begin{cases} 0, & \text{transfer} \\ 1, & \text{set_balance} \\ 2, & \text{force_transfer} \\ 3, & \text{transfer_keep_alive} \\ \ldots & \end{cases} $$

:::

-sec-num- Mortality {#id-mortality}

Definition -def-num- Extrinsic Mortality {#defn-extrinsic-mortality}

:::definition

Extrinsic mortality is a mechanism which ensures that an extrinsic is only valid within a certain period of the ongoing Polkadot lifetime. Extrinsics can also be immortal, as clarified in Section -sec-num-ref-.

The mortality mechanism works with two related values:

  • ${M}{{{per}}}$: the period of validity in terms of block numbers from the block hash specified as ${H}{{h}}{\left({B}\right)}$ in the payload (Definition -def-num-ref-). The requirement is ${M}{{{per}}}\geq{4}$ and ${M}{{{per}}}$ must be the power of two, such as 32, 64, 128, etc.

  • ${M}{{{pha}}}$: the phase in the period that this extrinsic’s lifetime begins. This value is calculated with a formula, and validators can use this value in order to determine which block hash is included in the payload. The requirement is ${M}{{{pha}}}<{M}_{{{per}}}$.

In order to tie a transaction’s lifetime to a certain block (${H}{{i}}{\left({B}\right)}$) after it was issued, without wasting precious space for block hashes, block numbers are divided into regular periods and the lifetime is instead expressed as a "phase" (${M}{{{pha}}}$) from these regular boundaries:

$$ {M}{pha}={H}{{i}}{\left({B}\right)} ; mod ; {M}_{{{per}}} $$

${M}{{{per}}}$ and ${M}{{{pha}}}$ are then included in the extrinsic, as clarified in Definition -def-num-ref-, in the SCALE encoded form of ${T}{mor}$ (Section -sec-num-ref-). Polkadot validators can use ${M}{{{pha}}}$ to figure out the block hash included in the payload, which will therefore result in a valid signature if the extrinsic is within the specified period or an invalid signature if the extrinsic "died".

:::

-sec-num- Example {#id-example}

The extrinsic author choses ${M}{{{per}}}={256}$ at block 10'000, resulting with ${M}{{{pha}}}={16}$. The extrinsic is then valid for blocks ranging from 10'000 to 10'256.

-sec-num- Encoding {#sect-mortality-encoding}

${T}{mor}$ refers to the SCALE encoded form of type ${M}{{{per}}}$ and ${M}{{{pha}}}$. ${T}{mor}$ is the size of two bytes if the extrinsic is considered mortal, or simply one bytes with a value equal to zero if the extrinsic is considered immortal.

$$ {T}{mor}:={E}{n}{c}{{{S}{C}}}{\left({M}{{{per}}},{M}{{{pha}}}\right)} $$

The SCALE encoded representation of mortality ${T}_{mor}$ deviates from most other types, as it’s specialized to be the smallest possible value, as described in Encode Mortality and Decode Mortality.

If the extrinsic is immortal, specify a single byte with a value equal to zero.

:::algorithm

Algorithm -algo-num- Encode Mortality {#algo-mortality-encode}

<Pseudocode content={encodeMortality} algID="encodeMortality" options={{ "lineNumber": true }} />

Algorithm -algo-num- Decode Mortality {#algo-mortality-decode}

<Pseudocode content={decodeMortality} algID="decodeMortality" options={{ "lineNumber": true }} />

where

  • ${T}^{{{b}{0}}}{\left\lbrace{mor}\right\rbrace}$: the first byte of ${T}{mor}$.

  • ${T}^{{{b}{1}}}{\left\lbrace{mor}\right\rbrace}$: the second byte of ${T}{mor}$.

  • Limit(${num}$, ${min}$, ${max}$): Ensures that ${num}$ is between ${min}$ and ${max}$. If ${min}$ or ${max}$ is defined as $\phi$, then there is no requirement for the specified minimum/maximum.

  • TZ(${num}$): returns the number of trailing zeros in the binary representation of ${num}$. For example, the binary representation of 40 is 0010 1000, which has three trailing zeros.

  • $\gg$: performs a binary right shift operation.

  • $\ll$: performs a binary left shift operation.

  • ${\mid}$ : performs a bitwise OR operation. :::