h3-sol is a tiny Rust library for checking H3 Cell IDs inside another
program.
H3 is a global grid system. It divides the world into hexagon-like cells and gives each cell a unique ID. Other systems can use those IDs when they want to talk about an area on Earth.
This library answers one question:
Is this u64 a real H3 Cell index?
It does not calculate maps, distances, coordinates, or locations. It checks whether the submitted number is one of the IDs the H3 grid system can assign to an actual grid cell.
The first version of this work was a Solana program that other programs could call by CPI. The H3 check itself is cheap, but CPI adds much more compute than the validation logic needs.
This crate is now meant to be included directly in other Rust/Solana programs. That lets callers validate H3 values inline and avoid the CPI overhead.
If h3-sol accepts a value, it means:
The submitted u64 is a valid H3 Cell index.
That is all it means.
A valid H3 Cell is just a valid grid cell ID. It does not prove that anyone or anything is actually located there.
This library does not prove:
- a server is physically inside the cell
- a network measurement is real
- a location claim came from a trusted source
- a user, validator, server, or device is bound to the cell
- the submitted cell is the correct cell for a real-world target
Those claims need to be checked by another protocol.
Add the crate as a dependency from this repository:
[dependencies]
h3-sol = { git = "https://github.com/<OWNER>/<REPO>", package = "h3-sol" }Then call it directly from your program:
use h3_sol::{is_valid_cell, validate_cell_at_resolution};
let cell = 0x85283473fffffff;
if is_valid_cell(cell) {
// The value is a valid H3 Cell index.
}
validate_cell_at_resolution(cell, 5)?;The crate name is h3-sol; the Rust import path is h3_sol.
Common helpers:
is_valid_cell(cell: u64) -> bool
is_valid_cell_at_resolution(cell: u64, expected_resolution: u8) -> bool
validate_cell(cell: u64) -> Result<(), H3ValidationError>
validate_cell_at_resolution(cell: u64, expected_resolution: u8) -> Result<(), H3ValidationError>Bit-field helpers:
resolution(cell: u64) -> u8
mode(cell: u64) -> u8
base_cell(cell: u64) -> u8
digit(cell: u64, pos: u8) -> u8
is_base_cell_pentagon(base: u8) -> boolConstants:
MAX_H3_RESOLUTION = 15
MAX_BASE_CELL = 121
H3_CELL_MODE = 1The library validates H3 Cell indexes only. It does not accept H3 directed edges, vertices, or other H3 index modes.
A valid H3 Cell must have:
- the H3 Cell mode bits
- no reserved bits set
- a resolution from
0through15 - a base cell from
0through121 - valid child digits for the chosen resolution
- unused child digit slots set to H3's unused digit value
- no invalid pentagon deleted-subsequence path
cargo testThe repository also includes a small counting script:
node scripts/count-valid-h3-corpus.mjs --max-resolution 15
node scripts/count-valid-h3-corpus.mjs --max-resolution 11 --exactFor example, resolution 11 alone has 237,279,209,162 valid H3 cells. Counting
is fast because it is math only; enumerating and executing every value on-chain
would not be practical at that scale.
h3-sol intentionally has:
- no
solana-programdependency - no Anchor dependency
- no Borsh or Serde dependency
- no H3 crate dependency
- no heap allocation in the validation path
- no floating point
- no geography, parent, child, neighbor, compaction, or lat/lon operations
The hot path validates packed H3 digit bits with masks instead of scanning all 15 digit slots. Ordinary hexagon cells do not enter a digit loop; pentagon cells only scan as far as needed to enforce H3's deleted-subsequence rule.
The goal is to keep the H3 validity check small enough for downstream programs to inline cheaply.
