From 43b36c0b8c2995ad2f69688ff09d9783c34f0e3f Mon Sep 17 00:00:00 2001 From: avalkov Date: Wed, 31 Aug 2022 10:50:52 +0300 Subject: [PATCH 1/6] Update APR calculations --- cmd/stats-service/main.go | 6 ++- config.yaml | 8 +++- internal/config/config.go | 13 ++++-- internal/handlers/handlers.go | 4 +- internal/rest/distribution/client.go | 59 ++++++++++++++++++++++++++++ internal/tasks/apr.go | 23 ++++++++++- internal/tasks/inflation.go | 8 ++-- internal/tasks/tasks.go | 45 +++++++++++++++------ 8 files changed, 139 insertions(+), 27 deletions(-) create mode 100644 internal/rest/distribution/client.go diff --git a/cmd/stats-service/main.go b/cmd/stats-service/main.go index f08dff7..f4956de 100644 --- a/cmd/stats-service/main.go +++ b/cmd/stats-service/main.go @@ -9,6 +9,7 @@ import ( "github.com/CudoVentures/cudos-stats-v2-service/internal/config" "github.com/CudoVentures/cudos-stats-v2-service/internal/handlers" "github.com/CudoVentures/cudos-stats-v2-service/internal/rest/bank" + "github.com/CudoVentures/cudos-stats-v2-service/internal/rest/distribution" "github.com/CudoVentures/cudos-stats-v2-service/internal/storage" "github.com/CudoVentures/cudos-stats-v2-service/internal/tasks" "github.com/cosmos/cosmos-sdk/simapp/params" @@ -45,12 +46,13 @@ func main() { stakingClient := stakingtypes.NewQueryClient(source.GrpcConn) bankingRestClient := bank.NewRestClient(cfg.Cudos.REST.Address) + distributionRestClient := distribution.NewRestClient(cfg.Cudos.REST.Address) keyValueStorage := storage.NewStorage() log.Info().Msg("Executing tasks") - if err := tasks.ExecuteTasks(cfg, nodeClient, stakingClient, bankingRestClient, keyValueStorage); err != nil { + if err := tasks.ExecuteTasks(cfg, nodeClient, stakingClient, bankingRestClient, distributionRestClient, keyValueStorage); err != nil { log.Fatal().Err(fmt.Errorf("error while executing tasks: %s", err)).Send() return } @@ -58,7 +60,7 @@ func main() { log.Info().Msg("Registering tasks") scheduler := gocron.NewScheduler(time.UTC) - if err := tasks.RegisterTasks(scheduler, cfg, nodeClient, stakingClient, bankingRestClient, keyValueStorage); err != nil { + if err := tasks.RegisterTasks(scheduler, cfg, nodeClient, stakingClient, bankingRestClient, distributionRestClient, keyValueStorage); err != nil { log.Fatal().Err(fmt.Errorf("error while registering tasks: %s", err)).Send() return } diff --git a/config.yaml b/config.yaml index 305ccb9..da6f1c5 100644 --- a/config.yaml +++ b/config.yaml @@ -1,10 +1,16 @@ port: 3000 -genesis: +inflation_genesis: initial_height: 1 norm_time_passed: 0.53172694105988 blocks_per_day: 17280 mint_denom: acudos gravity_account_address: cudos16n3lc7cywa68mg50qhp847034w88pntq8823tx +apr_genesis: + initial_height: 1068800 + norm_time_passed: 0.852119746111849790 + blocks_per_day: 12345 + mint_denom: acudos + gravity_account_address: cudos16n3lc7cywa68mg50qhp847034w88pntq8823tx cudos: node: rpc: diff --git a/internal/config/config.go b/internal/config/config.go index e491b70..3a014b4 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -26,14 +26,21 @@ func NewConfig(configPath string) (Config, error) { } type Config struct { - Port int `yaml:"port"` - Genesis struct { + Port int `yaml:"port"` + InflationGenesis struct { InitialHeight int64 `yaml:"initial_height"` NormTimePassed string `yaml:"norm_time_passed"` BlocksPerDay string `yaml:"blocks_per_day"` MintDenom string `yaml:"mint_denom"` GravityAccountAddress string `yaml:"gravity_account_address"` - } `yaml:"genesis"` + } `yaml:"inflation_genesis"` + APRGenesis struct { + InitialHeight int64 `yaml:"initial_height"` + NormTimePassed string `yaml:"norm_time_passed"` + BlocksPerDay string `yaml:"blocks_per_day"` + MintDenom string `yaml:"mint_denom"` + GravityAccountAddress string `yaml:"gravity_account_address"` + } `yaml:"apr_genesis"` Cudos struct { NodeDetails remote.Details `yaml:"node"` REST struct { diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index 9c59efb..b689a9a 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -182,12 +182,12 @@ func GetParamsHandler(cfg config.Config) func(http.ResponseWriter, *http.Request if err := json.NewEncoder(w).Encode(paramsResponse{ Params: params{ - MintDenom: cfg.Genesis.MintDenom, + MintDenom: cfg.InflationGenesis.MintDenom, InflationRateChange: "0.0", InflationMax: "0.0", InflationMin: "0.0", GoalBonded: "0.0", - BlocksPerYear: cfg.Genesis.BlocksPerDay, + BlocksPerYear: cfg.InflationGenesis.BlocksPerDay, }, }); err != nil { badRequest(w, err) diff --git a/internal/rest/distribution/client.go b/internal/rest/distribution/client.go new file mode 100644 index 0000000..6f7e259 --- /dev/null +++ b/internal/rest/distribution/client.go @@ -0,0 +1,59 @@ +package distribution + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" +) + +type client struct { + Url string +} + +func NewRestClient(url string) *client { + return &client{Url: url} +} + +func (c client) GetParams(ctx context.Context) (ParametersResponse, error) { + respStr, err := c.get(ctx, "/distribution/parameters") + if err != nil { + return ParametersResponse{}, err + } + + var res parametersResult + if err := json.Unmarshal([]byte(respStr), &res); err != nil { + return ParametersResponse{}, err + } + + return res.Result, nil +} + +func (c client) get(ctx context.Context, uri string) (string, error) { + getReq, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s%s", c.Url, uri), nil) + if err != nil { + return "", err + } + + resp, err := http.DefaultClient.Do(getReq) + if err != nil { + return "", err + } + + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return "", err + } + + return string(body), nil +} + +type parametersResult struct { + Result ParametersResponse `json:"result"` +} + +type ParametersResponse struct { + CommunityTax string `json:"community_tax"` +} diff --git a/internal/tasks/apr.go b/internal/tasks/apr.go index 48bf9e6..4b2952f 100644 --- a/internal/tasks/apr.go +++ b/internal/tasks/apr.go @@ -8,11 +8,14 @@ import ( cudoMintTypes "github.com/CudoVentures/cudos-node/x/cudoMint/types" "github.com/CudoVentures/cudos-stats-v2-service/internal/config" + sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/forbole/juno/v2/node/remote" ) -func getCalculateAPRHandler(genesisState cudoMintTypes.GenesisState, cfg config.Config, nodeClient *remote.Node, stakingClient stakingtypes.QueryClient, storage keyValueStorage) func() error { +func getCalculateAPRHandler(genesisState cudoMintTypes.GenesisState, cfg config.Config, nodeClient *remote.Node, stakingClient stakingtypes.QueryClient, + distClient distributionQueryClient, storage keyValueStorage) func() error { + return func() error { if genesisState.Minter.NormTimePassed.GT(finalNormTimePassed) { return nil @@ -27,7 +30,7 @@ func getCalculateAPRHandler(genesisState cudoMintTypes.GenesisState, cfg config. return fmt.Errorf("failed to get last block height %s", err) } - mintAmountInt, err := calculateMintedTokensSinceHeight(genesisState, cfg.Genesis.InitialHeight, latestBlockHeight, 30.43) + mintAmountInt, err := calculateMintedTokensSinceHeight(genesisState, cfg.APRGenesis.InitialHeight, latestBlockHeight, 30.43) if err != nil { return fmt.Errorf("failed to calculated minted tokens: %s", err) } @@ -42,6 +45,22 @@ func getCalculateAPRHandler(genesisState cudoMintTypes.GenesisState, cfg config. apr := mintAmountInt.ToDec().Quo(res.Pool.BondedTokens.ToDec()).MulInt64(int64(12)) + parametersResponse, err := distClient.GetParams(ctx) + if err != nil { + return fmt.Errorf("failed to get distribution parameters: %s", err) + } + + communityTax, err := sdk.NewDecFromStr(parametersResponse.CommunityTax) + if err != nil { + return fmt.Errorf("failed to parse community tax (%s): %s", parametersResponse.CommunityTax, err) + } + + communityTaxPortion := sdk.NewDec(1).Sub(communityTax) + + if communityTaxPortion.GT(sdk.NewDec(0)) { + apr = apr.Mul(communityTaxPortion) + } + if err := storage.SetValue(cfg.Storage.APRKey, apr.String()); err != nil { return fmt.Errorf("failed to set value %s for key %s", apr.String(), cfg.Storage.APRKey) } diff --git a/internal/tasks/inflation.go b/internal/tasks/inflation.go index 5e8bfa2..42f0add 100644 --- a/internal/tasks/inflation.go +++ b/internal/tasks/inflation.go @@ -88,7 +88,7 @@ func getCalculateInflationHandler(genesisState cudoMintTypes.GenesisState, cfg c var cudosNetworkTotalSupply sdk.Int for i := 0; i < len(totalSupply.Supply); i++ { - if totalSupply.Supply[i].Denom == cfg.Genesis.MintDenom { + if totalSupply.Supply[i].Denom == cfg.InflationGenesis.MintDenom { cudosNetworkTotalSupply = totalSupply.Supply[i].Amount totalSupply.Supply[i].Amount = currentTotalSupply } @@ -161,9 +161,9 @@ func getCudosNetworkCirculatingSupplyAtHeight(height int64, bankingClient bankQu var gravityModuleBalance sdk.Coin for { - gravityModuleBalance, err = bankingClient.GetBalance(ctx, height, cfg.Genesis.GravityAccountAddress, cfg.Genesis.MintDenom) + gravityModuleBalance, err = bankingClient.GetBalance(ctx, height, cfg.InflationGenesis.GravityAccountAddress, cfg.InflationGenesis.MintDenom) if err != nil { - return sdk.Int{}, fmt.Errorf("error while getting %s balance: %s", cfg.Genesis.GravityAccountAddress, err) + return sdk.Int{}, fmt.Errorf("error while getting %s balance: %s", cfg.InflationGenesis.GravityAccountAddress, err) } if !gravityModuleBalance.Amount.IsZero() { @@ -174,7 +174,7 @@ func getCudosNetworkCirculatingSupplyAtHeight(height int64, bankingClient bankQu } for i := 0; i < len(totalSupply.Supply); i++ { - if totalSupply.Supply[i].Denom == cfg.Genesis.MintDenom { + if totalSupply.Supply[i].Denom == cfg.InflationGenesis.MintDenom { return totalSupply.Supply[i].Amount.Sub(gravityModuleBalance.Amount), nil } } diff --git a/internal/tasks/tasks.go b/internal/tasks/tasks.go index 6c31dd7..4952d14 100644 --- a/internal/tasks/tasks.go +++ b/internal/tasks/tasks.go @@ -10,6 +10,7 @@ import ( "github.com/CudoVentures/cudos-stats-v2-service/internal/config" "github.com/CudoVentures/cudos-stats-v2-service/internal/erc20" "github.com/CudoVentures/cudos-stats-v2-service/internal/rest/bank" + "github.com/CudoVentures/cudos-stats-v2-service/internal/rest/distribution" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -20,32 +21,46 @@ import ( "github.com/rs/zerolog/log" ) -func ExecuteTasks(cfg config.Config, nodeClient *remote.Node, stakingClient stakingtypes.QueryClient, bankingClient bankQueryClient, storage keyValueStorage) error { - genesisState, err := createGenesisState(cfg) +func ExecuteTasks(cfg config.Config, nodeClient *remote.Node, stakingClient stakingtypes.QueryClient, bankingClient bankQueryClient, + distClient distributionQueryClient, storage keyValueStorage) error { + + inflationGenesisState, err := createGenesisState(cfg.InflationGenesis.NormTimePassed, cfg.InflationGenesis.BlocksPerDay) if err != nil { return err } - if err := getCalculateInflationHandler(*genesisState, cfg, nodeClient, bankingClient, storage)(); err != nil { + if err := getCalculateInflationHandler(*inflationGenesisState, cfg, nodeClient, bankingClient, storage)(); err != nil { return fmt.Errorf("inflation calculation failed: %s", err) } - if err := getCalculateAPRHandler(*genesisState, cfg, nodeClient, stakingClient, storage)(); err != nil { + aprGenesisState, err := createGenesisState(cfg.APRGenesis.NormTimePassed, cfg.APRGenesis.BlocksPerDay) + if err != nil { + return err + } + + if err := getCalculateAPRHandler(*aprGenesisState, cfg, nodeClient, stakingClient, distClient, storage)(); err != nil { return fmt.Errorf("apr calculation failed: %s", err) } return nil } -func RegisterTasks(scheduler *gocron.Scheduler, cfg config.Config, nodeClient *remote.Node, stakingClient stakingtypes.QueryClient, bankingClient bankQueryClient, storage keyValueStorage) error { - genesisState, err := createGenesisState(cfg) +func RegisterTasks(scheduler *gocron.Scheduler, cfg config.Config, nodeClient *remote.Node, stakingClient stakingtypes.QueryClient, bankingClient bankQueryClient, + distClient distributionQueryClient, storage keyValueStorage) error { + + inflationGenesisState, err := createGenesisState(cfg.InflationGenesis.NormTimePassed, cfg.InflationGenesis.BlocksPerDay) + if err != nil { + return err + } + + aprGenesisState, err := createGenesisState(cfg.APRGenesis.NormTimePassed, cfg.APRGenesis.BlocksPerDay) if err != nil { return err } if _, err := scheduler.Every(1).Day().At("00:00").Do(func() { - watchMethod(getCalculateInflationHandler(*genesisState, cfg, nodeClient, bankingClient, storage)) - watchMethod(getCalculateAPRHandler(*genesisState, cfg, nodeClient, stakingClient, storage)) + watchMethod(getCalculateInflationHandler(*inflationGenesisState, cfg, nodeClient, bankingClient, storage)) + watchMethod(getCalculateAPRHandler(*aprGenesisState, cfg, nodeClient, stakingClient, distClient, storage)) }); err != nil { return fmt.Errorf("scheduler failed to register tasks: %s", err) } @@ -164,15 +179,15 @@ func calculateMintedCoins(minter cudoMintTypes.Minter, increment sdk.Dec) sdk.De return (nextStep.Sub(prevStep)).Mul(sdk.NewDec(10).Power(24)) // formula calculates in mil of cudos + converting to acudos } -func createGenesisState(cfg config.Config) (*cudoMintTypes.GenesisState, error) { - normTimePassed, err := sdk.NewDecFromStr(cfg.Genesis.NormTimePassed) +func createGenesisState(normTimePassedStr, blocksPerDayStr string) (*cudoMintTypes.GenesisState, error) { + normTimePassed, err := sdk.NewDecFromStr(normTimePassedStr) if err != nil { - return nil, fmt.Errorf("failed to parse NormTimePassed %s: %s", cfg.Genesis.NormTimePassed, err) + return nil, fmt.Errorf("failed to parse NormTimePassed %s: %s", normTimePassedStr, err) } - blocksPerDay, ok := sdk.NewIntFromString(cfg.Genesis.BlocksPerDay) + blocksPerDay, ok := sdk.NewIntFromString(blocksPerDayStr) if !ok { - return nil, fmt.Errorf("failed to parse BlocksPerDay %s", cfg.Genesis.BlocksPerDay) + return nil, fmt.Errorf("failed to parse BlocksPerDay %s", blocksPerDayStr) } return cudoMintTypes.NewGenesisState(cudoMintTypes.NewMinter(sdk.NewDec(0), normTimePassed), cudoMintTypes.NewParams(blocksPerDay)), nil @@ -210,3 +225,7 @@ type bankQueryClient interface { GetTotalSupply(ctx context.Context, height int64) (bank.TotalSupplyResponse, error) GetBalance(ctx context.Context, height int64, address, denom string) (sdk.Coin, error) } + +type distributionQueryClient interface { + GetParams(ctx context.Context) (distribution.ParametersResponse, error) +} From ec0d80bb2864f0ffe584aa8dc442c2aa8c88181f Mon Sep 17 00:00:00 2001 From: Nathan Baum Date: Thu, 1 Sep 2022 16:04:44 +0100 Subject: [PATCH 2/6] Correct norm_time-passed for block 1068800 --- config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.yaml b/config.yaml index da6f1c5..1a406bf 100644 --- a/config.yaml +++ b/config.yaml @@ -7,7 +7,7 @@ inflation_genesis: gravity_account_address: cudos16n3lc7cywa68mg50qhp847034w88pntq8823tx apr_genesis: initial_height: 1068800 - norm_time_passed: 0.852119746111849790 + norm_time_passed: 0.701091267050712000 blocks_per_day: 12345 mint_denom: acudos gravity_account_address: cudos16n3lc7cywa68mg50qhp847034w88pntq8823tx From c6b2f21b4c4df80f7f1466d91bf83569055383a0 Mon Sep 17 00:00:00 2001 From: Nathan Baum Date: Thu, 1 Sep 2022 16:25:58 +0100 Subject: [PATCH 3/6] Compute APR using the real blocks per day --- config.yaml | 1 + internal/config/config.go | 1 + internal/tasks/apr.go | 8 +++++++- internal/tasks/tasks.go | 8 ++++++-- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/config.yaml b/config.yaml index 1a406bf..7898245 100644 --- a/config.yaml +++ b/config.yaml @@ -8,6 +8,7 @@ inflation_genesis: apr_genesis: initial_height: 1068800 norm_time_passed: 0.701091267050712000 + real_blocks_per_day: 14048 blocks_per_day: 12345 mint_denom: acudos gravity_account_address: cudos16n3lc7cywa68mg50qhp847034w88pntq8823tx diff --git a/internal/config/config.go b/internal/config/config.go index 3a014b4..df6927f 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -37,6 +37,7 @@ type Config struct { APRGenesis struct { InitialHeight int64 `yaml:"initial_height"` NormTimePassed string `yaml:"norm_time_passed"` + RealBlocksPerDay string `yaml:"real_blocks_per_day"` BlocksPerDay string `yaml:"blocks_per_day"` MintDenom string `yaml:"mint_denom"` GravityAccountAddress string `yaml:"gravity_account_address"` diff --git a/internal/tasks/apr.go b/internal/tasks/apr.go index 4b2952f..2b13e1d 100644 --- a/internal/tasks/apr.go +++ b/internal/tasks/apr.go @@ -9,6 +9,7 @@ import ( cudoMintTypes "github.com/CudoVentures/cudos-node/x/cudoMint/types" "github.com/CudoVentures/cudos-stats-v2-service/internal/config" sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/forbole/juno/v2/node/remote" ) @@ -30,7 +31,12 @@ func getCalculateAPRHandler(genesisState cudoMintTypes.GenesisState, cfg config. return fmt.Errorf("failed to get last block height %s", err) } - mintAmountInt, err := calculateMintedTokensSinceHeight(genesisState, cfg.APRGenesis.InitialHeight, latestBlockHeight, 30.43) + realBlocksPerDay, ok := sdk.NewIntFromString(cfg.APRGenesis.RealBlocksPerDay) + if !ok { + return fmt.Errorf("failed to parse RealBlocksPerDay %s", cfg.APRGenesis.RealBlocksPerDay) + } + + mintAmountInt, err := calculateMintedTokensSinceHeight(genesisState, cfg.APRGenesis.InitialHeight, latestBlockHeight, 30.43, realBlocksPerDay) if err != nil { return fmt.Errorf("failed to calculated minted tokens: %s", err) } diff --git a/internal/tasks/tasks.go b/internal/tasks/tasks.go index 4952d14..3f9a194 100644 --- a/internal/tasks/tasks.go +++ b/internal/tasks/tasks.go @@ -104,7 +104,7 @@ func getEthAccountsBalanceAtBlock(client *ethclient.Client, tokenAddress string, return totalBalance, nil } -func calculateMintedTokensSinceHeight(mintParams cudoMintTypes.GenesisState, genesisInitialHeight, sinceBlock int64, periodDays float64) (sdk.Int, error) { +func calculateMintedTokensSinceHeight(mintParams cudoMintTypes.GenesisState, genesisInitialHeight, sinceBlock int64, periodDays float64, realBlocksPerDay sdk.Int) (sdk.Int, error) { minter := mintParams.Minter params := mintParams.Params @@ -115,7 +115,11 @@ func calculateMintedTokensSinceHeight(mintParams cudoMintTypes.GenesisState, gen minter.NormTimePassed = updateNormTimePassed(mintParams, genesisInitialHeight, sinceBlock) mintAmountInt := sdk.NewInt(0) - totalBlocks := int64(float64(mintParams.Params.BlocksPerDay.Int64()) * periodDays) + + // We have to predict what the block count will be periodDays from now. Because + // mintParams.Params.BlocksPerDay is intentionally wrong, using that would give + // us the wrong result. We use the "real blocks per day" instead. + totalBlocks := int64(float64(realBlocksPerDay.Int64()) * periodDays) for height := int64(1); height <= totalBlocks; height++ { if minter.NormTimePassed.GT(finalNormTimePassed) { From 50b4ba18266b3b7c894748e51619108b9ef1e65b Mon Sep 17 00:00:00 2001 From: Nathan Baum Date: Thu, 1 Sep 2022 16:34:23 +0100 Subject: [PATCH 4/6] Tidy away unnecessary whitespace change --- internal/tasks/apr.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/tasks/apr.go b/internal/tasks/apr.go index 2b13e1d..0afb31b 100644 --- a/internal/tasks/apr.go +++ b/internal/tasks/apr.go @@ -9,7 +9,6 @@ import ( cudoMintTypes "github.com/CudoVentures/cudos-node/x/cudoMint/types" "github.com/CudoVentures/cudos-stats-v2-service/internal/config" sdk "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/forbole/juno/v2/node/remote" ) From 6a136e03ee432effaebf553009bf809928532c28 Mon Sep 17 00:00:00 2001 From: Nathan Baum Date: Thu, 1 Sep 2022 16:36:09 +0100 Subject: [PATCH 5/6] Ignore stats-service binary --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b2a7934..0233afa 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,6 @@ # Go workspace file go.work -cmd/stats-service/stats-service \ No newline at end of file +cmd/stats-service/stats-service + +/stats-service From c20700b2130eac666206c379001c0f0268f61b3c Mon Sep 17 00:00:00 2001 From: Nathan Baum Date: Fri, 2 Sep 2022 10:16:21 +0100 Subject: [PATCH 6/6] Use correct block height for APR fix --- config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.yaml b/config.yaml index 7898245..73c6b01 100644 --- a/config.yaml +++ b/config.yaml @@ -6,8 +6,8 @@ inflation_genesis: mint_denom: acudos gravity_account_address: cudos16n3lc7cywa68mg50qhp847034w88pntq8823tx apr_genesis: - initial_height: 1068800 - norm_time_passed: 0.701091267050712000 + initial_height: 1069391 + norm_time_passed: 0.701184759708210690 real_blocks_per_day: 14048 blocks_per_day: 12345 mint_denom: acudos