question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Two Modules with same Storage Name

See original GitHub issue

If two modules have the same name for their storage, only one item appears in the “chain state”.

For example:

          "name": "substrate_module_template",
          "prefix": "TemplateModule",

and

          "name": "template",
          "prefix": "TemplateModule",
image

Here is the full chain metadata:

{
  "magicNumber": 1635018093,
  "metadata": {
    "MetadataV4": {
      "modules": [
        {
          "name": "system",
          "prefix": "System",
          "storage": [
            {
              "name": "AccountNonce",
              "modifier": "Default",
              "type": {
                "MapType": {
                  "hasher": "Blake2_256",
                  "key": "AccountId",
                  "value": "Index",
                  "isLinked": false
                }
              },
              "fallback": "0x0000000000000000",
              "documentation": [
                " Extrinsics nonce for accounts."
              ]
            },
            {
              "name": "ExtrinsicCount",
              "modifier": "Optional",
              "type": {
                "PlainType": "u32"
              },
              "fallback": "0x00",
              "documentation": [
                " Total extrinsics count for the current block."
              ]
            },
            {
              "name": "AllExtrinsicsLen",
              "modifier": "Optional",
              "type": {
                "PlainType": "u32"
              },
              "fallback": "0x00",
              "documentation": [
                " Total length in bytes for all extrinsics put together, for the current block."
              ]
            },
            {
              "name": "BlockHash",
              "modifier": "Default",
              "type": {
                "MapType": {
                  "hasher": "Blake2_256",
                  "key": "BlockNumber",
                  "value": "Hash",
                  "isLinked": false
                }
              },
              "fallback": "0x0000000000000000000000000000000000000000000000000000000000000000",
              "documentation": [
                " Map of block numbers to block hashes."
              ]
            },
            {
              "name": "ExtrinsicData",
              "modifier": "Default",
              "type": {
                "MapType": {
                  "hasher": "Blake2_256",
                  "key": "u32",
                  "value": "Bytes",
                  "isLinked": false
                }
              },
              "fallback": "0x00",
              "documentation": [
                " Extrinsics data for the current block (maps extrinsic's index to its data)."
              ]
            },
            {
              "name": "RandomSeed",
              "modifier": "Default",
              "type": {
                "PlainType": "Hash"
              },
              "fallback": "0x0000000000000000000000000000000000000000000000000000000000000000",
              "documentation": [
                " Random seed of the current block."
              ]
            },
            {
              "name": "Number",
              "modifier": "Default",
              "type": {
                "PlainType": "BlockNumber"
              },
              "fallback": "0x0000000000000000",
              "documentation": [
                " The current block number being processed. Set by `execute_block`."
              ]
            },
            {
              "name": "ParentHash",
              "modifier": "Default",
              "type": {
                "PlainType": "Hash"
              },
              "fallback": "0x0000000000000000000000000000000000000000000000000000000000000000",
              "documentation": [
                " Hash of the previous block."
              ]
            },
            {
              "name": "ExtrinsicsRoot",
              "modifier": "Default",
              "type": {
                "PlainType": "Hash"
              },
              "fallback": "0x0000000000000000000000000000000000000000000000000000000000000000",
              "documentation": [
                " Extrinsics root of the current block, also part of the block header."
              ]
            },
            {
              "name": "Digest",
              "modifier": "Default",
              "type": {
                "PlainType": "Digest"
              },
              "fallback": "0x00",
              "documentation": [
                " Digest of the current block, also part of the block header."
              ]
            },
            {
              "name": "Events",
              "modifier": "Default",
              "type": {
                "PlainType": "Vec<EventRecord>"
              },
              "fallback": "0x00",
              "documentation": [
                " Events deposited for the current block."
              ]
            }
          ],
          "calls": null,
          "events": [
            {
              "name": "ExtrinsicSuccess",
              "args": [],
              "documentation": [
                " An extrinsic completed successfully."
              ]
            },
            {
              "name": "ExtrinsicFailed",
              "args": [],
              "documentation": [
                " An extrinsic failed."
              ]
            }
          ]
        },
        {
          "name": "timestamp",
          "prefix": "Timestamp",
          "storage": [
            {
              "name": "Now",
              "modifier": "Default",
              "type": {
                "PlainType": "Moment"
              },
              "fallback": "0x0000000000000000",
              "documentation": [
                " Current time for the current block."
              ]
            },
            {
              "name": "BlockPeriod",
              "modifier": "Optional",
              "type": {
                "PlainType": "Moment"
              },
              "fallback": "0x00",
              "documentation": [
                " Old storage item provided for compatibility. Remove after all networks upgraded."
              ]
            },
            {
              "name": "MinimumPeriod",
              "modifier": "Default",
              "type": {
                "PlainType": "Moment"
              },
              "fallback": "0x0300000000000000",
              "documentation": [
                " The minimum period between blocks. Beware that this is different to the *expected* period",
                " that the block production apparatus provides. Your chosen consensus system will generally",
                " work with this to determine a sensible block time. e.g. For Aura, it will be double this",
                " period on default settings."
              ]
            },
            {
              "name": "DidUpdate",
              "modifier": "Default",
              "type": {
                "PlainType": "bool"
              },
              "fallback": "0x00",
              "documentation": [
                " Did the timestamp get updated in this block?"
              ]
            }
          ],
          "calls": [
            {
              "name": "set",
              "args": [
                {
                  "name": "now",
                  "type": "Compact<Moment>"
                }
              ],
              "documentation": [
                " Set the current time.",
                "",
                " This call should be invoked exactly once per block. It will panic at the finalization phase,",
                " if this call hasn't been invoked by that time.",
                "",
                " The timestamp should be greater than the previous one by the amount specified by `minimum_period`.",
                "",
                " The dispatch origin for this call must be `Inherent`."
              ]
            }
          ],
          "events": null
        },
        {
          "name": "consensus",
          "prefix": "Consensus",
          "storage": [
            {
              "name": "OriginalAuthorities",
              "modifier": "Optional",
              "type": {
                "PlainType": "Vec<SessionKey>"
              },
              "fallback": "0x00",
              "documentation": []
            }
          ],
          "calls": [
            {
              "name": "report_misbehavior",
              "args": [
                {
                  "name": "_report",
                  "type": "Bytes"
                }
              ],
              "documentation": [
                " Report some misbehavior."
              ]
            },
            {
              "name": "note_offline",
              "args": [
                {
                  "name": "offline",
                  "type": "InherentOfflineReport"
                }
              ],
              "documentation": [
                " Note that the previous block's validator missed its opportunity to propose a block."
              ]
            },
            {
              "name": "remark",
              "args": [
                {
                  "name": "_remark",
                  "type": "Bytes"
                }
              ],
              "documentation": [
                " Make some on-chain remark."
              ]
            },
            {
              "name": "set_heap_pages",
              "args": [
                {
                  "name": "pages",
                  "type": "u64"
                }
              ],
              "documentation": [
                " Set the number of pages in the WebAssembly environment's heap."
              ]
            },
            {
              "name": "set_code",
              "args": [
                {
                  "name": "new",
                  "type": "Bytes"
                }
              ],
              "documentation": [
                " Set the new code."
              ]
            },
            {
              "name": "set_storage",
              "args": [
                {
                  "name": "items",
                  "type": "Vec<KeyValue>"
                }
              ],
              "documentation": [
                " Set some items of storage."
              ]
            },
            {
              "name": "kill_storage",
              "args": [
                {
                  "name": "keys",
                  "type": "Vec<Key>"
                }
              ],
              "documentation": [
                " Kill some items from storage."
              ]
            }
          ],
          "events": null
        },
        {
          "name": "aura",
          "prefix": "",
          "storage": null,
          "calls": null,
          "events": null
        },
        {
          "name": "indices",
          "prefix": "Indices",
          "storage": [
            {
              "name": "NextEnumSet",
              "modifier": "Default",
              "type": {
                "PlainType": "AccountIndex"
              },
              "fallback": "0x00000000",
              "documentation": [
                " The next free enumeration set."
              ]
            },
            {
              "name": "EnumSet",
              "modifier": "Default",
              "type": {
                "MapType": {
                  "hasher": "Blake2_256",
                  "key": "AccountIndex",
                  "value": "Vec<AccountId>",
                  "isLinked": false
                }
              },
              "fallback": "0x00",
              "documentation": [
                " The enumeration sets."
              ]
            }
          ],
          "calls": [],
          "events": [
            {
              "name": "NewAccountIndex",
              "args": [
                "AccountId",
                "AccountIndex"
              ],
              "documentation": [
                " A new account index was assigned.",
                "",
                " This event is not triggered when an existing index is reassigned",
                " to another `AccountId`."
              ]
            }
          ]
        },
        {
          "name": "balances",
          "prefix": "Balances",
          "storage": [
            {
              "name": "TotalIssuance",
              "modifier": "Default",
              "type": {
                "PlainType": "Balance"
              },
              "fallback": "0x00000000000000000000000000000000",
              "documentation": [
                " The total units issued in the system."
              ]
            },
            {
              "name": "ExistentialDeposit",
              "modifier": "Default",
              "type": {
                "PlainType": "Balance"
              },
              "fallback": "0x00000000000000000000000000000000",
              "documentation": [
                " The minimum amount required to keep an account open."
              ]
            },
            {
              "name": "TransferFee",
              "modifier": "Default",
              "type": {
                "PlainType": "Balance"
              },
              "fallback": "0x00000000000000000000000000000000",
              "documentation": [
                " The fee required to make a transfer."
              ]
            },
            {
              "name": "CreationFee",
              "modifier": "Default",
              "type": {
                "PlainType": "Balance"
              },
              "fallback": "0x00000000000000000000000000000000",
              "documentation": [
                " The fee required to create an account."
              ]
            },
            {
              "name": "TransactionBaseFee",
              "modifier": "Default",
              "type": {
                "PlainType": "Balance"
              },
              "fallback": "0x00000000000000000000000000000000",
              "documentation": [
                " The fee to be paid for making a transaction; the base."
              ]
            },
            {
              "name": "TransactionByteFee",
              "modifier": "Default",
              "type": {
                "PlainType": "Balance"
              },
              "fallback": "0x00000000000000000000000000000000",
              "documentation": [
                " The fee to be paid for making a transaction; the per-byte portion."
              ]
            },
            {
              "name": "Vesting",
              "modifier": "Optional",
              "type": {
                "MapType": {
                  "hasher": "Blake2_256",
                  "key": "AccountId",
                  "value": "VestingSchedule",
                  "isLinked": false
                }
              },
              "fallback": "0x00",
              "documentation": [
                " Information regarding the vesting of a given account."
              ]
            },
            {
              "name": "FreeBalance",
              "modifier": "Default",
              "type": {
                "MapType": {
                  "hasher": "Blake2_256",
                  "key": "AccountId",
                  "value": "Balance",
                  "isLinked": false
                }
              },
              "fallback": "0x00000000000000000000000000000000",
              "documentation": [
                " The 'free' balance of a given account.",
                "",
                " This is the only balance that matters in terms of most operations on tokens. It",
                " alone is used to determine the balance when in the contract execution environment. When this",
                " balance falls below the value of `ExistentialDeposit`, then the 'current account' is",
                " deleted: specifically `FreeBalance`. Further, the `OnFreeBalanceZero` callback",
                " is invoked, giving a chance to external modules to clean up data associated with",
                " the deleted account.",
                "",
                " `system::AccountNonce` is also deleted if `ReservedBalance` is also zero (it also gets",
                " collapsed to zero if it ever becomes less than `ExistentialDeposit`."
              ]
            },
            {
              "name": "ReservedBalance",
              "modifier": "Default",
              "type": {
                "MapType": {
                  "hasher": "Blake2_256",
                  "key": "AccountId",
                  "value": "Balance",
                  "isLinked": false
                }
              },
              "fallback": "0x00000000000000000000000000000000",
              "documentation": [
                " The amount of the balance of a given account that is externally reserved; this can still get",
                " slashed, but gets slashed last of all.",
                "",
                " This balance is a 'reserve' balance that other subsystems use in order to set aside tokens",
                " that are still 'owned' by the account holder, but which are suspendable.",
                "",
                " When this balance falls below the value of `ExistentialDeposit`, then this 'reserve account'",
                " is deleted: specifically, `ReservedBalance`.",
                "",
                " `system::AccountNonce` is also deleted if `FreeBalance` is also zero (it also gets",
                " collapsed to zero if it ever becomes less than `ExistentialDeposit`.)"
              ]
            },
            {
              "name": "Locks",
              "modifier": "Default",
              "type": {
                "MapType": {
                  "hasher": "Blake2_256",
                  "key": "AccountId",
                  "value": "Vec<BalanceLock>",
                  "isLinked": false
                }
              },
              "fallback": "0x00",
              "documentation": [
                " Any liquidity locks on some account balances."
              ]
            }
          ],
          "calls": [
            {
              "name": "transfer",
              "args": [
                {
                  "name": "dest",
                  "type": "Address"
                },
                {
                  "name": "value",
                  "type": "Compact<Balance>"
                }
              ],
              "documentation": [
                " Transfer some liquid free balance to another account.",
                "",
                " `transfer` will set the `FreeBalance` of the sender and receiver.",
                " It will decrease the total issuance of the system by the `TransferFee`.",
                " If the sender's account is below the existential deposit as a result",
                " of the transfer, the account will be reaped.",
                "",
                " The dispatch origin for this call must be `Signed` by the transactor."
              ]
            },
            {
              "name": "set_balance",
              "args": [
                {
                  "name": "who",
                  "type": "Address"
                },
                {
                  "name": "free",
                  "type": "Compact<Balance>"
                },
                {
                  "name": "reserved",
                  "type": "Compact<Balance>"
                }
              ],
              "documentation": [
                " Set the balances of a given account.",
                "",
                " This will alter `FreeBalance` and `ReservedBalance` in storage.",
                " If the new free or reserved balance is below the existential deposit,",
                " it will also decrease the total issuance of the system (`TotalIssuance`)",
                " and reset the account nonce (`system::AccountNonce`).",
                "",
                " The dispatch origin for this call is `root`."
              ]
            }
          ],
          "events": [
            {
              "name": "NewAccount",
              "args": [
                "AccountId",
                "Balance"
              ],
              "documentation": [
                " A new account was created."
              ]
            },
            {
              "name": "ReapedAccount",
              "args": [
                "AccountId"
              ],
              "documentation": [
                " An account was reaped."
              ]
            },
            {
              "name": "Transfer",
              "args": [
                "AccountId",
                "AccountId",
                "Balance",
                "Balance"
              ],
              "documentation": [
                " Transfer succeeded (from, to, value, fees)."
              ]
            }
          ]
        },
        {
          "name": "sudo",
          "prefix": "Sudo",
          "storage": [
            {
              "name": "Key",
              "modifier": "Default",
              "type": {
                "PlainType": "AccountId"
              },
              "fallback": "0x0000000000000000000000000000000000000000000000000000000000000000",
              "documentation": [
                " The `AccountId` of the sudo key."
              ]
            }
          ],
          "calls": [
            {
              "name": "sudo",
              "args": [
                {
                  "name": "proposal",
                  "type": "Proposal"
                }
              ],
              "documentation": [
                " Authenticates the sudo key and dispatches a function call with `Root` origin.",
                "",
                " The dispatch origin for this call must be _Signed_."
              ]
            },
            {
              "name": "set_key",
              "args": [
                {
                  "name": "new",
                  "type": "Address"
                }
              ],
              "documentation": [
                " Authenticates the current sudo key and sets the given AccountId (`new`) as the new sudo key.",
                "",
                " The dispatch origin for this call must be _Signed_."
              ]
            }
          ],
          "events": [
            {
              "name": "Sudid",
              "args": [
                "bool"
              ],
              "documentation": [
                " A sudo just took place."
              ]
            },
            {
              "name": "KeyChanged",
              "args": [
                "AccountId"
              ],
              "documentation": [
                " The sudoer just switched identity; the old key is supplied."
              ]
            }
          ]
        },
        {
          "name": "template",
          "prefix": "TemplateModule",
          "storage": [
            {
              "name": "Something",
              "modifier": "Optional",
              "type": {
                "PlainType": "u32"
              },
              "fallback": "0x00",
              "documentation": []
            }
          ],
          "calls": [
            {
              "name": "do_something",
              "args": [
                {
                  "name": "something",
                  "type": "u32"
                }
              ],
              "documentation": []
            }
          ],
          "events": [
            {
              "name": "SomethingStored",
              "args": [
                "u32",
                "AccountId"
              ],
              "documentation": []
            }
          ]
        },
        {
          "name": "substrate_module_template",
          "prefix": "TemplateModule",
          "storage": [
            {
              "name": "Something",
              "modifier": "Optional",
              "type": {
                "PlainType": "u32"
              },
              "fallback": "0x00",
              "documentation": []
            }
          ],
          "calls": [
            {
              "name": "do_something",
              "args": [
                {
                  "name": "something",
                  "type": "u32"
                }
              ],
              "documentation": []
            }
          ],
          "events": [
            {
              "name": "SomethingStored",
              "args": [
                "u32",
                "AccountId"
              ],
              "documentation": []
            }
          ]
        }
      ]
    }
  }
}

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:12 (11 by maintainers)

github_iconTop GitHub Comments

1reaction
amaurymcommented, Jun 25, 2019

Pick same name: -> should be forbidden. Pick same prefix: -> no problem.

Not sure what happens now if you create 2 modules with the same name, but imo that should be forbidden in substrate.

1reaction
jacogrcommented, Jun 25, 2019

Ok, the issue is - what is valid? The first item of a specific storage? The second? Which rules apply? As it stands the API needs to make assumptions as to which to take - it currently already makes an assumption - the second module as a whole is valid, overriding the first.

So certainly, different assumptions can be made - but it is just that, assumptions of developer intent. Since you can override calls, entries, anything - which is valid in which cases. (Since even at the base of substrate there are conflicts, e.g. storage due to hash(<ModuleName> <EntryName>))

It is not a UI thing, the UI only displays what the API provides it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

python: Two modules and classes with the same name under ...
You want to import the User modules in the package __init__.py files to make them available as attributes. So in both Helper/__init_.py and ......
Read more >
How to import two modules with same function name in Python
Let me create another module with two functions and the names the functions are: Add and Divide. I call this module as prog2.py...
Read more >
How to access/modify the same instance of a class across ...
I am struggling to access/modify the same instance of a class across multiple modules. Which software design pattern should I use to have...
Read more >
about Modules - PowerShell | Microsoft Learn
Explains how to install, import, and use PowerShell modules. ... includes commands of the same type with the same name, such as two...
Read more >
Placement of modules in LPA - IBM
When frequently-used modules are placed in LPA, all address spaces share the same copy, and central storage usage tends to be reduced.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found