Skip to main content

9. Extrinsics

9.1. Introduction

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.

9.2. Preliminaries

Definition 142. Extrinsic

An extrinsic , tx{t}{x}, is a tuple consisting of the extrinsic version, Tv{T}_{{v}} (Definition 143), and the body of the extrinsic, Tb{T}_{{b}}.

tx=(Tv,Tb){t}{x}\:={\left({T}_{{v}},{T}_{{b}}\right)}

The value of Tb{T}_{{b}} varies for each version. The current version 4 is described in Section 9.3.1..

Definition 143. Extrinsic Version

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

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

9.3. Extrinsics Body

9.3.1. Version 4

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

Tb=(Ai,Sig,E,Mi,Fi(m)){T}_{{b}}\:={\left({A}_{{i}},{Sig},{E},{M}_{{i}},{F}_{{i}}{\left({m}\right)}\right)}

where

  • Ai{A}_{{i}}: the 32-byte address of the sender (Definition 144).

  • Sig{Sig}: the signature of the sender (Definition 145).

  • E{E}: the extra data for the extrinsic (Definition 146).

  • Mi{M}_{{i}}: the indicator of the Polkadot module (Definition 147).

  • Fi(m){F}_{{i}}{\left({m}\right)}: the indicator of the function of the Polkadot module (Definition 148).

Definition 144. Extrinsic Address

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

Definition 145. Extrinsic Signature

The signature, Sig{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:={0,Ed25519, followed by: (b0,,b63)1,Sr25519, followed by: (b0,,b63)2,Ecdsa, followed by: (b0,,b64)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 sizes, 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{P}.

P:={Raw,if Raw256Blake2(Raw),if Raw>256Raw:=(Mi,Fi(m),E,Rv,Fv,Hh(G),Hh(B))\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

  • Mi{M}_{{i}}: the module indicator (Definition 147).

  • Fi(m){F}_{{i}}{\left({m}\right)}: the function indicator of the module (Definition 148).

  • E{E}: the extra data (Definition 146).

  • Rv{R}_{{v}}: a UINT32 containing the specification version (spec_version) of the Runtime (Section C.4.1.), which can be updated and is therefore subject to change.

  • Fv{F}_{{v}}: a UINT32 containing the transaction version (transaction_version) of the Runtime (Section C.4.1.), which can be updated and is therefore subject to change.

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

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

Definition 146. Extra Data

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

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

where

  • Tmor{T}_{mor}: contains the SCALE encoded mortality of the extrinsic (Definition 149).

  • N{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.

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

Definition 147. Module Indicator

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

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

Mi:={0,System1,Utility7,BalancesM_i := \begin{cases} 0, & \text{System} \\ 1, & \text{Utility} \\ \ldots & \\ 7, & \text{Balances} \\ \ldots & \end{cases}
Definition 148. Function Indicator

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

Fi(m)=(mi,params){F}_{{i}}{\left({m}\right)}\:={\left({m}_{{i}},{p}{a}{r}{a}{m}{s}\right)}

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

Balancesi:={0,transfer1,set_balance2,force_transfer3,transfer_keep_aliveBalances_i := \begin{cases} 0, & \text{transfer} \\ 1, & \text{set\_balance} \\ 2, & \text{force\_transfer} \\ 3, & \text{transfer\_keep\_alive} \\ \ldots & \end{cases}

9.3.2. Mortality

Definition 149. Extrinsic Mortality

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 9.3.2.2..

The mortality mechanism works with two related values:

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

  • Mpha{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 Mpha<Mper{M}_{{{pha}}}<{M}_{{{per}}}.

In order to tie a transaction’s lifetime to a certain block (Hi(B){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" (Mpha{M}_{{{pha}}}) from these regular boundaries:

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

Mper{M}_{{{per}}} and Mpha{M}_{{{pha}}} are then included in the extrinsic, as clarified in Definition 146, in the SCALE encoded form of Tmor{T}_{mor} (Section 9.3.2.2.). Polkadot validators can use Mpha{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".

9.3.2.1. Example

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

9.3.2.2. Encoding

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

Tmor=EncSC(Mper,Mpha){T}_{mor}\:={E}{n}{c}_{{{S}{C}}}{\left({M}_{{{per}}},{M}_{{{pha}}}\right)}

The SCALE encoded representation of mortality Tmor{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 the value equal to zero.

Algorithm 25. Encode Mortality
\begin{algorithm}
\caption{Encode Mortality}
\begin{algorithmic}
    \Require{$M_{per}, M_{pha}$}
    \Return $0 \enspace \textbf{if} \enspace \textit{extrinsic is immortal}$
    \State \textbf{init} $factor = $\call{Limit}{$M_{per} \gg 12, 1, \phi$}
    \State \textbf{init} $left = $\call{Limit}{\call{TZ}{$M_{per}$}$ - 1, 1, 15$}
    \State \textbf{init} $right = \frac{M_{pha}}{factor} \ll 4$
    \Return $left|right$
\end{algorithmic}
\end{algorithm}
Algorithm 26. Decode Mortality
\begin{algorithm}
\caption{Decode Mortality}
\begin{algorithmic}
    \Require{$T_{mor}$}
    \Return $\textit{Immortal} \enspace \textbf{if} \enspace T^{b0}_{mor} = 0$
    \State \textbf{init} $enc = T^{b0}_{mor} + (T^{b1}_{mor} \ll 8)$
    \State \textbf{init} $M_{per} = 2 \ll (enc\ mod\ (1 \ll 4))$
    \State \textbf{init} $factor =$ \call{Limit}{$M_{per} \gg 12, 1, \phi$}
    \State \textbf{init} $M_{pha} = (enc \gg 4) * factor$
    \Return $(M_{per}, M_{pha})$
\end{algorithmic}
\end{algorithm}

where

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

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

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

  • TZ(num{num}): returns the number of trailing zeros in the binary representation of num{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.