Skip to content

Commit

Permalink
enhancement(lib/genesis): Create struct of Runtime field of the Genes…
Browse files Browse the repository at this point in the history
…is struct. (#2808)

- Created struct for Runtime field of Genesis struct.
- Created structs for all the fields of Runtime struct.
- Wrote Marshal and Unmarshal methods for
    - some fields of Runtime struct
     - AuthorityAsAddress struct in lib/crypto/keypair.go
- Wrote Marshal method for Uint128.
- added empty string check for function argument of `PublicAddressToByteArray` function in `lib/crypto/keypair.go`
  • Loading branch information
axaysagathiya authored Jul 11, 2023
1 parent 1b9043b commit 25a2b79
Show file tree
Hide file tree
Showing 17 changed files with 721 additions and 520 deletions.
2 changes: 1 addition & 1 deletion cmd/gossamer/commands/import_runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func createGenesisWithRuntime(fp string, genesisSpecFilePath string) (string, er
return "", err
}

chainSpec.Genesis.Runtime["system"]["code"] = fmt.Sprintf("0x%x", runtime)
chainSpec.Genesis.Runtime.System.Code = fmt.Sprintf("0x%x", runtime)
jsonSpec, err := json.MarshalIndent(chainSpec, "", "\t")
if err != nil {
return "", err
Expand Down
2 changes: 1 addition & 1 deletion cmd/gossamer/commands/import_runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,5 @@ func TestCreateGenesisWithRuntime(t *testing.T) {
g := new(genesis.Genesis)
err = json.Unmarshal([]byte(out), g)
require.NoError(t, err)
require.Equal(t, testHex, g.Genesis.Runtime["system"]["code"].(string))
require.Equal(t, testHex, g.Genesis.Runtime.System.Code)
}
2 changes: 1 addition & 1 deletion dot/build_spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func BuildFromDB(path string) (*BuildSpec, error) {
},
}
tmpGen.Genesis.Raw = make(map[string]map[string]string)
tmpGen.Genesis.Runtime = make(map[string]map[string]interface{})
tmpGen.Genesis.Runtime = new(genesis.Runtime)

config := state.Config{
Path: path,
Expand Down
2 changes: 1 addition & 1 deletion dot/build_spec_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,5 @@ func TestBuildFromDB_Integration(t *testing.T) {
err = json.Unmarshal(res, &jGen)
require.NoError(t, err)

require.Equal(t, expected.Genesis.Raw["top"][codeHex], jGen.Genesis.Runtime["system"]["code"])
require.Equal(t, expected.Genesis.Raw["top"][codeHex], jGen.Genesis.Runtime.System.Code)
}
17 changes: 11 additions & 6 deletions dot/build_spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func TestBuildFromDB(t *testing.T) {
ProtocolID: "dot",
Genesis: genesis.Fields{
Raw: map[string]map[string]string{},
Runtime: map[string]map[string]interface{}{},
Runtime: new(genesis.Runtime),
},
}}},
{name: "invalid_db_path", path: t.TempDir(),
Expand All @@ -160,7 +160,7 @@ func TestBuildFromDB(t *testing.T) {
}
if tt.want != nil {
got.genesis.Genesis.Raw = map[string]map[string]string{}
got.genesis.Genesis.Runtime = map[string]map[string]interface{}{}
got.genesis.Genesis.Runtime = new(genesis.Runtime)
assert.Equal(t, tt.want, got)
}
})
Expand All @@ -171,9 +171,10 @@ func TestBuildFromGenesis(t *testing.T) {
rawGenesis := genesis.Genesis{
Name: "test",
Genesis: genesis.Fields{
Runtime: map[string]map[string]interface{}{
"System": {
"code": "mocktestcode",
Raw: map[string]map[string]string{},
Runtime: &genesis.Runtime{
System: &genesis.System{
Code: "mocktestcode",
},
},
},
Expand Down Expand Up @@ -208,7 +209,11 @@ func TestBuildFromGenesis(t *testing.T) {
Raw: map[string]map[string]string{"top" +
"": {"0x26aa394eea5630e07c48ae0c9558cef7c21aab032aaa6e946ca50ad39ab66603": "0x01",
"0x3a636f6465": "mocktestcode"}},
Runtime: map[string]map[string]interface{}{"System": {"code": "mocktestcode"}},
Runtime: &genesis.Runtime{
System: &genesis.System{
Code: "mocktestcode",
},
},
},
}},
},
Expand Down
2 changes: 1 addition & 1 deletion dot/rpc/modules/sync_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func NewStateSync(gData *genesis.Data, storageAPI StorageAPI) (SyncStateAPI, err
},
}
tmpGen.Genesis.Raw = make(map[string]map[string]string)
tmpGen.Genesis.Runtime = make(map[string]map[string]interface{})
tmpGen.Genesis.Runtime = new(genesis.Runtime)

// set genesis fields data
ent, err := storageAPI.Entries(nil)
Expand Down
2 changes: 1 addition & 1 deletion dot/rpc/modules/sync_state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func TestNewStateSync(t *testing.T) {
ProtocolID: "",
Genesis: genesis.Fields{
Raw: map[string]map[string]string{},
Runtime: map[string]map[string]interface{}{},
Runtime: new(genesis.Runtime),
},
},
},
Expand Down
17 changes: 17 additions & 0 deletions dot/types/authority.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package types

import (
"encoding/binary"
"encoding/json"
"fmt"
"io"

Expand Down Expand Up @@ -128,6 +129,22 @@ type AuthorityAsAddress struct {
Weight uint64
}

// UnmarshalJSON converts data to Go struct of type AuthorityAsAddress.
func (a *AuthorityAsAddress) UnmarshalJSON(buf []byte) error {
// It's encoded as an array [] instead of an object {}, which is why this need.
tmp := []interface{}{&a.Address, &a.Weight}
return json.Unmarshal(buf, &tmp)
}

func (a AuthorityAsAddress) MarshalJSON() ([]byte, error) {
tmp := []interface{}{&a.Address, &a.Weight}
buf, err := json.Marshal(tmp)
if err != nil {
return nil, err
}
return buf, nil
}

// AuthoritiesRawToAuthorityAsAddress converts an array of AuthorityRaws into an array of AuthorityAsAddress
func AuthoritiesRawToAuthorityAsAddress(authsRaw []AuthorityRaw, kt crypto.KeyType) ([]AuthorityAsAddress, error) {
auths := make([]AuthorityAsAddress, len(authsRaw))
Expand Down
49 changes: 49 additions & 0 deletions dot/types/authority_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2021 ChainSafe Systems (ON)
// SPDX-License-Identifier: LGPL-3.0-only

package types

import (
"testing"

"github.com/stretchr/testify/require"
)

var tcAuthorityAsAddress = []struct {
name string
jsonValue []byte
goValue AuthorityAsAddress
}{
{
name: "test1",
jsonValue: []byte{
91, 34, 53, 71, 114, 119, 118, 97, 69, 70, 53, 122, 88, 98, 50, 54, 70, 122,
57, 114, 99, 81, 112, 68, 87, 83, 53, 55, 67, 116, 69, 82, 72, 112, 78, 101,
104, 88, 67, 80, 99, 78, 111, 72, 71, 75, 117, 116, 81, 89, 34, 44, 49, 93,
},
goValue: AuthorityAsAddress{Address: "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", Weight: 1},
},
}

func TestAuthorityAsAddressMarshal(t *testing.T) {
for _, tt := range tcAuthorityAsAddress {
t.Run(tt.name, func(t *testing.T) {
marshalledValue, err := tt.goValue.MarshalJSON()
require.NoError(t, err)
require.Equal(t, tt.jsonValue, marshalledValue)
})
}

}

func TestAuthorityAsAddressUnmarshal(t *testing.T) {
for _, tt := range tcAuthorityAsAddress {
t.Run(tt.name, func(t *testing.T) {
var authorityAsAddress AuthorityAsAddress
err := authorityAsAddress.UnmarshalJSON(tt.jsonValue)
require.NoError(t, err)
require.EqualValues(t, tt.goValue, authorityAsAddress)
})
}

}
3 changes: 3 additions & 0 deletions lib/crypto/keypair.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ func publicKeyBytesToAddress(b []byte) common.Address {

// PublicAddressToByteArray returns []byte address for given PublicKey Address
func PublicAddressToByteArray(add common.Address) []byte {
if add == "" {
return nil
}
k := base58.Decode(string(add))
return k[1:33]
}
Expand Down
172 changes: 169 additions & 3 deletions lib/genesis/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
package genesis

import (
"encoding/json"

"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/lib/common"
)

Expand Down Expand Up @@ -46,8 +49,157 @@ type TelemetryEndpoint struct {

// Fields stores genesis raw data, and human readable runtime data
type Fields struct {
Raw map[string]map[string]string `json:"raw,omitempty"`
Runtime map[string]map[string]interface{} `json:"runtime,omitempty"`
Raw map[string]map[string]string `json:"raw,omitempty"`
Runtime *Runtime `json:"runtime,omitempty"`
}

// Runtime is the structure of the genesis runtime field.
type Runtime struct {
System *System `json:"system,omitempty"`
Babe *babe `json:"babe,omitempty"`
Grandpa *grandpa `json:"grandpa,omitempty"`
Balances *balances `json:"balances,omitempty"`
Sudo *sudo `json:"sudo,omitempty"`
Session *session `json:"session,omitempty"`
Staking *staking `json:"staking,omitempty"`
Indices *indices `json:"indices,omitempty"`
ImOnline *imOnline `json:"imOnline,omitempty"`
AuthorityDiscovery *authorityDiscovery `json:"authorityDiscovery,omitempty"`
Vesting *vesting `json:"vesting"`
NominationPools *nominationPools `json:"nominationPools,omitempty"`
Configuration *configuration `json:"configuration,omitempty"`
Paras *paras `json:"paras"`
Hrmp *hrmp `json:"hrmp"`
Registrar *registrar `json:"registrar,omitempty"`
XcmPallet *xcmPallet `json:"xcmPallet,omitempty"`
}

// System is the system structure inside the runtime field for the genesis.
type System struct {
Code string `json:"code,omitempty"`
}

type babe struct {
Authorities []types.AuthorityAsAddress `json:"authorities"`
EpochConfig *epochConfig `json:"epochConfig,omitempty"`
}

type epochConfig struct {
C []int `json:"c,omitempty"`
AllowedSlots string `json:"allowed_slots,omitempty"`
}

type grandpa struct {
Authorities []types.AuthorityAsAddress `json:"authorities"`
}

type balances struct {
Balances []balancesFields `json:"balances,omitempty"`
}

type balancesFields struct {
AccountID string
Balance float64
}

type sudo struct {
Key string `json:"key,omitempty"`
}

type indices struct {
Indices []interface{} `json:"indices"`
}

type imOnline struct {
Keys []string `json:"keys"`
}

type authorityDiscovery struct {
Keys []string `json:"keys"`
}

type vesting struct {
Vesting []interface{} `json:"vesting"`
}

type nominationPools struct {
MinJoinBond *uint `json:"minJoinBond,omitempty"`
MinCreateBond *uint `json:"minCreateBond,omitempty"`
MaxPools *uint `json:"maxPools,omitempty"`
MaxMembersPerPool *uint `json:"maxMembersPerPool,omitempty"`
MaxMembers *uint `json:"maxMembers,omitempty"`
}

type configuration struct {
Config config `json:"config,omitempty"`
}

type config struct {
MaxCodeSize *uint `json:"max_code_size"`
MaxHeadDataSize *uint `json:"max_head_data_size"`
MaxUpwardQueueCount *uint `json:"max_upward_queue_count"`
MaxUpwardQueueSize *uint `json:"max_upward_queue_size"`
MaxUpwardMessageSize *uint `json:"max_upward_message_size"`
MaxUpwardMessageNumPerCandidate *uint `json:"max_upward_message_num_per_candidate"`
HrmpMaxMessageNumPerCandidate *uint `json:"hrmp_max_message_num_per_candidate"`
ValidationUpgradeCooldown *uint `json:"validation_upgrade_cooldown"`
ValidationUpgradeDelay *uint `json:"validation_upgrade_delay"`
MaxPovSize *uint `json:"max_pov_size"`
MaxDownwardMessageSize *uint `json:"max_downward_message_size"`
UmpServiceTotalWeight *struct {
RefTime *uint `json:"ref_time"`
ProofSize *uint `json:"proof_size"`
} `json:"ump_service_total_weight"`
HrmpMaxParachainOutboundChannels *uint `json:"hrmp_max_parachain_outbound_channels"`
HrmpMaxParathreadOutboundChannels *uint `json:"hrmp_max_parathread_outbound_channels"`
HrmpSenderDeposit *uint `json:"hrmp_sender_deposit"`
HrmpRecipientDeposit *uint `json:"hrmp_recipient_deposit"`
HrmpChannelMaxCapacity *uint `json:"hrmp_channel_max_capacity"`
HrmpChannelMaxTotalSize *uint `json:"hrmp_channel_max_total_size"`
HrmpMaxParachainInboundChannels *uint `json:"hrmp_max_parachain_inbound_channels"`
HrmpMaxParathreadInboundChannels *uint `json:"hrmp_max_parathread_inbound_channels"`
HrmpChannelMaxMessageSize *uint `json:"hrmp_channel_max_message_size"`
CodeRetentionPeriod *uint `json:"code_retention_period"`
ParathreadCores *uint `json:"parathread_cores"`
ParathreadRetries *uint `json:"parathread_retries"`
GroupRotationFrequency *uint `json:"group_rotation_frequency"`
ChainAvailabilityPeriod *uint `json:"chain_availability_period"`
ThreadAvailabilityPeriod *uint `json:"thread_availability_period"`
SchedulingLookahead *uint `json:"scheduling_lookahead"`
MaxValidatorsPerCore *uint `json:"max_validators_per_core"`
MaxValidators *uint `json:"max_validators"`
DisputePeriod *uint `json:"dispute_period"`
DisputePostConclusionAcceptancePeriod *uint `json:"dispute_post_conclusion_acceptance_period"`
DisputeMaxSpamSlots *uint `json:"dispute_max_spam_slots"`
DisputeConclusionByTimeOutPeriod *uint `json:"dispute_conclusion_by_time_out_period"`
NoShowSlots *uint `json:"no_show_slots"`
NDelayTranches *uint `json:"n_delay_tranches"`
ZerothDelayTrancheWidth *uint `json:"zeroth_delay_tranche_width"`
NeededApprovals *uint `json:"needed_approvals"`
RelayVrfModuloSamples *uint `json:"relay_vrf_modulo_samples"`
UmpMaxIndividualWeight *struct {
RefTime *uint `json:"ref_time"`
ProofSize *uint `json:"proof_size"`
} `json:"ump_max_individual_weight"`
PvfCheckingEnabled bool `json:"pvf_checking_enabled"`
PvfVotingTTL *uint `json:"pvf_voting_ttl"`
MinimumValidationUpgradeDelay *uint `json:"minimum_validation_upgrade_delay"`
}

type paras struct {
Paras []interface{} `json:"paras"`
}

type hrmp struct {
PreopenHrmpChannels []interface{} `json:"preopenHrmpChannels"`
}

type registrar struct {
NextFreeParaID *uint `json:"nextFreeParaId,omitempty"`
}

type xcmPallet struct {
SafeXcmVersion *uint `json:"safeXcmVersion,omitempty"`
}

// GenesisData formats genesis for trie storage
Expand Down Expand Up @@ -84,7 +236,7 @@ func (g *Genesis) ToRaw() error {
}

grt := g.Genesis.Runtime
res, err := buildRawMap(grt)
res, err := buildRawMap(*grt)
if err != nil {
return err
}
Expand Down Expand Up @@ -121,3 +273,17 @@ func interfaceToTelemetryEndpoint(endpoints []interface{}) []*TelemetryEndpoint

return res
}

func (b *balancesFields) UnmarshalJSON(buf []byte) error {
tmp := []interface{}{&b.AccountID, &b.Balance}
return json.Unmarshal(buf, &tmp)
}

func (b balancesFields) MarshalJSON() ([]byte, error) {
tmp := []interface{}{&b.AccountID, &b.Balance}
buf, err := json.Marshal(tmp)
if err != nil {
return nil, err
}
return buf, nil
}
Loading

0 comments on commit 25a2b79

Please sign in to comment.