Skip to content

Commit 59d4901

Browse files
Savidclaude
andcommitted
fix(clickhouse): nullable storage_key on canonical_beacon_block_access_list
balance/nonce/code/touched access-list changes carry no storage slot. The column was a non-nullable FixedString(66) and the route appended nil for them, which zero-pads to 66 raw NUL bytes rather than NULL: ~48.9M rows on glamsterdam-devnet-7. Those values are not valid hex, so startsWith(storage_key, '0x') misses them and they render as garbage in exports and Grafana. storage_key is part of the table's ORDER BY, so the type cannot be changed by ALTER. The fix is applied to the original 006 table definition instead, with allow_nullable_key = 1 (already used in 001_init) so existing devnet data can be migrated by a rebuild rather than in place. The zero hash was rejected as a sentinel because storage_read legitimately has 2.3M rows at real storage slot 0x000..0, which NULL keeps distinct. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 1669229 commit 59d4901

4 files changed

Lines changed: 21 additions & 10 deletions

File tree

deploy/migrations/clickhouse/xatu/006_gloas_bals_support.up.sql

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ CREATE TABLE IF NOT EXISTS canonical_beacon_block_access_list_local ON CLUSTER '
3333
address FixedString(42) CODEC(ZSTD(1)),
3434
change_type LowCardinality(String) CODEC(ZSTD(1)),
3535
block_access_index UInt32 CODEC(DoubleDelta, ZSTD(1)),
36-
storage_key FixedString(66) CODEC(ZSTD(1)),
36+
-- Nullable: balance/nonce/code/touched changes carry no storage slot. A
37+
-- non-nullable FixedString would store 66 raw NUL bytes for them, which is
38+
-- not valid hex, and the zero hash is ambiguous with real storage slot 0.
39+
storage_key Nullable(FixedString(66)) CODEC(ZSTD(1)),
3740
new_value Nullable(String) CODEC(ZSTD(1)),
3841
meta_client_name LowCardinality(String) CODEC(ZSTD(1)),
3942
meta_client_id String CODEC(ZSTD(1)),
@@ -59,7 +62,8 @@ CREATE TABLE IF NOT EXISTS canonical_beacon_block_access_list_local ON CLUSTER '
5962
meta_labels Map(String, String) CODEC(ZSTD(1))
6063
) ENGINE = ReplicatedReplacingMergeTree(updated_date_time)
6164
PARTITION BY toStartOfMonth(slot_start_date_time)
62-
ORDER BY (slot_start_date_time, meta_network_name, block_hash, address, change_type, storage_key, block_access_index);
65+
ORDER BY (slot_start_date_time, meta_network_name, block_hash, address, change_type, storage_key, block_access_index)
66+
SETTINGS allow_nullable_key = 1;
6367

6468
CREATE TABLE IF NOT EXISTS canonical_beacon_block_access_list ON CLUSTER '{cluster}'
6569
AS canonical_beacon_block_access_list_local

pkg/clickhouse/route/canonical/canonical_beacon_block_access_list.gen.go

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

pkg/clickhouse/route/canonical/canonical_beacon_block_access_list.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,12 @@ func (b *canonicalBeaconBlockAccessListBatch) appendPayload(event *xatu.Decorate
8282
b.BlockAccessIndex.Append(0)
8383
}
8484

85+
// balance/nonce/code/touched changes carry no storage slot, so store NULL
86+
// rather than a zero-padded FixedString of raw NUL bytes.
8587
if storageKey := change.GetStorageKey(); storageKey != nil {
86-
b.StorageKey.Append([]byte(storageKey.GetValue()))
88+
b.StorageKey.Append(proto.NewNullable[[]byte]([]byte(storageKey.GetValue())))
8789
} else {
88-
b.StorageKey.Append(nil)
90+
b.StorageKey.Append(proto.Nullable[[]byte]{})
8991
}
9092

9193
if newValue := change.GetNewValue(); newValue != nil {

pkg/clickhouse/route/canonical/canonical_beacon_block_access_list_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ func TestSnapshot_canonical_beacon_block_access_list_balance(t *testing.T) {
8181
balAddressKey: "0xaabbccddee112233445566778899aabbccddeeff",
8282
balChangeTypeKey: balChangeTypeBalance,
8383
balBlockAccessIndexKey: uint32(2),
84-
balStorageKeyKey: "",
85-
balNewValueKey: "1000000000000000000",
84+
// Balance changes carry no storage slot, so storage_key is NULL.
85+
balStorageKeyKey: nil,
86+
balNewValueKey: "1000000000000000000",
8687
})
8788
}

0 commit comments

Comments
 (0)