Skip to content

Commit a2e548f

Browse files
authored
Merge pull request #119 from ethpandaops/release/state-expiry
Release/state expiry
2 parents 4a79f5d + 4701735 commit a2e548f

28 files changed

+8244
-3594
lines changed

backend/pkg/api/v1/proto/public.pb.go

Lines changed: 2035 additions & 831 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/pkg/api/v1/proto/public.proto

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,54 @@ message FilterMetadata {
8181
string order_by = 3;
8282
}
8383

84+
// StateExpiryAccessTotalResponse is the v1 API response for state expiry access totals.
85+
message StateExpiryAccessTotalResponse {
86+
StateExpiryAccessTotal item = 1;
87+
FilterMetadata filters = 2;
88+
}
89+
90+
// StateExpiryAccessTotal represents state expiry access statistics for public API consumption.
91+
message StateExpiryAccessTotal {
92+
// Total number of accounts accessed in last 365 days
93+
uint64 total_accounts = 1;
94+
// Number of expired accounts (not accessed in last 365 days)
95+
uint64 expired_accounts = 2;
96+
// Total number of contract accounts accessed in last 365 days
97+
uint64 total_contracts = 3;
98+
// Number of expired contracts (not accessed in last 365 days)
99+
uint64 expired_contracts = 4;
100+
}
101+
102+
// StateExpiryBlockResponse is the v1 API response for state expiry block information.
103+
// Returns the execution layer block number from approximately 1 year ago, which is
104+
// used as the expiry boundary for state expiry calculations.
105+
message StateExpiryBlockResponse {
106+
StateExpiryBlock item = 1;
107+
FilterMetadata filters = 2;
108+
}
109+
110+
// StateExpiryBlock represents the execution block from approximately 1 year ago
111+
// that serves as the boundary for state expiry calculations.
112+
message StateExpiryBlock {
113+
// The execution layer block number from approximately 1 year ago
114+
uint32 block_number = 1;
115+
}
116+
117+
// StateExpiryStorageTotalResponse is the v1 API response for storage slot totals.
118+
// This endpoint provides the latest total storage slot statistics for state expiry analysis.
119+
message StateExpiryStorageTotalResponse {
120+
StateExpiryStorageTotal item = 1;
121+
FilterMetadata filters = 2;
122+
}
123+
124+
// StateExpiryStorageTotal represents state expiry storage slot statistics for public API consumption.
125+
message StateExpiryStorageTotal {
126+
// Total number of storage slots accessed in last 365 days
127+
uint64 total_storage_slots = 1;
128+
// Number of expired storage slots (not accessed in last 365 days)
129+
uint64 expired_storage_slots = 2;
130+
}
131+
84132

85133
// Network represents an Ethereum network for public API consumption.
86134
// This provides essential network metadata needed by clients.
@@ -98,6 +146,86 @@ message NetworkFilterMetadata {
98146
int32 filtered_count = 3; // Networks after filtering
99147
}
100148

149+
// StateExpiryAccessHistoryResponse is the v1 API response for state expiry access history data.
150+
// This endpoint provides aggregated data about Ethereum address access patterns chunked by 10000 blocks.
151+
message StateExpiryAccessHistoryResponse {
152+
repeated StateExpiryAccessHistory items = 1;
153+
PaginationMetadata pagination = 2;
154+
FilterMetadata filters = 3;
155+
}
156+
157+
// StateExpiryAccessHistory represents address access statistics for a 10000-block chunk.
158+
// This data is useful for analyzing state expiry patterns and understanding address activity over time.
159+
message StateExpiryAccessHistory {
160+
// The starting block number of this 10000-block chunk
161+
uint32 chunk_start_block_number = 1;
162+
163+
// Number of unique accounts that were accessed for the first time in this chunk
164+
// These are addresses that had never been accessed before this chunk
165+
uint32 first_accessed_accounts = 2;
166+
167+
// Number of unique accounts whose most recent access was in this chunk
168+
// These addresses haven't been accessed in any later chunks
169+
uint32 last_accessed_accounts = 3;
170+
}
171+
172+
// StateExpiryStorageHistoryResponse is the v1 API response for state expiry storage slot history data.
173+
// This endpoint provides aggregated data about Ethereum storage slot access patterns chunked by 10000 blocks.
174+
message StateExpiryStorageHistoryResponse {
175+
repeated StateExpiryStorageHistory items = 1;
176+
PaginationMetadata pagination = 2;
177+
FilterMetadata filters = 3;
178+
}
179+
180+
// StateExpiryStorageHistory represents storage slot statistics for a 10000-block chunk.
181+
// This data is useful for analyzing state expiry patterns and understanding storage slot activity over time.
182+
message StateExpiryStorageHistory {
183+
// The starting block number of this 10000-block chunk
184+
uint32 chunk_start_block_number = 1;
185+
186+
// Number of storage slots that were accessed for the first time in this chunk
187+
// These are slots that had never been accessed before this chunk
188+
uint32 first_accessed_slots = 2;
189+
190+
// Number of storage slots whose most recent access was in this chunk
191+
// These slots haven't been accessed in any later chunks
192+
uint32 last_accessed_slots = 3;
193+
}
194+
195+
// StateExpiryStorageExpiredTopResponse is the v1 API response for top contracts by expired storage slots.
196+
// This endpoint provides the top 100 contracts ranked by the number of expired storage slots (not accessed in last 365 days).
197+
message StateExpiryStorageExpiredTopResponse {
198+
repeated StateExpiryStorageExpiredTop items = 1;
199+
FilterMetadata filters = 2;
200+
}
201+
202+
// StateExpiryStorageExpiredTop represents a contract ranked by expired storage slots for public API consumption.
203+
message StateExpiryStorageExpiredTop {
204+
// Rank by expired storage slots (1=highest)
205+
uint32 rank = 1;
206+
// The contract address
207+
string contract_address = 2;
208+
// Number of expired storage slots for this contract (not accessed in last 365 days)
209+
uint64 expired_slots = 3;
210+
}
211+
212+
// StateExpiryStorageTopResponse is the v1 API response for top contracts by total storage slots.
213+
// This endpoint provides the top 100 contracts ranked by the total number of storage slots.
214+
message StateExpiryStorageTopResponse {
215+
repeated StateExpiryStorageTop items = 1;
216+
FilterMetadata filters = 2;
217+
}
218+
219+
// StateExpiryStorageTop represents a contract ranked by total storage slots for public API consumption.
220+
message StateExpiryStorageTop {
221+
// Rank by total storage slots (1=highest)
222+
uint32 rank = 1;
223+
// The contract address
224+
string contract_address = 2;
225+
// Total number of storage slots for this contract
226+
uint64 total_storage_slots = 3;
227+
}
228+
101229
// ListBeaconSlotMevRelayResponse is the v1 API response for MEV relay bid counts by slot.
102230
message ListBeaconSlotMevRelayResponse {
103231
repeated MevRelayBidCount relays = 1;

backend/pkg/api/v1/rest/routes.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,5 +150,56 @@ func (r *PublicRouter) GetRoutes() []RouteConfig {
150150
Cache: middleware.CacheRealtime,
151151
Description: "Get prepared blocks for a specific slot",
152152
},
153+
154+
// State expiry endpoints
155+
{
156+
Path: "/{network}/state-expiry/access/history",
157+
Handler: r.handleStateExpiryAccessHistory,
158+
Methods: []string{http.MethodGet, http.MethodOptions},
159+
Cache: middleware.CacheNearRealtime,
160+
Description: "Get address access history chunked by 10000 blocks for state expiry analysis",
161+
},
162+
{
163+
Path: "/{network}/state-expiry/storage/history",
164+
Handler: r.handleStateExpiryStorageHistory,
165+
Methods: []string{http.MethodGet, http.MethodOptions},
166+
Cache: middleware.CacheNearRealtime,
167+
Description: "Get storage slot history chunked by 10000 blocks for state expiry analysis",
168+
},
169+
{
170+
Path: "/{network}/state-expiry/access/total",
171+
Handler: r.handleStateExpiryAccessTotal,
172+
Methods: []string{http.MethodGet, http.MethodOptions},
173+
Cache: middleware.CacheNearRealtime,
174+
Description: "Get total address access statistics for state expiry analysis",
175+
},
176+
{
177+
Path: "/{network}/state-expiry/storage/expired/top",
178+
Handler: r.handleStateExpiryStorageExpiredTop,
179+
Methods: []string{http.MethodGet, http.MethodOptions},
180+
Cache: middleware.CacheNearRealtime,
181+
Description: "Get top 100 contracts by expired storage slots for state expiry analysis",
182+
},
183+
{
184+
Path: "/{network}/state-expiry/storage/top",
185+
Handler: r.handleStateExpiryStorageTop,
186+
Methods: []string{http.MethodGet, http.MethodOptions},
187+
Cache: middleware.CacheNearRealtime,
188+
Description: "Get top 100 contracts by total storage slots for state expiry analysis",
189+
},
190+
{
191+
Path: "/{network}/state-expiry/storage/total",
192+
Handler: r.handleStateExpiryStorageTotal,
193+
Methods: []string{http.MethodGet, http.MethodOptions},
194+
Cache: middleware.CacheNearRealtime,
195+
Description: "Get total storage slot statistics for state expiry analysis",
196+
},
197+
{
198+
Path: "/{network}/state-expiry/expiry/block",
199+
Handler: r.handleStateExpiryBlock,
200+
Methods: []string{http.MethodGet, http.MethodOptions},
201+
Cache: middleware.CacheNearRealtime,
202+
Description: "Get the execution block number from approximately 1 year ago for state expiry boundary",
203+
},
153204
}
154205
}

0 commit comments

Comments
 (0)