diff --git a/.github/workflows/test-mainnet.yaml b/.github/workflows/test-mainnet.yaml index 8c7a76e6..b4b890db 100644 --- a/.github/workflows/test-mainnet.yaml +++ b/.github/workflows/test-mainnet.yaml @@ -56,7 +56,7 @@ jobs: run: ./bin/xatu-cbt infra start - name: Run mainnet tests (full suite) if: needs.detect.outputs.models == 'all' - run: ./bin/xatu-cbt test all --network mainnet --verbose --concurrency 10 + run: ./bin/xatu-cbt test all --network mainnet --verbose --concurrency 5 - name: Run mainnet tests (impacted only) if: needs.detect.outputs.models != 'all' run: | diff --git a/migrations/077_storage_slot_lifecycle.down.sql b/migrations/077_storage_slot_lifecycle.down.sql new file mode 100644 index 00000000..6f67ccde --- /dev/null +++ b/migrations/077_storage_slot_lifecycle.down.sql @@ -0,0 +1,4 @@ +DROP TABLE IF EXISTS `${NETWORK_NAME}`.int_storage_slot_lifecycle ON CLUSTER '{cluster}'; +DROP TABLE IF EXISTS `${NETWORK_NAME}`.int_storage_slot_lifecycle_local ON CLUSTER '{cluster}'; +DROP TABLE IF EXISTS `${NETWORK_NAME}`.int_storage_slot_lifecycle_boundary ON CLUSTER '{cluster}'; +DROP TABLE IF EXISTS `${NETWORK_NAME}`.int_storage_slot_lifecycle_boundary_local ON CLUSTER '{cluster}'; diff --git a/migrations/077_storage_slot_lifecycle.up.sql b/migrations/077_storage_slot_lifecycle.up.sql new file mode 100644 index 00000000..853efe74 --- /dev/null +++ b/migrations/077_storage_slot_lifecycle.up.sql @@ -0,0 +1,58 @@ +CREATE TABLE `${NETWORK_NAME}`.int_storage_slot_lifecycle_boundary_local ON CLUSTER '{cluster}' ( + `updated_date_time` DateTime COMMENT 'Timestamp when the record was last updated' CODEC(DoubleDelta, ZSTD(1)), + `address` String COMMENT 'The contract address' CODEC(ZSTD(1)), + `slot_key` String COMMENT 'The storage slot key' CODEC(ZSTD(1)), + `lifecycle_number` UInt32 COMMENT 'Reincarnation counter for this slot (1 = first lifecycle, 2 = second, etc.)' CODEC(DoubleDelta, ZSTD(1)), + `birth_block` UInt32 COMMENT 'Block where the slot transitioned from 0 to non-zero effective bytes' CODEC(DoubleDelta, ZSTD(1)), + `death_block` Nullable(UInt32) COMMENT 'Block where the slot transitioned from non-zero to 0 effective bytes (NULL if still alive)' CODEC(ZSTD(1)), + `effective_bytes_birth` UInt8 COMMENT 'Number of effective bytes at birth (the to_value of the 0->non-zero transition)' CODEC(ZSTD(1)), + `effective_bytes_death` Nullable(UInt8) COMMENT 'Number of effective bytes before death (the from_value of the non-zero->0 transition, NULL if still alive)' CODEC(ZSTD(1)) +) ENGINE = ReplicatedReplacingMergeTree( + '/clickhouse/{installation}/{cluster}/tables/{shard}/{database}/{table}', + '{replica}', + `updated_date_time` +) PARTITION BY intDiv(birth_block, 5000000) +ORDER BY (address, slot_key, lifecycle_number) +COMMENT 'Lifecycle boundaries per storage slot: birth (0→non-zero) and death (non-zero→0) blocks with effective bytes at each transition.'; + +CREATE TABLE `${NETWORK_NAME}`.int_storage_slot_lifecycle_boundary ON CLUSTER '{cluster}' +AS `${NETWORK_NAME}`.int_storage_slot_lifecycle_boundary_local +ENGINE = Distributed( + '{cluster}', + '${NETWORK_NAME}', + int_storage_slot_lifecycle_boundary_local, + cityHash64(address, slot_key) +); + +CREATE TABLE `${NETWORK_NAME}`.int_storage_slot_lifecycle_local ON CLUSTER '{cluster}' ( + `updated_date_time` DateTime COMMENT 'Timestamp when the record was last updated' CODEC(DoubleDelta, ZSTD(1)), + `address` String COMMENT 'The contract address' CODEC(ZSTD(1)), + `slot_key` String COMMENT 'The storage slot key' CODEC(ZSTD(1)), + `lifecycle_number` UInt32 COMMENT 'Reincarnation counter for this slot (1 = first lifecycle, 2 = second, etc.)' CODEC(DoubleDelta, ZSTD(1)), + `birth_block` UInt32 COMMENT 'Block where the slot transitioned from 0 to non-zero effective bytes' CODEC(DoubleDelta, ZSTD(1)), + `death_block` Nullable(UInt32) COMMENT 'Block where the slot transitioned from non-zero to 0 effective bytes (NULL if still alive)' CODEC(ZSTD(1)), + `lifespan_blocks` Nullable(UInt32) COMMENT 'Number of blocks between birth and death (NULL if still alive)' CODEC(ZSTD(1)), + `touch_count` UInt32 COMMENT 'Total number of times this slot was touched during this lifecycle' CODEC(DoubleDelta, ZSTD(1)), + `effective_bytes_birth` UInt8 COMMENT 'Number of effective bytes at birth (the to_value of the 0->non-zero transition)' CODEC(ZSTD(1)), + `effective_bytes_peak` UInt8 COMMENT 'Maximum effective bytes observed during this lifecycle' CODEC(ZSTD(1)), + `effective_bytes_death` Nullable(UInt8) COMMENT 'Number of effective bytes before death (the from_value of the non-zero->0 transition, NULL if still alive)' CODEC(ZSTD(1)), + `last_touch_block` UInt32 COMMENT 'Most recent block where this slot was touched in this lifecycle' CODEC(DoubleDelta, ZSTD(1)), + `interval_count` UInt32 COMMENT 'Number of touch-to-touch intervals observed (touch_count - 1 when > 1)' CODEC(DoubleDelta, ZSTD(1)), + `interval_sum` UInt64 COMMENT 'Sum of all touch-to-touch intervals in blocks (for computing mean)' CODEC(DoubleDelta, ZSTD(1)), + `interval_max` UInt32 COMMENT 'Maximum touch-to-touch interval in blocks' CODEC(DoubleDelta, ZSTD(1)) +) ENGINE = ReplicatedReplacingMergeTree( + '/clickhouse/{installation}/{cluster}/tables/{shard}/{database}/{table}', + '{replica}', + `updated_date_time` +) PARTITION BY intDiv(birth_block, 5000000) +ORDER BY (address, slot_key, lifecycle_number) +COMMENT 'Per-slot lifecycle metrics: birth/death blocks, touch counts, and touch-to-touch interval statistics. A lifecycle starts when a slot transitions from zero to non-zero (birth) and ends at the reverse (death). A slot can have multiple lifecycles.'; + +CREATE TABLE `${NETWORK_NAME}`.int_storage_slot_lifecycle ON CLUSTER '{cluster}' +AS `${NETWORK_NAME}`.int_storage_slot_lifecycle_local +ENGINE = Distributed( + '{cluster}', + '${NETWORK_NAME}', + int_storage_slot_lifecycle_local, + cityHash64(address, slot_key) +); diff --git a/models/transformations/int_storage_slot_lifecycle.sql b/models/transformations/int_storage_slot_lifecycle.sql new file mode 100644 index 00000000..968560d6 --- /dev/null +++ b/models/transformations/int_storage_slot_lifecycle.sql @@ -0,0 +1,212 @@ +--- +table: int_storage_slot_lifecycle +type: incremental +interval: + type: block + max: 1000 +fill: + direction: "tail" + allow_gap_skipping: false +schedules: + forwardfill: "@every 1m" +tags: + - execution + - storage + - lifecycle +dependencies: + - "{{transformation}}.int_storage_slot_lifecycle_boundary" + - "{{transformation}}.int_storage_slot_next_touch" + - "{{transformation}}.int_storage_slot_diff_by_address_slot" +--- +-- Aggregates touch statistics per lifecycle using boundaries from +-- int_storage_slot_lifecycle_boundary. Uses LAG for interval computation +-- and GROUP BY for aggregation. Merges batch stats with previous stats +-- for lifecycles that span multiple batches. +INSERT INTO + `{{ .self.database }}`.`{{ .self.table }}` +WITH +-- NO FINAL: only key columns needed, GROUP BY collapses duplicates +batch_touches AS ( + SELECT block_number, address, slot_key + FROM {{ index .dep "{{transformation}}" "int_storage_slot_next_touch" "helpers" "from" }} + WHERE block_number BETWEEN {{ .bounds.start }} AND {{ .bounds.end }} + GROUP BY block_number, address, slot_key +), +touched_slots AS ( + SELECT DISTINCT address, slot_key + FROM batch_touches +), +-- NO FINAL: deduplicates via argMax on version column +batch_diffs AS ( + SELECT + block_number, address, slot_key, + argMax(effective_bytes_to, updated_date_time) as effective_bytes_to + FROM {{ index .dep "{{transformation}}" "int_storage_slot_diff_by_address_slot" "helpers" "from" }} + WHERE block_number BETWEEN {{ .bounds.start }} AND {{ .bounds.end }} + GROUP BY block_number, address, slot_key +), +-- Lifecycle boundaries from Model A (argMax dedup) +boundaries AS ( + SELECT + address, + slot_key, + lifecycle_number, + argMax(birth_block, updated_date_time) as birth_block, + argMax(death_block, updated_date_time) as death_block, + argMax(effective_bytes_birth, updated_date_time) as effective_bytes_birth, + argMax(effective_bytes_death, updated_date_time) as effective_bytes_death + FROM ( + SELECT address, slot_key, lifecycle_number, birth_block, death_block, + effective_bytes_birth, effective_bytes_death, updated_date_time + FROM `{{ .self.database }}`.int_storage_slot_lifecycle_boundary + WHERE (address, slot_key) IN (SELECT address, slot_key FROM touched_slots) + AND birth_block <= {{ .bounds.end }} + ) + GROUP BY address, slot_key, lifecycle_number + HAVING (death_block IS NULL OR death_block >= {{ .bounds.start }}) +), +-- Self-query: previous stats for continuing lifecycles +prev_stats AS ( + SELECT + address, + slot_key, + lifecycle_number, + argMax(touch_count, updated_date_time) as touch_count, + argMax(effective_bytes_peak, updated_date_time) as effective_bytes_peak, + argMax(last_touch_block, updated_date_time) as last_touch_block, + argMax(interval_count, updated_date_time) as interval_count, + argMax(interval_sum, updated_date_time) as interval_sum, + argMax(interval_max, updated_date_time) as interval_max + FROM `{{ .self.database }}`.`{{ .self.table }}` + WHERE (address, slot_key) IN (SELECT address, slot_key FROM touched_slots) + AND birth_block <= {{ .bounds.end }} + GROUP BY address, slot_key, lifecycle_number +), +-- Join touches with diffs + boundaries + prev_stats +touches_enriched AS ( + SELECT + t.block_number as block_number, + t.address as address, + t.slot_key as slot_key, + d.effective_bytes_to as effective_bytes_to, + b.lifecycle_number as lifecycle_number, + b.birth_block as birth_block, + b.death_block as death_block, + b.effective_bytes_birth as effective_bytes_birth, + b.effective_bytes_death as effective_bytes_death, + ifNull(ps.touch_count, toUInt32(0)) as prev_tc, + ifNull(ps.effective_bytes_peak, toUInt8(0)) as prev_eb_peak, + ifNull(ps.last_touch_block, toUInt32(0)) as prev_ltb, + ifNull(ps.interval_count, toUInt32(0)) as prev_ic, + ifNull(ps.interval_sum, toUInt64(0)) as prev_isum, + ifNull(ps.interval_max, toUInt32(0)) as prev_imax + FROM batch_touches t + LEFT JOIN batch_diffs d + ON t.block_number = d.block_number + AND t.address = d.address + AND t.slot_key = d.slot_key + INNER JOIN boundaries b + ON t.address = b.address + AND t.slot_key = b.slot_key + AND t.block_number >= b.birth_block + AND (b.death_block IS NULL OR t.block_number <= b.death_block) + LEFT JOIN prev_stats ps + ON b.address = ps.address + AND b.slot_key = ps.slot_key + AND b.lifecycle_number = ps.lifecycle_number +), +-- Compute touch-to-touch intervals via LAG window function +-- NOTE: Explicit column aliases in touches_enriched and unqualified references here +-- avoid ClickHouse resolving names like t.block_number and failing in CTE scope. +touches_with_intervals AS ( + SELECT + block_number, + address, + slot_key, + effective_bytes_to, + lifecycle_number, + birth_block, + death_block, + effective_bytes_birth, + effective_bytes_death, + prev_tc, + prev_eb_peak, + prev_ltb, + prev_ic, + prev_isum, + prev_imax, + COALESCE( + nullIf( + toUInt32( + block_number - lagInFrame(block_number, 1, block_number) OVER ( + PARTITION BY address, slot_key, lifecycle_number + ORDER BY block_number + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW + ) + ), + 0 + ), + if(prev_ltb > 0 AND block_number > prev_ltb, + toUInt32(block_number - prev_ltb), + NULL + ) + ) as touch_interval + FROM touches_enriched +), +-- Aggregate batch stats per lifecycle +batch_agg AS ( + SELECT + address, + slot_key, + lifecycle_number, + any(birth_block) as birth_block, + any(death_block) as death_block, + any(effective_bytes_birth) as effective_bytes_birth, + any(effective_bytes_death) as effective_bytes_death, + any(prev_tc) as prev_tc, + any(prev_eb_peak) as prev_eb_peak, + any(prev_ic) as prev_ic, + any(prev_isum) as prev_isum, + any(prev_imax) as prev_imax, + toUInt32(COUNT(*)) as batch_touch_count, + MAX(effective_bytes_to) as batch_eb_peak, + MAX(block_number) as batch_last_touch, + toUInt32(countIf(touch_interval IS NOT NULL)) as batch_interval_count, + ifNull( + toUInt64(sumIf(touch_interval, touch_interval IS NOT NULL)), + toUInt64(0) + ) as batch_interval_sum, + ifNull( + toUInt32(maxIf(touch_interval, touch_interval IS NOT NULL)), + toUInt32(0) + ) as batch_interval_max + FROM touches_with_intervals + GROUP BY address, slot_key, lifecycle_number +) +-- Merge batch stats with previous stats for continuing lifecycles +SELECT + fromUnixTimestamp({{ .task.start }}) as updated_date_time, + address, + slot_key, + lifecycle_number, + birth_block, + death_block, + death_block - birth_block as lifespan_blocks, + toUInt32(prev_tc + batch_touch_count) as touch_count, + effective_bytes_birth, + greatest( + prev_eb_peak, + ifNull(batch_eb_peak, toUInt8(0)) + ) as effective_bytes_peak, + effective_bytes_death, + batch_last_touch as last_touch_block, + toUInt32(prev_ic + batch_interval_count) as interval_count, + prev_isum + batch_interval_sum as interval_sum, + greatest(prev_imax, batch_interval_max) as interval_max +FROM batch_agg +SETTINGS + max_bytes_before_external_sort = 10000000000, + max_bytes_before_external_group_by = 10000000000, + max_threads = 8, + distributed_aggregation_memory_efficient = 1, + join_algorithm = 'parallel_hash'; diff --git a/models/transformations/int_storage_slot_lifecycle_boundary.sql b/models/transformations/int_storage_slot_lifecycle_boundary.sql new file mode 100644 index 00000000..43290b9a --- /dev/null +++ b/models/transformations/int_storage_slot_lifecycle_boundary.sql @@ -0,0 +1,120 @@ +--- +table: int_storage_slot_lifecycle_boundary +type: incremental +interval: + type: block + max: 1000 +fill: + direction: "tail" + allow_gap_skipping: false +schedules: + forwardfill: "@every 1m" +tags: + - execution + - storage + - lifecycle +dependencies: + - "{{transformation}}.int_storage_slot_diff_by_address_slot" +--- +-- Detects lifecycle boundaries: births (0->non-zero) and deaths (non-zero->0). +-- Assigns lifecycle_number via cumulative SUM of births per slot. +INSERT INTO + `{{ .self.database }}`.`{{ .self.table }}` +WITH +-- NO FINAL: deduplicates via argMax, filters births/deaths after dedup +batch_events AS ( + SELECT + block_number, + address, + slot_key, + effective_bytes_from, + effective_bytes_to, + toUInt8(effective_bytes_from = 0 AND effective_bytes_to > 0) as is_birth, + toUInt8(effective_bytes_from > 0 AND effective_bytes_to = 0) as is_death + FROM ( + SELECT + block_number, address, slot_key, + argMax(effective_bytes_from, updated_date_time) as effective_bytes_from, + argMax(effective_bytes_to, updated_date_time) as effective_bytes_to + FROM {{ index .dep "{{transformation}}" "int_storage_slot_diff_by_address_slot" "helpers" "from" }} + WHERE block_number BETWEEN {{ .bounds.start }} AND {{ .bounds.end }} + GROUP BY block_number, address, slot_key + ) + WHERE (effective_bytes_from = 0 AND effective_bytes_to > 0) + OR (effective_bytes_from > 0 AND effective_bytes_to = 0) +), +event_slots AS ( + SELECT DISTINCT address, slot_key FROM batch_events +), +-- Self-query: single-pass tuple argMax picks latest (lifecycle, version) +prev_state AS ( + SELECT + address, + slot_key, + max(lifecycle_number) as lnum, + argMax(birth_block, (lifecycle_number, updated_date_time)) as birth, + argMax(effective_bytes_birth, (lifecycle_number, updated_date_time)) as eb_birth + FROM `{{ .self.database }}`.`{{ .self.table }}` + WHERE (address, slot_key) IN (SELECT address, slot_key FROM event_slots) + AND birth_block <= {{ .bounds.end }} + GROUP BY address, slot_key +), +-- Assign lifecycle_number = prev_lnum + cumulative births in batch +events_numbered AS ( + SELECT + e.block_number, + e.address, + e.slot_key, + e.effective_bytes_from, + e.effective_bytes_to, + e.is_birth, + e.is_death, + ifNull(p.lnum, toUInt32(0)) + toUInt32( + SUM(toUInt32(e.is_birth)) OVER ( + PARTITION BY e.address, e.slot_key + ORDER BY e.block_number + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW + ) + ) as lifecycle_number, + ifNull(p.birth, toUInt32(0)) as prev_birth, + ifNull(p.eb_birth, toUInt8(0)) as prev_eb_birth + FROM batch_events e + LEFT JOIN prev_state p + ON e.address = p.address AND e.slot_key = p.slot_key +), +-- Aggregate per lifecycle: one row with birth and death info +lifecycle_boundaries AS ( + SELECT + address, + slot_key, + lifecycle_number, + COALESCE( + MIN(if(is_birth = 1, block_number, NULL)), + any(prev_birth) + ) as birth_block, + MAX(if(is_death = 1, block_number, NULL)) as death_block, + COALESCE( + MIN(if(is_birth = 1, effective_bytes_to, NULL)), + any(prev_eb_birth) + ) as effective_bytes_birth, + MAX(if(is_death = 1, effective_bytes_from, NULL)) as effective_bytes_death + FROM events_numbered + WHERE lifecycle_number > 0 + GROUP BY address, slot_key, lifecycle_number +) +SELECT + fromUnixTimestamp({{ .task.start }}) as updated_date_time, + address, + slot_key, + lifecycle_number, + birth_block, + death_block, + effective_bytes_birth, + effective_bytes_death +FROM lifecycle_boundaries +SETTINGS + max_bytes_before_external_sort = 10000000000, + max_bytes_before_external_group_by = 10000000000, + max_threads = 8, + distributed_aggregation_memory_efficient = 1, + join_algorithm = 'parallel_hash'; diff --git a/pkg/proto/clickhouse/int_storage_slot_lifecycle.go b/pkg/proto/clickhouse/int_storage_slot_lifecycle.go new file mode 100644 index 00000000..3f85a845 --- /dev/null +++ b/pkg/proto/clickhouse/int_storage_slot_lifecycle.go @@ -0,0 +1,550 @@ +// Code generated by clickhouse-proto-gen. DO NOT EDIT. +// SQL query builder for int_storage_slot_lifecycle + +package clickhouse + +import ( + "fmt" +) + +// BuildListIntStorageSlotLifecycleQuery constructs a parameterized SQL query from a ListIntStorageSlotLifecycleRequest +func BuildListIntStorageSlotLifecycleQuery(req *ListIntStorageSlotLifecycleRequest, options ...QueryOption) (SQLQuery, error) { + // Validate that at least one primary key is provided + // Primary keys can come from base table or projections + if req.Address == nil { + return SQLQuery{}, fmt.Errorf("primary key field address is required") + } + + // Build query using QueryBuilder + qb := NewQueryBuilder() + + // Add primary key filter + switch filter := req.Address.Filter.(type) { + case *StringFilter_Eq: + qb.AddCondition("address", "=", filter.Eq) + case *StringFilter_Ne: + qb.AddCondition("address", "!=", filter.Ne) + case *StringFilter_Contains: + qb.AddLikeCondition("address", "%" + filter.Contains + "%") + case *StringFilter_StartsWith: + qb.AddLikeCondition("address", filter.StartsWith + "%") + case *StringFilter_EndsWith: + qb.AddLikeCondition("address", "%" + filter.EndsWith) + case *StringFilter_Like: + qb.AddLikeCondition("address", filter.Like) + case *StringFilter_NotLike: + qb.AddNotLikeCondition("address", filter.NotLike) + case *StringFilter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("address", StringSliceToInterface(filter.In.Values)) + } + case *StringFilter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("address", StringSliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + + // Add filter for column: updated_date_time + if req.UpdatedDateTime != nil { + switch filter := req.UpdatedDateTime.Filter.(type) { + case *UInt32Filter_Eq: + qb.AddCondition("updated_date_time", "=", DateTimeValue{filter.Eq}) + case *UInt32Filter_Ne: + qb.AddCondition("updated_date_time", "!=", DateTimeValue{filter.Ne}) + case *UInt32Filter_Lt: + qb.AddCondition("updated_date_time", "<", DateTimeValue{filter.Lt}) + case *UInt32Filter_Lte: + qb.AddCondition("updated_date_time", "<=", DateTimeValue{filter.Lte}) + case *UInt32Filter_Gt: + qb.AddCondition("updated_date_time", ">", DateTimeValue{filter.Gt}) + case *UInt32Filter_Gte: + qb.AddCondition("updated_date_time", ">=", DateTimeValue{filter.Gte}) + case *UInt32Filter_Between: + qb.AddBetweenCondition("updated_date_time", DateTimeValue{filter.Between.Min}, DateTimeValue{filter.Between.Max.GetValue()}) + case *UInt32Filter_In: + if len(filter.In.Values) > 0 { + converted := make([]interface{}, len(filter.In.Values)) + for i, v := range filter.In.Values { + converted[i] = DateTimeValue{v} + } + qb.AddInCondition("updated_date_time", converted) + } + case *UInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + converted := make([]interface{}, len(filter.NotIn.Values)) + for i, v := range filter.NotIn.Values { + converted[i] = DateTimeValue{v} + } + qb.AddNotInCondition("updated_date_time", converted) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: slot_key + if req.SlotKey != nil { + switch filter := req.SlotKey.Filter.(type) { + case *StringFilter_Eq: + qb.AddCondition("slot_key", "=", filter.Eq) + case *StringFilter_Ne: + qb.AddCondition("slot_key", "!=", filter.Ne) + case *StringFilter_Contains: + qb.AddLikeCondition("slot_key", "%" + filter.Contains + "%") + case *StringFilter_StartsWith: + qb.AddLikeCondition("slot_key", filter.StartsWith + "%") + case *StringFilter_EndsWith: + qb.AddLikeCondition("slot_key", "%" + filter.EndsWith) + case *StringFilter_Like: + qb.AddLikeCondition("slot_key", filter.Like) + case *StringFilter_NotLike: + qb.AddNotLikeCondition("slot_key", filter.NotLike) + case *StringFilter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("slot_key", StringSliceToInterface(filter.In.Values)) + } + case *StringFilter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("slot_key", StringSliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: lifecycle_number + if req.LifecycleNumber != nil { + switch filter := req.LifecycleNumber.Filter.(type) { + case *UInt32Filter_Eq: + qb.AddCondition("lifecycle_number", "=", filter.Eq) + case *UInt32Filter_Ne: + qb.AddCondition("lifecycle_number", "!=", filter.Ne) + case *UInt32Filter_Lt: + qb.AddCondition("lifecycle_number", "<", filter.Lt) + case *UInt32Filter_Lte: + qb.AddCondition("lifecycle_number", "<=", filter.Lte) + case *UInt32Filter_Gt: + qb.AddCondition("lifecycle_number", ">", filter.Gt) + case *UInt32Filter_Gte: + qb.AddCondition("lifecycle_number", ">=", filter.Gte) + case *UInt32Filter_Between: + qb.AddBetweenCondition("lifecycle_number", filter.Between.Min, filter.Between.Max.GetValue()) + case *UInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("lifecycle_number", UInt32SliceToInterface(filter.In.Values)) + } + case *UInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("lifecycle_number", UInt32SliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: birth_block + if req.BirthBlock != nil { + switch filter := req.BirthBlock.Filter.(type) { + case *UInt32Filter_Eq: + qb.AddCondition("birth_block", "=", filter.Eq) + case *UInt32Filter_Ne: + qb.AddCondition("birth_block", "!=", filter.Ne) + case *UInt32Filter_Lt: + qb.AddCondition("birth_block", "<", filter.Lt) + case *UInt32Filter_Lte: + qb.AddCondition("birth_block", "<=", filter.Lte) + case *UInt32Filter_Gt: + qb.AddCondition("birth_block", ">", filter.Gt) + case *UInt32Filter_Gte: + qb.AddCondition("birth_block", ">=", filter.Gte) + case *UInt32Filter_Between: + qb.AddBetweenCondition("birth_block", filter.Between.Min, filter.Between.Max.GetValue()) + case *UInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("birth_block", UInt32SliceToInterface(filter.In.Values)) + } + case *UInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("birth_block", UInt32SliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: death_block + if req.DeathBlock != nil { + switch filter := req.DeathBlock.Filter.(type) { + case *NullableUInt32Filter_Eq: + qb.AddCondition("death_block", "=", filter.Eq) + case *NullableUInt32Filter_Ne: + qb.AddCondition("death_block", "!=", filter.Ne) + case *NullableUInt32Filter_Lt: + qb.AddCondition("death_block", "<", filter.Lt) + case *NullableUInt32Filter_Lte: + qb.AddCondition("death_block", "<=", filter.Lte) + case *NullableUInt32Filter_Gt: + qb.AddCondition("death_block", ">", filter.Gt) + case *NullableUInt32Filter_Gte: + qb.AddCondition("death_block", ">=", filter.Gte) + case *NullableUInt32Filter_Between: + qb.AddBetweenCondition("death_block", filter.Between.Min, filter.Between.Max.GetValue()) + case *NullableUInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("death_block", UInt32SliceToInterface(filter.In.Values)) + } + case *NullableUInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("death_block", UInt32SliceToInterface(filter.NotIn.Values)) + } + case *NullableUInt32Filter_IsNull: + qb.AddIsNullCondition("death_block") + case *NullableUInt32Filter_IsNotNull: + qb.AddIsNotNullCondition("death_block") + default: + // Unsupported filter type + } + } + + // Add filter for column: lifespan_blocks + if req.LifespanBlocks != nil { + switch filter := req.LifespanBlocks.Filter.(type) { + case *NullableUInt32Filter_Eq: + qb.AddCondition("lifespan_blocks", "=", filter.Eq) + case *NullableUInt32Filter_Ne: + qb.AddCondition("lifespan_blocks", "!=", filter.Ne) + case *NullableUInt32Filter_Lt: + qb.AddCondition("lifespan_blocks", "<", filter.Lt) + case *NullableUInt32Filter_Lte: + qb.AddCondition("lifespan_blocks", "<=", filter.Lte) + case *NullableUInt32Filter_Gt: + qb.AddCondition("lifespan_blocks", ">", filter.Gt) + case *NullableUInt32Filter_Gte: + qb.AddCondition("lifespan_blocks", ">=", filter.Gte) + case *NullableUInt32Filter_Between: + qb.AddBetweenCondition("lifespan_blocks", filter.Between.Min, filter.Between.Max.GetValue()) + case *NullableUInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("lifespan_blocks", UInt32SliceToInterface(filter.In.Values)) + } + case *NullableUInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("lifespan_blocks", UInt32SliceToInterface(filter.NotIn.Values)) + } + case *NullableUInt32Filter_IsNull: + qb.AddIsNullCondition("lifespan_blocks") + case *NullableUInt32Filter_IsNotNull: + qb.AddIsNotNullCondition("lifespan_blocks") + default: + // Unsupported filter type + } + } + + // Add filter for column: touch_count + if req.TouchCount != nil { + switch filter := req.TouchCount.Filter.(type) { + case *UInt32Filter_Eq: + qb.AddCondition("touch_count", "=", filter.Eq) + case *UInt32Filter_Ne: + qb.AddCondition("touch_count", "!=", filter.Ne) + case *UInt32Filter_Lt: + qb.AddCondition("touch_count", "<", filter.Lt) + case *UInt32Filter_Lte: + qb.AddCondition("touch_count", "<=", filter.Lte) + case *UInt32Filter_Gt: + qb.AddCondition("touch_count", ">", filter.Gt) + case *UInt32Filter_Gte: + qb.AddCondition("touch_count", ">=", filter.Gte) + case *UInt32Filter_Between: + qb.AddBetweenCondition("touch_count", filter.Between.Min, filter.Between.Max.GetValue()) + case *UInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("touch_count", UInt32SliceToInterface(filter.In.Values)) + } + case *UInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("touch_count", UInt32SliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: effective_bytes_birth + if req.EffectiveBytesBirth != nil { + switch filter := req.EffectiveBytesBirth.Filter.(type) { + case *UInt32Filter_Eq: + qb.AddCondition("effective_bytes_birth", "=", filter.Eq) + case *UInt32Filter_Ne: + qb.AddCondition("effective_bytes_birth", "!=", filter.Ne) + case *UInt32Filter_Lt: + qb.AddCondition("effective_bytes_birth", "<", filter.Lt) + case *UInt32Filter_Lte: + qb.AddCondition("effective_bytes_birth", "<=", filter.Lte) + case *UInt32Filter_Gt: + qb.AddCondition("effective_bytes_birth", ">", filter.Gt) + case *UInt32Filter_Gte: + qb.AddCondition("effective_bytes_birth", ">=", filter.Gte) + case *UInt32Filter_Between: + qb.AddBetweenCondition("effective_bytes_birth", filter.Between.Min, filter.Between.Max.GetValue()) + case *UInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("effective_bytes_birth", UInt32SliceToInterface(filter.In.Values)) + } + case *UInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("effective_bytes_birth", UInt32SliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: effective_bytes_peak + if req.EffectiveBytesPeak != nil { + switch filter := req.EffectiveBytesPeak.Filter.(type) { + case *UInt32Filter_Eq: + qb.AddCondition("effective_bytes_peak", "=", filter.Eq) + case *UInt32Filter_Ne: + qb.AddCondition("effective_bytes_peak", "!=", filter.Ne) + case *UInt32Filter_Lt: + qb.AddCondition("effective_bytes_peak", "<", filter.Lt) + case *UInt32Filter_Lte: + qb.AddCondition("effective_bytes_peak", "<=", filter.Lte) + case *UInt32Filter_Gt: + qb.AddCondition("effective_bytes_peak", ">", filter.Gt) + case *UInt32Filter_Gte: + qb.AddCondition("effective_bytes_peak", ">=", filter.Gte) + case *UInt32Filter_Between: + qb.AddBetweenCondition("effective_bytes_peak", filter.Between.Min, filter.Between.Max.GetValue()) + case *UInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("effective_bytes_peak", UInt32SliceToInterface(filter.In.Values)) + } + case *UInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("effective_bytes_peak", UInt32SliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: effective_bytes_death + if req.EffectiveBytesDeath != nil { + switch filter := req.EffectiveBytesDeath.Filter.(type) { + case *NullableUInt32Filter_Eq: + qb.AddCondition("effective_bytes_death", "=", filter.Eq) + case *NullableUInt32Filter_Ne: + qb.AddCondition("effective_bytes_death", "!=", filter.Ne) + case *NullableUInt32Filter_Lt: + qb.AddCondition("effective_bytes_death", "<", filter.Lt) + case *NullableUInt32Filter_Lte: + qb.AddCondition("effective_bytes_death", "<=", filter.Lte) + case *NullableUInt32Filter_Gt: + qb.AddCondition("effective_bytes_death", ">", filter.Gt) + case *NullableUInt32Filter_Gte: + qb.AddCondition("effective_bytes_death", ">=", filter.Gte) + case *NullableUInt32Filter_Between: + qb.AddBetweenCondition("effective_bytes_death", filter.Between.Min, filter.Between.Max.GetValue()) + case *NullableUInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("effective_bytes_death", UInt32SliceToInterface(filter.In.Values)) + } + case *NullableUInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("effective_bytes_death", UInt32SliceToInterface(filter.NotIn.Values)) + } + case *NullableUInt32Filter_IsNull: + qb.AddIsNullCondition("effective_bytes_death") + case *NullableUInt32Filter_IsNotNull: + qb.AddIsNotNullCondition("effective_bytes_death") + default: + // Unsupported filter type + } + } + + // Add filter for column: last_touch_block + if req.LastTouchBlock != nil { + switch filter := req.LastTouchBlock.Filter.(type) { + case *UInt32Filter_Eq: + qb.AddCondition("last_touch_block", "=", filter.Eq) + case *UInt32Filter_Ne: + qb.AddCondition("last_touch_block", "!=", filter.Ne) + case *UInt32Filter_Lt: + qb.AddCondition("last_touch_block", "<", filter.Lt) + case *UInt32Filter_Lte: + qb.AddCondition("last_touch_block", "<=", filter.Lte) + case *UInt32Filter_Gt: + qb.AddCondition("last_touch_block", ">", filter.Gt) + case *UInt32Filter_Gte: + qb.AddCondition("last_touch_block", ">=", filter.Gte) + case *UInt32Filter_Between: + qb.AddBetweenCondition("last_touch_block", filter.Between.Min, filter.Between.Max.GetValue()) + case *UInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("last_touch_block", UInt32SliceToInterface(filter.In.Values)) + } + case *UInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("last_touch_block", UInt32SliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: interval_count + if req.IntervalCount != nil { + switch filter := req.IntervalCount.Filter.(type) { + case *UInt32Filter_Eq: + qb.AddCondition("interval_count", "=", filter.Eq) + case *UInt32Filter_Ne: + qb.AddCondition("interval_count", "!=", filter.Ne) + case *UInt32Filter_Lt: + qb.AddCondition("interval_count", "<", filter.Lt) + case *UInt32Filter_Lte: + qb.AddCondition("interval_count", "<=", filter.Lte) + case *UInt32Filter_Gt: + qb.AddCondition("interval_count", ">", filter.Gt) + case *UInt32Filter_Gte: + qb.AddCondition("interval_count", ">=", filter.Gte) + case *UInt32Filter_Between: + qb.AddBetweenCondition("interval_count", filter.Between.Min, filter.Between.Max.GetValue()) + case *UInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("interval_count", UInt32SliceToInterface(filter.In.Values)) + } + case *UInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("interval_count", UInt32SliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: interval_sum + if req.IntervalSum != nil { + switch filter := req.IntervalSum.Filter.(type) { + case *UInt64Filter_Eq: + qb.AddCondition("interval_sum", "=", filter.Eq) + case *UInt64Filter_Ne: + qb.AddCondition("interval_sum", "!=", filter.Ne) + case *UInt64Filter_Lt: + qb.AddCondition("interval_sum", "<", filter.Lt) + case *UInt64Filter_Lte: + qb.AddCondition("interval_sum", "<=", filter.Lte) + case *UInt64Filter_Gt: + qb.AddCondition("interval_sum", ">", filter.Gt) + case *UInt64Filter_Gte: + qb.AddCondition("interval_sum", ">=", filter.Gte) + case *UInt64Filter_Between: + qb.AddBetweenCondition("interval_sum", filter.Between.Min, filter.Between.Max.GetValue()) + case *UInt64Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("interval_sum", UInt64SliceToInterface(filter.In.Values)) + } + case *UInt64Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("interval_sum", UInt64SliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: interval_max + if req.IntervalMax != nil { + switch filter := req.IntervalMax.Filter.(type) { + case *UInt32Filter_Eq: + qb.AddCondition("interval_max", "=", filter.Eq) + case *UInt32Filter_Ne: + qb.AddCondition("interval_max", "!=", filter.Ne) + case *UInt32Filter_Lt: + qb.AddCondition("interval_max", "<", filter.Lt) + case *UInt32Filter_Lte: + qb.AddCondition("interval_max", "<=", filter.Lte) + case *UInt32Filter_Gt: + qb.AddCondition("interval_max", ">", filter.Gt) + case *UInt32Filter_Gte: + qb.AddCondition("interval_max", ">=", filter.Gte) + case *UInt32Filter_Between: + qb.AddBetweenCondition("interval_max", filter.Between.Min, filter.Between.Max.GetValue()) + case *UInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("interval_max", UInt32SliceToInterface(filter.In.Values)) + } + case *UInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("interval_max", UInt32SliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Handle pagination per AIP-132 + // Validate page size + if req.PageSize < 0 { + return SQLQuery{}, fmt.Errorf("page_size must be non-negative, got %d", req.PageSize) + } + if req.PageSize > 10000 { + return SQLQuery{}, fmt.Errorf("page_size must not exceed %d, got %d", 10000, req.PageSize) + } + + var limit, offset uint32 + limit = 100 // Default page size + if req.PageSize > 0 { + limit = uint32(req.PageSize) + } + if req.PageToken != "" { + decodedOffset, err := DecodePageToken(req.PageToken) + if err != nil { + return SQLQuery{}, fmt.Errorf("invalid page_token: %w", err) + } + offset = decodedOffset + } + + // Handle custom ordering if provided + var orderByClause string + if req.OrderBy != "" { + validFields := []string{"updated_date_time", "address", "slot_key", "lifecycle_number", "birth_block", "death_block", "lifespan_blocks", "touch_count", "effective_bytes_birth", "effective_bytes_peak", "effective_bytes_death", "last_touch_block", "interval_count", "interval_sum", "interval_max"} + orderFields, err := ParseOrderBy(req.OrderBy, validFields) + if err != nil { + return SQLQuery{}, fmt.Errorf("invalid order_by: %w", err) + } + orderByClause = BuildOrderByClause(orderFields) + } else { + // Default sorting by primary key + orderByClause = " ORDER BY address" + ", slot_key" + ", lifecycle_number" + } + + // Build column list + columns := []string{"toUnixTimestamp(`updated_date_time`) AS `updated_date_time`", "address", "slot_key", "lifecycle_number", "birth_block", "death_block", "lifespan_blocks", "touch_count", "toUInt32(`effective_bytes_birth`) AS `effective_bytes_birth`", "toUInt32(`effective_bytes_peak`) AS `effective_bytes_peak`", "toUInt32(`effective_bytes_death`) AS `effective_bytes_death`", "last_touch_block", "interval_count", "interval_sum", "interval_max"} + + return BuildParameterizedQuery("int_storage_slot_lifecycle", columns, qb, orderByClause, limit, offset, options...) +} + +// BuildGetIntStorageSlotLifecycleQuery constructs a parameterized SQL query from a GetIntStorageSlotLifecycleRequest +func BuildGetIntStorageSlotLifecycleQuery(req *GetIntStorageSlotLifecycleRequest, options ...QueryOption) (SQLQuery, error) { + // Validate primary key is provided + if req.Address == "" { + return SQLQuery{}, fmt.Errorf("primary key field address is required") + } + + // Build query with primary key condition + qb := NewQueryBuilder() + qb.AddCondition("address", "=", req.Address) + + // Build ORDER BY clause + orderByClause := " ORDER BY address, slot_key, lifecycle_number" + + // Build column list + columns := []string{"toUnixTimestamp(`updated_date_time`) AS `updated_date_time`", "address", "slot_key", "lifecycle_number", "birth_block", "death_block", "lifespan_blocks", "touch_count", "toUInt32(`effective_bytes_birth`) AS `effective_bytes_birth`", "toUInt32(`effective_bytes_peak`) AS `effective_bytes_peak`", "toUInt32(`effective_bytes_death`) AS `effective_bytes_death`", "last_touch_block", "interval_count", "interval_sum", "interval_max"} + + // Return single record + return BuildParameterizedQuery("int_storage_slot_lifecycle", columns, qb, orderByClause, 1, 0, options...) +} diff --git a/pkg/proto/clickhouse/int_storage_slot_lifecycle.pb.go b/pkg/proto/clickhouse/int_storage_slot_lifecycle.pb.go new file mode 100644 index 00000000..05089b1c --- /dev/null +++ b/pkg/proto/clickhouse/int_storage_slot_lifecycle.pb.go @@ -0,0 +1,860 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.2 +// protoc (unknown) +// source: int_storage_slot_lifecycle.proto + +package clickhouse + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type IntStorageSlotLifecycle struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Timestamp when the record was last updated + UpdatedDateTime uint32 `protobuf:"varint,11,opt,name=updated_date_time,json=updatedDateTime,proto3" json:"updated_date_time,omitempty"` + // The contract address + Address string `protobuf:"bytes,12,opt,name=address,proto3" json:"address,omitempty"` + // The storage slot key + SlotKey string `protobuf:"bytes,13,opt,name=slot_key,json=slotKey,proto3" json:"slot_key,omitempty"` + // Reincarnation counter for this slot (1 = first lifecycle, 2 = second, etc.) + LifecycleNumber uint32 `protobuf:"varint,14,opt,name=lifecycle_number,json=lifecycleNumber,proto3" json:"lifecycle_number,omitempty"` + // Block where the slot transitioned from 0 to non-zero effective bytes + BirthBlock uint32 `protobuf:"varint,15,opt,name=birth_block,json=birthBlock,proto3" json:"birth_block,omitempty"` + // Block where the slot transitioned from non-zero to 0 effective bytes (NULL if still alive) + DeathBlock *wrapperspb.UInt32Value `protobuf:"bytes,16,opt,name=death_block,json=deathBlock,proto3" json:"death_block,omitempty"` + // Number of blocks between birth and death (NULL if still alive) + LifespanBlocks *wrapperspb.UInt32Value `protobuf:"bytes,17,opt,name=lifespan_blocks,json=lifespanBlocks,proto3" json:"lifespan_blocks,omitempty"` + // Total number of times this slot was touched during this lifecycle + TouchCount uint32 `protobuf:"varint,18,opt,name=touch_count,json=touchCount,proto3" json:"touch_count,omitempty"` + // Number of effective bytes at birth (the to_value of the 0->non-zero transition) + EffectiveBytesBirth uint32 `protobuf:"varint,19,opt,name=effective_bytes_birth,json=effectiveBytesBirth,proto3" json:"effective_bytes_birth,omitempty"` + // Maximum effective bytes observed during this lifecycle + EffectiveBytesPeak uint32 `protobuf:"varint,20,opt,name=effective_bytes_peak,json=effectiveBytesPeak,proto3" json:"effective_bytes_peak,omitempty"` + // Number of effective bytes before death (the from_value of the non-zero->0 transition, NULL if still alive) + EffectiveBytesDeath *wrapperspb.UInt32Value `protobuf:"bytes,21,opt,name=effective_bytes_death,json=effectiveBytesDeath,proto3" json:"effective_bytes_death,omitempty"` + // Most recent block where this slot was touched in this lifecycle + LastTouchBlock uint32 `protobuf:"varint,22,opt,name=last_touch_block,json=lastTouchBlock,proto3" json:"last_touch_block,omitempty"` + // Number of touch-to-touch intervals observed (touch_count - 1 when > 1) + IntervalCount uint32 `protobuf:"varint,23,opt,name=interval_count,json=intervalCount,proto3" json:"interval_count,omitempty"` + // Sum of all touch-to-touch intervals in blocks (for computing mean) + IntervalSum uint64 `protobuf:"varint,24,opt,name=interval_sum,json=intervalSum,proto3" json:"interval_sum,omitempty"` + // Maximum touch-to-touch interval in blocks + IntervalMax uint32 `protobuf:"varint,25,opt,name=interval_max,json=intervalMax,proto3" json:"interval_max,omitempty"` +} + +func (x *IntStorageSlotLifecycle) Reset() { + *x = IntStorageSlotLifecycle{} + if protoimpl.UnsafeEnabled { + mi := &file_int_storage_slot_lifecycle_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IntStorageSlotLifecycle) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IntStorageSlotLifecycle) ProtoMessage() {} + +func (x *IntStorageSlotLifecycle) ProtoReflect() protoreflect.Message { + mi := &file_int_storage_slot_lifecycle_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use IntStorageSlotLifecycle.ProtoReflect.Descriptor instead. +func (*IntStorageSlotLifecycle) Descriptor() ([]byte, []int) { + return file_int_storage_slot_lifecycle_proto_rawDescGZIP(), []int{0} +} + +func (x *IntStorageSlotLifecycle) GetUpdatedDateTime() uint32 { + if x != nil { + return x.UpdatedDateTime + } + return 0 +} + +func (x *IntStorageSlotLifecycle) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *IntStorageSlotLifecycle) GetSlotKey() string { + if x != nil { + return x.SlotKey + } + return "" +} + +func (x *IntStorageSlotLifecycle) GetLifecycleNumber() uint32 { + if x != nil { + return x.LifecycleNumber + } + return 0 +} + +func (x *IntStorageSlotLifecycle) GetBirthBlock() uint32 { + if x != nil { + return x.BirthBlock + } + return 0 +} + +func (x *IntStorageSlotLifecycle) GetDeathBlock() *wrapperspb.UInt32Value { + if x != nil { + return x.DeathBlock + } + return nil +} + +func (x *IntStorageSlotLifecycle) GetLifespanBlocks() *wrapperspb.UInt32Value { + if x != nil { + return x.LifespanBlocks + } + return nil +} + +func (x *IntStorageSlotLifecycle) GetTouchCount() uint32 { + if x != nil { + return x.TouchCount + } + return 0 +} + +func (x *IntStorageSlotLifecycle) GetEffectiveBytesBirth() uint32 { + if x != nil { + return x.EffectiveBytesBirth + } + return 0 +} + +func (x *IntStorageSlotLifecycle) GetEffectiveBytesPeak() uint32 { + if x != nil { + return x.EffectiveBytesPeak + } + return 0 +} + +func (x *IntStorageSlotLifecycle) GetEffectiveBytesDeath() *wrapperspb.UInt32Value { + if x != nil { + return x.EffectiveBytesDeath + } + return nil +} + +func (x *IntStorageSlotLifecycle) GetLastTouchBlock() uint32 { + if x != nil { + return x.LastTouchBlock + } + return 0 +} + +func (x *IntStorageSlotLifecycle) GetIntervalCount() uint32 { + if x != nil { + return x.IntervalCount + } + return 0 +} + +func (x *IntStorageSlotLifecycle) GetIntervalSum() uint64 { + if x != nil { + return x.IntervalSum + } + return 0 +} + +func (x *IntStorageSlotLifecycle) GetIntervalMax() uint32 { + if x != nil { + return x.IntervalMax + } + return 0 +} + +// Request for listing int_storage_slot_lifecycle records +type ListIntStorageSlotLifecycleRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Filter by address - The contract address (PRIMARY KEY - required) + Address *StringFilter `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // Filter by slot_key - The storage slot key (ORDER BY column 2 - optional) + SlotKey *StringFilter `protobuf:"bytes,2,opt,name=slot_key,json=slotKey,proto3" json:"slot_key,omitempty"` + // Filter by lifecycle_number - Reincarnation counter for this slot (1 = first lifecycle, 2 = second, etc.) (ORDER BY column 3 - optional) + LifecycleNumber *UInt32Filter `protobuf:"bytes,3,opt,name=lifecycle_number,json=lifecycleNumber,proto3" json:"lifecycle_number,omitempty"` + // Filter by updated_date_time - Timestamp when the record was last updated (optional) + UpdatedDateTime *UInt32Filter `protobuf:"bytes,4,opt,name=updated_date_time,json=updatedDateTime,proto3" json:"updated_date_time,omitempty"` + // Filter by birth_block - Block where the slot transitioned from 0 to non-zero effective bytes (optional) + BirthBlock *UInt32Filter `protobuf:"bytes,5,opt,name=birth_block,json=birthBlock,proto3" json:"birth_block,omitempty"` + // Filter by death_block - Block where the slot transitioned from non-zero to 0 effective bytes (NULL if still alive) (optional) + DeathBlock *NullableUInt32Filter `protobuf:"bytes,6,opt,name=death_block,json=deathBlock,proto3" json:"death_block,omitempty"` + // Filter by lifespan_blocks - Number of blocks between birth and death (NULL if still alive) (optional) + LifespanBlocks *NullableUInt32Filter `protobuf:"bytes,7,opt,name=lifespan_blocks,json=lifespanBlocks,proto3" json:"lifespan_blocks,omitempty"` + // Filter by touch_count - Total number of times this slot was touched during this lifecycle (optional) + TouchCount *UInt32Filter `protobuf:"bytes,8,opt,name=touch_count,json=touchCount,proto3" json:"touch_count,omitempty"` + // Filter by effective_bytes_birth - Number of effective bytes at birth (the to_value of the 0->non-zero transition) (optional) + EffectiveBytesBirth *UInt32Filter `protobuf:"bytes,9,opt,name=effective_bytes_birth,json=effectiveBytesBirth,proto3" json:"effective_bytes_birth,omitempty"` + // Filter by effective_bytes_peak - Maximum effective bytes observed during this lifecycle (optional) + EffectiveBytesPeak *UInt32Filter `protobuf:"bytes,10,opt,name=effective_bytes_peak,json=effectiveBytesPeak,proto3" json:"effective_bytes_peak,omitempty"` + // Filter by effective_bytes_death - Number of effective bytes before death (the from_value of the non-zero->0 transition, NULL if still alive) (optional) + EffectiveBytesDeath *NullableUInt32Filter `protobuf:"bytes,11,opt,name=effective_bytes_death,json=effectiveBytesDeath,proto3" json:"effective_bytes_death,omitempty"` + // Filter by last_touch_block - Most recent block where this slot was touched in this lifecycle (optional) + LastTouchBlock *UInt32Filter `protobuf:"bytes,12,opt,name=last_touch_block,json=lastTouchBlock,proto3" json:"last_touch_block,omitempty"` + // Filter by interval_count - Number of touch-to-touch intervals observed (touch_count - 1 when > 1) (optional) + IntervalCount *UInt32Filter `protobuf:"bytes,13,opt,name=interval_count,json=intervalCount,proto3" json:"interval_count,omitempty"` + // Filter by interval_sum - Sum of all touch-to-touch intervals in blocks (for computing mean) (optional) + IntervalSum *UInt64Filter `protobuf:"bytes,14,opt,name=interval_sum,json=intervalSum,proto3" json:"interval_sum,omitempty"` + // Filter by interval_max - Maximum touch-to-touch interval in blocks (optional) + IntervalMax *UInt32Filter `protobuf:"bytes,15,opt,name=interval_max,json=intervalMax,proto3" json:"interval_max,omitempty"` + // The maximum number of int_storage_slot_lifecycle to return. + // If unspecified, at most 100 items will be returned. + // The maximum value is 10000; values above 10000 will be coerced to 10000. + PageSize int32 `protobuf:"varint,16,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + // A page token, received from a previous `ListIntStorageSlotLifecycle` call. + // Provide this to retrieve the subsequent page. + PageToken string `protobuf:"bytes,17,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` + // The order of results. Format: comma-separated list of fields. + // Example: "foo,bar" or "foo desc,bar" for descending order on foo. + // If unspecified, results will be returned in the default order. + OrderBy string `protobuf:"bytes,18,opt,name=order_by,json=orderBy,proto3" json:"order_by,omitempty"` +} + +func (x *ListIntStorageSlotLifecycleRequest) Reset() { + *x = ListIntStorageSlotLifecycleRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_int_storage_slot_lifecycle_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListIntStorageSlotLifecycleRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListIntStorageSlotLifecycleRequest) ProtoMessage() {} + +func (x *ListIntStorageSlotLifecycleRequest) ProtoReflect() protoreflect.Message { + mi := &file_int_storage_slot_lifecycle_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListIntStorageSlotLifecycleRequest.ProtoReflect.Descriptor instead. +func (*ListIntStorageSlotLifecycleRequest) Descriptor() ([]byte, []int) { + return file_int_storage_slot_lifecycle_proto_rawDescGZIP(), []int{1} +} + +func (x *ListIntStorageSlotLifecycleRequest) GetAddress() *StringFilter { + if x != nil { + return x.Address + } + return nil +} + +func (x *ListIntStorageSlotLifecycleRequest) GetSlotKey() *StringFilter { + if x != nil { + return x.SlotKey + } + return nil +} + +func (x *ListIntStorageSlotLifecycleRequest) GetLifecycleNumber() *UInt32Filter { + if x != nil { + return x.LifecycleNumber + } + return nil +} + +func (x *ListIntStorageSlotLifecycleRequest) GetUpdatedDateTime() *UInt32Filter { + if x != nil { + return x.UpdatedDateTime + } + return nil +} + +func (x *ListIntStorageSlotLifecycleRequest) GetBirthBlock() *UInt32Filter { + if x != nil { + return x.BirthBlock + } + return nil +} + +func (x *ListIntStorageSlotLifecycleRequest) GetDeathBlock() *NullableUInt32Filter { + if x != nil { + return x.DeathBlock + } + return nil +} + +func (x *ListIntStorageSlotLifecycleRequest) GetLifespanBlocks() *NullableUInt32Filter { + if x != nil { + return x.LifespanBlocks + } + return nil +} + +func (x *ListIntStorageSlotLifecycleRequest) GetTouchCount() *UInt32Filter { + if x != nil { + return x.TouchCount + } + return nil +} + +func (x *ListIntStorageSlotLifecycleRequest) GetEffectiveBytesBirth() *UInt32Filter { + if x != nil { + return x.EffectiveBytesBirth + } + return nil +} + +func (x *ListIntStorageSlotLifecycleRequest) GetEffectiveBytesPeak() *UInt32Filter { + if x != nil { + return x.EffectiveBytesPeak + } + return nil +} + +func (x *ListIntStorageSlotLifecycleRequest) GetEffectiveBytesDeath() *NullableUInt32Filter { + if x != nil { + return x.EffectiveBytesDeath + } + return nil +} + +func (x *ListIntStorageSlotLifecycleRequest) GetLastTouchBlock() *UInt32Filter { + if x != nil { + return x.LastTouchBlock + } + return nil +} + +func (x *ListIntStorageSlotLifecycleRequest) GetIntervalCount() *UInt32Filter { + if x != nil { + return x.IntervalCount + } + return nil +} + +func (x *ListIntStorageSlotLifecycleRequest) GetIntervalSum() *UInt64Filter { + if x != nil { + return x.IntervalSum + } + return nil +} + +func (x *ListIntStorageSlotLifecycleRequest) GetIntervalMax() *UInt32Filter { + if x != nil { + return x.IntervalMax + } + return nil +} + +func (x *ListIntStorageSlotLifecycleRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +func (x *ListIntStorageSlotLifecycleRequest) GetPageToken() string { + if x != nil { + return x.PageToken + } + return "" +} + +func (x *ListIntStorageSlotLifecycleRequest) GetOrderBy() string { + if x != nil { + return x.OrderBy + } + return "" +} + +// Response for listing int_storage_slot_lifecycle records +type ListIntStorageSlotLifecycleResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The list of int_storage_slot_lifecycle. + IntStorageSlotLifecycle []*IntStorageSlotLifecycle `protobuf:"bytes,1,rep,name=int_storage_slot_lifecycle,json=intStorageSlotLifecycle,proto3" json:"int_storage_slot_lifecycle,omitempty"` + // A token, which can be sent as `page_token` to retrieve the next page. + // If this field is omitted, there are no subsequent pages. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` +} + +func (x *ListIntStorageSlotLifecycleResponse) Reset() { + *x = ListIntStorageSlotLifecycleResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_int_storage_slot_lifecycle_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListIntStorageSlotLifecycleResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListIntStorageSlotLifecycleResponse) ProtoMessage() {} + +func (x *ListIntStorageSlotLifecycleResponse) ProtoReflect() protoreflect.Message { + mi := &file_int_storage_slot_lifecycle_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListIntStorageSlotLifecycleResponse.ProtoReflect.Descriptor instead. +func (*ListIntStorageSlotLifecycleResponse) Descriptor() ([]byte, []int) { + return file_int_storage_slot_lifecycle_proto_rawDescGZIP(), []int{2} +} + +func (x *ListIntStorageSlotLifecycleResponse) GetIntStorageSlotLifecycle() []*IntStorageSlotLifecycle { + if x != nil { + return x.IntStorageSlotLifecycle + } + return nil +} + +func (x *ListIntStorageSlotLifecycleResponse) GetNextPageToken() string { + if x != nil { + return x.NextPageToken + } + return "" +} + +// Request for getting a single int_storage_slot_lifecycle record by primary key +type GetIntStorageSlotLifecycleRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The contract address + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` // Primary key (required) +} + +func (x *GetIntStorageSlotLifecycleRequest) Reset() { + *x = GetIntStorageSlotLifecycleRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_int_storage_slot_lifecycle_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetIntStorageSlotLifecycleRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetIntStorageSlotLifecycleRequest) ProtoMessage() {} + +func (x *GetIntStorageSlotLifecycleRequest) ProtoReflect() protoreflect.Message { + mi := &file_int_storage_slot_lifecycle_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetIntStorageSlotLifecycleRequest.ProtoReflect.Descriptor instead. +func (*GetIntStorageSlotLifecycleRequest) Descriptor() ([]byte, []int) { + return file_int_storage_slot_lifecycle_proto_rawDescGZIP(), []int{3} +} + +func (x *GetIntStorageSlotLifecycleRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +// Response for getting a single int_storage_slot_lifecycle record +type GetIntStorageSlotLifecycleResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *IntStorageSlotLifecycle `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *GetIntStorageSlotLifecycleResponse) Reset() { + *x = GetIntStorageSlotLifecycleResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_int_storage_slot_lifecycle_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetIntStorageSlotLifecycleResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetIntStorageSlotLifecycleResponse) ProtoMessage() {} + +func (x *GetIntStorageSlotLifecycleResponse) ProtoReflect() protoreflect.Message { + mi := &file_int_storage_slot_lifecycle_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetIntStorageSlotLifecycleResponse.ProtoReflect.Descriptor instead. +func (*GetIntStorageSlotLifecycleResponse) Descriptor() ([]byte, []int) { + return file_int_storage_slot_lifecycle_proto_rawDescGZIP(), []int{4} +} + +func (x *GetIntStorageSlotLifecycleResponse) GetItem() *IntStorageSlotLifecycle { + if x != nil { + return x.Item + } + return nil +} + +var File_int_storage_slot_lifecycle_proto protoreflect.FileDescriptor + +var file_int_storage_slot_lifecycle_proto_rawDesc = []byte{ + 0x0a, 0x20, 0x69, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x6c, + 0x6f, 0x74, 0x5f, 0x6c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x03, 0x63, 0x62, 0x74, 0x1a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbc, 0x05, 0x0a, 0x17, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, + 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, + 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, + 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x6c, 0x6f, 0x74, 0x5f, + 0x6b, 0x65, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x6c, 0x6f, 0x74, 0x4b, + 0x65, 0x79, 0x12, 0x29, 0x0a, 0x10, 0x6c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x5f, + 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x6c, 0x69, + 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1f, 0x0a, + 0x0b, 0x62, 0x69, 0x72, 0x74, 0x68, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0f, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x0a, 0x62, 0x69, 0x72, 0x74, 0x68, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x3d, + 0x0a, 0x0b, 0x64, 0x65, 0x61, 0x74, 0x68, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x10, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x0a, 0x64, 0x65, 0x61, 0x74, 0x68, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x45, 0x0a, + 0x0f, 0x6c, 0x69, 0x66, 0x65, 0x73, 0x70, 0x61, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, + 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0e, 0x6c, 0x69, 0x66, 0x65, 0x73, 0x70, 0x61, 0x6e, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x5f, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x74, 0x6f, 0x75, 0x63, 0x68, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, + 0x76, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x62, 0x69, 0x72, 0x74, 0x68, 0x18, 0x13, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, + 0x79, 0x74, 0x65, 0x73, 0x42, 0x69, 0x72, 0x74, 0x68, 0x12, 0x30, 0x0a, 0x14, 0x65, 0x66, 0x66, + 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x70, 0x65, 0x61, + 0x6b, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, + 0x76, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x50, 0x65, 0x61, 0x6b, 0x12, 0x50, 0x0a, 0x15, 0x65, + 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x64, + 0x65, 0x61, 0x74, 0x68, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, + 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x44, 0x65, 0x61, 0x74, 0x68, 0x12, 0x28, 0x0a, + 0x10, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x5f, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x54, 0x6f, 0x75, + 0x63, 0x68, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x76, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, + 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x73, 0x75, 0x6d, 0x18, 0x18, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x53, 0x75, + 0x6d, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x61, + 0x78, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, + 0x6c, 0x4d, 0x61, 0x78, 0x22, 0xf9, 0x07, 0x0a, 0x22, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x74, + 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, 0x69, 0x66, 0x65, 0x63, + 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, + 0x62, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, + 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2c, 0x0a, 0x08, 0x73, 0x6c, 0x6f, 0x74, + 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, + 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x73, + 0x6c, 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x3c, 0x0a, 0x10, 0x6c, 0x69, 0x66, 0x65, 0x63, 0x79, + 0x63, 0x6c, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x52, 0x0f, 0x6c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x4e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x11, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x11, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x52, 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x65, 0x54, + 0x69, 0x6d, 0x65, 0x12, 0x32, 0x0a, 0x0b, 0x62, 0x69, 0x72, 0x74, 0x68, 0x5f, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x55, + 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x62, 0x69, 0x72, + 0x74, 0x68, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x3a, 0x0a, 0x0b, 0x64, 0x65, 0x61, 0x74, 0x68, + 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, + 0x62, 0x74, 0x2e, 0x4e, 0x75, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x55, 0x49, 0x6e, 0x74, 0x33, + 0x32, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x64, 0x65, 0x61, 0x74, 0x68, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x12, 0x42, 0x0a, 0x0f, 0x6c, 0x69, 0x66, 0x65, 0x73, 0x70, 0x61, 0x6e, 0x5f, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, + 0x62, 0x74, 0x2e, 0x4e, 0x75, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x55, 0x49, 0x6e, 0x74, 0x33, + 0x32, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0e, 0x6c, 0x69, 0x66, 0x65, 0x73, 0x70, 0x61, + 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x32, 0x0a, 0x0b, 0x74, 0x6f, 0x75, 0x63, 0x68, + 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, + 0x62, 0x74, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, + 0x0a, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x45, 0x0a, 0x15, 0x65, + 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x62, + 0x69, 0x72, 0x74, 0x68, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, + 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x13, 0x65, + 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x69, 0x72, + 0x74, 0x68, 0x12, 0x43, 0x0a, 0x14, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x70, 0x65, 0x61, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x52, 0x12, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, 0x79, + 0x74, 0x65, 0x73, 0x50, 0x65, 0x61, 0x6b, 0x12, 0x4d, 0x0a, 0x15, 0x65, 0x66, 0x66, 0x65, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x64, 0x65, 0x61, 0x74, 0x68, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x4e, 0x75, 0x6c, + 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x52, 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, 0x79, 0x74, 0x65, + 0x73, 0x44, 0x65, 0x61, 0x74, 0x68, 0x12, 0x3b, 0x0a, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x74, + 0x6f, 0x75, 0x63, 0x68, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x52, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x54, 0x6f, 0x75, 0x63, 0x68, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x12, 0x38, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x62, + 0x74, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0d, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x34, 0x0a, + 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x73, 0x75, 0x6d, 0x18, 0x0e, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, + 0x53, 0x75, 0x6d, 0x12, 0x34, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, + 0x6d, 0x61, 0x78, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, 0x2e, + 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0b, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, + 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, + 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x62, + 0x79, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x42, 0x79, + 0x22, 0xa8, 0x01, 0x0a, 0x23, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, 0x72, + 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, 0x1a, 0x69, 0x6e, 0x74, 0x5f, + 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x5f, 0x6c, 0x69, 0x66, + 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, + 0x62, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, + 0x74, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x17, 0x69, 0x6e, 0x74, 0x53, + 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, + 0x63, 0x6c, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, + 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, + 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x3d, 0x0a, 0x21, 0x47, + 0x65, 0x74, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, + 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x56, 0x0a, 0x22, 0x47, 0x65, + 0x74, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, + 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x30, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, + 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, + 0x6c, 0x6f, 0x74, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x04, 0x69, 0x74, + 0x65, 0x6d, 0x32, 0xd3, 0x01, 0x0a, 0x1e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, + 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x59, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x27, 0x2e, + 0x63, 0x62, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, + 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, + 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x56, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x26, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x47, 0x65, + 0x74, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, + 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x27, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, 0x72, + 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x74, 0x68, 0x70, 0x61, 0x6e, 0x64, 0x61, 0x6f, + 0x70, 0x73, 0x2f, 0x78, 0x61, 0x74, 0x75, 0x2d, 0x63, 0x62, 0x74, 0x2f, 0x70, 0x6b, 0x67, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x68, 0x6f, 0x75, 0x73, 0x65, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_int_storage_slot_lifecycle_proto_rawDescOnce sync.Once + file_int_storage_slot_lifecycle_proto_rawDescData = file_int_storage_slot_lifecycle_proto_rawDesc +) + +func file_int_storage_slot_lifecycle_proto_rawDescGZIP() []byte { + file_int_storage_slot_lifecycle_proto_rawDescOnce.Do(func() { + file_int_storage_slot_lifecycle_proto_rawDescData = protoimpl.X.CompressGZIP(file_int_storage_slot_lifecycle_proto_rawDescData) + }) + return file_int_storage_slot_lifecycle_proto_rawDescData +} + +var file_int_storage_slot_lifecycle_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_int_storage_slot_lifecycle_proto_goTypes = []any{ + (*IntStorageSlotLifecycle)(nil), // 0: cbt.IntStorageSlotLifecycle + (*ListIntStorageSlotLifecycleRequest)(nil), // 1: cbt.ListIntStorageSlotLifecycleRequest + (*ListIntStorageSlotLifecycleResponse)(nil), // 2: cbt.ListIntStorageSlotLifecycleResponse + (*GetIntStorageSlotLifecycleRequest)(nil), // 3: cbt.GetIntStorageSlotLifecycleRequest + (*GetIntStorageSlotLifecycleResponse)(nil), // 4: cbt.GetIntStorageSlotLifecycleResponse + (*wrapperspb.UInt32Value)(nil), // 5: google.protobuf.UInt32Value + (*StringFilter)(nil), // 6: cbt.StringFilter + (*UInt32Filter)(nil), // 7: cbt.UInt32Filter + (*NullableUInt32Filter)(nil), // 8: cbt.NullableUInt32Filter + (*UInt64Filter)(nil), // 9: cbt.UInt64Filter +} +var file_int_storage_slot_lifecycle_proto_depIdxs = []int32{ + 5, // 0: cbt.IntStorageSlotLifecycle.death_block:type_name -> google.protobuf.UInt32Value + 5, // 1: cbt.IntStorageSlotLifecycle.lifespan_blocks:type_name -> google.protobuf.UInt32Value + 5, // 2: cbt.IntStorageSlotLifecycle.effective_bytes_death:type_name -> google.protobuf.UInt32Value + 6, // 3: cbt.ListIntStorageSlotLifecycleRequest.address:type_name -> cbt.StringFilter + 6, // 4: cbt.ListIntStorageSlotLifecycleRequest.slot_key:type_name -> cbt.StringFilter + 7, // 5: cbt.ListIntStorageSlotLifecycleRequest.lifecycle_number:type_name -> cbt.UInt32Filter + 7, // 6: cbt.ListIntStorageSlotLifecycleRequest.updated_date_time:type_name -> cbt.UInt32Filter + 7, // 7: cbt.ListIntStorageSlotLifecycleRequest.birth_block:type_name -> cbt.UInt32Filter + 8, // 8: cbt.ListIntStorageSlotLifecycleRequest.death_block:type_name -> cbt.NullableUInt32Filter + 8, // 9: cbt.ListIntStorageSlotLifecycleRequest.lifespan_blocks:type_name -> cbt.NullableUInt32Filter + 7, // 10: cbt.ListIntStorageSlotLifecycleRequest.touch_count:type_name -> cbt.UInt32Filter + 7, // 11: cbt.ListIntStorageSlotLifecycleRequest.effective_bytes_birth:type_name -> cbt.UInt32Filter + 7, // 12: cbt.ListIntStorageSlotLifecycleRequest.effective_bytes_peak:type_name -> cbt.UInt32Filter + 8, // 13: cbt.ListIntStorageSlotLifecycleRequest.effective_bytes_death:type_name -> cbt.NullableUInt32Filter + 7, // 14: cbt.ListIntStorageSlotLifecycleRequest.last_touch_block:type_name -> cbt.UInt32Filter + 7, // 15: cbt.ListIntStorageSlotLifecycleRequest.interval_count:type_name -> cbt.UInt32Filter + 9, // 16: cbt.ListIntStorageSlotLifecycleRequest.interval_sum:type_name -> cbt.UInt64Filter + 7, // 17: cbt.ListIntStorageSlotLifecycleRequest.interval_max:type_name -> cbt.UInt32Filter + 0, // 18: cbt.ListIntStorageSlotLifecycleResponse.int_storage_slot_lifecycle:type_name -> cbt.IntStorageSlotLifecycle + 0, // 19: cbt.GetIntStorageSlotLifecycleResponse.item:type_name -> cbt.IntStorageSlotLifecycle + 1, // 20: cbt.IntStorageSlotLifecycleService.List:input_type -> cbt.ListIntStorageSlotLifecycleRequest + 3, // 21: cbt.IntStorageSlotLifecycleService.Get:input_type -> cbt.GetIntStorageSlotLifecycleRequest + 2, // 22: cbt.IntStorageSlotLifecycleService.List:output_type -> cbt.ListIntStorageSlotLifecycleResponse + 4, // 23: cbt.IntStorageSlotLifecycleService.Get:output_type -> cbt.GetIntStorageSlotLifecycleResponse + 22, // [22:24] is the sub-list for method output_type + 20, // [20:22] is the sub-list for method input_type + 20, // [20:20] is the sub-list for extension type_name + 20, // [20:20] is the sub-list for extension extendee + 0, // [0:20] is the sub-list for field type_name +} + +func init() { file_int_storage_slot_lifecycle_proto_init() } +func file_int_storage_slot_lifecycle_proto_init() { + if File_int_storage_slot_lifecycle_proto != nil { + return + } + file_common_proto_init() + if !protoimpl.UnsafeEnabled { + file_int_storage_slot_lifecycle_proto_msgTypes[0].Exporter = func(v any, i int) any { + switch v := v.(*IntStorageSlotLifecycle); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_int_storage_slot_lifecycle_proto_msgTypes[1].Exporter = func(v any, i int) any { + switch v := v.(*ListIntStorageSlotLifecycleRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_int_storage_slot_lifecycle_proto_msgTypes[2].Exporter = func(v any, i int) any { + switch v := v.(*ListIntStorageSlotLifecycleResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_int_storage_slot_lifecycle_proto_msgTypes[3].Exporter = func(v any, i int) any { + switch v := v.(*GetIntStorageSlotLifecycleRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_int_storage_slot_lifecycle_proto_msgTypes[4].Exporter = func(v any, i int) any { + switch v := v.(*GetIntStorageSlotLifecycleResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_int_storage_slot_lifecycle_proto_rawDesc, + NumEnums: 0, + NumMessages: 5, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_int_storage_slot_lifecycle_proto_goTypes, + DependencyIndexes: file_int_storage_slot_lifecycle_proto_depIdxs, + MessageInfos: file_int_storage_slot_lifecycle_proto_msgTypes, + }.Build() + File_int_storage_slot_lifecycle_proto = out.File + file_int_storage_slot_lifecycle_proto_rawDesc = nil + file_int_storage_slot_lifecycle_proto_goTypes = nil + file_int_storage_slot_lifecycle_proto_depIdxs = nil +} diff --git a/pkg/proto/clickhouse/int_storage_slot_lifecycle.proto b/pkg/proto/clickhouse/int_storage_slot_lifecycle.proto new file mode 100644 index 00000000..399fe89e --- /dev/null +++ b/pkg/proto/clickhouse/int_storage_slot_lifecycle.proto @@ -0,0 +1,119 @@ +syntax = "proto3"; + +package cbt; + +import "common.proto"; +import "google/protobuf/wrappers.proto"; + +option go_package = "github.com/ethpandaops/xatu-cbt/pkg/proto/clickhouse"; +// Per-slot lifecycle metrics: birth/death blocks, touch counts, and touch-to-touch interval statistics. A lifecycle starts when a slot transitions from zero to non-zero (birth) and ends at the reverse (death). A slot can have multiple lifecycles. + +message IntStorageSlotLifecycle { + // Timestamp when the record was last updated + uint32 updated_date_time = 11; + // The contract address + string address = 12; + // The storage slot key + string slot_key = 13; + // Reincarnation counter for this slot (1 = first lifecycle, 2 = second, etc.) + uint32 lifecycle_number = 14; + // Block where the slot transitioned from 0 to non-zero effective bytes + uint32 birth_block = 15; + // Block where the slot transitioned from non-zero to 0 effective bytes (NULL if still alive) + google.protobuf.UInt32Value death_block = 16; + // Number of blocks between birth and death (NULL if still alive) + google.protobuf.UInt32Value lifespan_blocks = 17; + // Total number of times this slot was touched during this lifecycle + uint32 touch_count = 18; + // Number of effective bytes at birth (the to_value of the 0->non-zero transition) + uint32 effective_bytes_birth = 19; + // Maximum effective bytes observed during this lifecycle + uint32 effective_bytes_peak = 20; + // Number of effective bytes before death (the from_value of the non-zero->0 transition, NULL if still alive) + google.protobuf.UInt32Value effective_bytes_death = 21; + // Most recent block where this slot was touched in this lifecycle + uint32 last_touch_block = 22; + // Number of touch-to-touch intervals observed (touch_count - 1 when > 1) + uint32 interval_count = 23; + // Sum of all touch-to-touch intervals in blocks (for computing mean) + uint64 interval_sum = 24; + // Maximum touch-to-touch interval in blocks + uint32 interval_max = 25; +} + +// Request for listing int_storage_slot_lifecycle records +message ListIntStorageSlotLifecycleRequest { + // Filter by address - The contract address (PRIMARY KEY - required) + StringFilter address = 1; + + // Filter by slot_key - The storage slot key (ORDER BY column 2 - optional) + StringFilter slot_key = 2; + + // Filter by lifecycle_number - Reincarnation counter for this slot (1 = first lifecycle, 2 = second, etc.) (ORDER BY column 3 - optional) + UInt32Filter lifecycle_number = 3; + + // Filter by updated_date_time - Timestamp when the record was last updated (optional) + UInt32Filter updated_date_time = 4; + // Filter by birth_block - Block where the slot transitioned from 0 to non-zero effective bytes (optional) + UInt32Filter birth_block = 5; + // Filter by death_block - Block where the slot transitioned from non-zero to 0 effective bytes (NULL if still alive) (optional) + NullableUInt32Filter death_block = 6; + // Filter by lifespan_blocks - Number of blocks between birth and death (NULL if still alive) (optional) + NullableUInt32Filter lifespan_blocks = 7; + // Filter by touch_count - Total number of times this slot was touched during this lifecycle (optional) + UInt32Filter touch_count = 8; + // Filter by effective_bytes_birth - Number of effective bytes at birth (the to_value of the 0->non-zero transition) (optional) + UInt32Filter effective_bytes_birth = 9; + // Filter by effective_bytes_peak - Maximum effective bytes observed during this lifecycle (optional) + UInt32Filter effective_bytes_peak = 10; + // Filter by effective_bytes_death - Number of effective bytes before death (the from_value of the non-zero->0 transition, NULL if still alive) (optional) + NullableUInt32Filter effective_bytes_death = 11; + // Filter by last_touch_block - Most recent block where this slot was touched in this lifecycle (optional) + UInt32Filter last_touch_block = 12; + // Filter by interval_count - Number of touch-to-touch intervals observed (touch_count - 1 when > 1) (optional) + UInt32Filter interval_count = 13; + // Filter by interval_sum - Sum of all touch-to-touch intervals in blocks (for computing mean) (optional) + UInt64Filter interval_sum = 14; + // Filter by interval_max - Maximum touch-to-touch interval in blocks (optional) + UInt32Filter interval_max = 15; + + // The maximum number of int_storage_slot_lifecycle to return. + // If unspecified, at most 100 items will be returned. + // The maximum value is 10000; values above 10000 will be coerced to 10000. + int32 page_size = 16; + // A page token, received from a previous `ListIntStorageSlotLifecycle` call. + // Provide this to retrieve the subsequent page. + string page_token = 17; + // The order of results. Format: comma-separated list of fields. + // Example: "foo,bar" or "foo desc,bar" for descending order on foo. + // If unspecified, results will be returned in the default order. + string order_by = 18; +} + +// Response for listing int_storage_slot_lifecycle records +message ListIntStorageSlotLifecycleResponse { + // The list of int_storage_slot_lifecycle. + repeated IntStorageSlotLifecycle int_storage_slot_lifecycle = 1; + // A token, which can be sent as `page_token` to retrieve the next page. + // If this field is omitted, there are no subsequent pages. + string next_page_token = 2; +} + +// Request for getting a single int_storage_slot_lifecycle record by primary key +message GetIntStorageSlotLifecycleRequest { + // The contract address + string address = 1; // Primary key (required) +} + +// Response for getting a single int_storage_slot_lifecycle record +message GetIntStorageSlotLifecycleResponse { + IntStorageSlotLifecycle item = 1; +} + +// Query int_storage_slot_lifecycle data +service IntStorageSlotLifecycleService { + // List records | Retrieve paginated results with optional filtering + rpc List(ListIntStorageSlotLifecycleRequest) returns (ListIntStorageSlotLifecycleResponse); + // Get record | Retrieve a single record by primary key + rpc Get(GetIntStorageSlotLifecycleRequest) returns (GetIntStorageSlotLifecycleResponse); +} diff --git a/pkg/proto/clickhouse/int_storage_slot_lifecycle_boundary.go b/pkg/proto/clickhouse/int_storage_slot_lifecycle_boundary.go new file mode 100644 index 00000000..d622b1d4 --- /dev/null +++ b/pkg/proto/clickhouse/int_storage_slot_lifecycle_boundary.go @@ -0,0 +1,336 @@ +// Code generated by clickhouse-proto-gen. DO NOT EDIT. +// SQL query builder for int_storage_slot_lifecycle_boundary + +package clickhouse + +import ( + "fmt" +) + +// BuildListIntStorageSlotLifecycleBoundaryQuery constructs a parameterized SQL query from a ListIntStorageSlotLifecycleBoundaryRequest +func BuildListIntStorageSlotLifecycleBoundaryQuery(req *ListIntStorageSlotLifecycleBoundaryRequest, options ...QueryOption) (SQLQuery, error) { + // Validate that at least one primary key is provided + // Primary keys can come from base table or projections + if req.Address == nil { + return SQLQuery{}, fmt.Errorf("primary key field address is required") + } + + // Build query using QueryBuilder + qb := NewQueryBuilder() + + // Add primary key filter + switch filter := req.Address.Filter.(type) { + case *StringFilter_Eq: + qb.AddCondition("address", "=", filter.Eq) + case *StringFilter_Ne: + qb.AddCondition("address", "!=", filter.Ne) + case *StringFilter_Contains: + qb.AddLikeCondition("address", "%" + filter.Contains + "%") + case *StringFilter_StartsWith: + qb.AddLikeCondition("address", filter.StartsWith + "%") + case *StringFilter_EndsWith: + qb.AddLikeCondition("address", "%" + filter.EndsWith) + case *StringFilter_Like: + qb.AddLikeCondition("address", filter.Like) + case *StringFilter_NotLike: + qb.AddNotLikeCondition("address", filter.NotLike) + case *StringFilter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("address", StringSliceToInterface(filter.In.Values)) + } + case *StringFilter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("address", StringSliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + + // Add filter for column: updated_date_time + if req.UpdatedDateTime != nil { + switch filter := req.UpdatedDateTime.Filter.(type) { + case *UInt32Filter_Eq: + qb.AddCondition("updated_date_time", "=", DateTimeValue{filter.Eq}) + case *UInt32Filter_Ne: + qb.AddCondition("updated_date_time", "!=", DateTimeValue{filter.Ne}) + case *UInt32Filter_Lt: + qb.AddCondition("updated_date_time", "<", DateTimeValue{filter.Lt}) + case *UInt32Filter_Lte: + qb.AddCondition("updated_date_time", "<=", DateTimeValue{filter.Lte}) + case *UInt32Filter_Gt: + qb.AddCondition("updated_date_time", ">", DateTimeValue{filter.Gt}) + case *UInt32Filter_Gte: + qb.AddCondition("updated_date_time", ">=", DateTimeValue{filter.Gte}) + case *UInt32Filter_Between: + qb.AddBetweenCondition("updated_date_time", DateTimeValue{filter.Between.Min}, DateTimeValue{filter.Between.Max.GetValue()}) + case *UInt32Filter_In: + if len(filter.In.Values) > 0 { + converted := make([]interface{}, len(filter.In.Values)) + for i, v := range filter.In.Values { + converted[i] = DateTimeValue{v} + } + qb.AddInCondition("updated_date_time", converted) + } + case *UInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + converted := make([]interface{}, len(filter.NotIn.Values)) + for i, v := range filter.NotIn.Values { + converted[i] = DateTimeValue{v} + } + qb.AddNotInCondition("updated_date_time", converted) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: slot_key + if req.SlotKey != nil { + switch filter := req.SlotKey.Filter.(type) { + case *StringFilter_Eq: + qb.AddCondition("slot_key", "=", filter.Eq) + case *StringFilter_Ne: + qb.AddCondition("slot_key", "!=", filter.Ne) + case *StringFilter_Contains: + qb.AddLikeCondition("slot_key", "%" + filter.Contains + "%") + case *StringFilter_StartsWith: + qb.AddLikeCondition("slot_key", filter.StartsWith + "%") + case *StringFilter_EndsWith: + qb.AddLikeCondition("slot_key", "%" + filter.EndsWith) + case *StringFilter_Like: + qb.AddLikeCondition("slot_key", filter.Like) + case *StringFilter_NotLike: + qb.AddNotLikeCondition("slot_key", filter.NotLike) + case *StringFilter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("slot_key", StringSliceToInterface(filter.In.Values)) + } + case *StringFilter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("slot_key", StringSliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: lifecycle_number + if req.LifecycleNumber != nil { + switch filter := req.LifecycleNumber.Filter.(type) { + case *UInt32Filter_Eq: + qb.AddCondition("lifecycle_number", "=", filter.Eq) + case *UInt32Filter_Ne: + qb.AddCondition("lifecycle_number", "!=", filter.Ne) + case *UInt32Filter_Lt: + qb.AddCondition("lifecycle_number", "<", filter.Lt) + case *UInt32Filter_Lte: + qb.AddCondition("lifecycle_number", "<=", filter.Lte) + case *UInt32Filter_Gt: + qb.AddCondition("lifecycle_number", ">", filter.Gt) + case *UInt32Filter_Gte: + qb.AddCondition("lifecycle_number", ">=", filter.Gte) + case *UInt32Filter_Between: + qb.AddBetweenCondition("lifecycle_number", filter.Between.Min, filter.Between.Max.GetValue()) + case *UInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("lifecycle_number", UInt32SliceToInterface(filter.In.Values)) + } + case *UInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("lifecycle_number", UInt32SliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: birth_block + if req.BirthBlock != nil { + switch filter := req.BirthBlock.Filter.(type) { + case *UInt32Filter_Eq: + qb.AddCondition("birth_block", "=", filter.Eq) + case *UInt32Filter_Ne: + qb.AddCondition("birth_block", "!=", filter.Ne) + case *UInt32Filter_Lt: + qb.AddCondition("birth_block", "<", filter.Lt) + case *UInt32Filter_Lte: + qb.AddCondition("birth_block", "<=", filter.Lte) + case *UInt32Filter_Gt: + qb.AddCondition("birth_block", ">", filter.Gt) + case *UInt32Filter_Gte: + qb.AddCondition("birth_block", ">=", filter.Gte) + case *UInt32Filter_Between: + qb.AddBetweenCondition("birth_block", filter.Between.Min, filter.Between.Max.GetValue()) + case *UInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("birth_block", UInt32SliceToInterface(filter.In.Values)) + } + case *UInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("birth_block", UInt32SliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: death_block + if req.DeathBlock != nil { + switch filter := req.DeathBlock.Filter.(type) { + case *NullableUInt32Filter_Eq: + qb.AddCondition("death_block", "=", filter.Eq) + case *NullableUInt32Filter_Ne: + qb.AddCondition("death_block", "!=", filter.Ne) + case *NullableUInt32Filter_Lt: + qb.AddCondition("death_block", "<", filter.Lt) + case *NullableUInt32Filter_Lte: + qb.AddCondition("death_block", "<=", filter.Lte) + case *NullableUInt32Filter_Gt: + qb.AddCondition("death_block", ">", filter.Gt) + case *NullableUInt32Filter_Gte: + qb.AddCondition("death_block", ">=", filter.Gte) + case *NullableUInt32Filter_Between: + qb.AddBetweenCondition("death_block", filter.Between.Min, filter.Between.Max.GetValue()) + case *NullableUInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("death_block", UInt32SliceToInterface(filter.In.Values)) + } + case *NullableUInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("death_block", UInt32SliceToInterface(filter.NotIn.Values)) + } + case *NullableUInt32Filter_IsNull: + qb.AddIsNullCondition("death_block") + case *NullableUInt32Filter_IsNotNull: + qb.AddIsNotNullCondition("death_block") + default: + // Unsupported filter type + } + } + + // Add filter for column: effective_bytes_birth + if req.EffectiveBytesBirth != nil { + switch filter := req.EffectiveBytesBirth.Filter.(type) { + case *UInt32Filter_Eq: + qb.AddCondition("effective_bytes_birth", "=", filter.Eq) + case *UInt32Filter_Ne: + qb.AddCondition("effective_bytes_birth", "!=", filter.Ne) + case *UInt32Filter_Lt: + qb.AddCondition("effective_bytes_birth", "<", filter.Lt) + case *UInt32Filter_Lte: + qb.AddCondition("effective_bytes_birth", "<=", filter.Lte) + case *UInt32Filter_Gt: + qb.AddCondition("effective_bytes_birth", ">", filter.Gt) + case *UInt32Filter_Gte: + qb.AddCondition("effective_bytes_birth", ">=", filter.Gte) + case *UInt32Filter_Between: + qb.AddBetweenCondition("effective_bytes_birth", filter.Between.Min, filter.Between.Max.GetValue()) + case *UInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("effective_bytes_birth", UInt32SliceToInterface(filter.In.Values)) + } + case *UInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("effective_bytes_birth", UInt32SliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: effective_bytes_death + if req.EffectiveBytesDeath != nil { + switch filter := req.EffectiveBytesDeath.Filter.(type) { + case *NullableUInt32Filter_Eq: + qb.AddCondition("effective_bytes_death", "=", filter.Eq) + case *NullableUInt32Filter_Ne: + qb.AddCondition("effective_bytes_death", "!=", filter.Ne) + case *NullableUInt32Filter_Lt: + qb.AddCondition("effective_bytes_death", "<", filter.Lt) + case *NullableUInt32Filter_Lte: + qb.AddCondition("effective_bytes_death", "<=", filter.Lte) + case *NullableUInt32Filter_Gt: + qb.AddCondition("effective_bytes_death", ">", filter.Gt) + case *NullableUInt32Filter_Gte: + qb.AddCondition("effective_bytes_death", ">=", filter.Gte) + case *NullableUInt32Filter_Between: + qb.AddBetweenCondition("effective_bytes_death", filter.Between.Min, filter.Between.Max.GetValue()) + case *NullableUInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("effective_bytes_death", UInt32SliceToInterface(filter.In.Values)) + } + case *NullableUInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("effective_bytes_death", UInt32SliceToInterface(filter.NotIn.Values)) + } + case *NullableUInt32Filter_IsNull: + qb.AddIsNullCondition("effective_bytes_death") + case *NullableUInt32Filter_IsNotNull: + qb.AddIsNotNullCondition("effective_bytes_death") + default: + // Unsupported filter type + } + } + + // Handle pagination per AIP-132 + // Validate page size + if req.PageSize < 0 { + return SQLQuery{}, fmt.Errorf("page_size must be non-negative, got %d", req.PageSize) + } + if req.PageSize > 10000 { + return SQLQuery{}, fmt.Errorf("page_size must not exceed %d, got %d", 10000, req.PageSize) + } + + var limit, offset uint32 + limit = 100 // Default page size + if req.PageSize > 0 { + limit = uint32(req.PageSize) + } + if req.PageToken != "" { + decodedOffset, err := DecodePageToken(req.PageToken) + if err != nil { + return SQLQuery{}, fmt.Errorf("invalid page_token: %w", err) + } + offset = decodedOffset + } + + // Handle custom ordering if provided + var orderByClause string + if req.OrderBy != "" { + validFields := []string{"updated_date_time", "address", "slot_key", "lifecycle_number", "birth_block", "death_block", "effective_bytes_birth", "effective_bytes_death"} + orderFields, err := ParseOrderBy(req.OrderBy, validFields) + if err != nil { + return SQLQuery{}, fmt.Errorf("invalid order_by: %w", err) + } + orderByClause = BuildOrderByClause(orderFields) + } else { + // Default sorting by primary key + orderByClause = " ORDER BY address" + ", slot_key" + ", lifecycle_number" + } + + // Build column list + columns := []string{"toUnixTimestamp(`updated_date_time`) AS `updated_date_time`", "address", "slot_key", "lifecycle_number", "birth_block", "death_block", "toUInt32(`effective_bytes_birth`) AS `effective_bytes_birth`", "toUInt32(`effective_bytes_death`) AS `effective_bytes_death`"} + + return BuildParameterizedQuery("int_storage_slot_lifecycle_boundary", columns, qb, orderByClause, limit, offset, options...) +} + +// BuildGetIntStorageSlotLifecycleBoundaryQuery constructs a parameterized SQL query from a GetIntStorageSlotLifecycleBoundaryRequest +func BuildGetIntStorageSlotLifecycleBoundaryQuery(req *GetIntStorageSlotLifecycleBoundaryRequest, options ...QueryOption) (SQLQuery, error) { + // Validate primary key is provided + if req.Address == "" { + return SQLQuery{}, fmt.Errorf("primary key field address is required") + } + + // Build query with primary key condition + qb := NewQueryBuilder() + qb.AddCondition("address", "=", req.Address) + + // Build ORDER BY clause + orderByClause := " ORDER BY address, slot_key, lifecycle_number" + + // Build column list + columns := []string{"toUnixTimestamp(`updated_date_time`) AS `updated_date_time`", "address", "slot_key", "lifecycle_number", "birth_block", "death_block", "toUInt32(`effective_bytes_birth`) AS `effective_bytes_birth`", "toUInt32(`effective_bytes_death`) AS `effective_bytes_death`"} + + // Return single record + return BuildParameterizedQuery("int_storage_slot_lifecycle_boundary", columns, qb, orderByClause, 1, 0, options...) +} diff --git a/pkg/proto/clickhouse/int_storage_slot_lifecycle_boundary.pb.go b/pkg/proto/clickhouse/int_storage_slot_lifecycle_boundary.pb.go new file mode 100644 index 00000000..dc890210 --- /dev/null +++ b/pkg/proto/clickhouse/int_storage_slot_lifecycle_boundary.pb.go @@ -0,0 +1,688 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.2 +// protoc (unknown) +// source: int_storage_slot_lifecycle_boundary.proto + +package clickhouse + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type IntStorageSlotLifecycleBoundary struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Timestamp when the record was last updated + UpdatedDateTime uint32 `protobuf:"varint,11,opt,name=updated_date_time,json=updatedDateTime,proto3" json:"updated_date_time,omitempty"` + // The contract address + Address string `protobuf:"bytes,12,opt,name=address,proto3" json:"address,omitempty"` + // The storage slot key + SlotKey string `protobuf:"bytes,13,opt,name=slot_key,json=slotKey,proto3" json:"slot_key,omitempty"` + // Reincarnation counter for this slot (1 = first lifecycle, 2 = second, etc.) + LifecycleNumber uint32 `protobuf:"varint,14,opt,name=lifecycle_number,json=lifecycleNumber,proto3" json:"lifecycle_number,omitempty"` + // Block where the slot transitioned from 0 to non-zero effective bytes + BirthBlock uint32 `protobuf:"varint,15,opt,name=birth_block,json=birthBlock,proto3" json:"birth_block,omitempty"` + // Block where the slot transitioned from non-zero to 0 effective bytes (NULL if still alive) + DeathBlock *wrapperspb.UInt32Value `protobuf:"bytes,16,opt,name=death_block,json=deathBlock,proto3" json:"death_block,omitempty"` + // Number of effective bytes at birth (the to_value of the 0->non-zero transition) + EffectiveBytesBirth uint32 `protobuf:"varint,17,opt,name=effective_bytes_birth,json=effectiveBytesBirth,proto3" json:"effective_bytes_birth,omitempty"` + // Number of effective bytes before death (the from_value of the non-zero->0 transition, NULL if still alive) + EffectiveBytesDeath *wrapperspb.UInt32Value `protobuf:"bytes,18,opt,name=effective_bytes_death,json=effectiveBytesDeath,proto3" json:"effective_bytes_death,omitempty"` +} + +func (x *IntStorageSlotLifecycleBoundary) Reset() { + *x = IntStorageSlotLifecycleBoundary{} + if protoimpl.UnsafeEnabled { + mi := &file_int_storage_slot_lifecycle_boundary_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IntStorageSlotLifecycleBoundary) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IntStorageSlotLifecycleBoundary) ProtoMessage() {} + +func (x *IntStorageSlotLifecycleBoundary) ProtoReflect() protoreflect.Message { + mi := &file_int_storage_slot_lifecycle_boundary_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use IntStorageSlotLifecycleBoundary.ProtoReflect.Descriptor instead. +func (*IntStorageSlotLifecycleBoundary) Descriptor() ([]byte, []int) { + return file_int_storage_slot_lifecycle_boundary_proto_rawDescGZIP(), []int{0} +} + +func (x *IntStorageSlotLifecycleBoundary) GetUpdatedDateTime() uint32 { + if x != nil { + return x.UpdatedDateTime + } + return 0 +} + +func (x *IntStorageSlotLifecycleBoundary) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *IntStorageSlotLifecycleBoundary) GetSlotKey() string { + if x != nil { + return x.SlotKey + } + return "" +} + +func (x *IntStorageSlotLifecycleBoundary) GetLifecycleNumber() uint32 { + if x != nil { + return x.LifecycleNumber + } + return 0 +} + +func (x *IntStorageSlotLifecycleBoundary) GetBirthBlock() uint32 { + if x != nil { + return x.BirthBlock + } + return 0 +} + +func (x *IntStorageSlotLifecycleBoundary) GetDeathBlock() *wrapperspb.UInt32Value { + if x != nil { + return x.DeathBlock + } + return nil +} + +func (x *IntStorageSlotLifecycleBoundary) GetEffectiveBytesBirth() uint32 { + if x != nil { + return x.EffectiveBytesBirth + } + return 0 +} + +func (x *IntStorageSlotLifecycleBoundary) GetEffectiveBytesDeath() *wrapperspb.UInt32Value { + if x != nil { + return x.EffectiveBytesDeath + } + return nil +} + +// Request for listing int_storage_slot_lifecycle_boundary records +type ListIntStorageSlotLifecycleBoundaryRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Filter by address - The contract address (PRIMARY KEY - required) + Address *StringFilter `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // Filter by slot_key - The storage slot key (ORDER BY column 2 - optional) + SlotKey *StringFilter `protobuf:"bytes,2,opt,name=slot_key,json=slotKey,proto3" json:"slot_key,omitempty"` + // Filter by lifecycle_number - Reincarnation counter for this slot (1 = first lifecycle, 2 = second, etc.) (ORDER BY column 3 - optional) + LifecycleNumber *UInt32Filter `protobuf:"bytes,3,opt,name=lifecycle_number,json=lifecycleNumber,proto3" json:"lifecycle_number,omitempty"` + // Filter by updated_date_time - Timestamp when the record was last updated (optional) + UpdatedDateTime *UInt32Filter `protobuf:"bytes,4,opt,name=updated_date_time,json=updatedDateTime,proto3" json:"updated_date_time,omitempty"` + // Filter by birth_block - Block where the slot transitioned from 0 to non-zero effective bytes (optional) + BirthBlock *UInt32Filter `protobuf:"bytes,5,opt,name=birth_block,json=birthBlock,proto3" json:"birth_block,omitempty"` + // Filter by death_block - Block where the slot transitioned from non-zero to 0 effective bytes (NULL if still alive) (optional) + DeathBlock *NullableUInt32Filter `protobuf:"bytes,6,opt,name=death_block,json=deathBlock,proto3" json:"death_block,omitempty"` + // Filter by effective_bytes_birth - Number of effective bytes at birth (the to_value of the 0->non-zero transition) (optional) + EffectiveBytesBirth *UInt32Filter `protobuf:"bytes,7,opt,name=effective_bytes_birth,json=effectiveBytesBirth,proto3" json:"effective_bytes_birth,omitempty"` + // Filter by effective_bytes_death - Number of effective bytes before death (the from_value of the non-zero->0 transition, NULL if still alive) (optional) + EffectiveBytesDeath *NullableUInt32Filter `protobuf:"bytes,8,opt,name=effective_bytes_death,json=effectiveBytesDeath,proto3" json:"effective_bytes_death,omitempty"` + // The maximum number of int_storage_slot_lifecycle_boundary to return. + // If unspecified, at most 100 items will be returned. + // The maximum value is 10000; values above 10000 will be coerced to 10000. + PageSize int32 `protobuf:"varint,9,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + // A page token, received from a previous `ListIntStorageSlotLifecycleBoundary` call. + // Provide this to retrieve the subsequent page. + PageToken string `protobuf:"bytes,10,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` + // The order of results. Format: comma-separated list of fields. + // Example: "foo,bar" or "foo desc,bar" for descending order on foo. + // If unspecified, results will be returned in the default order. + OrderBy string `protobuf:"bytes,11,opt,name=order_by,json=orderBy,proto3" json:"order_by,omitempty"` +} + +func (x *ListIntStorageSlotLifecycleBoundaryRequest) Reset() { + *x = ListIntStorageSlotLifecycleBoundaryRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_int_storage_slot_lifecycle_boundary_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListIntStorageSlotLifecycleBoundaryRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListIntStorageSlotLifecycleBoundaryRequest) ProtoMessage() {} + +func (x *ListIntStorageSlotLifecycleBoundaryRequest) ProtoReflect() protoreflect.Message { + mi := &file_int_storage_slot_lifecycle_boundary_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListIntStorageSlotLifecycleBoundaryRequest.ProtoReflect.Descriptor instead. +func (*ListIntStorageSlotLifecycleBoundaryRequest) Descriptor() ([]byte, []int) { + return file_int_storage_slot_lifecycle_boundary_proto_rawDescGZIP(), []int{1} +} + +func (x *ListIntStorageSlotLifecycleBoundaryRequest) GetAddress() *StringFilter { + if x != nil { + return x.Address + } + return nil +} + +func (x *ListIntStorageSlotLifecycleBoundaryRequest) GetSlotKey() *StringFilter { + if x != nil { + return x.SlotKey + } + return nil +} + +func (x *ListIntStorageSlotLifecycleBoundaryRequest) GetLifecycleNumber() *UInt32Filter { + if x != nil { + return x.LifecycleNumber + } + return nil +} + +func (x *ListIntStorageSlotLifecycleBoundaryRequest) GetUpdatedDateTime() *UInt32Filter { + if x != nil { + return x.UpdatedDateTime + } + return nil +} + +func (x *ListIntStorageSlotLifecycleBoundaryRequest) GetBirthBlock() *UInt32Filter { + if x != nil { + return x.BirthBlock + } + return nil +} + +func (x *ListIntStorageSlotLifecycleBoundaryRequest) GetDeathBlock() *NullableUInt32Filter { + if x != nil { + return x.DeathBlock + } + return nil +} + +func (x *ListIntStorageSlotLifecycleBoundaryRequest) GetEffectiveBytesBirth() *UInt32Filter { + if x != nil { + return x.EffectiveBytesBirth + } + return nil +} + +func (x *ListIntStorageSlotLifecycleBoundaryRequest) GetEffectiveBytesDeath() *NullableUInt32Filter { + if x != nil { + return x.EffectiveBytesDeath + } + return nil +} + +func (x *ListIntStorageSlotLifecycleBoundaryRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +func (x *ListIntStorageSlotLifecycleBoundaryRequest) GetPageToken() string { + if x != nil { + return x.PageToken + } + return "" +} + +func (x *ListIntStorageSlotLifecycleBoundaryRequest) GetOrderBy() string { + if x != nil { + return x.OrderBy + } + return "" +} + +// Response for listing int_storage_slot_lifecycle_boundary records +type ListIntStorageSlotLifecycleBoundaryResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The list of int_storage_slot_lifecycle_boundary. + IntStorageSlotLifecycleBoundary []*IntStorageSlotLifecycleBoundary `protobuf:"bytes,1,rep,name=int_storage_slot_lifecycle_boundary,json=intStorageSlotLifecycleBoundary,proto3" json:"int_storage_slot_lifecycle_boundary,omitempty"` + // A token, which can be sent as `page_token` to retrieve the next page. + // If this field is omitted, there are no subsequent pages. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` +} + +func (x *ListIntStorageSlotLifecycleBoundaryResponse) Reset() { + *x = ListIntStorageSlotLifecycleBoundaryResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_int_storage_slot_lifecycle_boundary_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListIntStorageSlotLifecycleBoundaryResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListIntStorageSlotLifecycleBoundaryResponse) ProtoMessage() {} + +func (x *ListIntStorageSlotLifecycleBoundaryResponse) ProtoReflect() protoreflect.Message { + mi := &file_int_storage_slot_lifecycle_boundary_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListIntStorageSlotLifecycleBoundaryResponse.ProtoReflect.Descriptor instead. +func (*ListIntStorageSlotLifecycleBoundaryResponse) Descriptor() ([]byte, []int) { + return file_int_storage_slot_lifecycle_boundary_proto_rawDescGZIP(), []int{2} +} + +func (x *ListIntStorageSlotLifecycleBoundaryResponse) GetIntStorageSlotLifecycleBoundary() []*IntStorageSlotLifecycleBoundary { + if x != nil { + return x.IntStorageSlotLifecycleBoundary + } + return nil +} + +func (x *ListIntStorageSlotLifecycleBoundaryResponse) GetNextPageToken() string { + if x != nil { + return x.NextPageToken + } + return "" +} + +// Request for getting a single int_storage_slot_lifecycle_boundary record by primary key +type GetIntStorageSlotLifecycleBoundaryRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The contract address + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` // Primary key (required) +} + +func (x *GetIntStorageSlotLifecycleBoundaryRequest) Reset() { + *x = GetIntStorageSlotLifecycleBoundaryRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_int_storage_slot_lifecycle_boundary_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetIntStorageSlotLifecycleBoundaryRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetIntStorageSlotLifecycleBoundaryRequest) ProtoMessage() {} + +func (x *GetIntStorageSlotLifecycleBoundaryRequest) ProtoReflect() protoreflect.Message { + mi := &file_int_storage_slot_lifecycle_boundary_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetIntStorageSlotLifecycleBoundaryRequest.ProtoReflect.Descriptor instead. +func (*GetIntStorageSlotLifecycleBoundaryRequest) Descriptor() ([]byte, []int) { + return file_int_storage_slot_lifecycle_boundary_proto_rawDescGZIP(), []int{3} +} + +func (x *GetIntStorageSlotLifecycleBoundaryRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +// Response for getting a single int_storage_slot_lifecycle_boundary record +type GetIntStorageSlotLifecycleBoundaryResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *IntStorageSlotLifecycleBoundary `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *GetIntStorageSlotLifecycleBoundaryResponse) Reset() { + *x = GetIntStorageSlotLifecycleBoundaryResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_int_storage_slot_lifecycle_boundary_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetIntStorageSlotLifecycleBoundaryResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetIntStorageSlotLifecycleBoundaryResponse) ProtoMessage() {} + +func (x *GetIntStorageSlotLifecycleBoundaryResponse) ProtoReflect() protoreflect.Message { + mi := &file_int_storage_slot_lifecycle_boundary_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetIntStorageSlotLifecycleBoundaryResponse.ProtoReflect.Descriptor instead. +func (*GetIntStorageSlotLifecycleBoundaryResponse) Descriptor() ([]byte, []int) { + return file_int_storage_slot_lifecycle_boundary_proto_rawDescGZIP(), []int{4} +} + +func (x *GetIntStorageSlotLifecycleBoundaryResponse) GetItem() *IntStorageSlotLifecycleBoundary { + if x != nil { + return x.Item + } + return nil +} + +var File_int_storage_slot_lifecycle_boundary_proto protoreflect.FileDescriptor + +var file_int_storage_slot_lifecycle_boundary_proto_rawDesc = []byte{ + 0x0a, 0x29, 0x69, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x6c, + 0x6f, 0x74, 0x5f, 0x6c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x5f, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x63, 0x62, 0x74, + 0x1a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, + 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x93, + 0x03, 0x0a, 0x1f, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, + 0x74, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x61, + 0x72, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, + 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x6c, 0x6f, 0x74, + 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x6c, 0x6f, 0x74, + 0x4b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x10, 0x6c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, + 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x6c, + 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1f, + 0x0a, 0x0b, 0x62, 0x69, 0x72, 0x74, 0x68, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0f, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x62, 0x69, 0x72, 0x74, 0x68, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, + 0x3d, 0x0a, 0x0b, 0x64, 0x65, 0x61, 0x74, 0x68, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x10, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x61, 0x74, 0x68, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x32, + 0x0a, 0x15, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, + 0x73, 0x5f, 0x62, 0x69, 0x72, 0x74, 0x68, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x13, 0x65, + 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x69, 0x72, + 0x74, 0x68, 0x12, 0x50, 0x0a, 0x15, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x64, 0x65, 0x61, 0x74, 0x68, 0x18, 0x12, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, + 0x13, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x44, + 0x65, 0x61, 0x74, 0x68, 0x22, 0xe1, 0x04, 0x0a, 0x2a, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x74, + 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, 0x69, 0x66, 0x65, 0x63, + 0x79, 0x63, 0x6c, 0x65, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x12, 0x2c, 0x0a, 0x08, 0x73, 0x6c, 0x6f, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x73, 0x6c, 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x3c, + 0x0a, 0x10, 0x6c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x55, + 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0f, 0x6c, 0x69, 0x66, + 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x11, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x55, 0x49, + 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0f, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x32, 0x0a, 0x0b, 0x62, + 0x69, 0x72, 0x74, 0x68, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x52, 0x0a, 0x62, 0x69, 0x72, 0x74, 0x68, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, + 0x3a, 0x0a, 0x0b, 0x64, 0x65, 0x61, 0x74, 0x68, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x4e, 0x75, 0x6c, 0x6c, 0x61, + 0x62, 0x6c, 0x65, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, + 0x0a, 0x64, 0x65, 0x61, 0x74, 0x68, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x45, 0x0a, 0x15, 0x65, + 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x62, + 0x69, 0x72, 0x74, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, + 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x13, 0x65, + 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x69, 0x72, + 0x74, 0x68, 0x12, 0x4d, 0x0a, 0x15, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x64, 0x65, 0x61, 0x74, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x4e, 0x75, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, + 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x13, 0x65, 0x66, + 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x44, 0x65, 0x61, 0x74, + 0x68, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, + 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x19, 0x0a, + 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x42, 0x79, 0x22, 0xc9, 0x01, 0x0a, 0x2b, 0x4c, 0x69, 0x73, + 0x74, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, + 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x23, 0x69, 0x6e, 0x74, 0x5f, + 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x5f, 0x6c, 0x69, 0x66, + 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x5f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x53, + 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, + 0x63, 0x6c, 0x65, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x52, 0x1f, 0x69, 0x6e, 0x74, + 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, 0x69, 0x66, 0x65, 0x63, + 0x79, 0x63, 0x6c, 0x65, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x12, 0x26, 0x0a, 0x0f, + 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x45, 0x0a, 0x29, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x74, 0x53, 0x74, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, + 0x6c, 0x65, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x66, 0x0a, 0x2a, 0x47, + 0x65, 0x74, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, + 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, + 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x69, 0x74, 0x65, + 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x49, 0x6e, + 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, 0x69, 0x66, 0x65, + 0x63, 0x79, 0x63, 0x6c, 0x65, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x52, 0x04, 0x69, + 0x74, 0x65, 0x6d, 0x32, 0xfb, 0x01, 0x0a, 0x26, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, + 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x42, + 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x69, + 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2f, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, + 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, + 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, + 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x03, 0x47, 0x65, 0x74, + 0x12, 0x2e, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, + 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, + 0x65, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2f, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x6f, + 0x72, 0x61, 0x67, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, + 0x65, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x65, 0x74, 0x68, 0x70, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x70, 0x73, 0x2f, 0x78, 0x61, 0x74, 0x75, + 0x2d, 0x63, 0x62, 0x74, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, + 0x6c, 0x69, 0x63, 0x6b, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, +} + +var ( + file_int_storage_slot_lifecycle_boundary_proto_rawDescOnce sync.Once + file_int_storage_slot_lifecycle_boundary_proto_rawDescData = file_int_storage_slot_lifecycle_boundary_proto_rawDesc +) + +func file_int_storage_slot_lifecycle_boundary_proto_rawDescGZIP() []byte { + file_int_storage_slot_lifecycle_boundary_proto_rawDescOnce.Do(func() { + file_int_storage_slot_lifecycle_boundary_proto_rawDescData = protoimpl.X.CompressGZIP(file_int_storage_slot_lifecycle_boundary_proto_rawDescData) + }) + return file_int_storage_slot_lifecycle_boundary_proto_rawDescData +} + +var file_int_storage_slot_lifecycle_boundary_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_int_storage_slot_lifecycle_boundary_proto_goTypes = []any{ + (*IntStorageSlotLifecycleBoundary)(nil), // 0: cbt.IntStorageSlotLifecycleBoundary + (*ListIntStorageSlotLifecycleBoundaryRequest)(nil), // 1: cbt.ListIntStorageSlotLifecycleBoundaryRequest + (*ListIntStorageSlotLifecycleBoundaryResponse)(nil), // 2: cbt.ListIntStorageSlotLifecycleBoundaryResponse + (*GetIntStorageSlotLifecycleBoundaryRequest)(nil), // 3: cbt.GetIntStorageSlotLifecycleBoundaryRequest + (*GetIntStorageSlotLifecycleBoundaryResponse)(nil), // 4: cbt.GetIntStorageSlotLifecycleBoundaryResponse + (*wrapperspb.UInt32Value)(nil), // 5: google.protobuf.UInt32Value + (*StringFilter)(nil), // 6: cbt.StringFilter + (*UInt32Filter)(nil), // 7: cbt.UInt32Filter + (*NullableUInt32Filter)(nil), // 8: cbt.NullableUInt32Filter +} +var file_int_storage_slot_lifecycle_boundary_proto_depIdxs = []int32{ + 5, // 0: cbt.IntStorageSlotLifecycleBoundary.death_block:type_name -> google.protobuf.UInt32Value + 5, // 1: cbt.IntStorageSlotLifecycleBoundary.effective_bytes_death:type_name -> google.protobuf.UInt32Value + 6, // 2: cbt.ListIntStorageSlotLifecycleBoundaryRequest.address:type_name -> cbt.StringFilter + 6, // 3: cbt.ListIntStorageSlotLifecycleBoundaryRequest.slot_key:type_name -> cbt.StringFilter + 7, // 4: cbt.ListIntStorageSlotLifecycleBoundaryRequest.lifecycle_number:type_name -> cbt.UInt32Filter + 7, // 5: cbt.ListIntStorageSlotLifecycleBoundaryRequest.updated_date_time:type_name -> cbt.UInt32Filter + 7, // 6: cbt.ListIntStorageSlotLifecycleBoundaryRequest.birth_block:type_name -> cbt.UInt32Filter + 8, // 7: cbt.ListIntStorageSlotLifecycleBoundaryRequest.death_block:type_name -> cbt.NullableUInt32Filter + 7, // 8: cbt.ListIntStorageSlotLifecycleBoundaryRequest.effective_bytes_birth:type_name -> cbt.UInt32Filter + 8, // 9: cbt.ListIntStorageSlotLifecycleBoundaryRequest.effective_bytes_death:type_name -> cbt.NullableUInt32Filter + 0, // 10: cbt.ListIntStorageSlotLifecycleBoundaryResponse.int_storage_slot_lifecycle_boundary:type_name -> cbt.IntStorageSlotLifecycleBoundary + 0, // 11: cbt.GetIntStorageSlotLifecycleBoundaryResponse.item:type_name -> cbt.IntStorageSlotLifecycleBoundary + 1, // 12: cbt.IntStorageSlotLifecycleBoundaryService.List:input_type -> cbt.ListIntStorageSlotLifecycleBoundaryRequest + 3, // 13: cbt.IntStorageSlotLifecycleBoundaryService.Get:input_type -> cbt.GetIntStorageSlotLifecycleBoundaryRequest + 2, // 14: cbt.IntStorageSlotLifecycleBoundaryService.List:output_type -> cbt.ListIntStorageSlotLifecycleBoundaryResponse + 4, // 15: cbt.IntStorageSlotLifecycleBoundaryService.Get:output_type -> cbt.GetIntStorageSlotLifecycleBoundaryResponse + 14, // [14:16] is the sub-list for method output_type + 12, // [12:14] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name +} + +func init() { file_int_storage_slot_lifecycle_boundary_proto_init() } +func file_int_storage_slot_lifecycle_boundary_proto_init() { + if File_int_storage_slot_lifecycle_boundary_proto != nil { + return + } + file_common_proto_init() + if !protoimpl.UnsafeEnabled { + file_int_storage_slot_lifecycle_boundary_proto_msgTypes[0].Exporter = func(v any, i int) any { + switch v := v.(*IntStorageSlotLifecycleBoundary); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_int_storage_slot_lifecycle_boundary_proto_msgTypes[1].Exporter = func(v any, i int) any { + switch v := v.(*ListIntStorageSlotLifecycleBoundaryRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_int_storage_slot_lifecycle_boundary_proto_msgTypes[2].Exporter = func(v any, i int) any { + switch v := v.(*ListIntStorageSlotLifecycleBoundaryResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_int_storage_slot_lifecycle_boundary_proto_msgTypes[3].Exporter = func(v any, i int) any { + switch v := v.(*GetIntStorageSlotLifecycleBoundaryRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_int_storage_slot_lifecycle_boundary_proto_msgTypes[4].Exporter = func(v any, i int) any { + switch v := v.(*GetIntStorageSlotLifecycleBoundaryResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_int_storage_slot_lifecycle_boundary_proto_rawDesc, + NumEnums: 0, + NumMessages: 5, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_int_storage_slot_lifecycle_boundary_proto_goTypes, + DependencyIndexes: file_int_storage_slot_lifecycle_boundary_proto_depIdxs, + MessageInfos: file_int_storage_slot_lifecycle_boundary_proto_msgTypes, + }.Build() + File_int_storage_slot_lifecycle_boundary_proto = out.File + file_int_storage_slot_lifecycle_boundary_proto_rawDesc = nil + file_int_storage_slot_lifecycle_boundary_proto_goTypes = nil + file_int_storage_slot_lifecycle_boundary_proto_depIdxs = nil +} diff --git a/pkg/proto/clickhouse/int_storage_slot_lifecycle_boundary.proto b/pkg/proto/clickhouse/int_storage_slot_lifecycle_boundary.proto new file mode 100644 index 00000000..50640a47 --- /dev/null +++ b/pkg/proto/clickhouse/int_storage_slot_lifecycle_boundary.proto @@ -0,0 +1,91 @@ +syntax = "proto3"; + +package cbt; + +import "common.proto"; +import "google/protobuf/wrappers.proto"; + +option go_package = "github.com/ethpandaops/xatu-cbt/pkg/proto/clickhouse"; +// Lifecycle boundaries per storage slot: birth (0→non-zero) and death (non-zero→0) blocks with effective bytes at each transition. + +message IntStorageSlotLifecycleBoundary { + // Timestamp when the record was last updated + uint32 updated_date_time = 11; + // The contract address + string address = 12; + // The storage slot key + string slot_key = 13; + // Reincarnation counter for this slot (1 = first lifecycle, 2 = second, etc.) + uint32 lifecycle_number = 14; + // Block where the slot transitioned from 0 to non-zero effective bytes + uint32 birth_block = 15; + // Block where the slot transitioned from non-zero to 0 effective bytes (NULL if still alive) + google.protobuf.UInt32Value death_block = 16; + // Number of effective bytes at birth (the to_value of the 0->non-zero transition) + uint32 effective_bytes_birth = 17; + // Number of effective bytes before death (the from_value of the non-zero->0 transition, NULL if still alive) + google.protobuf.UInt32Value effective_bytes_death = 18; +} + +// Request for listing int_storage_slot_lifecycle_boundary records +message ListIntStorageSlotLifecycleBoundaryRequest { + // Filter by address - The contract address (PRIMARY KEY - required) + StringFilter address = 1; + + // Filter by slot_key - The storage slot key (ORDER BY column 2 - optional) + StringFilter slot_key = 2; + + // Filter by lifecycle_number - Reincarnation counter for this slot (1 = first lifecycle, 2 = second, etc.) (ORDER BY column 3 - optional) + UInt32Filter lifecycle_number = 3; + + // Filter by updated_date_time - Timestamp when the record was last updated (optional) + UInt32Filter updated_date_time = 4; + // Filter by birth_block - Block where the slot transitioned from 0 to non-zero effective bytes (optional) + UInt32Filter birth_block = 5; + // Filter by death_block - Block where the slot transitioned from non-zero to 0 effective bytes (NULL if still alive) (optional) + NullableUInt32Filter death_block = 6; + // Filter by effective_bytes_birth - Number of effective bytes at birth (the to_value of the 0->non-zero transition) (optional) + UInt32Filter effective_bytes_birth = 7; + // Filter by effective_bytes_death - Number of effective bytes before death (the from_value of the non-zero->0 transition, NULL if still alive) (optional) + NullableUInt32Filter effective_bytes_death = 8; + + // The maximum number of int_storage_slot_lifecycle_boundary to return. + // If unspecified, at most 100 items will be returned. + // The maximum value is 10000; values above 10000 will be coerced to 10000. + int32 page_size = 9; + // A page token, received from a previous `ListIntStorageSlotLifecycleBoundary` call. + // Provide this to retrieve the subsequent page. + string page_token = 10; + // The order of results. Format: comma-separated list of fields. + // Example: "foo,bar" or "foo desc,bar" for descending order on foo. + // If unspecified, results will be returned in the default order. + string order_by = 11; +} + +// Response for listing int_storage_slot_lifecycle_boundary records +message ListIntStorageSlotLifecycleBoundaryResponse { + // The list of int_storage_slot_lifecycle_boundary. + repeated IntStorageSlotLifecycleBoundary int_storage_slot_lifecycle_boundary = 1; + // A token, which can be sent as `page_token` to retrieve the next page. + // If this field is omitted, there are no subsequent pages. + string next_page_token = 2; +} + +// Request for getting a single int_storage_slot_lifecycle_boundary record by primary key +message GetIntStorageSlotLifecycleBoundaryRequest { + // The contract address + string address = 1; // Primary key (required) +} + +// Response for getting a single int_storage_slot_lifecycle_boundary record +message GetIntStorageSlotLifecycleBoundaryResponse { + IntStorageSlotLifecycleBoundary item = 1; +} + +// Query int_storage_slot_lifecycle_boundary data +service IntStorageSlotLifecycleBoundaryService { + // List records | Retrieve paginated results with optional filtering + rpc List(ListIntStorageSlotLifecycleBoundaryRequest) returns (ListIntStorageSlotLifecycleBoundaryResponse); + // Get record | Retrieve a single record by primary key + rpc Get(GetIntStorageSlotLifecycleBoundaryRequest) returns (GetIntStorageSlotLifecycleBoundaryResponse); +} diff --git a/tests/mainnet/models/int_storage_slot_lifecycle.yaml b/tests/mainnet/models/int_storage_slot_lifecycle.yaml new file mode 100644 index 00000000..ab50d590 --- /dev/null +++ b/tests/mainnet/models/int_storage_slot_lifecycle.yaml @@ -0,0 +1,157 @@ +model: int_storage_slot_lifecycle +network: mainnet +external_data: + canonical_execution_contracts: + url: https://data.ethpandaops.io/xatu-cbt/tests/mainnet/int_storage_slot_lifecycle_canonical_execution_contracts.parquet + network_column: meta_network_name + canonical_execution_storage_diffs: + url: https://data.ethpandaops.io/xatu-cbt/tests/mainnet/int_storage_slot_lifecycle_canonical_execution_storage_diffs.parquet + network_column: meta_network_name + canonical_execution_storage_reads: + url: https://data.ethpandaops.io/xatu-cbt/tests/mainnet/int_storage_slot_lifecycle_canonical_execution_storage_reads.parquet + network_column: meta_network_name + canonical_execution_traces: + url: https://data.ethpandaops.io/xatu-cbt/tests/mainnet/int_storage_slot_lifecycle_canonical_execution_traces.parquet + network_column: meta_network_name + canonical_execution_transaction: + url: https://data.ethpandaops.io/xatu-cbt/tests/mainnet/int_storage_slot_lifecycle_canonical_execution_transaction.parquet + network_column: meta_network_name +assertions: + - name: Row count should be greater than zero + sql: | + SELECT COUNT(*) AS row_count FROM int_storage_slot_lifecycle FINAL + assertions: + - type: greater_than + column: row_count + value: 0 + - name: No rows with zero touch count + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle FINAL + WHERE touch_count < 1 + assertions: + - type: equals + column: bad_rows + value: 0 + - name: No null address or slot_key values + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle FINAL + WHERE address IS NULL OR slot_key IS NULL + assertions: + - type: equals + column: bad_rows + value: 0 + - name: effective_bytes_peak should be at least effective_bytes_birth + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle FINAL + WHERE effective_bytes_peak < effective_bytes_birth + assertions: + - type: equals + column: bad_rows + value: 0 + - name: last_touch_block should be at or after birth_block + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle FINAL + WHERE last_touch_block < birth_block + assertions: + - type: equals + column: bad_rows + value: 0 + - name: lifespan_blocks should be non-negative when death_block is set + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle FINAL + WHERE death_block IS NOT NULL AND lifespan_blocks < 0 + assertions: + - type: equals + column: bad_rows + value: 0 + - name: interval_count should not exceed touch_count minus one + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle FINAL + WHERE interval_count > touch_count - 1 + assertions: + - type: equals + column: bad_rows + value: 0 + - name: interval_count should equal touch_count minus one + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle FINAL + WHERE touch_count > 0 AND interval_count != touch_count - 1 + assertions: + - type: equals + column: bad_rows + value: 0 + - name: interval_sum should be at least interval_max when intervals exist + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle FINAL + WHERE interval_count > 0 AND interval_sum < interval_max + assertions: + - type: equals + column: bad_rows + value: 0 + - name: interval stats should be zero when there are no intervals + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle FINAL + WHERE interval_count = 0 AND (interval_sum > 0 OR interval_max > 0) + assertions: + - type: equals + column: bad_rows + value: 0 + - name: No null lifecycle_number or birth_block + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle FINAL + WHERE lifecycle_number IS NULL OR birth_block IS NULL + assertions: + - type: equals + column: bad_rows + value: 0 + - name: lifecycle_number should be positive + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle FINAL + WHERE lifecycle_number = 0 + assertions: + - type: equals + column: bad_rows + value: 0 + - name: death_block should be at or after birth_block when set + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle FINAL + WHERE death_block IS NOT NULL AND death_block < birth_block + assertions: + - type: equals + column: bad_rows + value: 0 + - name: lifespan should equal death_block minus birth_block when set + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle FINAL + WHERE death_block IS NOT NULL + AND lifespan_blocks != death_block - birth_block + assertions: + - type: equals + column: bad_rows + value: 0 + - name: last_touch_block should be within lifecycle bounds when death_block is set + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle FINAL + WHERE death_block IS NOT NULL AND last_touch_block > death_block + assertions: + - type: equals + column: bad_rows + value: 0 + - name: effective bytes should be within 0-32 bounds + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle FINAL + WHERE effective_bytes_birth > 32 + OR effective_bytes_peak > 32 + OR (effective_bytes_death IS NOT NULL AND effective_bytes_death > 32) + assertions: + - type: equals + column: bad_rows + value: 0 + - name: effective_bytes_death should be null when death_block is null + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle FINAL + WHERE death_block IS NULL AND effective_bytes_death IS NOT NULL + assertions: + - type: equals + column: bad_rows + value: 0 diff --git a/tests/mainnet/models/int_storage_slot_lifecycle_boundary.yaml b/tests/mainnet/models/int_storage_slot_lifecycle_boundary.yaml new file mode 100644 index 00000000..0a2a3bf0 --- /dev/null +++ b/tests/mainnet/models/int_storage_slot_lifecycle_boundary.yaml @@ -0,0 +1,129 @@ +model: int_storage_slot_lifecycle_boundary +network: mainnet +external_data: + canonical_execution_contracts: + url: https://data.ethpandaops.io/xatu-cbt/tests/mainnet/int_storage_slot_lifecycle_boundary_canonical_execution_contracts.parquet + network_column: meta_network_name + canonical_execution_storage_diffs: + url: https://data.ethpandaops.io/xatu-cbt/tests/mainnet/int_storage_slot_lifecycle_boundary_canonical_execution_storage_diffs.parquet + network_column: meta_network_name + canonical_execution_traces: + url: https://data.ethpandaops.io/xatu-cbt/tests/mainnet/int_storage_slot_lifecycle_boundary_canonical_execution_traces.parquet + network_column: meta_network_name + canonical_execution_transaction: + url: https://data.ethpandaops.io/xatu-cbt/tests/mainnet/int_storage_slot_lifecycle_boundary_canonical_execution_transaction.parquet + network_column: meta_network_name +assertions: + - name: Row count should be greater than zero + sql: | + SELECT COUNT(*) AS row_count FROM int_storage_slot_lifecycle_boundary FINAL + assertions: + - type: greater_than + column: row_count + value: 0 + - name: All lifecycle numbers must be positive + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle_boundary FINAL + WHERE lifecycle_number <= 0 + assertions: + - type: equals + column: bad_rows + value: 0 + - name: No null addresses + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle_boundary FINAL + WHERE address IS NULL OR address = '' + assertions: + - type: equals + column: bad_rows + value: 0 + - name: No null slot keys + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle_boundary FINAL + WHERE slot_key IS NULL OR slot_key = '' + assertions: + - type: equals + column: bad_rows + value: 0 + - name: Birth block must always be populated + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle_boundary FINAL + WHERE birth_block IS NULL OR birth_block = 0 + assertions: + - type: equals + column: bad_rows + value: 0 + - name: Effective bytes at birth must be positive + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle_boundary FINAL + WHERE effective_bytes_birth <= 0 + assertions: + - type: equals + column: bad_rows + value: 0 + - name: Effective bytes at birth must be within 1-32 + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle_boundary FINAL + WHERE effective_bytes_birth > 32 + assertions: + - type: equals + column: bad_rows + value: 0 + - name: Death block must be at or after birth block when present + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle_boundary FINAL + WHERE death_block IS NOT NULL AND death_block < birth_block + assertions: + - type: equals + column: bad_rows + value: 0 + - name: Effective bytes at death must be positive when death occurs + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle_boundary FINAL + WHERE death_block IS NOT NULL AND (effective_bytes_death IS NULL OR effective_bytes_death <= 0) + assertions: + - type: equals + column: bad_rows + value: 0 + - name: Effective bytes at death must be within 1-32 when death occurs + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle_boundary FINAL + WHERE death_block IS NOT NULL AND effective_bytes_death > 32 + assertions: + - type: equals + column: bad_rows + value: 0 + - name: Each address-slot-lifecycle combination must be unique + sql: | + SELECT COUNT(*) AS duplicate_count + FROM ( + SELECT address, slot_key, lifecycle_number, COUNT(*) AS cnt + FROM int_storage_slot_lifecycle_boundary FINAL + GROUP BY address, slot_key, lifecycle_number + HAVING cnt > 1 + ) + assertions: + - type: equals + column: duplicate_count + value: 0 + - name: Lifecycle numbers should be consecutive per slot + sql: | + SELECT COUNT(*) AS bad_rows + FROM ( + SELECT address, slot_key, max(lifecycle_number) AS max_lnum, count() AS lnum_count + FROM int_storage_slot_lifecycle_boundary FINAL + GROUP BY address, slot_key + HAVING max_lnum != lnum_count + ) + assertions: + - type: equals + column: bad_rows + value: 0 + - name: Death info must be null when no death block exists + sql: | + SELECT COUNT(*) AS bad_rows FROM int_storage_slot_lifecycle_boundary FINAL + WHERE death_block IS NULL AND effective_bytes_death IS NOT NULL + assertions: + - type: equals + column: bad_rows + value: 0