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

feat(multiple): read from genesis file #23

Closed
wants to merge 37 commits into from

Conversation

MaxMustermann2
Copy link
Contributor

This pull request sets up genesis data structures for the modules assets, delegation, operator and dogfood. The data is read, marshaled and then validated before the node starts. Once the node starts, the data is sent to the module keepers at genesis where stateful validations can take place.

Secondly, it makes some minor changes (comments and clean-up) in the dogfood module.

Lastly, it also sets up a CLI way for validators to export their consensus public key as a bytes32 object to use within Solidity.

exocored keys consensus-pubkey-to-bytes --output json | jq -r .bytes
F0F6919E522C5B97DB2C8255BFF743F9DFDDD7AD9FC37CB0C1670B480D0F9914

For reference, the (JSON) string object can be exported as follows:

exocored tendermint show-validator
{"@type":"/cosmos.crypto.ed25519.PubKey","key":"8PaRnlIsW5fbLIJVv/dD+d/d162fw3ywwWcLSA0PmRQ="}

The same key can be recovered from the mnemonic (which can also be read from stdin manually)

echo "${MNEMONIC}" | exocored init localnet --chain-id exocorelocal_233-1 --recover

The bootstrapping contract and its script are required to generate the
genesis state, which includes the following:
- Registration of client chain
- Registration of client chain assets / tokens, with the total deposit
  value
- Total amount delegated to each operator for each asset ID
- Total amount deposited by each staker for each asset ID, and the
  portion of it that is currently withdrawable
The delegation module by itself does not store a lot of information. The
small portion that it does store is handled by this commit at the time
of genesis. It validates that the formats of the StakerID, the AssetID
and the OperatorAddress are correct and that the amount is not nil.
The map was used to store operator consensus key to vote power mapping
as of the last iteration. However, the same information is available
with the iteration `GetAllExocoreValidators` and the same complexity.
explain why the protobuf.Any type is used
When the `bytes32` consensus key from Solidity is dumped for the genesis
file to import, it is not directly readable as bytes. We have to read it
via the `hexutil` import. This import expectes double the length (32 * 2
= 64) plus a prefix (`0x`) length of 2, and operators on the string as
the input.
There was a duplicates check being enforced, that should not have been,
and vice-versa.
if err != nil {
return err
}
output, _ := cmd.Flags().GetString(cli.OutputFlag)

Check warning

Code scanning / gosec

Returned error is not propagated up the stack. Warning

Returned error is not propagated up the stack.
Comment on lines +283 to +288
for k1, v1 := range m1 {
v2, ok := m2[k1]
if !ok || !v1.Equal(v2) {
return false
}
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
instead, generate it on the fly (to avoid gitleaks thinking it is an API
key)
Assumptions:
- `assets` module genesis is only responsible for deposits
- `delegation` module genesis then locks up the assets based on its
  genesis state, from its own perspective as well as in the `assets`
  module.
- `operator` module genesis verifies that the delegated amount provided
  to it is the same as that provided to the delegation module.
Clarify that the check made by the operator module indirectly includes a
check for the assets data
Checks in the delegation module include:
- assetID corresponds to a registered staking asset
- free (unbonded) deposits for stakerID and assetID combination exceed
  (or are equal to) the delegation amount.

Checks in the operator module (on loop 3, amounts) include:
- the operator is registered (during loop 1), since this is not
  something that the delegation module can enforce.
- the amount delegated by {staker,asset,operator} equals the amount
  delegated for the same combination according to the delegation module.
- the combinations {staker,asset,operator} that exist in the module
  equal those provided by the delegation module. this check helps skip
  the `IsStakingAsset` check within this module.
Comment on lines +124 to +144
for stakerID, assetMap := range map1 {
if assetMap2, ok := map2[stakerID]; ok {
for assetID, operatorMap := range assetMap {
if operatorMap2, ok := assetMap2[assetID]; ok {
for operatorAddress, amount := range operatorMap {
if amount2, ok := operatorMap2[operatorAddress]; ok {
if !amount.Equal(amount2) {
return false // Amounts differ
}
} else {
return false // OperatorAddress not found in map2
}
}
} else {
return false // AssetID not found in map2
}
}
} else {
return false // StakerID not found in map2
}
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
Comment on lines +126 to +140
for assetID, operatorMap := range assetMap {
if operatorMap2, ok := assetMap2[assetID]; ok {
for operatorAddress, amount := range operatorMap {
if amount2, ok := operatorMap2[operatorAddress]; ok {
if !amount.Equal(amount2) {
return false // Amounts differ
}
} else {
return false // OperatorAddress not found in map2
}
}
} else {
return false // AssetID not found in map2
}
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
Comment on lines +128 to +136
for operatorAddress, amount := range operatorMap {
if amount2, ok := operatorMap2[operatorAddress]; ok {
if !amount.Equal(amount2) {
return false // Amounts differ
}
} else {
return false // OperatorAddress not found in map2
}
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
Comment on lines 147 to 156
for stakerID, assetMap := range map2 {
if _, ok := map1[stakerID]; !ok {
return false // Extra StakerID in map2
}
for assetID, _ := range assetMap {
if _, ok := map1[stakerID][assetID]; !ok {
return false // Extra AssetID in map2
}
}
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
The dogfood module accepts a list of validators as input. These
validators must be registered within the operator module for the chain's
ChainID.
// #nosec G703 // already validated
consKey, _ := operatortypes.HexStringToPubKey(val.PublicKey)
// #nosec G601 // this only fails if the key is of a type not already defined.
consAddr, _ := operatortypes.TMCryptoPublicKeyToConsAddr(consKey)

Check warning

Code scanning / gosec

Returned error is not propagated up the stack. Warning

Returned error is not propagated up the stack.
Comment on lines +151 to +155
for assetID := range assetMap {
if _, ok := map1[stakerID][assetID]; !ok {
return false // Extra AssetID in map2
}
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
@MaxMustermann2
Copy link
Contributor Author

Closing this PR to break it down into multiple PRs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant