feat: view the result of attested data#141
Conversation
WalkthroughAdds binary attestation payload parsing and ABI-decoding utilities (parseAttestationPayload and related types), exposes them via public exports, implements byte-level/ABI decoders, updates the attestation example to verify and parse signed payloads, and expands README/API docs with parsing examples and a full attestation workflow. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Client
participant AttestationService
participant Parser as parseAttestationPayload
participant Verifier as SignatureVerifier
Client->>AttestationService: requestAttestation(args)
AttestationService-->>Client: canonicalPayload + signature
Client->>Parser: parseAttestationPayload(canonicalPayload)
Note over Parser: decode header, stream/action, args\ndecode ABI-encoded result -> rows
Parser-->>Client: ParsedAttestationPayload
Client->>Verifier: sha256(canonicalPayload) + signature
Verifier->>Verifier: recoverAddress(hash, signature)
Verifier-->>Client: validatorAddress
Client->>Client: validate validatorAddress & use parsed rows
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25–35 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 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.
Actionable comments posted: 1
🧹 Nitpick comments (1)
examples/attestation/index.ts (1)
17-18: Import from the public SDK surface
Now thatparseAttestationPayloadis part of the public API, pull it from the same entry point asNodeTNClient("../../src"). Importing directly from../../src/util/AttestationEncodingpunches through the package boundary and will break once the build outputs land indist/. Swap the import toimport { NodeTNClient, parseAttestationPayload } from "../../src";.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
README.md(3 hunks)docs/api-reference.md(1 hunks)examples/attestation/index.ts(5 hunks)src/internal.ts(1 hunks)src/util/AttestationEncoding.ts(4 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
examples/attestation/index.ts (2)
src/internal.ts (1)
parseAttestationPayload(26-26)src/util/AttestationEncoding.ts (1)
parseAttestationPayload(520-661)
src/util/AttestationEncoding.ts (1)
src/internal.ts (3)
DecodedRow(30-30)ParsedAttestationPayload(31-31)parseAttestationPayload(26-26)
🪛 markdownlint-cli2 (0.18.1)
README.md
287-287: Hard tabs
Column: 1
(MD010, no-hard-tabs)
315-315: Hard tabs
Column: 1
(MD010, no-hard-tabs)
Time Submission Status
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
README.md (2)
277-309: Enhance code example with error handling and result structure clarity.The example successfully demonstrates the happy path but lacks error handling. Consider adding:
- Try-catch wrapper for signature recovery (invalid signatures)
- Clarification on the structure of
parsed.result(is it an array of rows? What's the row format?)Consider adding a note or expanded example showing:
- Error handling when signature recovery fails
- How to inspect and iterate over
parsed.resultrows (per line 305's comment "result.length rows")- Expected fields within each decoded row
This would provide users a complete workflow from the raw payload to actionable data.
320-320: Clarify ABI encoding details for Result field.Line 320 updates the payload structure to indicate the Result field is "ABI-encoded, length-prefixed". This is a critical detail for correctness but lacks explanation.
Consider adding a brief inline note explaining what "ABI-encoded" means in this context (e.g., "Solidity ABI encoding" or link to relevant decoding documentation). This would help users understand why
parseAttestationPayloadis necessary rather than simple binary decoding.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
README.md(3 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
README.md
287-287: Hard tabs
Column: 1
(MD010, no-hard-tabs)
297-297: Hard tabs
Column: 1
(MD010, no-hard-tabs)
298-298: Hard tabs
Column: 1
(MD010, no-hard-tabs)
299-299: Hard tabs
Column: 1
(MD010, no-hard-tabs)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (2)
README.md (2)
486-486: Quick Reference entry aligns with new functionality.Adding
parseAttestationPayload(canonicalPayload)to the Quick Reference table is appropriate and follows the existing pattern. The table now correctly reflects the new public API for parsing.
277-309: Code example verified as correct — no changes needed.All verification points confirm the README example is accurate:
- Payload slicing (65-byte signature): Matches the documented payload structure in
src/util/AttestationEncoding.ts- ParsedAttestationPayload type: Correctly exported interface with
.result: DecodedRow[]property matching the example usage- ethers imports: Both
sha256andrecoverAddressare available as direct named exports in ethers v6.13.5 (the project's dependency)The code example is ready as-is.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/util/AttestationEncoding.ts (2)
500-657: Comprehensive attestation payload parser with good error handling.The
parseAttestationPayloadfunction correctly parses the canonical format:
- Clear documentation of the 8-field payload structure
- Sequential parsing with proper bounds checking
- Descriptive error messages for each field
- Correct use of big-endian for block height and length prefixes
- Arguments decoded using
decodeEncodedValue- Results decoded using
decodeABIDatapointsThe data provider decoding logic (lines 556-576) handles multiple formats (raw 20-byte addresses, UTF-8 strings, hex strings) which provides good flexibility, though it's somewhat complex.
Optional refactor suggestion: The data provider decoding logic could be extracted into a helper function (e.g.,
decodeDataProvider(bytes: Uint8Array): string) to improve readability and testability, but this is a minor enhancement and not critical.
772-813: Good test coverage for helper functions.The new tests verify:
- Endianness correctness for uint16 and uint32 reads
- Empty result and error cases for
decodeCanonicalQueryResultThe
parseAttestationPayloadtest is marked TODO with a note thatexamples/attestation/index.tsprovides integration test coverage. While integration tests are valuable, consider adding a unit test with synthetic ABI-encoded data to improve test coverage and catch regressions earlier.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
README.md(3 hunks)docs/api-reference.md(1 hunks)src/util/AttestationEncoding.ts(4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/util/AttestationEncoding.ts (1)
src/internal.ts (3)
DecodedRow(30-30)ParsedAttestationPayload(31-31)parseAttestationPayload(26-26)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (17)
README.md (4)
277-309: Excellent addition of attestation parsing documentation.The new section clearly demonstrates the complete workflow: extracting the canonical payload, separating the signature, verifying the validator, and parsing the structured data. The example is comprehensive and well-structured.
Note: A past review flagged hard tab characters in this code block (lines 287, 297-299), but the current code appears to use consistent 2-space indentation. If the markdown linter still reports issues, ensure no hard tabs remain.
308-308: Verify API Reference link completeness.The cross-reference to the API documentation is appropriate. Based on past reviews, ensure that the referenced section includes formal type definitions for both
ParsedAttestationPayloadandDecodedRowwith complete field descriptions and examples.I will verify the completeness of the API Reference documentation in my review of
docs/api-reference.md.
320-320: Good clarification on ABI encoding.Adding "ABI-encoded" to the Result field description provides important context for developers working with attestation payloads. This aligns with the implementation and the parsing examples.
486-486: LGTM - Quick reference entry is clear and helpful.The addition to the quick reference table follows the existing format and improves discoverability of the new parsing functionality.
docs/api-reference.md (4)
750-806: Excellent comprehensive documentation for parseAttestationPayload.The documentation is thorough and well-structured:
- Clear function signature and parameters
- Complete return type documentation with all fields explained
- Comprehensive example demonstrating signature verification and parsing
- Proper cross-reference to
DecodedRowtype at line 767
808-840: DecodedRow type now properly documented.The formal type definition for
DecodedRowhas been added as requested in previous reviews. The documentation includes:
- Complete interface definition
- Field descriptions with context-specific usage
- Concrete example with real data
- Important constraint note (exactly two values for attestation results)
This addresses the past review concern about missing formal type documentation.
841-860: Clear documentation of ABI result format.The Attestation Result Format section provides essential information:
- Exact ABI encoding signature (
abi.encode(uint256[], int256[]))- Important note about 18-decimal fixed-point representation
- Concrete example showing the decoded structure
This helps developers understand the binary format and properly interpret the values.
861-909: Comprehensive attestation workflow documentation.The Complete Attestation Workflow section provides an excellent end-to-end guide:
- Five clear steps from request to data usage
- Includes important retry logic for async signature polling
- Demonstrates proper signature verification
- Shows practical data access patterns
This serves as a valuable reference for developers implementing attestation verification.
src/util/AttestationEncoding.ts (9)
10-10: LGTM - Appropriate ethers import for ABI decoding.The
AbiCoderimport from ethers v6 is correctly used in thedecodeABIDatapointsfunction to decode ABI-encoded attestation results.
99-135: Well-implemented endianness-aware read helpers.The new read functions (
readUint16LE,readUint32BE,readUint16BE) correctly handle both little-endian and big-endian byte order. The use of>>> 0ensures proper unsigned conversion, and the implementations are tested (lines 772-789).
137-173: Clean and well-documented type definitions.The new types (
DecodedDataType,DecodedEncodedValue,DecodedRow,ParsedAttestationPayload) are well-structured and properly exported. They provide clear interfaces for working with decoded attestation data and align with the API documentation.
175-218: Correct implementation of DataType decoding.The
decodeDataTypefunction properly reverses the encoding format:
- Version validation ensures compatibility
- Variable-length name field is handled correctly
- Returns both the decoded type and new offset for sequential parsing
220-269: Proper EncodedValue decoding implementation.The
decodeEncodedValuefunction correctly reverses the kwil-jsEncodedValue.MarshalBinary()format:
- Version validation for forward compatibility
- Proper handling of variable-length type and data arrays
- Sequential offset tracking for parsing multiple values
271-353: Correct value decoding with proper signed integer handling.The
decodedValueToJSanddecodeSingleValuefunctions properly convert decoded values to JavaScript types:
- NULL handling checks both empty arrays and null indicator bytes
- Array iteration is correct
- Signed integer fix: Lines 325-329 now use
view.getBigInt64(0, false)for proper two's-complement signed int64 decoding, addressing the past review concern about unsigned interpretation- Appropriate fallbacks for unknown types
Note: The past review issue regarding signed integer decoding has been resolved by using
DataView.getBigInt64().
355-423: Robust canonical query result decoder.The
decodeCanonicalQueryResultfunction correctly parses the canonical format:
- Clear documentation of the binary format in comments
- Proper bounds checking before each read operation
- Descriptive error messages with context (row/column indices)
- Correct sequential offset tracking through nested loops
425-470: Correct ABI datapoints decoding.The
decodeABIDatapointsfunction properly decodes ABI-encoded attestation results:
- Handles empty data gracefully
- Uses correct ABI types (
uint256[],int256[])- Validates timestamp/value array length consistency
- Applies 18-decimal fixed-point conversion via
formatFixedPoint- Provides clear error messages
472-498: Well-implemented fixed-point formatter.The
formatFixedPointfunction correctly converts fixed-point BigInt values to decimal strings:
- Proper handling of negative values
- Correct fractional part padding with leading zeros
- Trailing zero removal for cleaner output
- Edge case handling when fractional part is zero
resolves: https://github.com/trufnetwork/trufscan/issues/117
Summary by CodeRabbit
New Features
Documentation
Examples