Copy a tlog-tiles client locally - #589
Merged
Merged
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #589 +/- ##
==========================================
- Coverage 27.30% 24.91% -2.40%
==========================================
Files 28 29 +1
Lines 2197 2408 +211
==========================================
Hits 600 600
- Misses 1469 1680 +211
Partials 128 128 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
phbnf
reviewed
Aug 13, 2026
phbnf
left a comment
There was a problem hiding this comment.
I'm assuming all these functions have been copy/pated. I've done a few checks to verify this, but not comprehensive.
Comment on lines
+396
to
+475
| // nWithSuffix returns a tiles-spec "N" path, with a partial suffix if p > 0. | ||
| func nWithSuffix(l, n uint64, p uint8) string { | ||
| suffix := "" | ||
| if p > 0 { | ||
| suffix = fmt.Sprintf(".p/%d", p) | ||
| } | ||
| return fmt.Sprintf("%s%s", fmtN(n), suffix) | ||
| } | ||
|
|
||
| // tilePath builds the relative path to the subtree tile with the given level and index in tile space. | ||
| // If p > 0 the path represents a partial tile. | ||
| func tilePath(tileLevel, tileIndex uint64, p uint8) string { | ||
| return fmt.Sprintf("tile/%d/%s", tileLevel, nWithSuffix(tileLevel, tileIndex, p)) | ||
| } | ||
|
|
||
| // fmtN returns the "N" part of a Tiles-spec path. | ||
| // | ||
| // N is grouped into chunks of 3 decimal digits, starting with the most significant digit, and | ||
| // padding with zeroes as necessary. | ||
| // Digit groups are prefixed with "x", except for the least-significant group which has no prefix, | ||
| // and separated with slashes. | ||
| // | ||
| // See https://github.com/C2SP/C2SP/blob/main/tlog-tiles.md#:~:text=index%201234067%20will%20be%20encoded%20as%20x001/x234/067 | ||
| func fmtN(N uint64) string { | ||
| n := fmt.Sprintf("%03d", N%1000) | ||
| N /= 1000 | ||
| for N > 0 { | ||
| n = fmt.Sprintf("x%03d/%s", N%1000, n) | ||
| N /= 1000 | ||
| } | ||
| return n | ||
| } | ||
|
|
||
| // hashTile represents a tile within the Merkle hash tree. | ||
| // Leaf HashTiles will have a corresponding EntryBundle, where each | ||
| // entry in the EntryBundle slice hashes to the value at the same | ||
| // index in the Nodes slice. | ||
| type hashTile struct { | ||
| // Nodes stores the leaf hash nodes in this tile. | ||
| // Note that only non-ephemeral nodes are stored. | ||
| Nodes [][]byte | ||
| } | ||
|
|
||
| // UnmarshalText implements encoding/TextUnmarshaler and reads HashTiles | ||
| // which are encoded using the tlog-tiles spec. | ||
| func (t *hashTile) UnmarshalText(raw []byte) error { | ||
| if len(raw)%sha256.Size != 0 { | ||
| return fmt.Errorf("%d is not a multiple of %d", len(raw), sha256.Size) | ||
| } | ||
| nodes := make([][]byte, 0, len(raw)/sha256.Size) | ||
| for index := 0; index < len(raw); index += sha256.Size { | ||
| data := raw[index : index+sha256.Size] | ||
| nodes = append(nodes, data) | ||
| } | ||
| t.Nodes = nodes | ||
| return nil | ||
| } | ||
|
|
||
| // partialTileSize returns the expected number of leaves in a tile at the given tile level and index | ||
| // within a tree of the specified logSize, or 0 if the tile is expected to be fully populated. | ||
| func partialTileSize(level, index, logSize uint64) uint8 { | ||
| sizeAtLevel := logSize >> (level * tileHeight) | ||
| fullTiles := sizeAtLevel / tileWidth | ||
| if index < fullTiles { | ||
| return 0 | ||
| } | ||
| return uint8(sizeAtLevel % tileWidth) | ||
| } | ||
|
|
||
| // nodeCoordsToTileAddress returns the (TileLevel, TileIndex) in tile-space, and the | ||
| // (NodeLevel, NodeIndex) address within that tile of the specified tree node co-ordinates. | ||
| func nodeCoordsToTileAddress(treeLevel, treeIndex uint64) (uint64, uint64, uint, uint64) { | ||
| tileRowWidth := uint64(1 << (tileHeight - treeLevel%tileHeight)) | ||
| tileLevel := treeLevel / tileHeight | ||
| tileIndex := treeIndex / tileRowWidth | ||
| nodeLevel := uint(treeLevel % tileHeight) | ||
| nodeIndex := uint64(treeIndex % tileRowWidth) | ||
|
|
||
| return tileLevel, tileIndex, nodeLevel, nodeIndex | ||
| } |
There was a problem hiding this comment.
Maybe all of this could actually go in formats?
Contributor
Author
There was a problem hiding this comment.
That's not a bad idea - worth thinking about!
phbnf
approved these changes
Aug 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR removes the dep on Tessera caused by the
tlog-tilesfeeder using Tessera'sclientpackage.While having this like so isn't a significant problem at the moment since there's not a truly circular dependency, "core" Tessera now does have a strong dep on this repo as part of both the MTC implementation, and Tessera's support for synchronous witnessing of logs.
Since, eventually, feeders will go away (logs now are expected to send their checkpoints directly to witnesses themselves), this is more of a pre-emptive dependency tidy up to avoid a "looks circular" smell.