Skip to content

Conversation

@wolf31o2
Copy link
Member

@wolf31o2 wolf31o2 commented Nov 12, 2025

Signed-off-by: Chris Gianelloni wolf31o2@blinklabs.io

Summary by CodeRabbit

  • Bug Fixes

    • Fixed block verification error handling so failures return consistent, reliable results.
  • Refactor

    • Reordered verification outputs for clearer success/error signaling.
    • Adjusted header checks to prevent incorrect validations.
  • New Features

    • Exposed additional block metadata fields for downstream use.
  • Tests

    • Updated tests to align with new verification output ordering.

@wolf31o2 wolf31o2 requested a review from a team as a code owner November 12, 2025 21:06
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 12, 2025

📝 Walkthrough

Walkthrough

The PR changes VerifyBlock in ledger/verify_block.go to return (bool, string, uint64, uint64, error) instead of (error, bool, string, uint64, uint64), and updates all return statements and error paths to the new ordering. BlockHexCbor gains two exported fields (Spk int, BlockBodyCbor string) and its CBOR tag is changed from a private anonymous field with toarray to cbor.StructAsArray. Corresponding test(s) in ledger/verify_block_test.go are updated to match the new return-value order.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20-30 minutes

  • Review return-value ordering and all modified error-return sites in ledger/verify_block.go.
  • Verify the new BlockHexCbor fields and CBOR tag change are correct for serialization/deserialization.
  • Confirm ledger/verify_block_test.go updates correctly capture reordered returns and still validate expected behavior.

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: refactoring the VerifyBlock function to move the error return value to the end of the return signature.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/verify-block-signature

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e2d9edb and 87bd6cc.

📒 Files selected for processing (2)
  • ledger/verify_block.go (4 hunks)
  • ledger/verify_block_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • ledger/verify_block_test.go
🔇 Additional comments (4)
ledger/verify_block.go (4)

43-98: LGTM! Consistent error handling throughout.

All error paths have been correctly updated to return (false, "", 0, 0, error), maintaining consistency with the new function signature. The use of zero values for non-error return parameters is appropriate.


103-103: LGTM! Success return correctly updated.

The success return statement properly reflects the new signature order with the nil error in the last position.


31-31: Function signature refactor verified: all callers updated correctly.

The change moves the error return to the last position per Go conventions. The single call site found in ledger/verify_block_test.go:53 is already updated to handle the new signature correctly.


146-146: The review comment is based on a misunderstanding of the change.

This is not a functional change—it's a refactor to align with the established codebase pattern. The change from an anonymous field with cbor:",toarray" to embedding cbor.StructAsArray produces identical CBOR encoding behavior. Embedding cbor.StructAsArray is the idiomatic pattern throughout gouroboros: it appears 200+ times in the codebase, particularly across the ledger package, while the tag-based pattern appears only ~25 times (mostly on anonymous empty structs as markers). The change makes BlockHexCbor consistent with hundreds of other structs in the codebase.

Likely an incorrect or invalid review comment.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
ledger/verify_block_test.go (4)

53-56: Update assertions to check success-path invariants (err, vrf, numbers) and tighten failure handling

Return-order fix is correct. Strengthen the test so valid cases assert nil error and non-empty metadata; fail fast on mismatches.

Apply:

-      isValid, _, _, _, err := VerifyBlock(tc.blockHexCbor)
-      if tc.expectedValid != isValid {
-        t.Errorf("unexpected error: %v", err)
-      }
+      isValid, vrfHex, blockNo, slotNo, err := VerifyBlock(tc.blockHexCbor)
+      if tc.expectedValid {
+        if err != nil {
+          t.Fatalf("expected valid with no error, got: %v", err)
+        }
+        if !isValid {
+          t.Fatalf("expected valid block")
+        }
+        if vrfHex == "" || blockNo == 0 || slotNo == 0 {
+          t.Fatalf("unexpected empty metadata: vrf=%q blockNo=%d slotNo=%d", vrfHex, blockNo, slotNo)
+        }
+      } else {
+        if isValid {
+          t.Fatalf("expected invalid block")
+        }
+        // err may be nil for some invalids (e.g., boolean checks). If you set tc.expectedErr, assert it below.
+      }

3-5: Use or remove expectedErr; if used, import strings and assert message substrings

The field exists but isn’t used. Either drop it or assert error text when provided.

Option A — assert when set:

 import (
-  "testing"
+  "strings"
+  "testing"
 )
@@
       } else {
         if isValid {
           t.Fatalf("expected invalid block")
         }
+        if tc.expectedErr != "" {
+          if err == nil || !strings.Contains(err.Error(), tc.expectedErr) {
+            t.Fatalf("expected error containing %q, got: %v", tc.expectedErr, err)
+          }
+        }
       }

Option B — remove the unused field:

   testCases := []struct {
     name          string
     blockHexCbor  BlockHexCbor
     expectedValid bool
-    expectedErr   string
   }{

Also applies to: 7-13, 53-56


7-7: Rename test to reflect scope (it verifies the whole block, not just the body)

Suggest: TestVerifyBlock. Keeps tests discoverable/accurate.

-func TestVerifyBlockBody(t *testing.T) {
+func TestVerifyBlock(t *testing.T) {

17-47: Consider moving giant CBOR literals to testdata fixtures

Loading from testdata or small helpers will reduce noise and improve readability/DIFFs.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8312b54 and e2d9edb.

📒 Files selected for processing (2)
  • ledger/verify_block.go (2 hunks)
  • ledger/verify_block_test.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
ledger/verify_block.go (7)
ledger/block.go (2)
  • BlockHeader (26-26)
  • NewBlockHeaderFromCbor (55-78)
ledger/babbage/babbage.go (2)
  • NewBabbageBlockHeaderFromCbor (1000-1006)
  • BabbageBlockHeader (152-158)
ledger/conway/conway.go (1)
  • ConwayBlockHeader (152-154)
ledger/verify_kes.go (1)
  • VerifyKes (129-149)
ledger/common/vrf.go (1)
  • VrfResult (21-25)
ledger/verify_vrf.go (2)
  • MkInputVrf (39-55)
  • VrfVerifyAndHash (57-83)
ledger/verify_block_body.go (1)
  • VerifyBlockBody (52-91)
ledger/verify_block_test.go (1)
ledger/verify_block.go (1)
  • VerifyBlock (31-143)
🔇 Additional comments (5)
ledger/verify_block_test.go (1)

1-59: No legacy VerifyBlock callers — error is returned last.
VerifyBlock's signature is (bool, string, uint64, uint64, error) (ledger/verify_block.go:31) and callers bind err last (e.g., ledger/verify_block_test.go:53: isValid, _, _, _, err := VerifyBlock(...)).

ledger/verify_block.go (4)

40-53: LGTM! Proper validation for Leios blocks.

The validation logic correctly rejects negative flags and unsupported Leios block types before proceeding with verification. The integer conversion at line 47 is safe since the non-negative check precedes it.


84-94: LGTM! Proper handling of Babbage and Conway headers.

The type assertion logic correctly handles both BabbageBlockHeader and ConwayBlockHeader (which embeds BabbageBlockHeader). The error message includes the actual type for debugging, which is helpful.


96-142: LGTM! Verification logic correctly updated.

All KES, VRF, and block body verification calls now use babbageHeader, and all return statements correctly follow the new signature with error as the final value.


31-31: Function signature change verified and correctly implemented.

The refactored signature correctly places error as the final return value, aligning with Go best practices. Verification confirms that all callers, including the test file at ledger/verify_block_test.go:53, have been updated to handle the new return order correctly:

isValid, _, _, _, err := VerifyBlock(tc.blockHexCbor)

The unpacking order matches the new signature perfectly.

Comment on lines 55 to 82
// For backward compatibility, try to decode as Babbage header first
// This allows the function to work with different eras that have compatible structures
headerCborByte, headerDecodeError := hex.DecodeString(headerCborHex)
if headerDecodeError != nil {
return fmt.Errorf(
return false, "", 0, 0, fmt.Errorf(
"VerifyBlock: headerCborByte decode error, %v",
headerDecodeError.Error(),
), false, "", 0, 0
)
}
header, headerUnmarshalError := NewBabbageBlockHeaderFromCbor(
headerCborByte,
)
var header BlockHeader
var headerUnmarshalError error
header, headerUnmarshalError = NewBabbageBlockHeaderFromCbor(headerCborByte)
if headerUnmarshalError != nil {
return fmt.Errorf(
"VerifyBlock: header unmarshal error, %v",
headerUnmarshalError.Error(),
), false, "", 0, 0
// If Babbage decoding fails, try the era-specific decoder
header, headerUnmarshalError = NewBlockHeaderFromCbor(
blockType,
headerCborByte,
)
if headerUnmarshalError != nil {
return false, "", 0, 0, fmt.Errorf(
"VerifyBlock: header unmarshal error, %v",
headerUnmarshalError.Error(),
)
}
}
if header == nil {
return errors.New("VerifyBlock: header returned empty"), false, "", 0, 0
return false, "", 0, 0, errors.New("VerifyBlock: header returned empty")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Clarify backward compatibility scope or remove pre-Babbage fallback.

The decoding logic attempts era-specific fallback (lines 69-72) for pre-Babbage blocks, but the subsequent code (lines 86-94) requires Babbage-compatible headers and explicitly rejects non-Babbage types. This means blocks from Shelley, Allegra, Mary, or Alonzo eras will decode successfully via NewBlockHeaderFromCbor but then fail at the type assertion, resulting in a less clear error message.

Consider one of these approaches:

  1. Remove the fallback if only Babbage+ blocks are supported: validate blockType upfront and return an error for pre-Babbage eras before attempting any decoding.
  2. Support pre-Babbage eras: extend the verification logic to handle header types from earlier eras.
  3. Improve error messaging: if the fallback is intentionally kept for robustness, ensure the error at line 92 clearly indicates that pre-Babbage blocks aren't supported.

Example of upfront validation approach:

+	// VerifyBlock only supports Babbage and later eras
+	if blockType < BlockTypeBabbage && blockType != BlockTypeConway {
+		return false, "", 0, 0, fmt.Errorf(
+			"VerifyBlock: block verification only supported for Babbage and later eras, got block type: %d",
+			blockType,
+		)
+	}
+
 	// For backward compatibility, try to decode as Babbage header first

Committable suggestion skipped: line range outside the PR's diff.

Signed-off-by: Chris Gianelloni <wolf31o2@blinklabs.io>
@wolf31o2 wolf31o2 force-pushed the refactor/verify-block-signature branch from e2d9edb to 87bd6cc Compare November 12, 2025 23:01
@wolf31o2
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 12, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@wolf31o2 wolf31o2 merged commit 5bd2560 into main Nov 13, 2025
10 checks passed
@wolf31o2 wolf31o2 deleted the refactor/verify-block-signature branch November 13, 2025 13:34
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.

3 participants