@@ -150,3 +150,33 @@ func requireEntriesAsSet(t *testing.T, got [][]byte, expected ...[]byte) {
150150 }
151151 require .Equal (t , expSet , gotSet )
152152}
153+
154+ // TestDeltaIndexerBlobs_ZeroValuePoolAndAccount is a regression for the
155+ // proto3-zero-value bug that permanently 400s /v1/query/indexer-blobs when
156+ // chain state contains a Pool{Id:0} or Account{Address:nil}. Because proto3
157+ // omits zero-valued scalar fields from the wire, marshalling Pool{Id:0,Amount:5000}
158+ // produces bytes with only field #2 (Amount). Pre-fix, poolEntryKey called
159+ // codec.GetRawProtoField(entry, 1) and returned "field number 1 not found",
160+ // which bubbled up as lib.ErrUnmarshal and HTTP 400 on every affected height.
161+ // Post-fix, the missing field is treated as an empty (zero-value) key.
162+ func TestDeltaIndexerBlobs_ZeroValuePoolAndAccount (t * testing.T ) {
163+ zeroPool := mustMarshalProto (t , & Pool {Id : 0 , Amount : 5000 })
164+ normalPool := mustMarshalProto (t , & Pool {Id : 32768 , Amount : 25_000_000_000_000 })
165+ zeroAcc := mustMarshalProto (t , & Account {Address : nil , Amount : 1 })
166+ normalAcc := mustMarshalProto (t , & Account {Address : bytes .Repeat ([]byte {7 }, 20 ), Amount : 42 })
167+
168+ curr := & IndexerBlob {
169+ Block : mustMarshalProto (t , & lib.BlockResult {}),
170+ Accounts : [][]byte {zeroAcc , normalAcc },
171+ Pools : [][]byte {zeroPool , normalPool },
172+ }
173+ prev := & IndexerBlob {
174+ Block : mustMarshalProto (t , & lib.BlockResult {}),
175+ Accounts : [][]byte {zeroAcc , normalAcc },
176+ Pools : [][]byte {zeroPool , normalPool },
177+ }
178+
179+ delta , err := DeltaIndexerBlobs (& IndexerBlobs {Current : curr , Previous : prev })
180+ require .NoError (t , err , "zero-value Pool.Id / Account.Address must not error" )
181+ require .NotNil (t , delta )
182+ }
0 commit comments