diff --git a/app/upgrades/v0.2.0/constants.go b/app/upgrades/v0.2.0/constants.go new file mode 100644 index 0000000000..42f8b16cb2 --- /dev/null +++ b/app/upgrades/v0.2.0/constants.go @@ -0,0 +1,14 @@ +package vx + +import ( + store "github.com/cosmos/cosmos-sdk/store/types" + "github.com/lavanet/lava/app/upgrades" +) + +const UpgradeName = "vx" + +var Upgrade = upgrades.Upgrade{ + UpgradeName: UpgradeName, // upgrade name defined few lines above + CreateUpgradeHandler: CreateUpgradeHandler, // create CreateUpgradeHandler in upgrades.go below + StoreUpgrades: store.StoreUpgrades{}, // StoreUpgrades has 3 fields: Added/Renamed/Deleted any module that fits these description should be added in the way below +} diff --git a/app/upgrades/v0.2.0/upgrade_test.go b/app/upgrades/v0.2.0/upgrade_test.go new file mode 100644 index 0000000000..7adf0dad04 --- /dev/null +++ b/app/upgrades/v0.2.0/upgrade_test.go @@ -0,0 +1,47 @@ +//go:build ignore + +package vx_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ignite-hq/cli/ignite/pkg/cosmoscmd" + keepertest "github.com/lavanet/lava/testutil/keeper" + v020 "github.com/lavanet/lava/x/spec/migrations/v0.2.0" + "github.com/stretchr/testify/suite" +) + +type UpgradeTestSuite struct { + suite.Suite + + ctx sdk.Context + app cosmoscmd.App +} + +func (suite *UpgradeTestSuite) SetupTestApp() { + suite.app, suite.ctx = app.TestSetup() +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(UpgradeTestSuite)) +} + +func (suite *UpgradeTestSuite) TestBody() { + suite.SetupTestApp() // setup test app + suite.T().Log("test") +} + +func (suite *UpgradeTestSuite) TestAddingBlockLastUpdated() { + _, keepers, ctx := keepertest.InitAllKeepers(suite.T()) + sdkctx := sdk.UnwrapSDKContext(ctx) + suite.T().Log("TestAddingBlockLastUpdated") + + migrator := v020.NewMigrator(keepers.Spec) + migrator.MigrateToV020(sdkctx) + + allSpec := keepers.Spec.GetAllSpec(sdk.UnwrapSDKContext(ctx)) + for _, spec := range allSpec { + suite.Require().Equal(0, spec.BlockLastUpdated) + } +} diff --git a/app/upgrades/v0.2.0/upgrades.go b/app/upgrades/v0.2.0/upgrades.go new file mode 100644 index 0000000000..4d9d723d73 --- /dev/null +++ b/app/upgrades/v0.2.0/upgrades.go @@ -0,0 +1,31 @@ +package vx + +import ( + "log" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + "github.com/lavanet/lava/app/keepers" + "github.com/lavanet/lava/app/upgrades" + v020 "github.com/lavanet/lava/x/spec/migrations/v0.2.0" +) + +func CreateUpgradeHandler( + mm *module.Manager, + configurator module.Configurator, + bpm upgrades.BaseAppParamManager, + keepers *keepers.LavaKeepers, +) upgradetypes.UpgradeHandler { + return func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + log.Println("########################") + log.Println("# STARTING UPGRADE #") + log.Println("########################") + + // delete all existing conflicts + migrator := v020.NewMigrator(keepers.SpecKeeper) + migrator.MigrateToV020(ctx) + + return mm.RunMigrations(ctx, configurator, vm) + } +} diff --git a/docs/static/openapi.yml b/docs/static/openapi.yml index 9a2d2c5f24..7e304223b8 100644 --- a/docs/static/openapi.yml +++ b/docs/static/openapi.yml @@ -30390,6 +30390,15 @@ paths: type: string moniker: type: string + currentEpoch: + type: string + format: uint64 + timeLeftToNextPairing: + type: string + format: uint64 + specLastUpdatedBlock: + type: string + format: uint64 default: description: An unexpected error response. schema: @@ -31360,6 +31369,9 @@ paths: allowed_block_lag_for_qos_sync: type: string format: int64 + block_last_updated: + type: string + format: uint64 pagination: type: object properties: @@ -31606,6 +31618,9 @@ paths: allowed_block_lag_for_qos_sync: type: string format: int64 + block_last_updated: + type: string + format: uint64 default: description: An unexpected error response. schema: @@ -53354,8 +53369,6 @@ definitions: CacheMisses: type: string format: uint64 - lavanet.lava.pairing.Empty: - type: object lavanet.lava.pairing.EpochPayments: type: object properties: @@ -53749,6 +53762,15 @@ definitions: type: string moniker: type: string + currentEpoch: + type: string + format: uint64 + timeLeftToNextPairing: + type: string + format: uint64 + specLastUpdatedBlock: + type: string + format: uint64 lavanet.lava.pairing.QueryGetProviderPaymentStorageResponse: type: object properties: @@ -54190,6 +54212,9 @@ definitions: allowed_block_lag_for_qos_sync: type: string format: int64 + block_last_updated: + type: string + format: uint64 pagination: type: object properties: @@ -54349,6 +54374,9 @@ definitions: allowed_block_lag_for_qos_sync: type: string format: int64 + block_last_updated: + type: string + format: uint64 lavanet.lava.spec.QueryParamsResponse: type: object properties: @@ -54624,6 +54652,9 @@ definitions: allowed_block_lag_for_qos_sync: type: string format: int64 + block_last_updated: + type: string + format: uint64 lavanet.lava.spec.SpecCategory: type: object properties: diff --git a/go.mod b/go.mod index 2ab4a72448..375ec23ce8 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/stretchr/testify v1.8.0 github.com/tendermint/tendermint v0.34.23 github.com/tendermint/tm-db v0.6.7 - google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 + google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37 google.golang.org/grpc v1.51.0 google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 gopkg.in/yaml.v2 v2.4.0 @@ -197,11 +197,11 @@ require ( go.opencensus.io v0.23.0 // indirect golang.org/x/crypto v0.1.0 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e - golang.org/x/net v0.2.0 + golang.org/x/net v0.3.0 golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.2.0 // indirect - golang.org/x/term v0.2.0 // indirect - golang.org/x/text v0.4.0 // indirect + golang.org/x/sys v0.3.0 // indirect + golang.org/x/term v0.3.0 // indirect + golang.org/x/text v0.5.0 // indirect golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce diff --git a/go.sum b/go.sum index c9e43f05e9..b655146c38 100644 --- a/go.sum +++ b/go.sum @@ -1646,8 +1646,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1784,14 +1784,14 @@ golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1801,8 +1801,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1976,8 +1976,8 @@ google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37 h1:jmIfw8+gSvXcZSgaFAGyInDXeWzUhvYH57G/5GKMn70= +google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= diff --git a/proto/pairing/query.proto b/proto/pairing/query.proto index cd33fe7736..891a229ca0 100644 --- a/proto/pairing/query.proto +++ b/proto/pairing/query.proto @@ -111,6 +111,9 @@ message QueryGetPairingRequest { message QueryGetPairingResponse { repeated lavanet.lava.epochstorage.StakeEntry providers = 1 [(gogoproto.nullable) = false]; + uint64 currentEpoch = 2; + uint64 timeLeftToNextPairing = 3; + uint64 specLastUpdatedBlock = 4; } message QueryVerifyPairingRequest { diff --git a/proto/spec/spec.proto b/proto/spec/spec.proto index 93719f8d5a..2f64bd46d5 100644 --- a/proto/spec/spec.proto +++ b/proto/spec/spec.proto @@ -19,4 +19,5 @@ message Spec { uint32 blocks_in_finalization_proof = 8; int64 average_block_time =9; int64 allowed_block_lag_for_qos_sync = 10; + uint64 block_last_updated = 11; } \ No newline at end of file diff --git a/testutil/keeper/keepers_init.go b/testutil/keeper/keepers_init.go index 63bedd7d0d..683a903d10 100644 --- a/testutil/keeper/keepers_init.go +++ b/testutil/keeper/keepers_init.go @@ -3,6 +3,7 @@ package keeper import ( "context" "testing" + "time" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -25,9 +26,12 @@ import ( "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/rpc/core" + tenderminttypes "github.com/tendermint/tendermint/types" tmdb "github.com/tendermint/tm-db" ) +const BLOCK_TIME = 30 * time.Second + type Keepers struct { Epochstorage epochstoragekeeper.Keeper Spec speckeeper.Keeper @@ -36,6 +40,7 @@ type Keepers struct { BankKeeper mockBankKeeper AccountKeeper mockAccountKeeper ParamsKeeper paramskeeper.Keeper + BlockStore MockBlockStore } type Servers struct { @@ -112,6 +117,7 @@ func InitAllKeepers(t testing.TB) (*Servers, *Keepers, context.Context) { ks.Pairing = *pairingkeeper.NewKeeper(cdc, pairingStoreKey, pairingMemStoreKey, pairingparamsSubspace, &ks.BankKeeper, &ks.AccountKeeper, ks.Spec, &ks.Epochstorage) ks.ParamsKeeper = paramsKeeper ks.Conflict = *conflictkeeper.NewKeeper(cdc, conflictStoreKey, conflictMemStoreKey, conflictparamsSubspace, &ks.BankKeeper, &ks.AccountKeeper, ks.Pairing, ks.Epochstorage, ks.Spec) + ks.BlockStore = MockBlockStore{height: 0, blockHistory: make(map[int64]*tenderminttypes.Block)} ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.TestingLogger()) @@ -129,62 +135,80 @@ func InitAllKeepers(t testing.TB) (*Servers, *Keepers, context.Context) { ss.PairingServer = pairingkeeper.NewMsgServerImpl(ks.Pairing) ss.ConflictServer = conflictkeeper.NewMsgServerImpl(ks.Conflict) + core.SetEnvironment(&core.Environment{BlockStore: &ks.BlockStore}) + ks.Epochstorage.SetEpochDetails(ctx, *epochstoragetypes.DefaultGenesis().EpochDetails) NewBlock(sdk.WrapSDKContext(ctx), &ks) return &ss, &ks, sdk.WrapSDKContext(ctx) } -func AdvanceBlock(ctx context.Context, ks *Keepers) context.Context { +func AdvanceBlock(ctx context.Context, ks *Keepers, customBlockTime ...time.Duration) context.Context { unwrapedCtx := sdk.UnwrapSDKContext(ctx) block := uint64(unwrapedCtx.BlockHeight() + 1) unwrapedCtx = unwrapedCtx.WithBlockHeight(int64(block)) - - NewBlock(sdk.WrapSDKContext(unwrapedCtx), ks) - + if len(customBlockTime) > 0 { + NewBlock(sdk.WrapSDKContext(unwrapedCtx), ks, customBlockTime...) + } else { + NewBlock(sdk.WrapSDKContext(unwrapedCtx), ks) + } return sdk.WrapSDKContext(unwrapedCtx) } -func AdvanceBlocks(ctx context.Context, ks *Keepers, blocks int) context.Context { - for i := 0; i < blocks; i++ { - ctx = AdvanceBlock(ctx, ks) +func AdvanceBlocks(ctx context.Context, ks *Keepers, blocks int, customBlockTime ...time.Duration) context.Context { + if len(customBlockTime) > 0 { + for i := 0; i < blocks; i++ { + ctx = AdvanceBlock(ctx, ks, customBlockTime...) + } + } else { + for i := 0; i < blocks; i++ { + ctx = AdvanceBlock(ctx, ks) + } } return ctx } -func AdvanceToBlock(ctx context.Context, ks *Keepers, block uint64) context.Context { +func AdvanceToBlock(ctx context.Context, ks *Keepers, block uint64, customBlockTime ...time.Duration) context.Context { unwrapedCtx := sdk.UnwrapSDKContext(ctx) if uint64(unwrapedCtx.BlockHeight()) == block { return ctx } - for uint64(unwrapedCtx.BlockHeight()) < block { - ctx = AdvanceBlock(ctx, ks) - unwrapedCtx = sdk.UnwrapSDKContext(ctx) + if len(customBlockTime) > 0 { + for uint64(unwrapedCtx.BlockHeight()) < block { + ctx = AdvanceBlock(ctx, ks, customBlockTime...) + unwrapedCtx = sdk.UnwrapSDKContext(ctx) + } + } else { + for uint64(unwrapedCtx.BlockHeight()) < block { + ctx = AdvanceBlock(ctx, ks) + unwrapedCtx = sdk.UnwrapSDKContext(ctx) + } } return ctx } // Make sure you save the new context -func AdvanceEpoch(ctx context.Context, ks *Keepers) context.Context { +func AdvanceEpoch(ctx context.Context, ks *Keepers, customBlockTime ...time.Duration) context.Context { unwrapedCtx := sdk.UnwrapSDKContext(ctx) nextEpochBlockNum, err := ks.Epochstorage.GetNextEpoch(unwrapedCtx, ks.Epochstorage.GetEpochStart(unwrapedCtx)) if err != nil { panic(err) } - + if len(customBlockTime) > 0 { + return AdvanceToBlock(ctx, ks, nextEpochBlockNum, customBlockTime...) + } return AdvanceToBlock(ctx, ks, nextEpochBlockNum) } // Make sure you save the new context -func NewBlock(ctx context.Context, ks *Keepers) { +func NewBlock(ctx context.Context, ks *Keepers, customTime ...time.Duration) { unwrapedCtx := sdk.UnwrapSDKContext(ctx) + block := uint64(unwrapedCtx.BlockHeight()) if ks.Epochstorage.IsEpochStart(sdk.UnwrapSDKContext(ctx)) { - block := uint64(unwrapedCtx.BlockHeight()) - ks.Epochstorage.FixateParams(unwrapedCtx, block) // begin block ks.Epochstorage.SetEpochDetailsStart(unwrapedCtx, block) @@ -201,7 +225,9 @@ func NewBlock(ctx context.Context, ks *Keepers) { ks.Conflict.CheckAndHandleAllVotes(unwrapedCtx) - blockstore := MockBlockStore{} - blockstore.SetHeight(sdk.UnwrapSDKContext(ctx).BlockHeight()) - core.SetEnvironment(&core.Environment{BlockStore: &blockstore}) + if len(customTime) > 0 { + ks.BlockStore.AdvanceBlock(customTime[0]) + } else { + ks.BlockStore.AdvanceBlock(BLOCK_TIME) + } } diff --git a/testutil/keeper/mock_keepers.go b/testutil/keeper/mock_keepers.go index bca6f50d21..3027824bdc 100644 --- a/testutil/keeper/mock_keepers.go +++ b/testutil/keeper/mock_keepers.go @@ -2,6 +2,7 @@ package keeper import ( "fmt" + "time" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -111,13 +112,36 @@ func (k *mockBankKeeper) SubFromBalance(addr sdk.AccAddress, amounts sdk.Coins) } type MockBlockStore struct { - height int64 + height int64 + blockHistory map[int64]*tenderminttypes.Block } func (b *MockBlockStore) SetHeight(height int64) { b.height = height } +func (b *MockBlockStore) AdvanceBlock(blockTime time.Duration) { + // keep block height in mock blockstore + blockInt64 := b.height + 1 + b.SetHeight(blockInt64) + + // create mock block header + blockHeader := tenderminttypes.Header{} + blockHeader.Height = blockInt64 + if prevBlock, ok := b.blockHistory[b.height-1]; ok { + blockHeader.Time = prevBlock.Time.Add(blockTime) + } else { + blockHeader.Time = time.Now() + } + + // update the blockstore's block history with current block + b.SetBlockHistoryEntry(blockInt64, &tenderminttypes.Block{Header: blockHeader}) +} + +func (b *MockBlockStore) SetBlockHistoryEntry(height int64, blockCore *tenderminttypes.Block) { + b.blockHistory[height] = blockCore +} + func (b *MockBlockStore) Base() int64 { return 0 } @@ -139,7 +163,7 @@ func (b *MockBlockStore) LoadBlockMeta(height int64) *tenderminttypes.BlockMeta } func (b *MockBlockStore) LoadBlock(height int64) *tenderminttypes.Block { - return &tenderminttypes.Block{} + return b.blockHistory[height] } func (b *MockBlockStore) SaveBlock(block *tenderminttypes.Block, blockParts *tenderminttypes.PartSet, seenCommit *tenderminttypes.Commit) { diff --git a/x/pairing/keeper/grpc_query_get_pairing.go b/x/pairing/keeper/grpc_query_get_pairing.go index 524f255ea6..10a0b109e6 100644 --- a/x/pairing/keeper/grpc_query_get_pairing.go +++ b/x/pairing/keeper/grpc_query_get_pairing.go @@ -6,11 +6,13 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/lavanet/lava/utils" "github.com/lavanet/lava/x/pairing/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) +// Gets a client's provider list in a specific chain. Also returns the start block of the current epoch, time (in seconds) until there's a new pairing, the block that the chain in the request's spec was changed func (k Keeper) GetPairing(goCtx context.Context, req *types.QueryGetPairingRequest) (*types.QueryGetPairingResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "invalid request") @@ -18,20 +20,42 @@ func (k Keeper) GetPairing(goCtx context.Context, req *types.QueryGetPairingRequ ctx := sdk.UnwrapSDKContext(goCtx) // TODO: validate chainID - + // check client address clientAddr, err := sdk.AccAddressFromBech32(req.Client) if err != nil { return nil, fmt.Errorf("invalid creator address %s error: %s", req.Client, err) } + // Make sure the chain ID exists and the chain's functional foundAndActive, _ := k.specKeeper.IsSpecFoundAndActive(ctx, req.ChainID) // TODO: handle spec changes if !foundAndActive { return nil, errors.New("spec not found or not enabled") } + + // Get pairing list for latest block providers, err := k.GetPairingForClient(ctx, req.ChainID, clientAddr) if err != nil { return nil, fmt.Errorf("could not get pairing for chainID: %s, client addr: %s, blockHeight: %d, err: %s", req.ChainID, clientAddr, ctx.BlockHeight(), err) } - return &types.QueryGetPairingResponse{Providers: providers}, nil + + // Calculate the time left until the new epoch (when epoch changes, new pairing is generated) + timeLeftToNextPairing, err := k.calculateNextEpochTime(ctx) + if err != nil { + // we don't want to fail the query if the calculateNextEpochTime function fails. This shouldn't happen, it's a fail-safe + utils.LavaFormatError("calculate next epoch time failed. Returning default time=0", err, nil) + timeLeftToNextPairing = 0 + } + + // Get current epoch start block + currentEpoch := k.epochStorageKeeper.GetEpochStart(ctx) + + // Get the block in which there was the latest change for the current spec + spec, found := k.specKeeper.GetSpec(ctx, req.GetChainID()) + if !found { + return nil, errors.New("spec not found or not enabled") + } + specLastUpdatedBlock := spec.BlockLastUpdated + + return &types.QueryGetPairingResponse{Providers: providers, CurrentEpoch: currentEpoch, TimeLeftToNextPairing: timeLeftToNextPairing, SpecLastUpdatedBlock: specLastUpdatedBlock}, nil } diff --git a/x/pairing/keeper/msg_server_relay_payment_test.go b/x/pairing/keeper/msg_server_relay_payment_test.go index 4779be626a..cf769dc9a1 100644 --- a/x/pairing/keeper/msg_server_relay_payment_test.go +++ b/x/pairing/keeper/msg_server_relay_payment_test.go @@ -1037,8 +1037,10 @@ func TestRelayPaymentDataReliability(t *testing.T) { require.Nil(t, err) vrfRes0, _ := utils.CalculateVrfOnRelay(relayRequest, relayReply, ts.clients[0].vrfSk, currentEpoch) + require.Nil(t, err) - index0, _ = utils.GetIndexForVrf(vrfRes0, uint32(ts.keepers.Pairing.ServicersToPairCountRaw(sdk.UnwrapSDKContext(ts.ctx))), ts.spec.ReliabilityThreshold) + index0, err = utils.GetIndexForVrf(vrfRes0, uint32(ts.keepers.Pairing.ServicersToPairCountRaw(sdk.UnwrapSDKContext(ts.ctx))), ts.spec.ReliabilityThreshold) + require.Nil(t, err) providers, err = ts.keepers.Pairing.GetPairingForClient(sdk.UnwrapSDKContext(ts.ctx), relayRequest.ChainID, ts.clients[0].address) require.Nil(t, err) diff --git a/x/pairing/keeper/pairing.go b/x/pairing/keeper/pairing.go index 23778ab57f..6dd8f34da0 100644 --- a/x/pairing/keeper/pairing.go +++ b/x/pairing/keeper/pairing.go @@ -2,12 +2,15 @@ package keeper import ( "fmt" + "math" "math/big" "strconv" + "time" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/utils" epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types" + pairingtypes "github.com/lavanet/lava/x/pairing/types" tendermintcrypto "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/rpc/core" ) @@ -76,6 +79,7 @@ func (k Keeper) VerifyPairingData(ctx sdk.Context, chainID string, clientAddress // first argument has all metadata, second argument is only the addresses func (k Keeper) GetPairingForClient(ctx sdk.Context, chainID string, clientAddress sdk.AccAddress) (providers []epochstoragetypes.StakeEntry, errorRet error) { currentEpoch := k.epochStorageKeeper.GetEpochStart(ctx) + clientStakeEntry, err := k.VerifyPairingData(ctx, chainID, clientAddress, currentEpoch) if err != nil { // user is not valid for pairing @@ -217,3 +221,136 @@ func (k Keeper) returnSubsetOfProvidersByStake(ctx sdk.Context, clientAddress sd } return returnedProviders } + +const ( + EPOCH_BLOCK_DIVIDER uint64 = 5 // determines how many blocks from the previous epoch will be included in the average block time calculation + MIN_SAMPLE_STEP uint64 = 1 // the minimal sample step when calculating the average block time +) + +// Function to calculate how much time (in seconds) is left until the next epoch +func (k Keeper) calculateNextEpochTime(ctx sdk.Context) (uint64, error) { + // Get current epoch + currentEpoch := k.epochStorageKeeper.GetEpochStart(ctx) + + // Calculate the average block time (i.e., how much time it takes to create a new block, in average) + averageBlockTime, err := k.calculateAverageBlockTime(ctx, currentEpoch) + if err != nil { + return 0, fmt.Errorf("could not calculate average block time, err: %s", err) + } + + // Get the next epoch + nextEpochStart, err := k.epochStorageKeeper.GetNextEpoch(ctx, currentEpoch) + if err != nil { + return 0, fmt.Errorf("could not get next epoch start, err: %s", err) + } + + // Get epochBlocksOverlap + overlapBlocks := k.EpochBlocksOverlap(ctx) + + // Get number of blocks from the current block to the next epoch + blocksUntilNewEpoch := nextEpochStart + overlapBlocks - uint64(ctx.BlockHeight()) + + // Calculate the time left for the next pairing in seconds (blocks left * avg block time) + timeLeftToNextEpoch := blocksUntilNewEpoch * averageBlockTime + + return timeLeftToNextEpoch, nil +} + +// Function to calculate the average block time (i.e., how much time it takes to create a new block, in average) +func (k Keeper) calculateAverageBlockTime(ctx sdk.Context, epoch uint64) (uint64, error) { + // Get epochBlocks (the number of blocks in an epoch) + epochBlocks, err := k.epochStorageKeeper.EpochBlocks(ctx, epoch) + if err != nil { + return 0, fmt.Errorf("could not get epochBlocks, err: %s", err) + } + + // Define sample step. Determines which timestamps will be taken in the average block time calculation. + // if epochBlock < EPOCH_BLOCK_DIVIDER -> sampleStep = MIN_SAMPLE_STEP. + // else sampleStep will be epochBlocks/EPOCH_BLOCK_DIVIDER + if MIN_SAMPLE_STEP > epochBlocks { + return 0, fmt.Errorf("invalid MIN_SAMPLE_STEP value since it's larger than epochBlocks. MIN_SAMPLE_STEP: %v, epochBlocks: %v", MIN_SAMPLE_STEP, epochBlocks) + } + sampleStep := MIN_SAMPLE_STEP + if epochBlocks > EPOCH_BLOCK_DIVIDER { + sampleStep = epochBlocks / EPOCH_BLOCK_DIVIDER + } + + // Get a list of the previous epoch's blocks timestamp and height + prevEpochTimestampAndHeightList, err := k.getPreviousEpochTimestampsByHeight(ctx, epoch, sampleStep) + if pairingtypes.NoPreviousEpochForAverageBlockTimeCalculationError.Is(err) || pairingtypes.PreviousEpochStartIsBlockZeroError.Is(err) { + // if the errors indicate that we're on the first epoch / after a fork or previous epoch start is 0, we return averageBlockTime=0 without an error + return 0, nil + } + if err != nil { + return 0, fmt.Errorf("couldn't get prevEpochTimestampAndHeightList. err: %v", err) + } + + // Calculate the average block time from prevEpochTimestampAndHeightList + averageBlockTime, err := calculateAverageBlockTimeFromList(ctx, prevEpochTimestampAndHeightList, sampleStep) + if pairingtypes.NotEnoughBlocksToCalculateAverageBlockTimeError.Is(err) || pairingtypes.AverageBlockTimeIsLessOrEqualToZeroError.Is(err) { + // we shouldn't fail the get-pairing query because the average block time calculation failed (to indicate the fail, we return 0) + return 0, nil + } + if err != nil { + return 0, fmt.Errorf("couldn't calculate average block time. err: %v", err) + } + + return averageBlockTime, nil +} + +type blockHeightAndTime struct { + blockHeight uint64 + blockTime time.Time +} + +// Function to get a list of the timestamps of the blocks in the previous epoch of the input (so it'll be deterministic) +func (k Keeper) getPreviousEpochTimestampsByHeight(ctx sdk.Context, epoch uint64, sampleStep uint64) ([]blockHeightAndTime, error) { + // Check for special cases: + // 1. no previous epoch - we're on the first epoch / after a fork. Since there is no previous epoch to calculate average time on, return an empty slice and no error + // 2. start of previous epoch is block 0 - we're on the second epoch. To get the block's header using the "core" module, the block height can't be zero (causes panic). In this case, we also return an empty slice and no error + prevEpoch, err := k.epochStorageKeeper.GetPreviousEpochStartForBlock(ctx, epoch) + if err != nil { + return nil, pairingtypes.NoPreviousEpochForAverageBlockTimeCalculationError + } else if prevEpoch == 0 { + return nil, pairingtypes.PreviousEpochStartIsBlockZeroError + } + + // Get previous epoch timestamps, in sampleStep steps + prevEpochTimestampAndHeightList := []blockHeightAndTime{} + for block := prevEpoch; block <= epoch; block += sampleStep { + // Get current block's height and timestamp + blockInt64 := int64(block) + blockCore, err := core.Block(nil, &blockInt64) + if err != nil { + return nil, fmt.Errorf("could not get current block header, block: %v, err: %s", blockInt64, err) + } + currentBlockTimestamp := blockCore.Block.Header.Time.UTC() + blockHeightAndTimeStruct := blockHeightAndTime{blockHeight: block, blockTime: currentBlockTimestamp} + + // Append the timestamp to the timestamp list + prevEpochTimestampAndHeightList = append(prevEpochTimestampAndHeightList, blockHeightAndTimeStruct) + } + + return prevEpochTimestampAndHeightList, nil +} + +func calculateAverageBlockTimeFromList(ctx sdk.Context, blockHeightAndTimeList []blockHeightAndTime, sampleStep uint64) (uint64, error) { + if len(blockHeightAndTimeList) <= 1 { + return 0, utils.LavaFormatError("There isn't enough blockHeight structs in the previous epoch to calculate average block time", pairingtypes.NotEnoughBlocksToCalculateAverageBlockTimeError, nil) + } + + averageBlockTime := time.Duration(math.MaxInt64) + for i := 1; i < len(blockHeightAndTimeList); i++ { + // Calculate the average block time creation over sampleStep blocks + currentAverageBlockTime := blockHeightAndTimeList[i].blockTime.Sub(blockHeightAndTimeList[i-1].blockTime) / time.Duration(sampleStep) + if currentAverageBlockTime <= 0 { + return 0, utils.LavaFormatError("calculated average block time is less than or equal to zero", pairingtypes.AverageBlockTimeIsLessOrEqualToZeroError, &map[string]string{"block": fmt.Sprintf("%v", blockHeightAndTimeList[i].blockHeight), "block timestamp": blockHeightAndTimeList[i].blockTime.String(), "prevBlock": fmt.Sprintf("%v", blockHeightAndTimeList[i-1].blockHeight), "prevBlock timestamp": blockHeightAndTimeList[i-1].blockTime.String()}) + } + // save the minimal average block time + if averageBlockTime > currentAverageBlockTime { + averageBlockTime = currentAverageBlockTime + } + } + + return uint64(averageBlockTime.Seconds()), nil +} diff --git a/x/pairing/keeper/pairing_test.go b/x/pairing/keeper/pairing_test.go index 0c70659856..b23d10cfda 100644 --- a/x/pairing/keeper/pairing_test.go +++ b/x/pairing/keeper/pairing_test.go @@ -2,10 +2,12 @@ package keeper_test import ( "testing" + "time" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/lavanet/lava/testutil/common" testkeeper "github.com/lavanet/lava/testutil/keeper" + "github.com/lavanet/lava/x/pairing/types" "github.com/stretchr/testify/require" ) @@ -60,3 +62,118 @@ func TestPairingUniqueness(t *testing.T) { require.True(t, diffrent) } + +// Test that verifies that new get-pairing return values (CurrentEpoch, TimeLeftToNextPairing, SpecLastUpdatedBlock) is working properly +func TestGetPairing(t *testing.T) { + // BLOCK_TIME = 30sec (testutil/keeper/keepers_init.go) + constBlockTime := testkeeper.BLOCK_TIME + + // setup testnet with mock spec, stake a client and a provider + ts := setupForPaymentTest(t) + // get epochBlocks (number of blocks in an epoch) + epochBlocks := ts.keepers.Epochstorage.EpochBlocksRaw(sdk.UnwrapSDKContext(ts.ctx)) + + // define tests - different epoch, valid tells if the payment request should work + tests := []struct { + name string + validPairingExists bool + isEpochTimesChanged bool + }{ + {"zeroEpoch", false, false}, + {"firstEpoch", true, false}, + {"commonEpoch", true, false}, + {"epochTimesChanged", true, true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + + // Advance an epoch according to the test + switch tt.name { + case "zeroEpoch": + // do nothing + case "firstEpoch": + ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) + case "commonEpoch": + for i := 0; i < 5; i++ { + ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) + } + case "epochTimesChanged": + for i := 0; i < 5; i++ { + ts.ctx = testkeeper.AdvanceEpoch(ts.ctx, ts.keepers) + } + smallerBlockTime := constBlockTime / 2 + ts.ctx = testkeeper.AdvanceBlocks(ts.ctx, ts.keepers, int(epochBlocks)/2, smallerBlockTime) + ts.ctx = testkeeper.AdvanceBlocks(ts.ctx, ts.keepers, int(epochBlocks)/2) + } + + // construct get-pairing request + pairingReq := types.QueryGetPairingRequest{ChainID: ts.spec.Index, Client: ts.clients[0].address.String()} + + // get pairing for client (for epoch zero there is no pairing -> expect to fail) + pairing, err := ts.keepers.Pairing.GetPairing(ts.ctx, &pairingReq) + if !tt.validPairingExists { + require.NotNil(t, err) + } else { + require.Nil(t, err) + + // verify the expected provider + require.Equal(t, ts.providers[0].address.String(), pairing.Providers[0].Address) + + // verify the current epoch + currentEpoch := ts.keepers.Epochstorage.GetEpochStart(sdk.UnwrapSDKContext(ts.ctx)) + require.Equal(t, currentEpoch, pairing.CurrentEpoch) + + // verify the SpecLastUpdatedBlock + specLastUpdatedBlock := ts.spec.BlockLastUpdated + require.Equal(t, specLastUpdatedBlock, pairing.SpecLastUpdatedBlock) + + // get timestamps from previous epoch + prevEpoch, err := ts.keepers.Epochstorage.GetPreviousEpochStartForBlock(sdk.UnwrapSDKContext(ts.ctx), currentEpoch) + require.Nil(t, err) + + // if prevEpoch == 0 -> averageBlockTime = 0, else calculate the time (like the actual get-pairing function) + averageBlockTime := uint64(0) + if prevEpoch != 0 { + // get timestamps + timestampList := []time.Time{} + for block := prevEpoch; block <= currentEpoch; block++ { + blockCore := ts.keepers.BlockStore.LoadBlock(int64(block)) + timestampList = append(timestampList, blockCore.Time) + } + + // calculate average block time + totalTime := uint64(0) + for i := 1; i < len(timestampList); i++ { + totalTime += uint64(timestampList[i].Sub(timestampList[i-1]).Seconds()) + } + averageBlockTime = totalTime / epochBlocks + } + + // Get the next epoch + nextEpochStart, err := ts.keepers.Epochstorage.GetNextEpoch(sdk.UnwrapSDKContext(ts.ctx), currentEpoch) + require.Nil(t, err) + + // Get epochBlocksOverlap + overlapBlocks := ts.keepers.Pairing.EpochBlocksOverlap(sdk.UnwrapSDKContext(ts.ctx)) + + // Get number of blocks from the current block to the next epoch + blocksUntilNewEpoch := nextEpochStart + overlapBlocks - uint64(sdk.UnwrapSDKContext(ts.ctx).BlockHeight()) + + // Calculate the time left for the next pairing in seconds (blocks left * avg block time) + timeLeftToNextPairing := blocksUntilNewEpoch * averageBlockTime + + // verify the TimeLeftToNextPairing + if !tt.isEpochTimesChanged { + require.Equal(t, timeLeftToNextPairing, pairing.TimeLeftToNextPairing) + } else { + // averageBlockTime in get-pairing query -> minimal average across sampled epoch + // averageBlockTime in this test -> normal average across epoch + // we've used a smaller blocktime some of the time -> averageBlockTime from get-pairing is smaller than the averageBlockTime calculated in this test + require.Less(t, pairing.TimeLeftToNextPairing, timeLeftToNextPairing) + } + } + + }) + } +} diff --git a/x/pairing/types/errors.go b/x/pairing/types/errors.go index 1b3bfaf012..3bc2851b3b 100644 --- a/x/pairing/types/errors.go +++ b/x/pairing/types/errors.go @@ -8,5 +8,9 @@ import ( // x/pairing module sentinel errors var ( - ErrSample = sdkerrors.Register(ModuleName, 1100, "sample error") + ErrSample = sdkerrors.Register(ModuleName, 1100, "sample error") + NoPreviousEpochForAverageBlockTimeCalculationError = sdkerrors.New("NoPreviousEpochForAverageBlockTimeCalculationError Error", 685, "Can't get previous epoch for average block time calculation.") + PreviousEpochStartIsBlockZeroError = sdkerrors.New("PreviousEpochStartIsBlockZeroError Error", 686, "Previous epoch start is block 0, can't be used for average block time calculation (core.Block(0) panics).") + AverageBlockTimeIsLessOrEqualToZeroError = sdkerrors.New("AverageBlockTimeIsLessOrEqualToZeroError Error", 687, "The calculated average block time is less or equal to zero") + NotEnoughBlocksToCalculateAverageBlockTimeError = sdkerrors.New("NotEnoughBlocksToCalculateAverageBlockTimeError Error", 688, "There isn't enough blocks in the previous epoch to calculate average block time") ) diff --git a/x/pairing/types/expected_keepers.go b/x/pairing/types/expected_keepers.go index e4d927c3ea..f3b465ea5e 100644 --- a/x/pairing/types/expected_keepers.go +++ b/x/pairing/types/expected_keepers.go @@ -43,6 +43,7 @@ type EpochstorageKeeper interface { BypassCurrentAndAppendNewEpochStakeEntry(ctx sdk.Context, storageType string, chainID string, stakeEntry epochstoragetypes.StakeEntry) (added bool, err error) AddFixationRegistry(fixationKey string, getParamFunction func(sdk.Context) any) GetDeletedEpochs(ctx sdk.Context) []uint64 + EpochBlocks(ctx sdk.Context, block uint64) (res uint64, err error) } type AccountKeeper interface { diff --git a/x/pairing/types/query.pb.go b/x/pairing/types/query.pb.go index d43a882fbe..37c0830a70 100644 --- a/x/pairing/types/query.pb.go +++ b/x/pairing/types/query.pb.go @@ -359,7 +359,10 @@ func (m *QueryGetPairingRequest) GetClient() string { } type QueryGetPairingResponse struct { - Providers []types.StakeEntry `protobuf:"bytes,1,rep,name=providers,proto3" json:"providers"` + Providers []types.StakeEntry `protobuf:"bytes,1,rep,name=providers,proto3" json:"providers"` + CurrentEpoch uint64 `protobuf:"varint,2,opt,name=currentEpoch,proto3" json:"currentEpoch,omitempty"` + TimeLeftToNextPairing uint64 `protobuf:"varint,3,opt,name=timeLeftToNextPairing,proto3" json:"timeLeftToNextPairing,omitempty"` + SpecLastUpdatedBlock uint64 `protobuf:"varint,4,opt,name=specLastUpdatedBlock,proto3" json:"specLastUpdatedBlock,omitempty"` } func (m *QueryGetPairingResponse) Reset() { *m = QueryGetPairingResponse{} } @@ -402,6 +405,27 @@ func (m *QueryGetPairingResponse) GetProviders() []types.StakeEntry { return nil } +func (m *QueryGetPairingResponse) GetCurrentEpoch() uint64 { + if m != nil { + return m.CurrentEpoch + } + return 0 +} + +func (m *QueryGetPairingResponse) GetTimeLeftToNextPairing() uint64 { + if m != nil { + return m.TimeLeftToNextPairing + } + return 0 +} + +func (m *QueryGetPairingResponse) GetSpecLastUpdatedBlock() uint64 { + if m != nil { + return m.SpecLastUpdatedBlock + } + return 0 +} + type QueryVerifyPairingRequest struct { ChainID string `protobuf:"bytes,1,opt,name=chainID,proto3" json:"chainID,omitempty"` Client string `protobuf:"bytes,2,opt,name=client,proto3" json:"client,omitempty"` @@ -1236,86 +1260,90 @@ func init() { func init() { proto.RegisterFile("pairing/query.proto", fileDescriptor_6bd8a3cd41a2a1ee) } var fileDescriptor_6bd8a3cd41a2a1ee = []byte{ - // 1264 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x5f, 0x6f, 0xdb, 0xd4, - 0x1b, 0xee, 0x49, 0xba, 0x6e, 0x7d, 0xa7, 0x4a, 0xbf, 0xdf, 0x59, 0x28, 0x99, 0x55, 0x42, 0x65, - 0xd6, 0x7f, 0x5b, 0xb1, 0xd7, 0xac, 0xaa, 0x26, 0x56, 0x26, 0x75, 0xeb, 0xd6, 0x75, 0x4c, 0xa2, - 0xcb, 0x54, 0x2e, 0xb8, 0xa9, 0xdc, 0xe4, 0x2c, 0x35, 0x73, 0x6c, 0xd7, 0x76, 0x4a, 0xab, 0x28, - 0x02, 0x81, 0xb8, 0x9d, 0x40, 0x70, 0xc3, 0x3d, 0x12, 0xe2, 0x86, 0x7b, 0x3e, 0x00, 0x68, 0x57, - 0x68, 0xd2, 0x6e, 0xb8, 0x01, 0xa1, 0x16, 0xf1, 0x39, 0x90, 0xcf, 0x79, 0x8f, 0x1b, 0xb7, 0x8e, - 0xe3, 0xb4, 0xd5, 0xae, 0x9a, 0x13, 0xbf, 0x7f, 0x9e, 0xe7, 0x39, 0xc7, 0xe7, 0x7d, 0x1a, 0xb8, - 0xe4, 0x1a, 0xa6, 0x67, 0xda, 0x75, 0x7d, 0xbb, 0xc9, 0xbc, 0x3d, 0xcd, 0xf5, 0x9c, 0xc0, 0xa1, - 0x05, 0xcb, 0xd8, 0x31, 0x6c, 0x16, 0x68, 0xe1, 0x5f, 0x0d, 0x23, 0x94, 0x42, 0xdd, 0xa9, 0x3b, - 0x3c, 0x40, 0x0f, 0x3f, 0x89, 0x58, 0x65, 0xac, 0xee, 0x38, 0x75, 0x8b, 0xe9, 0x86, 0x6b, 0xea, - 0x86, 0x6d, 0x3b, 0x81, 0x11, 0x98, 0x8e, 0xed, 0xe3, 0xd3, 0xab, 0x55, 0xc7, 0x6f, 0x38, 0xbe, - 0xbe, 0x69, 0xf8, 0x4c, 0xb4, 0xd0, 0x77, 0xe6, 0x36, 0x59, 0x60, 0xcc, 0xe9, 0xae, 0x51, 0x37, - 0x6d, 0x1e, 0x8c, 0xb1, 0x05, 0x09, 0xc5, 0x35, 0x3c, 0xa3, 0x21, 0x2b, 0x8c, 0xc9, 0x6f, 0x99, - 0xeb, 0x54, 0xb7, 0x36, 0x5c, 0x63, 0xaf, 0xc1, 0xec, 0x40, 0x3e, 0x9d, 0x8c, 0x72, 0x3c, 0x67, - 0xc7, 0xac, 0x31, 0x4f, 0x06, 0x6c, 0xf8, 0x81, 0xe3, 0x19, 0x75, 0x86, 0x71, 0xf3, 0x32, 0xae, - 0x69, 0x9b, 0xdb, 0x4d, 0x76, 0x34, 0x6a, 0xa3, 0x6a, 0x99, 0xe1, 0x52, 0x56, 0xc1, 0xac, 0x12, - 0xef, 0x89, 0x31, 0xba, 0x1f, 0x18, 0xcf, 0xd8, 0x06, 0xb3, 0x03, 0xa9, 0x93, 0x5a, 0x00, 0xfa, - 0x38, 0xe4, 0xb4, 0xc6, 0x01, 0x57, 0xd8, 0x76, 0x93, 0xf9, 0x81, 0xfa, 0x18, 0x2e, 0xc5, 0xbe, - 0xf5, 0x5d, 0xc7, 0xf6, 0x19, 0x7d, 0x0f, 0x86, 0x04, 0xb1, 0x22, 0x19, 0x27, 0xd3, 0x17, 0xcb, - 0x63, 0x5a, 0x92, 0xca, 0x9a, 0xc8, 0xba, 0x33, 0xf8, 0xe2, 0xaf, 0xb7, 0x07, 0x2a, 0x98, 0xa1, - 0xce, 0xc1, 0x1b, 0xa2, 0x24, 0xe2, 0x93, 0xbd, 0x68, 0x11, 0xce, 0x57, 0xb7, 0x0c, 0xd3, 0x5e, - 0x5d, 0xe6, 0x55, 0x87, 0x2b, 0x72, 0xa9, 0xb6, 0x61, 0xf4, 0x68, 0x0a, 0x02, 0xf9, 0x00, 0x80, - 0x53, 0xb9, 0x17, 0x32, 0x29, 0x92, 0xf1, 0xfc, 0xf4, 0xc5, 0xf2, 0x44, 0x1c, 0x4c, 0x27, 0x6f, - 0xed, 0x49, 0x14, 0x8c, 0xa8, 0x3a, 0xd2, 0xe9, 0x28, 0x0c, 0x39, 0xcd, 0xc0, 0x6d, 0x06, 0xc5, - 0x1c, 0xef, 0x8f, 0x2b, 0x55, 0x47, 0x11, 0xee, 0x72, 0x61, 0x33, 0xe0, 0x6d, 0x41, 0x21, 0x9e, - 0xf0, 0x3a, 0xd1, 0x3e, 0x44, 0xb1, 0x56, 0x58, 0xb0, 0x26, 0xf6, 0xa1, 0x27, 0xe0, 0xb0, 0x96, - 0x38, 0x35, 0xb2, 0x96, 0x58, 0xa9, 0x35, 0x78, 0xf3, 0x58, 0x2d, 0xe4, 0xb2, 0x0a, 0xc3, 0xf2, - 0x84, 0xf9, 0x27, 0xa1, 0x72, 0x98, 0xad, 0x7e, 0x06, 0x97, 0x79, 0x97, 0x8f, 0x98, 0x67, 0x3e, - 0xdd, 0x3b, 0x2d, 0x68, 0xaa, 0xc0, 0x05, 0x59, 0xbb, 0x98, 0xe7, 0x4f, 0xa2, 0x35, 0x2d, 0xc0, - 0xb9, 0x4d, 0xcb, 0xa9, 0x3e, 0x2b, 0x0e, 0x8e, 0x93, 0xe9, 0xc1, 0x8a, 0x58, 0xa8, 0x0f, 0x40, - 0x49, 0x02, 0x80, 0x4c, 0x0b, 0x70, 0x6e, 0xc7, 0xb0, 0xcc, 0x1a, 0xef, 0x7f, 0xa1, 0x22, 0x16, - 0xe1, 0xb7, 0xa6, 0x5d, 0x63, 0xbb, 0xbc, 0x79, 0xbe, 0x22, 0x16, 0xea, 0x2a, 0xcc, 0x49, 0xc1, - 0xd6, 0xf9, 0xdb, 0xb9, 0x26, 0x5e, 0xce, 0x27, 0x42, 0x06, 0x71, 0x20, 0xe4, 0x31, 0x96, 0x14, - 0xa3, 0x52, 0x82, 0x20, 0x96, 0xfa, 0x95, 0x40, 0xb9, 0x9f, 0x5a, 0x88, 0xf6, 0x39, 0x01, 0xb5, - 0xd9, 0x33, 0x1c, 0xdf, 0xdb, 0x9b, 0xc9, 0xef, 0x6d, 0xef, 0x76, 0xb8, 0x89, 0x19, 0x3a, 0xa9, - 0x2d, 0x94, 0x64, 0xc9, 0xb2, 0xb2, 0x4b, 0x72, 0x1f, 0xe0, 0xf0, 0x4e, 0x45, 0xb0, 0x93, 0x9a, - 0xb8, 0x80, 0xb5, 0xf0, 0x02, 0xd6, 0xc4, 0x1d, 0x8f, 0x17, 0xb0, 0xb6, 0x66, 0xd4, 0x19, 0xe6, - 0x56, 0x3a, 0x32, 0xd5, 0xe7, 0x39, 0x14, 0x31, 0x63, 0xf7, 0x7e, 0x45, 0xcc, 0xbf, 0x1e, 0x11, - 0xe9, 0x4a, 0x4c, 0x8f, 0x1c, 0xd7, 0x63, 0xaa, 0xa7, 0x1e, 0x82, 0x4d, 0x4c, 0x90, 0xf7, 0x61, - 0x22, 0x7a, 0xa3, 0xb1, 0x78, 0xbc, 0x71, 0xfa, 0xa1, 0xfc, 0x8e, 0xc0, 0x64, 0xaf, 0x7c, 0xd4, - 0xf0, 0x13, 0x18, 0x75, 0x13, 0x23, 0x70, 0x3b, 0x67, 0xbb, 0xcc, 0x8c, 0xc4, 0x1c, 0x94, 0xaa, - 0x4b, 0x45, 0xd5, 0x41, 0x56, 0x4b, 0x96, 0x95, 0xce, 0xea, 0xac, 0xce, 0xd5, 0x9f, 0x52, 0x87, - 0x94, 0x8e, 0x19, 0x74, 0xc8, 0x9f, 0xad, 0x0e, 0x67, 0x77, 0x4c, 0xe6, 0x61, 0x4c, 0x6e, 0xf3, - 0xbd, 0xf0, 0x1a, 0xc7, 0x3e, 0x7e, 0xfa, 0xe9, 0x70, 0xe1, 0xad, 0x2e, 0x59, 0xa8, 0xc5, 0x87, - 0x30, 0xc2, 0x3a, 0x1f, 0xe0, 0x0e, 0xbc, 0x93, 0x2c, 0x41, 0xac, 0x06, 0x32, 0x8f, 0xe7, 0xab, - 0x4f, 0x11, 0xe7, 0x92, 0x65, 0x25, 0xe2, 0x3c, 0xab, 0xfd, 0xfe, 0x85, 0x20, 0xb5, 0xe3, 0x8d, - 0xba, 0x53, 0xcb, 0x9f, 0x86, 0xda, 0xd9, 0xed, 0xa5, 0x81, 0x86, 0x6b, 0xdd, 0x67, 0x1e, 0x9f, - 0xc0, 0x1d, 0xa3, 0xd5, 0xa8, 0xd5, 0x3c, 0xe6, 0xfb, 0x72, 0xb4, 0xe2, 0xb2, 0x73, 0xe8, 0xe6, - 0xe2, 0x43, 0x37, 0x1a, 0xa0, 0xf9, 0xce, 0x01, 0xfa, 0x29, 0x7a, 0x8e, 0x8e, 0x16, 0x28, 0xcb, - 0x0a, 0x5c, 0xa8, 0x3a, 0xb6, 0xdf, 0x6c, 0x44, 0x33, 0xa7, 0x2f, 0x97, 0x10, 0x25, 0x87, 0x8d, - 0x1b, 0xc6, 0xee, 0xdd, 0x75, 0x0e, 0x68, 0xb0, 0x22, 0x16, 0xe5, 0x7f, 0xff, 0x0f, 0xe7, 0x78, - 0x67, 0xfa, 0x25, 0x81, 0x21, 0xe1, 0x37, 0xe9, 0x74, 0xb2, 0xe6, 0xc7, 0xed, 0xad, 0x32, 0x93, - 0x21, 0x52, 0x10, 0x51, 0xaf, 0x7c, 0xf1, 0xea, 0x9f, 0x6f, 0x73, 0x25, 0x3a, 0xa6, 0x63, 0x0a, - 0xff, 0xab, 0xc7, 0x7d, 0x3e, 0xfd, 0x9e, 0xc0, 0x70, 0xe4, 0x52, 0xe9, 0xb5, 0xb4, 0xf2, 0x47, - 0xec, 0xaf, 0x32, 0x9b, 0x2d, 0x18, 0xe1, 0xcc, 0x71, 0x38, 0xd7, 0xe8, 0x4c, 0x17, 0x38, 0x32, - 0x41, 0x6f, 0xe1, 0xce, 0xb5, 0xe9, 0x37, 0x04, 0xce, 0xa3, 0x23, 0xa5, 0x69, 0xc4, 0xe3, 0x36, - 0x57, 0xb9, 0x9a, 0x25, 0x14, 0x51, 0xe9, 0x1c, 0xd5, 0x0c, 0x9d, 0x4a, 0x46, 0x25, 0x0c, 0x5a, - 0x27, 0xa6, 0x1f, 0x09, 0xc0, 0xa1, 0xb9, 0xa4, 0x69, 0x1a, 0x1c, 0xf3, 0xb3, 0xca, 0xbb, 0x19, - 0xa3, 0x11, 0xdc, 0x22, 0x07, 0xb7, 0x40, 0xe7, 0x93, 0xc1, 0xd5, 0x59, 0xb0, 0x21, 0x3f, 0x47, - 0x00, 0xf5, 0x96, 0xc0, 0xdc, 0xa6, 0xbf, 0x11, 0x18, 0x89, 0xf9, 0x43, 0xaa, 0xa7, 0xb4, 0x4f, - 0xb2, 0xb2, 0xca, 0xf5, 0xec, 0x09, 0x08, 0xb9, 0xc2, 0x21, 0x3f, 0xa2, 0x0f, 0x93, 0x21, 0xef, - 0xf0, 0xa4, 0x14, 0xd4, 0x7a, 0x4b, 0x1e, 0x84, 0xb6, 0xde, 0xe2, 0xaf, 0x6a, 0x9b, 0x7e, 0x95, - 0x03, 0x75, 0x3d, 0x83, 0xe3, 0x48, 0x17, 0x37, 0xb3, 0x95, 0x53, 0x1e, 0x9c, 0xbe, 0x10, 0xaa, - 0xf1, 0x88, 0xab, 0x71, 0x9f, 0x2e, 0x27, 0xab, 0x91, 0xed, 0xdf, 0x61, 0xbd, 0xc5, 0x67, 0x55, - 0x9b, 0x7e, 0x9e, 0x83, 0x89, 0xde, 0xcd, 0x97, 0x2c, 0x2b, 0x55, 0x8a, 0x7e, 0x5c, 0x6d, 0xaa, - 0x14, 0x7d, 0x19, 0x54, 0x75, 0x99, 0x4b, 0x71, 0x9b, 0x2e, 0x9e, 0x46, 0x0a, 0xfa, 0x8a, 0xc0, - 0x68, 0xb2, 0xcf, 0xa0, 0xb7, 0x7a, 0xbc, 0x5b, 0x69, 0x2e, 0x4b, 0x59, 0x3c, 0x59, 0x32, 0x72, - 0xbb, 0xcd, 0xb9, 0xdd, 0xa4, 0x0b, 0xe9, 0x57, 0xdb, 0x51, 0x76, 0xd1, 0xc6, 0xfe, 0x4e, 0xe0, - 0x72, 0x72, 0x8b, 0x70, 0x33, 0x6f, 0xa5, 0xef, 0xc1, 0xc9, 0x89, 0xf5, 0x74, 0x82, 0xea, 0x02, - 0x27, 0x76, 0x9d, 0x6a, 0xfd, 0x11, 0xa3, 0x3f, 0x13, 0x18, 0x89, 0x19, 0x06, 0x5a, 0x4e, 0x17, - 0x38, 0xc9, 0x0a, 0x29, 0x37, 0xfa, 0xca, 0x41, 0xc8, 0xf3, 0x1c, 0xb2, 0x46, 0x67, 0x93, 0x21, - 0xc7, 0x7f, 0xc7, 0x8a, 0x76, 0xe0, 0x27, 0x02, 0xff, 0x8b, 0xd5, 0x0b, 0x85, 0x2f, 0xa7, 0x6b, - 0xd7, 0x37, 0xe6, 0x6e, 0x4e, 0x4c, 0x9d, 0xe5, 0x98, 0x27, 0xe9, 0x95, 0x2c, 0x98, 0xe9, 0x0f, - 0x04, 0x86, 0x23, 0xdb, 0x92, 0x3a, 0xb1, 0x8f, 0xfa, 0xa7, 0xd4, 0x89, 0x7d, 0xcc, 0x09, 0xf5, - 0x1a, 0x3f, 0x4d, 0x9f, 0x79, 0xe2, 0x07, 0x39, 0xbd, 0x85, 0x36, 0xac, 0x7d, 0x78, 0xa3, 0xdf, - 0x59, 0x7a, 0xb1, 0x5f, 0x22, 0x2f, 0xf7, 0x4b, 0xe4, 0xef, 0xfd, 0x12, 0xf9, 0xfa, 0xa0, 0x34, - 0xf0, 0xf2, 0xa0, 0x34, 0xf0, 0xc7, 0x41, 0x69, 0xe0, 0xe3, 0xa9, 0xba, 0x19, 0x6c, 0x35, 0x37, - 0xb5, 0xaa, 0xd3, 0x88, 0x57, 0xde, 0x8d, 0x6a, 0x07, 0x7b, 0x2e, 0xf3, 0x37, 0x87, 0xf8, 0x0f, - 0x7d, 0x37, 0xfe, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x4f, 0x78, 0xa0, 0xc7, 0x27, 0x15, 0x00, 0x00, + // 1320 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x5d, 0x6f, 0xdb, 0x54, + 0x18, 0xae, 0x93, 0xad, 0x5b, 0xdf, 0x51, 0x09, 0xce, 0xb2, 0x92, 0x59, 0x25, 0x4c, 0x66, 0xfd, + 0xda, 0x8a, 0xbd, 0x66, 0x55, 0x35, 0xb1, 0x32, 0xa9, 0x5d, 0xb7, 0xae, 0xa3, 0x82, 0x2e, 0xa3, + 0x5c, 0x70, 0x53, 0xb9, 0xc9, 0x69, 0x6a, 0xe6, 0xd8, 0xae, 0x3f, 0x4a, 0xab, 0x28, 0x02, 0x81, + 0xb8, 0x9d, 0x40, 0x70, 0xc3, 0x3d, 0x12, 0xe2, 0x86, 0x7b, 0x7e, 0x00, 0x68, 0x57, 0x68, 0xd2, + 0x6e, 0xb8, 0x01, 0xa1, 0x16, 0xf1, 0x03, 0xf8, 0x05, 0xc8, 0xe7, 0xbc, 0xc7, 0x8d, 0x5b, 0xc7, + 0x71, 0xda, 0x6a, 0x57, 0xed, 0xb1, 0xdf, 0x8f, 0xe7, 0x79, 0xce, 0xc9, 0x79, 0x9f, 0x04, 0x2e, + 0x3a, 0xba, 0xe1, 0x1a, 0x56, 0x5d, 0xdb, 0x0a, 0xa8, 0xbb, 0xab, 0x3a, 0xae, 0xed, 0xdb, 0xa4, + 0x60, 0xea, 0xdb, 0xba, 0x45, 0x7d, 0x35, 0xfc, 0xab, 0x62, 0x84, 0x5c, 0xa8, 0xdb, 0x75, 0x9b, + 0x05, 0x68, 0xe1, 0x7f, 0x3c, 0x56, 0x1e, 0xae, 0xdb, 0x76, 0xdd, 0xa4, 0x9a, 0xee, 0x18, 0x9a, + 0x6e, 0x59, 0xb6, 0xaf, 0xfb, 0x86, 0x6d, 0x79, 0xf8, 0xf6, 0x5a, 0xd5, 0xf6, 0x1a, 0xb6, 0xa7, + 0xad, 0xeb, 0x1e, 0xe5, 0x2d, 0xb4, 0xed, 0xa9, 0x75, 0xea, 0xeb, 0x53, 0x9a, 0xa3, 0xd7, 0x0d, + 0x8b, 0x05, 0x63, 0x6c, 0x41, 0x40, 0x71, 0x74, 0x57, 0x6f, 0x88, 0x0a, 0xc3, 0xe2, 0x29, 0x75, + 0xec, 0xea, 0xe6, 0x9a, 0xa3, 0xef, 0x36, 0xa8, 0xe5, 0x8b, 0xb7, 0xa3, 0x51, 0x8e, 0x6b, 0x6f, + 0x1b, 0x35, 0xea, 0x8a, 0x80, 0x35, 0xcf, 0xb7, 0x5d, 0xbd, 0x4e, 0x31, 0x6e, 0x5a, 0xc4, 0x05, + 0x96, 0xb1, 0x15, 0xd0, 0xc3, 0x51, 0x6b, 0x55, 0xd3, 0x08, 0x97, 0xa2, 0x0a, 0x66, 0x95, 0x58, + 0x4f, 0x8c, 0xd1, 0x3c, 0x5f, 0x7f, 0x42, 0xd7, 0xa8, 0xe5, 0x0b, 0x9d, 0x94, 0x02, 0x90, 0x47, + 0x21, 0xa7, 0x15, 0x06, 0xb8, 0x42, 0xb7, 0x02, 0xea, 0xf9, 0xca, 0x23, 0xb8, 0x18, 0x7b, 0xea, + 0x39, 0xb6, 0xe5, 0x51, 0xf2, 0x0e, 0xf4, 0x73, 0x62, 0x45, 0xe9, 0x8a, 0x34, 0x7e, 0xa1, 0x3c, + 0xac, 0x26, 0xa9, 0xac, 0xf2, 0xac, 0xf9, 0x33, 0xcf, 0xfe, 0x7a, 0xb3, 0xaf, 0x82, 0x19, 0xca, + 0x14, 0x5c, 0xe2, 0x25, 0x11, 0x9f, 0xe8, 0x45, 0x8a, 0x70, 0xae, 0xba, 0xa9, 0x1b, 0xd6, 0xd2, + 0x02, 0xab, 0x3a, 0x50, 0x11, 0x4b, 0xa5, 0x05, 0x43, 0x87, 0x53, 0x10, 0xc8, 0x7b, 0x00, 0x8c, + 0xca, 0xbd, 0x90, 0x49, 0x51, 0xba, 0x92, 0x1f, 0xbf, 0x50, 0x1e, 0x89, 0x83, 0x69, 0xe7, 0xad, + 0x3e, 0x8e, 0x82, 0x11, 0x55, 0x5b, 0x3a, 0x19, 0x82, 0x7e, 0x3b, 0xf0, 0x9d, 0xc0, 0x2f, 0xe6, + 0x58, 0x7f, 0x5c, 0x29, 0x1a, 0x8a, 0x70, 0x97, 0x09, 0x9b, 0x01, 0x6f, 0x13, 0x0a, 0xf1, 0x84, + 0x97, 0x89, 0xf6, 0x21, 0x8a, 0xb5, 0x48, 0xfd, 0x15, 0xbe, 0x0f, 0x5d, 0x01, 0x87, 0xb5, 0xf8, + 0xa9, 0x11, 0xb5, 0xf8, 0x4a, 0xf9, 0x4f, 0x82, 0xd7, 0x8f, 0x14, 0x43, 0x32, 0x4b, 0x30, 0x20, + 0x8e, 0x98, 0x77, 0x1c, 0x2e, 0x07, 0xd9, 0x44, 0x81, 0x57, 0xaa, 0x81, 0xeb, 0x52, 0xcb, 0xbf, + 0x17, 0xa6, 0x30, 0x10, 0x67, 0x2a, 0xb1, 0x67, 0x64, 0x1a, 0x2e, 0xf9, 0x46, 0x83, 0x2e, 0xd3, + 0x0d, 0xff, 0x43, 0xfb, 0x7d, 0xba, 0x23, 0xf0, 0x14, 0xf3, 0x2c, 0x38, 0xf9, 0x25, 0x29, 0x43, + 0xc1, 0x73, 0x68, 0x75, 0x59, 0xf7, 0xfc, 0x55, 0xa7, 0xa6, 0xfb, 0xb4, 0x36, 0x6f, 0xda, 0xd5, + 0x27, 0xc5, 0x33, 0x2c, 0x29, 0xf1, 0x9d, 0xf2, 0x19, 0x5c, 0x66, 0x9c, 0x3f, 0xa2, 0xae, 0xb1, + 0xb1, 0x7b, 0x52, 0x0d, 0x89, 0x0c, 0xe7, 0x05, 0x53, 0x86, 0x75, 0xa0, 0x12, 0xad, 0x49, 0x01, + 0xce, 0xae, 0xb7, 0xe1, 0xe1, 0x0b, 0xe5, 0x01, 0xc8, 0x49, 0x00, 0x50, 0xf7, 0x02, 0x9c, 0xdd, + 0xd6, 0x4d, 0xa3, 0xc6, 0xfa, 0x9f, 0xaf, 0xf0, 0x45, 0xf8, 0xd4, 0xb0, 0x6a, 0x74, 0x87, 0x35, + 0xcf, 0x57, 0xf8, 0x42, 0x59, 0x82, 0x29, 0xb1, 0x7d, 0xab, 0xec, 0xb2, 0x58, 0xe1, 0x77, 0xc5, + 0x63, 0xbe, 0x29, 0xfc, 0x7c, 0x8a, 0x4f, 0x95, 0xa0, 0x18, 0x95, 0xe2, 0x04, 0xb1, 0xd4, 0xaf, + 0x12, 0x94, 0x7b, 0xa9, 0x85, 0x68, 0x9f, 0x4a, 0xa0, 0x04, 0x5d, 0xc3, 0xf1, 0x1a, 0xb9, 0x95, + 0x7c, 0x8d, 0x74, 0x6f, 0x87, 0x47, 0x2a, 0x43, 0x27, 0xa5, 0x89, 0x92, 0xcc, 0x99, 0x66, 0x76, + 0x49, 0xee, 0x03, 0x1c, 0x5c, 0xf1, 0x08, 0x76, 0x54, 0xe5, 0xf3, 0x40, 0x0d, 0xe7, 0x81, 0xca, + 0x47, 0x0e, 0xce, 0x03, 0x75, 0x45, 0xaf, 0x53, 0xcc, 0xad, 0xb4, 0x65, 0x2a, 0x4f, 0x73, 0x28, + 0x62, 0xc6, 0xee, 0xbd, 0x8a, 0x98, 0x7f, 0x39, 0x22, 0x92, 0xc5, 0x98, 0x1e, 0x39, 0xa6, 0xc7, + 0x58, 0x57, 0x3d, 0x38, 0x9b, 0x98, 0x20, 0xef, 0xc2, 0x48, 0x74, 0xbf, 0x60, 0xf1, 0x78, 0xe3, + 0xf4, 0x43, 0xf9, 0x9d, 0x04, 0xa3, 0xdd, 0xf2, 0x51, 0xc3, 0x4f, 0x60, 0xc8, 0x49, 0x8c, 0xc0, + 0xed, 0x9c, 0xec, 0x30, 0xc2, 0x12, 0x73, 0x50, 0xaa, 0x0e, 0x15, 0x15, 0x1b, 0x59, 0xcd, 0x99, + 0x66, 0x3a, 0xab, 0xd3, 0x3a, 0x57, 0x7f, 0x0a, 0x1d, 0x52, 0x3a, 0x66, 0xd0, 0x21, 0x7f, 0xba, + 0x3a, 0x9c, 0xde, 0x31, 0x99, 0x86, 0x61, 0xb1, 0xcd, 0x6c, 0x1a, 0x60, 0x1f, 0x2f, 0xfd, 0x74, + 0x38, 0xf0, 0x46, 0x87, 0x2c, 0xd4, 0xe2, 0x03, 0x18, 0xa4, 0xed, 0x2f, 0x70, 0x07, 0xde, 0x4a, + 0x96, 0x20, 0x56, 0x03, 0x99, 0xc7, 0xf3, 0x95, 0x0d, 0xc4, 0x39, 0x67, 0x9a, 0x89, 0x38, 0x4f, + 0x6b, 0xbf, 0x7f, 0x91, 0x90, 0xda, 0xd1, 0x46, 0x9d, 0xa9, 0xe5, 0x4f, 0x42, 0xed, 0xf4, 0xf6, + 0x52, 0x47, 0xff, 0xb7, 0xea, 0x51, 0x97, 0xf9, 0x81, 0xb6, 0xd1, 0xaa, 0xd7, 0x6a, 0x2e, 0xf5, + 0x3c, 0x31, 0x5a, 0x71, 0xd9, 0x3e, 0x74, 0x73, 0xf1, 0xa1, 0x1b, 0x0d, 0xd0, 0x7c, 0xfb, 0x00, + 0xfd, 0x14, 0x2d, 0x50, 0x5b, 0x0b, 0x94, 0x65, 0x11, 0xce, 0x57, 0x6d, 0xcb, 0x0b, 0x1a, 0xd1, + 0xcc, 0xe9, 0xc9, 0xb3, 0x44, 0xc9, 0x61, 0xe3, 0x86, 0xbe, 0x73, 0x77, 0x15, 0xbd, 0x0a, 0x5f, + 0x94, 0xff, 0x7d, 0x0d, 0xce, 0xb2, 0xce, 0xe4, 0x4b, 0x09, 0xfa, 0xb9, 0xfd, 0x25, 0xe3, 0xc9, + 0x9a, 0x1f, 0x75, 0xdb, 0xf2, 0x44, 0x86, 0x48, 0x4e, 0x44, 0xb9, 0xfa, 0xc5, 0x8b, 0x7f, 0xbe, + 0xcd, 0x95, 0xc8, 0xb0, 0x86, 0x29, 0xec, 0xaf, 0x16, 0xff, 0xda, 0x41, 0xbe, 0x97, 0x60, 0x20, + 0x32, 0xcd, 0xe4, 0x7a, 0x5a, 0xf9, 0x43, 0x6e, 0x5c, 0x9e, 0xcc, 0x16, 0x8c, 0x70, 0xa6, 0x18, + 0x9c, 0xeb, 0x64, 0xa2, 0x03, 0x1c, 0x91, 0xa0, 0x35, 0x71, 0xe7, 0x5a, 0xe4, 0x1b, 0x09, 0xce, + 0xa1, 0x41, 0x26, 0x69, 0xc4, 0xe3, 0xae, 0x5b, 0xbe, 0x96, 0x25, 0x14, 0x51, 0x69, 0x0c, 0xd5, + 0x04, 0x19, 0x4b, 0x46, 0xc5, 0x0d, 0x5a, 0x3b, 0xa6, 0x1f, 0x25, 0x80, 0x03, 0xab, 0x4b, 0xd2, + 0x34, 0x38, 0x62, 0xaf, 0xe5, 0xb7, 0x33, 0x46, 0x23, 0xb8, 0x59, 0x06, 0x6e, 0x86, 0x4c, 0x27, + 0x83, 0xab, 0x53, 0x7f, 0x4d, 0xfc, 0x1f, 0x01, 0xd4, 0x9a, 0x1c, 0x73, 0x8b, 0xfc, 0x26, 0xc1, + 0x60, 0xcc, 0x1f, 0x12, 0x2d, 0xa5, 0x7d, 0x92, 0x95, 0x95, 0x6f, 0x64, 0x4f, 0x40, 0xc8, 0x15, + 0x06, 0x79, 0x99, 0x3c, 0x4c, 0x86, 0xbc, 0xcd, 0x92, 0x52, 0x50, 0x6b, 0x4d, 0x71, 0x10, 0x5a, + 0x5a, 0x93, 0x7d, 0x54, 0x5b, 0xe4, 0xab, 0x1c, 0x28, 0xab, 0x19, 0x1c, 0x47, 0xba, 0xb8, 0x99, + 0xad, 0x9c, 0xfc, 0xe0, 0xe4, 0x85, 0x50, 0x8d, 0x65, 0xa6, 0xc6, 0x7d, 0xb2, 0x90, 0xac, 0x46, + 0xb6, 0x6f, 0xe7, 0x5a, 0x93, 0xcd, 0xaa, 0x16, 0xf9, 0x3c, 0x07, 0x23, 0xdd, 0x9b, 0xcf, 0x99, + 0x66, 0xaa, 0x14, 0xbd, 0xb8, 0xda, 0x54, 0x29, 0x7a, 0x32, 0xa8, 0xca, 0x02, 0x93, 0xe2, 0x0e, + 0x99, 0x3d, 0x89, 0x14, 0xe4, 0x85, 0x04, 0x43, 0xc9, 0x3e, 0x83, 0xdc, 0xee, 0xf2, 0xd9, 0x4a, + 0x73, 0x59, 0xf2, 0xec, 0xf1, 0x92, 0x91, 0xdb, 0x1d, 0xc6, 0xed, 0x16, 0x99, 0x49, 0xbf, 0xda, + 0x0e, 0xb3, 0x8b, 0x36, 0xf6, 0x77, 0x09, 0x2e, 0x27, 0xb7, 0x08, 0x37, 0xf3, 0x76, 0xfa, 0x1e, + 0x1c, 0x9f, 0x58, 0x57, 0x27, 0xa8, 0xcc, 0x30, 0x62, 0x37, 0x88, 0xda, 0x1b, 0x31, 0xf2, 0xb3, + 0x04, 0x83, 0x31, 0xc3, 0x40, 0xca, 0xe9, 0x02, 0x27, 0x59, 0x21, 0xf9, 0x66, 0x4f, 0x39, 0x08, + 0x79, 0x9a, 0x41, 0x56, 0xc9, 0x64, 0x32, 0xe4, 0xf8, 0xcf, 0x6a, 0xd1, 0x0e, 0xfc, 0x24, 0xc1, + 0xab, 0xb1, 0x7a, 0xa1, 0xf0, 0xe5, 0x74, 0xed, 0x7a, 0xc6, 0xdc, 0xc9, 0x89, 0x29, 0x93, 0x0c, + 0xf3, 0x28, 0xb9, 0x9a, 0x05, 0x33, 0xf9, 0x41, 0x82, 0x81, 0xc8, 0xb6, 0xa4, 0x4e, 0xec, 0xc3, + 0xfe, 0x29, 0x75, 0x62, 0x1f, 0x71, 0x42, 0xdd, 0xc6, 0x4f, 0xe0, 0x51, 0x97, 0xff, 0x3e, 0xa8, + 0x35, 0xd1, 0x86, 0xb5, 0x0e, 0x6e, 0xf4, 0xf9, 0xb9, 0x67, 0x7b, 0x25, 0xe9, 0xf9, 0x5e, 0x49, + 0xfa, 0x7b, 0xaf, 0x24, 0x7d, 0xbd, 0x5f, 0xea, 0x7b, 0xbe, 0x5f, 0xea, 0xfb, 0x63, 0xbf, 0xd4, + 0xf7, 0xf1, 0x58, 0xdd, 0xf0, 0x37, 0x83, 0x75, 0xb5, 0x6a, 0x37, 0xe2, 0x95, 0x77, 0xa2, 0xda, + 0xfe, 0xae, 0x43, 0xbd, 0xf5, 0x7e, 0xf6, 0xbb, 0xe3, 0xcd, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, + 0xc1, 0x80, 0xec, 0xd3, 0xb6, 0x15, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -2079,6 +2107,21 @@ func (m *QueryGetPairingResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) _ = i var l int _ = l + if m.SpecLastUpdatedBlock != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.SpecLastUpdatedBlock)) + i-- + dAtA[i] = 0x20 + } + if m.TimeLeftToNextPairing != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.TimeLeftToNextPairing)) + i-- + dAtA[i] = 0x18 + } + if m.CurrentEpoch != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.CurrentEpoch)) + i-- + dAtA[i] = 0x10 + } if len(m.Providers) > 0 { for iNdEx := len(m.Providers) - 1; iNdEx >= 0; iNdEx-- { { @@ -2828,6 +2871,15 @@ func (m *QueryGetPairingResponse) Size() (n int) { n += 1 + l + sovQuery(uint64(l)) } } + if m.CurrentEpoch != 0 { + n += 1 + sovQuery(uint64(m.CurrentEpoch)) + } + if m.TimeLeftToNextPairing != 0 { + n += 1 + sovQuery(uint64(m.TimeLeftToNextPairing)) + } + if m.SpecLastUpdatedBlock != 0 { + n += 1 + sovQuery(uint64(m.SpecLastUpdatedBlock)) + } return n } @@ -3784,6 +3836,63 @@ func (m *QueryGetPairingResponse) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CurrentEpoch", wireType) + } + m.CurrentEpoch = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CurrentEpoch |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TimeLeftToNextPairing", wireType) + } + m.TimeLeftToNextPairing = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TimeLeftToNextPairing |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SpecLastUpdatedBlock", wireType) + } + m.SpecLastUpdatedBlock = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SpecLastUpdatedBlock |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) diff --git a/x/spec/migrations/v0.2.0/migrations.go b/x/spec/migrations/v0.2.0/migrations.go new file mode 100644 index 0000000000..994f7a75c8 --- /dev/null +++ b/x/spec/migrations/v0.2.0/migrations.go @@ -0,0 +1,28 @@ +package v020 // migrations.go + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/lavanet/lava/x/spec/keeper" +) + +type Migrator struct { + keeper keeper.Keeper +} + +func NewMigrator(keeper keeper.Keeper) Migrator { + return Migrator{keeper: keeper} +} + +func (m Migrator) MigrateToV020(ctx sdk.Context) error { + return initBlockLastUpdated(ctx, m.keeper) +} + +func initBlockLastUpdated(ctx sdk.Context, k keeper.Keeper) error { + specs := k.GetAllSpec(ctx) + for _, spec := range specs { + spec.BlockLastUpdated = uint64(ctx.BlockHeight()) + k.SetSpec(ctx, spec) + } + + return nil +} diff --git a/x/spec/proposal_handler.go b/x/spec/proposal_handler.go index 4c1d2b0f96..4aad878a96 100644 --- a/x/spec/proposal_handler.go +++ b/x/spec/proposal_handler.go @@ -89,6 +89,9 @@ func handleSpecProposal(ctx sdk.Context, k keeper.Keeper, p *types.SpecAddPropos if err != nil { return utils.LavaError(ctx, logger, "invalid_spec", details, err.Error()) } + + spec.BlockLastUpdated = uint64(ctx.BlockHeight()) + k.SetSpec(ctx, spec) // TODO: add api types once its implemented to the event @@ -98,6 +101,7 @@ func handleSpecProposal(ctx sdk.Context, k keeper.Keeper, p *types.SpecAddPropos } else { name = SPEC_ADD } + spec.BlockLastUpdated = uint64(ctx.BlockHeight()) utils.LogLavaEvent(ctx, logger, name, details, "Gov Proposal Accepted Spec") } diff --git a/x/spec/types/spec.pb.go b/x/spec/types/spec.pb.go index 05661ffff3..7d52ef78f6 100644 --- a/x/spec/types/spec.pb.go +++ b/x/spec/types/spec.pb.go @@ -34,6 +34,7 @@ type Spec struct { BlocksInFinalizationProof uint32 `protobuf:"varint,8,opt,name=blocks_in_finalization_proof,json=blocksInFinalizationProof,proto3" json:"blocks_in_finalization_proof,omitempty"` AverageBlockTime int64 `protobuf:"varint,9,opt,name=average_block_time,json=averageBlockTime,proto3" json:"average_block_time,omitempty"` AllowedBlockLagForQosSync int64 `protobuf:"varint,10,opt,name=allowed_block_lag_for_qos_sync,json=allowedBlockLagForQosSync,proto3" json:"allowed_block_lag_for_qos_sync,omitempty"` + BlockLastUpdated uint64 `protobuf:"varint,11,opt,name=block_last_updated,json=blockLastUpdated,proto3" json:"block_last_updated,omitempty"` } func (m *Spec) Reset() { *m = Spec{} } @@ -139,6 +140,13 @@ func (m *Spec) GetAllowedBlockLagForQosSync() int64 { return 0 } +func (m *Spec) GetBlockLastUpdated() uint64 { + if m != nil { + return m.BlockLastUpdated + } + return 0 +} + func init() { proto.RegisterType((*Spec)(nil), "lavanet.lava.spec.Spec") } @@ -146,35 +154,37 @@ func init() { func init() { proto.RegisterFile("spec/spec.proto", fileDescriptor_c4cc771ffab81d0a) } var fileDescriptor_c4cc771ffab81d0a = []byte{ - // 448 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x92, 0xcd, 0x8e, 0xd3, 0x30, - 0x10, 0xc7, 0x1b, 0x9a, 0xfd, 0x32, 0x42, 0x80, 0x55, 0x56, 0xde, 0x15, 0x1b, 0x02, 0xe2, 0x90, - 0x03, 0x4a, 0x24, 0xf6, 0x00, 0x37, 0xb4, 0xd5, 0x52, 0x81, 0xc4, 0x01, 0xd2, 0x3d, 0x71, 0xb1, - 0x26, 0xc9, 0x34, 0xb5, 0x70, 0xed, 0x10, 0x9b, 0xb2, 0xe5, 0x29, 0x78, 0x0c, 0x1e, 0x65, 0x8f, - 0x3d, 0x72, 0x42, 0xa8, 0xbd, 0xf3, 0x0c, 0x28, 0x4e, 0x22, 0x2a, 0x71, 0x89, 0x3f, 0x7e, 0xbf, - 0xff, 0xcc, 0x48, 0x31, 0xb9, 0x6b, 0x2a, 0xcc, 0x93, 0xe6, 0x13, 0x57, 0xb5, 0xb6, 0x9a, 0xde, - 0x97, 0xb0, 0x04, 0x85, 0x36, 0x6e, 0xd6, 0xb8, 0x01, 0xa7, 0xa3, 0x52, 0x97, 0xda, 0xd1, 0xa4, - 0xd9, 0xb5, 0xe2, 0xe9, 0x71, 0x9b, 0xc4, 0x7a, 0x29, 0x72, 0xe4, 0x50, 0x89, 0xf6, 0xfe, 0xc9, - 0x9f, 0x21, 0xf1, 0xa7, 0x15, 0xe6, 0x74, 0x44, 0xf6, 0x84, 0x2a, 0xf0, 0x9a, 0x79, 0xa1, 0x17, - 0x1d, 0xa5, 0xed, 0x81, 0x52, 0xe2, 0x2b, 0x58, 0x20, 0xbb, 0xe5, 0x2e, 0xdd, 0x9e, 0xbe, 0x20, - 0x3e, 0x54, 0xc2, 0xb0, 0x61, 0x38, 0x8c, 0x6e, 0x3f, 0x3f, 0x8b, 0xff, 0x1b, 0x21, 0x9e, 0xb6, - 0x6d, 0x2e, 0x2a, 0x31, 0xf6, 0x6f, 0x7e, 0x3d, 0x1a, 0xa4, 0x2e, 0x40, 0x19, 0x39, 0x40, 0x05, - 0x99, 0xc4, 0x82, 0xf9, 0xa1, 0x17, 0x1d, 0xa6, 0xfd, 0x91, 0x9e, 0x93, 0x07, 0x35, 0x4a, 0x01, - 0x99, 0x90, 0xc2, 0xae, 0xb8, 0x9d, 0xd7, 0x68, 0xe6, 0x5a, 0x16, 0x6c, 0x2f, 0xf4, 0xa2, 0x3b, - 0xe9, 0x68, 0x07, 0x5e, 0xf5, 0x8c, 0xbe, 0x24, 0xac, 0x00, 0x0b, 0x7c, 0x37, 0xd9, 0xd7, 0xdf, - 0x77, 0xf5, 0x8f, 0x1b, 0x9e, 0xfe, 0xc3, 0xaf, 0xbb, 0x76, 0x6f, 0xc8, 0xe3, 0x4c, 0xea, 0xfc, - 0x13, 0x2f, 0x84, 0xb1, 0xa0, 0x72, 0xe4, 0x33, 0x5d, 0xf3, 0x99, 0x50, 0x20, 0xc5, 0x37, 0x2c, - 0x78, 0x13, 0x63, 0x07, 0xae, 0xf5, 0x99, 0x13, 0x2f, 0x3b, 0x6f, 0xa2, 0xeb, 0x49, 0x6f, 0x5d, - 0x82, 0x05, 0xfa, 0x8a, 0x3c, 0x74, 0x82, 0xe1, 0x42, 0xf5, 0x05, 0xc0, 0x0a, 0xad, 0x78, 0x55, - 0x6b, 0x3d, 0x63, 0x87, 0xae, 0xc8, 0x49, 0xeb, 0xbc, 0x55, 0x93, 0x1d, 0xe3, 0x7d, 0x23, 0xd0, - 0x67, 0x84, 0xc2, 0x12, 0x6b, 0x28, 0x91, 0xb7, 0x23, 0x59, 0xb1, 0x40, 0x76, 0x14, 0x7a, 0xd1, - 0x30, 0xbd, 0xd7, 0x91, 0x71, 0x03, 0xae, 0xc4, 0x02, 0xe9, 0x05, 0x09, 0x40, 0x4a, 0xfd, 0x15, - 0x8b, 0xce, 0x96, 0x50, 0xba, 0xd9, 0x3f, 0x6b, 0xc3, 0xcd, 0x4a, 0xe5, 0x8c, 0xb8, 0xe4, 0x49, - 0x67, 0xb9, 0xe4, 0x3b, 0x28, 0x27, 0xba, 0xfe, 0xa0, 0xcd, 0x74, 0xa5, 0xf2, 0xf1, 0xf8, 0xc7, - 0x26, 0xf0, 0x6e, 0x36, 0x81, 0xb7, 0xde, 0x04, 0xde, 0xef, 0x4d, 0xe0, 0x7d, 0xdf, 0x06, 0x83, - 0xf5, 0x36, 0x18, 0xfc, 0xdc, 0x06, 0x83, 0x8f, 0x4f, 0x4b, 0x61, 0xe7, 0x5f, 0xb2, 0x38, 0xd7, - 0x8b, 0xa4, 0xfb, 0xaf, 0x6e, 0x4d, 0xae, 0xdd, 0xab, 0x4b, 0xec, 0xaa, 0x42, 0x93, 0xed, 0xbb, - 0xb7, 0x73, 0xfe, 0x37, 0x00, 0x00, 0xff, 0xff, 0x5d, 0xe6, 0x00, 0x4b, 0x8f, 0x02, 0x00, 0x00, + // 473 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x92, 0xcf, 0x6e, 0xd3, 0x40, + 0x10, 0xc6, 0x63, 0xea, 0xfe, 0xdb, 0x0a, 0x51, 0x56, 0xa1, 0xda, 0x56, 0xd4, 0x18, 0xc4, 0xc1, + 0x07, 0x64, 0x4b, 0xf4, 0x00, 0x37, 0xd4, 0xa8, 0x44, 0x20, 0x71, 0x00, 0xa7, 0x5c, 0xb8, 0xac, + 0xc6, 0xf6, 0xc4, 0x59, 0xb1, 0xd9, 0x35, 0xde, 0x6d, 0x68, 0x78, 0x0a, 0x1e, 0x80, 0x07, 0xe0, + 0x51, 0x7a, 0xec, 0x91, 0x13, 0x42, 0xc9, 0x8b, 0x20, 0xaf, 0x6d, 0x11, 0x89, 0xcb, 0xfe, 0x99, + 0xef, 0xf7, 0xcd, 0x37, 0x87, 0x21, 0xf7, 0x4c, 0x85, 0x79, 0xd2, 0x1c, 0x71, 0x55, 0x6b, 0xab, + 0xe9, 0x7d, 0x09, 0x0b, 0x50, 0x68, 0xe3, 0xe6, 0x8e, 0x1b, 0xe1, 0x64, 0x58, 0xea, 0x52, 0x3b, + 0x35, 0x69, 0x5e, 0x2d, 0x78, 0x72, 0xd4, 0x3a, 0xb1, 0x5e, 0x88, 0x1c, 0x39, 0x54, 0xa2, 0xad, + 0x3f, 0xf9, 0xe1, 0x13, 0x7f, 0x52, 0x61, 0x4e, 0x87, 0x64, 0x5b, 0xa8, 0x02, 0xaf, 0x99, 0x17, + 0x7a, 0xd1, 0x7e, 0xda, 0x7e, 0x28, 0x25, 0xbe, 0x82, 0x39, 0xb2, 0x3b, 0xae, 0xe8, 0xde, 0xf4, + 0x05, 0xf1, 0xa1, 0x12, 0x86, 0x6d, 0x85, 0x5b, 0xd1, 0xc1, 0xf3, 0xd3, 0xf8, 0xbf, 0x11, 0xe2, + 0x49, 0x1b, 0x73, 0x5e, 0x89, 0x91, 0x7f, 0xf3, 0xfb, 0xd1, 0x20, 0x75, 0x06, 0xca, 0xc8, 0x2e, + 0x2a, 0xc8, 0x24, 0x16, 0xcc, 0x0f, 0xbd, 0x68, 0x2f, 0xed, 0xbf, 0xf4, 0x8c, 0x3c, 0xa8, 0x51, + 0x0a, 0xc8, 0x84, 0x14, 0x76, 0xc9, 0xed, 0xac, 0x46, 0x33, 0xd3, 0xb2, 0x60, 0xdb, 0xa1, 0x17, + 0xdd, 0x4d, 0x87, 0x1b, 0xe2, 0x65, 0xaf, 0xd1, 0x97, 0x84, 0x15, 0x60, 0x81, 0x6f, 0x3a, 0xfb, + 0xfe, 0x3b, 0xae, 0xff, 0x51, 0xa3, 0xa7, 0xff, 0xe4, 0xd7, 0x5d, 0xdc, 0x1b, 0xf2, 0x38, 0x93, + 0x3a, 0xff, 0xcc, 0x0b, 0x61, 0x2c, 0xa8, 0x1c, 0xf9, 0x54, 0xd7, 0x7c, 0x2a, 0x14, 0x48, 0xf1, + 0x0d, 0x0b, 0xde, 0xd8, 0xd8, 0xae, 0x8b, 0x3e, 0x75, 0xe0, 0x45, 0xc7, 0x8d, 0x75, 0x3d, 0xee, + 0xa9, 0x0b, 0xb0, 0x40, 0x5f, 0x91, 0x87, 0x0e, 0x30, 0x5c, 0xa8, 0xbe, 0x01, 0x58, 0xa1, 0x15, + 0xaf, 0x6a, 0xad, 0xa7, 0x6c, 0xcf, 0x35, 0x39, 0x6e, 0x99, 0xb7, 0x6a, 0xbc, 0x41, 0xbc, 0x6f, + 0x00, 0xfa, 0x8c, 0x50, 0x58, 0x60, 0x0d, 0x25, 0xf2, 0x76, 0x24, 0x2b, 0xe6, 0xc8, 0xf6, 0x43, + 0x2f, 0xda, 0x4a, 0x0f, 0x3b, 0x65, 0xd4, 0x08, 0x97, 0x62, 0x8e, 0xf4, 0x9c, 0x04, 0x20, 0xa5, + 0xfe, 0x8a, 0x45, 0x47, 0x4b, 0x28, 0xdd, 0xec, 0x5f, 0xb4, 0xe1, 0x66, 0xa9, 0x72, 0x46, 0x9c, + 0xf3, 0xb8, 0xa3, 0x9c, 0xf3, 0x1d, 0x94, 0x63, 0x5d, 0x7f, 0xd0, 0x66, 0xb2, 0x54, 0x79, 0x13, + 0xd8, 0x5b, 0x8d, 0xe5, 0x57, 0x55, 0x01, 0x16, 0x0b, 0x76, 0x10, 0x7a, 0x91, 0x9f, 0x1e, 0x66, + 0x2d, 0x6f, 0xec, 0xc7, 0xb6, 0x3e, 0x1a, 0xfd, 0x5c, 0x05, 0xde, 0xcd, 0x2a, 0xf0, 0x6e, 0x57, + 0x81, 0xf7, 0x67, 0x15, 0x78, 0xdf, 0xd7, 0xc1, 0xe0, 0x76, 0x1d, 0x0c, 0x7e, 0xad, 0x83, 0xc1, + 0xa7, 0xa7, 0xa5, 0xb0, 0xb3, 0xab, 0x2c, 0xce, 0xf5, 0x3c, 0xe9, 0xb6, 0xc0, 0xdd, 0xc9, 0xb5, + 0xdb, 0xd1, 0xc4, 0x2e, 0x2b, 0x34, 0xd9, 0x8e, 0xdb, 0xb4, 0xb3, 0xbf, 0x01, 0x00, 0x00, 0xff, + 0xff, 0x3e, 0x64, 0x13, 0x0b, 0xbd, 0x02, 0x00, 0x00, } func (this *Spec) Equal(that interface{}) bool { @@ -231,6 +241,9 @@ func (this *Spec) Equal(that interface{}) bool { if this.AllowedBlockLagForQosSync != that1.AllowedBlockLagForQosSync { return false } + if this.BlockLastUpdated != that1.BlockLastUpdated { + return false + } return true } func (m *Spec) Marshal() (dAtA []byte, err error) { @@ -253,6 +266,11 @@ func (m *Spec) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.BlockLastUpdated != 0 { + i = encodeVarintSpec(dAtA, i, uint64(m.BlockLastUpdated)) + i-- + dAtA[i] = 0x58 + } if m.AllowedBlockLagForQosSync != 0 { i = encodeVarintSpec(dAtA, i, uint64(m.AllowedBlockLagForQosSync)) i-- @@ -381,6 +399,9 @@ func (m *Spec) Size() (n int) { if m.AllowedBlockLagForQosSync != 0 { n += 1 + sovSpec(uint64(m.AllowedBlockLagForQosSync)) } + if m.BlockLastUpdated != 0 { + n += 1 + sovSpec(uint64(m.BlockLastUpdated)) + } return n } @@ -652,6 +673,25 @@ func (m *Spec) Unmarshal(dAtA []byte) error { break } } + case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockLastUpdated", wireType) + } + m.BlockLastUpdated = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSpec + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlockLastUpdated |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipSpec(dAtA[iNdEx:])