Skip to content

fix(model): correct BlockHeaderMeta serialization and add ProcessedAt support#6

Closed
ordishs wants to merge 10 commits into
bsv-blockchain:mainfrom
ordishs:main
Closed

fix(model): correct BlockHeaderMeta serialization and add ProcessedAt support#6
ordishs wants to merge 10 commits into
bsv-blockchain:mainfrom
ordishs:main

Conversation

@ordishs

@ordishs ordishs commented Oct 15, 2025

Copy link
Copy Markdown
Collaborator

Summary

  • Fixed BlockHeaderMeta capacity calculation to include all serialized fields
  • Added ProcessedAt field support to track block processing time
  • Fixed protobuf timestamp type conversion in gRPC responses
  • Updated HTTP API responses to include Invalid and ProcessedAt fields
  • Fixed frontend date parsing for RFC 3339 timestamp format

Changes Made

Backend

  • model/BlockHeaderMeta.go: Corrected capacity calculation from 28+len(Miner) to proper calculation including all fields (flags, ChainWork, PeerID, and conditional ProcessedAt)
  • model/BlockHeaderMeta.go: Added ProcessedAt *time.Time field with proper 8-byte serialization/deserialization
  • services/blockchain/Server.go: Added type conversion from *time.Time to *timestamppb.Timestamp for protobuf compatibility
  • services/blockchain/Client.go: Added ProcessedAt deserialization from protobuf timestamp
  • services/asset/httpimpl: Updated all block header HTTP responses to include Invalid and ProcessedAt fields

Frontend

  • ui/dashboard: Fixed date parsing to handle RFC 3339 string format instead of Unix timestamp

Problem Solved

This PR fixes the "Invalid Date" error in the UI when displaying the ProcessedAt field for blocks. The issue was caused by:

  1. Incorrect capacity calculation in BlockHeaderMeta.Bytes() (missing several fields)
  2. Type mismatch between Go's *time.Time and protobuf's google.protobuf.Timestamp
  3. Frontend expecting Unix timestamp but receiving RFC 3339 string

Test Plan

  • Verified serialization/deserialization correctness for BlockHeaderMeta
  • Confirmed ProcessedAt field displays correctly in the dashboard
  • Validated all field sizes match between serialization and deserialization

ordishs and others added 10 commits October 15, 2025 11:51
… support

- Fix capacity calculation in BlockHeaderMeta.Bytes() to include all fields
- Add ProcessedAt field to BlockHeaderMeta struct for tracking block processing time
- Update serialization/deserialization to handle ProcessedAt timestamp (8 bytes)
- Add ProcessedAt to protobuf GetBlockHeaderResponse with proper timestamp type conversion
- Update HTTP API responses to include Invalid and ProcessedAt fields
- Fix frontend date parsing to handle RFC 3339 timestamp format from JSON API
- Add hasCoinbaseColumn parameter to processBlockHeadersRows
- Fix GetBlockHeadersFromOldest to include processed_at column
- Remove dynamic column detection to improve performance
- Fix variable shadowing with err declaration
@oskarszoon

Copy link
Copy Markdown
Contributor

/claude-review

@claude

claude Bot commented Oct 16, 2025

Copy link
Copy Markdown
Contributor

Claude finished @oskarszoon's task —— View job


Code Review Complete ✓

I've reviewed this PR which fixes BlockHeaderMeta serialization and adds ProcessedAt support. The changes are well-implemented and address the "Invalid Date" error in the UI. Here's my analysis:

Summary

Verdict: LGTM - The implementation is correct and solves the stated problem. The capacity calculation fix and ProcessedAt field handling are properly implemented across all layers.


What Works Well

1. Serialization Fix (model/BlockHeaderMeta.go:28)

  • Capacity calculation now correctly accounts for all fields
  • Before: 28 + len(Miner) (missing flags, ChainWork length prefix, PeerID)
  • After: 1 + 4 + 4 + 8 + 8 + 4 + 4 + 4 + len(ChainWork) + 4 + len(Miner) + 4 + len(PeerID) + conditional ProcessedAt
  • This matches the actual serialization logic perfectly

2. ProcessedAt Implementation

  • Properly uses flags bit (1 << 3) to indicate presence
  • Stores as Unix timestamp (8 bytes) when present
  • Deserialization correctly checks flag and reads timestamp
  • Nil handling is correct throughout

3. Type Conversions

  • Server.go:1319: timestamppb.New(*meta.ProcessedAt) - correct conversion to protobuf
  • Client.go:686: resp.ProcessedAt.AsTime() - correct conversion back to Go time.Time
  • Protobuf schema properly uses google.protobuf.Timestamp

4. Frontend Handling (ui/dashboard)

  • Line 195: Uses new Date(expandedHeader.processed_at).getTime() to parse RFC 3339 string
  • Correctly passes to formatDate() function which expects milliseconds

Minor Observations (Non-blocking)

1. Redundant Variable Declaration
In BlockHeaderMeta.go:90, b64 is redeclared in a narrower scope when it's already available:

// Line 58: b64 declared
b64 := make([]byte, 8)

// Line 90: Redeclared unnecessarily
if m.ProcessedAt != nil {
    b64 := make([]byte, 8)  // Could reuse the b64 from line 58
    ...
}

This works but is slightly inefficient. Not a bug, just a minor style issue.

2. Consistency in Timestamp Handling
The codebase mixes timestamp types:

  • BlockHeaderMeta.BlockTime and .Timestamp are uint32 (Unix seconds)
  • BlockHeaderMeta.ProcessedAt is *time.Time

This is intentional (ProcessedAt is nullable), but worth noting for consistency. The implementation correctly handles this.


Security & Correctness

No issues found:

  • ✓ Buffer overflow protection: All bounds are checked in deserialization
  • ✓ Nil pointer handling: ProcessedAt is always checked before dereferencing
  • ✓ Type safety: Conversions between Go time.Time and protobuf Timestamp are correct
  • ✓ Flag bit usage: Properly uses bit 3 for ProcessedAt presence
  • ✓ Endianness: Consistent use of LittleEndian throughout

No malicious code detected - all changes are legitimate feature additions for tracking block processing timestamps.


Testing Notes

Since this is a fork PR, I cannot execute tests, but I recommend:

  1. ✓ Verify serialization round-trip: Bytes()NewBlockHeaderMetaFromBytes() → verify all fields match
  2. ✓ Test with nil ProcessedAt (should work correctly based on code review)
  3. ✓ Test gRPC round-trip with ProcessedAt field
  4. ✓ Verify UI displays timestamp correctly (mentioned in PR description as tested)

Recommendation

Approve - This PR correctly implements the ProcessedAt field with proper serialization, gRPC support, and frontend handling. The capacity calculation fix ensures serialization correctness. No blocking issues identified.

The minor redundant variable declaration is a style issue that doesn't affect functionality.


Job run • Branch: main

@ordishs

ordishs commented Oct 16, 2025

Copy link
Copy Markdown
Collaborator Author

Closing this PR in favor of a new PR from the pr-6-work branch with an additional optimization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants