fix(nitronode): trim blockhash, set it to null in DB#851
Conversation
📝 WalkthroughWalkthroughA Postgres migration makes ChangesLegacy empty block_hash normalization
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
nitronode/store/database/contract_event.go (1)
20-20:⚠️ Potential issue | 🟠 MajorHandle nullable
block_hashat the model boundary.The migration allows
NULLvalues inblock_hash(line 9:DROP NOT NULL, line 10:UPDATE...SET block_hash = NULL), butContractEvent.BlockHashremains a non-nullablestringtype. While GORM convertsNULLto empty string during scan, this creates an implicit and unclear contract: getters at lines 89 and 107 both callstrings.TrimSpace(ev.BlockHash)without explicit null handling, making it ambiguous whether empty string represents actual empty data or aNULLfrom the database.To clarify intent and prevent future bugs, change
BlockHashtosql.NullStringand update both getters to checkValidbefore accessing the string value.Proposed fix (nullable model field + explicit normalization)
+import "database/sql" type ContractEvent struct { @@ - BlockHash string `gorm:"column:block_hash"` + BlockHash sql.NullString `gorm:"column:block_hash"` @@ } func (s *DBStore) StoreContractEvent(ev core.BlockchainEvent) error { contractEvent := &ContractEvent{ @@ - BlockHash: ev.BlockHash, + BlockHash: sql.NullString{String: ev.BlockHash, Valid: true}, @@ } @@ } func (s *DBStore) GetLatestContractEventBlockHashAndNumber(contractAddress string, blockchainID uint64) (uint64, string, error) { @@ - return ev.BlockNumber, strings.TrimSpace(ev.BlockHash), nil + hash := "" + if ev.BlockHash.Valid { + hash = strings.TrimSpace(ev.BlockHash.String) + } + return ev.BlockNumber, hash, nil } @@ func (s *DBStore) GetPreviousDistinctBlockHash(contractAddress string, blockchainID uint64, belowBlockNumber uint64) (uint64, string, error) { @@ - return ev.BlockNumber, strings.TrimSpace(ev.BlockHash), nil + hash := "" + if ev.BlockHash.Valid { + hash = strings.TrimSpace(ev.BlockHash.String) + } + return ev.BlockNumber, hash, nil }Also applies to lines 32–40 (StoreContractEvent), 78–90 (GetLatestContractEventBlockHashAndNumber), and 95–108 (GetPreviousDistinctBlockHash).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@nitronode/store/database/contract_event.go` at line 20, The BlockHash field in the ContractEvent struct is defined as a non-nullable string type, but the database migration allows NULL values, creating an implicit and unclear contract. Change the BlockHash field from string to sql.NullString to explicitly represent nullable data. Then update all code that accesses BlockHash (including the getters around lines 89 and 107, the StoreContractEvent struct around lines 32-40, and the GetLatestContractEventBlockHashAndNumber and GetPreviousDistinctBlockHash functions) to check the Valid field of the sql.NullString before accessing the string value instead of calling strings.TrimSpace without null handling.
🧹 Nitpick comments (1)
nitronode/store/database/contract_event_test.go (1)
93-135: ⚡ Quick winAdd an explicit
NULL-hash regression case.Current coverage validates padded legacy values, but migration writes real
NULLs. Add a subtest insertingblock_hash = NULL(raw SQL) and assert both getters return""without error.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@nitronode/store/database/contract_event_test.go` around lines 93 - 135, Add a new subtest to the TestGetContractEventBlockHash_TrimsPaddedEmpty function that validates NULL block_hash values from migrations. Insert a contract event with block_hash set to NULL using raw SQL, then call both GetLatestContractEventBlockHashAndNumber and GetPreviousDistinctBlockHash methods and assert that both return an empty string without error. This ensures the code handles actual NULL values from database migrations, not just the padded legacy values already covered by the existing subtests.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@nitronode/store/database/contract_event.go`:
- Line 20: The BlockHash field in the ContractEvent struct is defined as a
non-nullable string type, but the database migration allows NULL values,
creating an implicit and unclear contract. Change the BlockHash field from
string to sql.NullString to explicitly represent nullable data. Then update all
code that accesses BlockHash (including the getters around lines 89 and 107, the
StoreContractEvent struct around lines 32-40, and the
GetLatestContractEventBlockHashAndNumber and GetPreviousDistinctBlockHash
functions) to check the Valid field of the sql.NullString before accessing the
string value instead of calling strings.TrimSpace without null handling.
---
Nitpick comments:
In `@nitronode/store/database/contract_event_test.go`:
- Around line 93-135: Add a new subtest to the
TestGetContractEventBlockHash_TrimsPaddedEmpty function that validates NULL
block_hash values from migrations. Insert a contract event with block_hash set
to NULL using raw SQL, then call both GetLatestContractEventBlockHashAndNumber
and GetPreviousDistinctBlockHash methods and assert that both return an empty
string without error. This ensures the code handles actual NULL values from
database migrations, not just the padded legacy values already covered by the
existing subtests.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 88107b0c-df5c-4dd9-a750-51b858987a2a
📒 Files selected for processing (3)
nitronode/config/migrations/postgres/20260618000000_make_block_hash_nullable.sqlnitronode/store/database/contract_event.gonitronode/store/database/contract_event_test.go
## v1.4.1 Patch release. ### Bug Fixes - **fix(nitronode): trim blockhash, set it to null in DB (#851)** — make `block_hash` nullable (migration `20260618000000_make_block_hash_nullable.sql`) and trim/null the stored blockhash in `contract_event` persistence. ### Notes - nitronode-only fix. SDK packages (`@yellow-org/sdk`, `sdk-compat`, `sdk-mcp`) version-bumped to 1.4.1 for strict mirror but **not republished to npm** — no SDK code changed since v1.4.0. - No `mcp-v` tag. ### Artifacts **Docker images** (`ghcr.io/layer-3/nitrolite`, tag `v1.4.1`) — `nitronode`, `faucet-app`, `playground`.
## v1.4.1 Patch release. ### Bug Fixes - **fix(nitronode): trim blockhash, set it to null in DB (#851)** — make `block_hash` nullable (migration `20260618000000_make_block_hash_nullable.sql`) and trim/null the stored blockhash in `contract_event` persistence. ### Notes - nitronode-only fix. SDK packages (`@yellow-org/sdk`, `sdk-compat`, `sdk-mcp`) version-bumped to 1.4.1 for strict mirror but **not republished to npm** — no SDK code changed since v1.4.0. - No `mcp-v` tag. ### Artifacts **Docker images** (`ghcr.io/layer-3/nitrolite`, tag `v1.4.1`) — `nitronode`, `faucet-app`, `playground`. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Updated version to 1.4.1 across all packages and services. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Summary by CodeRabbit
Release Notes