From 944a023cc776d149cffbf938793d5bd4ae8c5cc3 Mon Sep 17 00:00:00 2001 From: Jernej Kos Date: Tue, 19 May 2020 10:56:54 +0200 Subject: [PATCH] oasis-test-runner/e2e: Add test for genesis restore from v20.6 --- go/common/entity/entity.go | 25 +++++++---- go/oasis-node/cmd/registry/entity/entity.go | 11 +++++ go/oasis-test-runner/oasis/entity.go | 24 +++++++++- go/oasis-test-runner/oasis/oasis.go | 25 ++++++++--- go/oasis-test-runner/scenario/e2e/e2e.go | 2 + .../scenario/e2e/restore_previous.go | 44 +++++++++++++++++++ go/registry/api/api.go | 4 ++ .../restore-previous/genesis-v20.6.json | 1 + 8 files changed, 120 insertions(+), 16 deletions(-) create mode 100644 go/oasis-test-runner/scenario/e2e/restore_previous.go create mode 100644 tests/fixture-data/restore-previous/genesis-v20.6.json diff --git a/go/common/entity/entity.go b/go/common/entity/entity.go index 9ac3f13a5ca..463d214de40 100644 --- a/go/common/entity/entity.go +++ b/go/common/entity/entity.go @@ -139,13 +139,9 @@ func LoadDescriptor(f string) (*Entity, error) { return &ent, nil } -// Generate generates a new entity and serializes it to disk. -func Generate(baseDir string, signerFactory signature.SignerFactory, template *Entity) (*Entity, signature.Signer, error) { +// GenerateWithSigner generates a new entity using an existing signer and serializes it to disk. +func GenerateWithSigner(baseDir string, signer signature.Signer, template *Entity) (*Entity, error) { // Generate a new entity. - signer, err := signerFactory.Generate(signature.SignerEntity, rand.Reader) - if err != nil { - return nil, nil, err - } ent := &Entity{ DescriptorVersion: LatestEntityDescriptorVersion, ID: signer.Public(), @@ -155,10 +151,23 @@ func Generate(baseDir string, signerFactory signature.SignerFactory, template *E ent.AllowEntitySignedNodes = template.AllowEntitySignedNodes } - if err = ent.Save(baseDir); err != nil { - return nil, nil, err + if err := ent.Save(baseDir); err != nil { + return nil, err } + return ent, nil +} +// Generate generates a new entity and serializes it to disk. +func Generate(baseDir string, signerFactory signature.SignerFactory, template *Entity) (*Entity, signature.Signer, error) { + // Generate a new entity. + signer, err := signerFactory.Generate(signature.SignerEntity, rand.Reader) + if err != nil { + return nil, nil, err + } + ent, err := GenerateWithSigner(baseDir, signer, template) + if err != nil { + return nil, nil, err + } return ent, signer, nil } diff --git a/go/oasis-node/cmd/registry/entity/entity.go b/go/oasis-node/cmd/registry/entity/entity.go index 27a4d2a53c1..020e954f585 100644 --- a/go/oasis-node/cmd/registry/entity/entity.go +++ b/go/oasis-node/cmd/registry/entity/entity.go @@ -31,6 +31,7 @@ const ( cfgAllowEntitySignedNodes = "entity.debug.allow_entity_signed_nodes" CfgNodeID = "entity.node.id" CfgNodeDescriptor = "entity.node.descriptor" + CfgReuseSigner = "entity.reuse_signer" entityGenesisFilename = "entity_genesis.json" ) @@ -378,6 +379,14 @@ func loadOrGenerateEntity(dataDir string, generate bool) (*entity.Entity, signat AllowEntitySignedNodes: viper.GetBool(cfgAllowEntitySignedNodes), } + if viper.GetBool(CfgReuseSigner) { + signer, err := entitySignerFactory.Load(signature.SignerEntity) + if err != nil { + return nil, nil, fmt.Errorf("loadOrGenerateEntity: failed to load existing signer: %w", err) + } + ent, err := entity.GenerateWithSigner(dataDir, signer, template) + return ent, signer, err + } return entity.Generate(dataDir, entitySignerFactory, template) } @@ -414,10 +423,12 @@ func init() { _ = entityFlags.MarkHidden(cfgAllowEntitySignedNodes) _ = viper.BindPFlags(entityFlags) + initFlags.Bool(CfgReuseSigner, false, "Reuse entity signer instead of generating a new one") initFlags.AddFlagSet(cmdFlags.ForceFlags) initFlags.AddFlagSet(cmdFlags.DebugTestEntityFlags) initFlags.AddFlagSet(cmdFlags.DebugDontBlameOasisFlag) initFlags.AddFlagSet(entityFlags) + _ = viper.BindPFlags(initFlags) updateFlags.StringSlice(CfgNodeID, nil, "ID(s) of nodes associated with this entity") updateFlags.StringSlice(CfgNodeDescriptor, nil, "Node genesis descriptor(s) of nodes associated with this entity") diff --git a/go/oasis-test-runner/oasis/entity.go b/go/oasis-test-runner/oasis/entity.go index e9fc42dcad5..736e58b0c4f 100644 --- a/go/oasis-test-runner/oasis/entity.go +++ b/go/oasis-test-runner/oasis/entity.go @@ -11,9 +11,12 @@ import ( "github.com/oasislabs/oasis-core/go/oasis-node/cmd/common" "github.com/oasislabs/oasis-core/go/oasis-node/cmd/common/flags" cmdSigner "github.com/oasislabs/oasis-core/go/oasis-node/cmd/common/signer" + cmdEntity "github.com/oasislabs/oasis-core/go/oasis-node/cmd/registry/entity" "github.com/oasislabs/oasis-core/go/oasis-test-runner/env" ) +const entityIdentitySeedTemplate = "oasis entity %d" + var entityArgsDebugTest = []string{ "--" + flags.CfgDebugDontBlameOasis, "--" + flags.CfgDebugTestEntity, @@ -139,12 +142,31 @@ func (net *Network) NewEntity(cfg *EntityCfg) (*Entity, error) { return nil, fmt.Errorf("oasis/entity: failed to create entity subdir: %w", err) } - if !cfg.Restore { + var extraArgs []string + switch { + case cfg.Restore: + // Restore an existing entity. + case net.cfg.DeterministicIdentities: + // Generate a deterministic entity. + err = net.generateDeterministicIdentity( + entityDir, + fmt.Sprintf(entityIdentitySeedTemplate, len(net.entities)), + []signature.SignerRole{signature.SignerEntity}, + ) + if err != nil { + return nil, fmt.Errorf("oasis/entity: failed to create deterministic identity: %w", err) + } + extraArgs = append(extraArgs, "--"+cmdEntity.CfgReuseSigner) + + fallthrough + default: + // Generate a fresh new entity. args := []string{ "registry", "entity", "init", "--" + cmdSigner.CfgSigner, fileSigner.SignerName, "--" + cmdSigner.CfgCLISignerDir, entityDir.String(), } + args = append(args, extraArgs...) var w io.WriteCloser w, err = entityDir.NewLogWriter("provision.log") diff --git a/go/oasis-test-runner/oasis/oasis.go b/go/oasis-test-runner/oasis/oasis.go index 19a6b0aca29..f4ee64f86c8 100644 --- a/go/oasis-test-runner/oasis/oasis.go +++ b/go/oasis-test-runner/oasis/oasis.go @@ -599,7 +599,7 @@ func (net *Network) runNodeBinary(consoleWriter io.Writer, args ...string) error return cmd.Run() } -func (net *Network) generateDeterministicNodeIdentity(dir *env.Dir, rawSeed string) error { +func (net *Network) generateDeterministicIdentity(dir *env.Dir, rawSeed string, roles []signature.SignerRole) error { h := crypto.SHA512.New() _, _ = h.Write([]byte(rawSeed)) seed := h.Sum(nil) @@ -609,16 +609,27 @@ func (net *Network) generateDeterministicNodeIdentity(dir *env.Dir, rawSeed stri return err } - factory, err := fileSigner.NewFactory(dir.String(), signature.SignerNode) - if err != nil { - return err - } - if _, err = factory.Generate(signature.SignerNode, rng); err != nil { - return err + for _, role := range roles { + factory, err := fileSigner.NewFactory(dir.String(), role) + if err != nil { + return err + } + if _, err = factory.Generate(role, rng); err != nil { + return err + } } + return nil } +func (net *Network) generateDeterministicNodeIdentity(dir *env.Dir, rawSeed string) error { + return net.generateDeterministicIdentity(dir, rawSeed, []signature.SignerRole{ + signature.SignerNode, + signature.SignerP2P, + signature.SignerConsensus, + }) +} + // generateTempSocketPath returns a unique filename for a node's internal socket in the test base dir // // This function is used to obtain shorter socket path than the one in datadir since that one might diff --git a/go/oasis-test-runner/scenario/e2e/e2e.go b/go/oasis-test-runner/scenario/e2e/e2e.go index d7426c1d80c..49848724e63 100644 --- a/go/oasis-test-runner/scenario/e2e/e2e.go +++ b/go/oasis-test-runner/scenario/e2e/e2e.go @@ -124,6 +124,8 @@ func RegisterScenarios() error { Debond, // Late start test. LateStart, + // Restore from v20.6 genesis file. + RestoreV206, } { if err := cmd.Register(s); err != nil { return err diff --git a/go/oasis-test-runner/scenario/e2e/restore_previous.go b/go/oasis-test-runner/scenario/e2e/restore_previous.go new file mode 100644 index 00000000000..b5e00e25847 --- /dev/null +++ b/go/oasis-test-runner/scenario/e2e/restore_previous.go @@ -0,0 +1,44 @@ +package e2e + +import ( + "fmt" + + "github.com/oasislabs/oasis-core/go/oasis-test-runner/oasis" + "github.com/oasislabs/oasis-core/go/oasis-test-runner/scenario" +) + +// RestoreV206 tests restoring from a v20.6 genesis document. +var RestoreV206 scenario.Scenario = &restorePrevious{ + runtimeImpl: *newRuntimeImpl("restore-v206", "simple-keyvalue-client", nil), + // Use the genesis document from v20.6 E2E tests (scenario: e2e/runtime/runtime). + genesisFile: "tests/fixture-data/restore-previous/genesis-v20.6.json", +} + +type restorePrevious struct { + runtimeImpl + + genesisFile string +} + +func (s *restorePrevious) Clone() scenario.Scenario { + return &restorePrevious{ + runtimeImpl: *s.runtimeImpl.Clone().(*runtimeImpl), + genesisFile: s.genesisFile, + } +} + +func (s *restorePrevious) Fixture() (*oasis.NetworkFixture, error) { + f, err := s.runtimeImpl.Fixture() + if err != nil { + return nil, err + } + + if s.genesisFile == "" { + return nil, fmt.Errorf("genesis file not specified in scenario") + } + f.Network.GenesisFile = s.genesisFile + // Use deterministic identities so we can use the same keys. + f.Network.DeterministicIdentities = true + + return f, nil +} diff --git a/go/registry/api/api.go b/go/registry/api/api.go index ccc0e9b1c9a..a92bd57585a 100644 --- a/go/registry/api/api.go +++ b/go/registry/api/api.go @@ -614,6 +614,10 @@ func VerifyRegisterNodeArgs( // nolint: gocyclo return nil, nil, err } + logger.Warn("RegisterNode: using v0 node descriptor", + "node", n, + ) + expectedSigners = append(expectedSigners, legacyTLSKey) } else { if !n.TLS.PubKey.IsValid() { diff --git a/tests/fixture-data/restore-previous/genesis-v20.6.json b/tests/fixture-data/restore-previous/genesis-v20.6.json new file mode 100644 index 00000000000..9685c9ea503 --- /dev/null +++ b/tests/fixture-data/restore-previous/genesis-v20.6.json @@ -0,0 +1 @@ +{"height":0,"genesis_time":"2020-05-19T13:32:16.930823239+02:00","chain_id":"test: oasis-core tests","epochtime":{"params":{"interval":30,"debug_mock_backend":false},"base":0},"registry":{"params":{"debug_allow_unroutable_addresses":true,"debug_allow_test_runtimes":true,"gas_costs":{"deregister_entity":1000,"register_entity":1000,"register_node":1000,"register_runtime":1000,"runtime_epoch_maintenance":1000,"unfreeze_node":1000,"update_keymanager":1000},"max_node_expiration":5},"entities":[{"untrusted_raw_value":"o2JpZFggJTUtHd4XYQjh//e6eYU7Pa/XMFG88WE+jixvceIfWrllbm9kZXOJWCAtC7hm0WDw4nQwLgzhAx5RHsizpe3gD8Jb48r/tM+IfVggB14NG+Joea3j09rVt0SEPQ4Z6Ned1EEi6rzZoa2YrYxYIA23qMXEcAzuFofG8KuawEe8M4Ygfi3mJ/su5RUhgGeyWCCFxZVS5y78zA7IQOaPlPhMALCmCt7l7ZwktzMGCDHGbVggoWk0qdNhp7XNQDX4YFJY2KeFM+9u4fo16DeSdW1gChhYICJbqGzFjKGb8XluXHgBIkI/kyVF2WSbumQloLWcbB3bWCC2gBZKvGzFIVsZdAiG7inZ84vTP9+eKusZP8y7NGBxb1ggmh+b9hN+2oLAflZACgBgVHA0EjeZK3ew6kml75s2wN5YIIj2MkdyOORURiuevD0ySGVJhC4HBWD4SG/NHthsayH9eBlhbGxvd19lbnRpdHlfc2lnbmVkX25vZGVz9A==","signature":{"public_key":"JTUtHd4XYQjh//e6eYU7Pa/XMFG88WE+jixvceIfWrk=","signature":"v6byk3AnGDmRpejmLAc3N/1fLkER65aRMHRXE/NvQQ9R8v2ogwP8oidmHtkPdd46rbQXMU6njxKUmbqlaoMJDg=="}},{"untrusted_raw_value":"o2JpZFggTqUyj5Q+9vZtqu10yw6Zw7HEX3Ywe0JQA9vHyzY47TVlbm9kZXP2eBlhbGxvd19lbnRpdHlfc2lnbmVkX25vZGVz9Q==","signature":{"public_key":"TqUyj5Q+9vZtqu10yw6Zw7HEX3Ywe0JQA9vHyzY47TU=","signature":"5CnlsannKM749UmwEadxMJ6WTAQA4tffytgwUm8WLYdpcMEBXv9aK4qwATUrO5O3hJyob0uCRRX3MHk8o/qWDw=="}}],"runtimes":[{"untrusted_raw_value":"q2JpZFggwAAAAAAAAAD///////////////////////////////9ka2luZAJlbWVyZ2Wkamdyb3VwX3NpemUBbXJvdW5kX3RpbWVvdXQbAAAAAlQL5ABxZ3JvdXBfYmFja3VwX3NpemUAcmFsbG93ZWRfc3RyYWdnbGVycwBnZ2VuZXNpc6Rlcm91bmQAZXN0YXRl9mpzdGF0ZV9yb290WCDGcrjR71btKKuHw2IsURQGm90617j5c3SY0MAezvCWenBzdG9yYWdlX3JlY2VpcHRz9mdzdG9yYWdlqGpncm91cF9zaXplAW1tYXhfYXBwbHlfb3BzAm1tYXhfbWVyZ2Vfb3BzAm9tYXhfbWVyZ2Vfcm9vdHMIc2NoZWNrcG9pbnRfaW50ZXJ2YWwAc2NoZWNrcG9pbnRfbnVtX2tlcHQAdWNoZWNrcG9pbnRfY2h1bmtfc2l6ZQB4G21heF9hcHBseV93cml0ZV9sb2dfZW50cmllcxoAAYagaGV4ZWN1dG9ypGpncm91cF9zaXplAW1yb3VuZF90aW1lb3V0GwAAAAJUC+QAcWdyb3VwX2JhY2t1cF9zaXplAHJhbGxvd2VkX3N0cmFnZ2xlcnMAaHZlcnNpb25zoWd2ZXJzaW9uo2VNYWpvcgBlTWlub3IAZVBhdGNoAGllbnRpdHlfaWRYIE6lMo+UPvb2bartdMsOmcOxxF92MHtCUAPbx8s2OO01bHRlZV9oYXJkd2FyZQBtdHhuX3NjaGVkdWxlcqVpYWxnb3JpdGhtaGJhdGNoaW5namdyb3VwX3NpemUBbm1heF9iYXRjaF9zaXplGQPoc2JhdGNoX2ZsdXNoX3RpbWVvdXQaO5rKAHRtYXhfYmF0Y2hfc2l6ZV9ieXRlcxoBAAAAcGFkbWlzc2lvbl9wb2xpY3mhaGFueV9ub2RloA==","signature":{"public_key":"TqUyj5Q+9vZtqu10yw6Zw7HEX3Ywe0JQA9vHyzY47TU=","signature":"IhIV15g5hYkN2JWmtVhrszQUpAree+zXC9QFvEGkbz1/qXGYLAXNErTXWYXXUgD7mAwmbJl/xpjJ+3awkwoXDw=="}},{"untrusted_raw_value":"rGJpZFgggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABka2luZAFlbWVyZ2Wkamdyb3VwX3NpemUCbXJvdW5kX3RpbWVvdXQbAAAAAlQL5ABxZ3JvdXBfYmFja3VwX3NpemUBcmFsbG93ZWRfc3RyYWdnbGVycwBnZ2VuZXNpc6Rlcm91bmQAZXN0YXRl9mpzdGF0ZV9yb290WCDGcrjR71btKKuHw2IsURQGm90617j5c3SY0MAezvCWenBzdG9yYWdlX3JlY2VpcHRz9mdzdG9yYWdlqGpncm91cF9zaXplAm1tYXhfYXBwbHlfb3BzAm1tYXhfbWVyZ2Vfb3BzAm9tYXhfbWVyZ2Vfcm9vdHMIc2NoZWNrcG9pbnRfaW50ZXJ2YWwAc2NoZWNrcG9pbnRfbnVtX2tlcHQAdWNoZWNrcG9pbnRfY2h1bmtfc2l6ZQB4G21heF9hcHBseV93cml0ZV9sb2dfZW50cmllcxoAAYagaGV4ZWN1dG9ypGpncm91cF9zaXplAm1yb3VuZF90aW1lb3V0GwAAAAJUC+QAcWdyb3VwX2JhY2t1cF9zaXplAXJhbGxvd2VkX3N0cmFnZ2xlcnMAaHZlcnNpb25zoWd2ZXJzaW9uo2VNYWpvcgBlTWlub3IAZVBhdGNoAGllbnRpdHlfaWRYIE6lMo+UPvb2bartdMsOmcOxxF92MHtCUAPbx8s2OO01a2tleV9tYW5hZ2VyWCDAAAAAAAAAAP///////////////////////////////2x0ZWVfaGFyZHdhcmUAbXR4bl9zY2hlZHVsZXKlaWFsZ29yaXRobWhiYXRjaGluZ2pncm91cF9zaXplAW5tYXhfYmF0Y2hfc2l6ZQFzYmF0Y2hfZmx1c2hfdGltZW91dBo7msoAdG1heF9iYXRjaF9zaXplX2J5dGVzGQPocGFkbWlzc2lvbl9wb2xpY3mhaGFueV9ub2RloA==","signature":{"public_key":"TqUyj5Q+9vZtqu10yw6Zw7HEX3Ywe0JQA9vHyzY47TU=","signature":"uQ23rrxhJJy0PCoVBu77Ziw2zYMdRrFi8/G4sNgQJRUh7GbojY0YW7jeAmm5zCvAs1GZuF64fvK64+Bs/inXBA=="}}],"nodes":[{"untrusted_raw_value":"qGJpZFggLQu4ZtFg8OJ0MC4M4QMeUR7Is6Xt4A/CW+PK/7TPiH1jcDJwomJpZFgg3NaiXoRM24g/ICmKIG3/UO0OQxe+2irGUZ7rWh8J+TBpYWRkcmVzc2Vz9mVyb2xlcwhocnVudGltZXP2aWNvbW1pdHRlZaNpYWRkcmVzc2Vz9mtjZXJ0aWZpY2F0ZVkBDTCCAQkwgbygAwIBAgIBATAFBgMrZXAwFTETMBEGA1UEAxMKb2FzaXMtbm9kZTAeFw0yMDA1MTkxMDMyMTZaFw0yMTA1MTkxMTMyMTZaMBUxEzARBgNVBAMTCm9hc2lzLW5vZGUwKjAFBgMrZXADIQDZLefij1qG2TT/j1AQ1t5khdEV9CnU72iULTXrFZwSYKMxMC8wDgYDVR0PAQH/BAQDAgKkMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAFBgMrZXADQQCUDDmJDmda2GhIl111OZxzdPTuhjVU62eX+/RL23eA5JgnyTSzSqC2gj5vuIkfCbb72d2dyvJdzKq355iDLgQFcG5leHRfY2VydGlmaWNhdGVZAQ0wggEJMIG8oAMCAQICAQEwBQYDK2VwMBUxEzARBgNVBAMTCm9hc2lzLW5vZGUwHhcNMjAwNTE5MTAzMjE2WhcNMjEwNTE5MTEzMjE2WjAVMRMwEQYDVQQDEwpvYXNpcy1ub2RlMCowBQYDK2VwAyEApl2HmxXVMkjxNtvuf48HQ3iaKPpIeQ85QOBx2sctAN2jMTAvMA4GA1UdDwEB/wQEAwICpDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwBQYDK2VwA0EAdrLD2ZsWUvvi1LRmxcYMRmPFqox/TC/t2jARL0XYsQaM5LDkztwfZNvfB1szMcOVE7GEWqVwKt1E6Rl9yTIrAmljb25zZW5zdXOiYmlkWCCbEqlS24adZOI3uU0a9ekAZtFnIYSFrdqSxJho+9Thu2lhZGRyZXNzZXOBomJpZFggLQu4ZtFg8OJ0MC4M4QMeUR7Is6Xt4A/CW+PK/7TPiH1nYWRkcmVzc6NiSVBQAAAAAAAAAAAAAP//fwAAAWRQb3J0GU4gZFpvbmVgaWVudGl0eV9pZFggJTUtHd4XYQjh//e6eYU7Pa/XMFG88WE+jixvceIfWrlqZXhwaXJhdGlvbgE=","signatures":[{"public_key":"LQu4ZtFg8OJ0MC4M4QMeUR7Is6Xt4A/CW+PK/7TPiH0=","signature":"kQvza9D/HPnlRd/RkMXbMjgmP6Fny0zxFV7+VSYzOkGrUv+Fn649MkcI4QQUJ/kcJ0e5MTujkBNQvOPTvFkHCQ=="},{"public_key":"3NaiXoRM24g/ICmKIG3/UO0OQxe+2irGUZ7rWh8J+TA=","signature":"xNamBMgL5VLOHLfr/WXmAKPBQ0u/lQ0U/TMkdsjQUJ8oMSaSd/BTvZNNez5qdwl0Dlw0iMoIztEpXDyefjVfAw=="},{"public_key":"mxKpUtuGnWTiN7lNGvXpAGbRZyGEha3aksSYaPvU4bs=","signature":"j3sbRgwv2dtk93SjdsG3Zl0ZDhwGpsRpATcdxsg+dXE2PXsS9k4inAhZIlcBFspkSDfVoc4TcVvrHVV+BGzAAg=="},{"public_key":"2S3n4o9ahtk0/49QENbeZIXRFfQp1O9olC016xWcEmA=","signature":"BRPybA1H+WQcRb4cNxbWbMmzD9poLz4vRWGktbDSeEU7lr44ppE3Myja1nWiAamSBr4F8SYataypPlhefDyHBQ=="}]},{"untrusted_raw_value":"qGJpZFggIluobMWMoZvxeW5ceAEiQj+TJUXZZJu6ZCWgtZxsHdtjcDJwomJpZFgga/RQDub2bJS7m01WKyGnUOCsmgpp2PGjGtx0r8GT259pYWRkcmVzc2Vz9mVyb2xlcwhocnVudGltZXP2aWNvbW1pdHRlZaNpYWRkcmVzc2Vz9mtjZXJ0aWZpY2F0ZVkBDTCCAQkwgbygAwIBAgIBATAFBgMrZXAwFTETMBEGA1UEAxMKb2FzaXMtbm9kZTAeFw0yMDA1MTkxMDMyMTZaFw0yMTA1MTkxMTMyMTZaMBUxEzARBgNVBAMTCm9hc2lzLW5vZGUwKjAFBgMrZXADIQBhZZuKf6iW3LNNaV5V3VBPorfcrZU9EiU3LDiNEDUMD6MxMC8wDgYDVR0PAQH/BAQDAgKkMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAFBgMrZXADQQBmzRc439smVaygPlzzKa02FWEA0fuAAFc5JhwtCnI0wZHKn3VJgthCaGVO+00LNSgSrGPFE2BCcse40LtkSJQCcG5leHRfY2VydGlmaWNhdGVZAQ0wggEJMIG8oAMCAQICAQEwBQYDK2VwMBUxEzARBgNVBAMTCm9hc2lzLW5vZGUwHhcNMjAwNTE5MTAzMjE2WhcNMjEwNTE5MTEzMjE2WjAVMRMwEQYDVQQDEwpvYXNpcy1ub2RlMCowBQYDK2VwAyEAJ8GdiHBBAPNmeWlNSk7EWCUrs50lDIuYEsauwJTlujyjMTAvMA4GA1UdDwEB/wQEAwICpDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwBQYDK2VwA0EAL0fIQN7V4XXzhKZXGyhs+ZnkyC/WpmlMuPTn/rgKNvLJ+6+QxXBt4cEHSYKS+9Q3cu88Oitj+orN+kSa4mTLCmljb25zZW5zdXOiYmlkWCDlS9jOy2rQ+OgN9OkQOdp9c668mkK4cq9BqZgogrSYPGlhZGRyZXNzZXOBomJpZFggIluobMWMoZvxeW5ceAEiQj+TJUXZZJu6ZCWgtZxsHdtnYWRkcmVzc6NiSVBQAAAAAAAAAAAAAP//fwAAAWRQb3J0GU4iZFpvbmVgaWVudGl0eV9pZFggJTUtHd4XYQjh//e6eYU7Pa/XMFG88WE+jixvceIfWrlqZXhwaXJhdGlvbgE=","signatures":[{"public_key":"IluobMWMoZvxeW5ceAEiQj+TJUXZZJu6ZCWgtZxsHds=","signature":"vqsdLLEW21KQC5C9uBKwHnsN8vbEdNB6jw0vEazcSUP0E+mXi3NeXJ8SwF9uq/RE8hCIrNOZla/O3nAKjLtPBg=="},{"public_key":"a/RQDub2bJS7m01WKyGnUOCsmgpp2PGjGtx0r8GT258=","signature":"eG4e/3YJPjkkEdyoRr90P4wbEsD3CRP/3xvEXDj5cfsk+76dLsEauDUPs65SDPNL34q5yO3WjdW3ydtWmkfPAw=="},{"public_key":"5UvYzstq0PjoDfTpEDnafXOuvJpCuHKvQamYKIK0mDw=","signature":"YkirOxT1AClVnKqfEEXl/sDkaRGX/5cFyo/im8zJv4/EjX270EbOzrJscBw8e11Nhor7Khv9uhn3bkf0L6U/Dw=="},{"public_key":"YWWbin+oltyzTWleVd1QT6K33K2VPRIlNyw4jRA1DA8=","signature":"DMltros7Iy1jSbRoweNPJr0lqIArLo3JdIDaQEWcVCczALANgHa49Oh00PpcH4ks66FYkO41G3eVmOJdQbsEDQ=="}]},{"untrusted_raw_value":"qGJpZFggtoAWSrxsxSFbGXQIhu4p2fOL0z/fnirrGT/MuzRgcW9jcDJwomJpZFggqpanrXkRo85cAtdiOOU2zrOTHESo5w4ggW1FhwuexP5pYWRkcmVzc2Vz9mVyb2xlcwhocnVudGltZXP2aWNvbW1pdHRlZaNpYWRkcmVzc2Vz9mtjZXJ0aWZpY2F0ZVkBDTCCAQkwgbygAwIBAgIBATAFBgMrZXAwFTETMBEGA1UEAxMKb2FzaXMtbm9kZTAeFw0yMDA1MTkxMDMyMTZaFw0yMTA1MTkxMTMyMTZaMBUxEzARBgNVBAMTCm9hc2lzLW5vZGUwKjAFBgMrZXADIQDaxzyCQr9g5Be2RmxHEq+ZPVqEoOgiH5oCvgJyToSv66MxMC8wDgYDVR0PAQH/BAQDAgKkMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAFBgMrZXADQQDcFv2xQr5mBHgB+maEglXWTuQ8chh2JcZHyNla9d4CYyDTfCd8wspS431+QINMHFzZCYpR7A3wKVj1JR1QScMNcG5leHRfY2VydGlmaWNhdGVZAQ0wggEJMIG8oAMCAQICAQEwBQYDK2VwMBUxEzARBgNVBAMTCm9hc2lzLW5vZGUwHhcNMjAwNTE5MTAzMjE2WhcNMjEwNTE5MTEzMjE2WjAVMRMwEQYDVQQDEwpvYXNpcy1ub2RlMCowBQYDK2VwAyEAi28z+CCUpYjTdHpgJP3SjBVPriA512bsCBKRLBmmp2yjMTAvMA4GA1UdDwEB/wQEAwICpDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwBQYDK2VwA0EAZfwe/eD8UWvOc81cG8ENElIBq181FIq2Pd4jlTT8UEdcS6bcN+W8NlVM7aEIp2C6Ms+P2UOWC6zDv4a3u5HHBGljb25zZW5zdXOiYmlkWCA0KqIWL3USZgjuJY825MWECJ/9FchhJsbagk5WSjWSQmlhZGRyZXNzZXOBomJpZFggtoAWSrxsxSFbGXQIhu4p2fOL0z/fnirrGT/MuzRgcW9nYWRkcmVzc6NiSVBQAAAAAAAAAAAAAP//fwAAAWRQb3J0GU4kZFpvbmVgaWVudGl0eV9pZFggJTUtHd4XYQjh//e6eYU7Pa/XMFG88WE+jixvceIfWrlqZXhwaXJhdGlvbgE=","signatures":[{"public_key":"toAWSrxsxSFbGXQIhu4p2fOL0z/fnirrGT/MuzRgcW8=","signature":"v18xiYkZUHVin1unRXJ5d6GWhGp/wXc02NaccgyHiaG07Pju2KCWPddzZ+8cFqM5feCk+0jmkCEpu1m3HcAdCg=="},{"public_key":"qpanrXkRo85cAtdiOOU2zrOTHESo5w4ggW1FhwuexP4=","signature":"JhL8ltvimDyomKrM1UQh+L30Wk0aP53wzIGZyvtYdw1QJeeML06JRR+7DJltAHISfZmD6lkdfN+E/+ruZ+3JCg=="},{"public_key":"NCqiFi91EmYI7iWPNuTFhAif/RXIYSbG2oJOVko1kkI=","signature":"DB0FWGv5+sYS/zgWEpe6FEjpyG6GTfeFjipx0KPW+bXiK0qP1vN3BfFAU6vjv8qChJRcT5S8P+zh8AQ6NQZ/DA=="},{"public_key":"2sc8gkK/YOQXtkZsRxKvmT1ahKDoIh+aAr4Cck6Er+s=","signature":"On613l0+sQogzkoiVX8xsI2erFd6I9jOP14fCkNxwfWFHP6Qi50TN2GsWsn9KZWB1I/4lZMO+35FnIS8onPzAA=="}]}]},"roothash":{"params":{"gas_costs":{"compute_commit":1000,"merge_commit":1000}}},"staking":{"params":{"thresholds":{"0":"0","1":"0","2":"0","3":"0","4":"0","5":"0","6":"0"},"commission_schedule_rules":{},"min_delegation":"0","fee_split_weight_propose":"0","fee_split_weight_vote":"1","fee_split_weight_next_propose":"0","reward_factor_epoch_signed":"0","reward_factor_block_proposed":"0"},"total_supply":"200000000000","common_pool":"0","last_block_fees":"0","ledger":{"TqUyj5Q+9vZtqu10yw6Zw7HEX3Ywe0JQA9vHyzY47TU=":{"general":{"balance":"100000000000","nonce":0},"escrow":{"active":{"balance":"100000000000","total_shares":"1"},"debonding":{"balance":"0","total_shares":"0"},"commission_schedule":{"rates":null,"bounds":null},"stake_accumulator":{}}}},"delegations":{"TqUyj5Q+9vZtqu10yw6Zw7HEX3Ywe0JQA9vHyzY47TU=":{"TqUyj5Q+9vZtqu10yw6Zw7HEX3Ywe0JQA9vHyzY47TU=":{"shares":"1"}}}},"keymanager":{"statuses":[{"id":"wAAAAAAAAAD///////////////////////////////8=","is_initialized":false,"is_secure":false,"checksum":"","nodes":null,"policy":null}]},"scheduler":{"params":{"min_validators":1,"max_validators":100,"max_validators_per_entity":3,"debug_bypass_stake":false,"debug_static_validators":false,"reward_factor_epoch_election_any":"0"}},"beacon":{"params":{"debug_deterministic":true}},"consensus":{"backend":"tendermint","params":{"timeout_commit":250000000,"skip_timeout_commit":false,"empty_block_interval":0,"max_tx_size":32768,"max_block_size":22020096,"max_block_gas":0,"max_evidence_age_blocks":100000,"max_evidence_age_time":172800000000000,"gas_costs":{"tx_byte":1}}},"halt_epoch":18446744073709551615,"extra_data":null} \ No newline at end of file