Geolocation
The DoubleZero Geolocation service helps users determine the physical location of devices using latency measurements. RTT (round-trip time) measurements between known-location infrastructure and a target device provide cryptographically-signed proof that a device is within a certain distance of a given point. Onchain recording of measurements to the DoubleZero Ledger is planned for a future release.
Use cases include regulatory compliance (e.g., GDPR — proving validators operate within the EU), geographic distribution audits, and any application that needs verifiable proof of where a device or IP is.
How it works
flowchart LR
subgraph DZ["DoubleZero Network"]
DZD["DZD\n(known location)"]
Probe["geoProbe\n(bare metal server)"]
DZD -- "TWAMP\n(continuous latency)" --> Probe
end
subgraph Target["Target Device"]
T["Target\n(validator / server)"]
end
Probe -- "RTT measurement" --> T
T -- "RTT response" --> Probe
Probe -. "signed offset" .-> T
The following diagram shows the three probe flow types — Outbound, OutboundIcmp, and Inbound — which differ in how the geoProbe communicates with the target:
flowchart TB
subgraph out["Outbound Flow (TWAMP)"]
direction LR
P1["geoProbe"] -- "TWAMP probe" --> T1["Target"]
T1 -- "TWAMP reply" --> P1
end
subgraph icmp["OutboundIcmp Flow"]
direction LR
P3["geoProbe"] -- "ICMP Echo Request" --> T3["Target"]
T3 -- "ICMP Echo Reply" --> P3
end
subgraph in["Inbound Flow (NAT-friendly)"]
direction LR
T2["Target"] -- "signed packets" --> P2["geoProbe"]
P2 -- "reply" --> T2
end
Geolocation uses a three-tier measurement chain:
DZD (known location) ◄──TWAMP──► geoProbe ◄──RTT──► Target device
- DZD <-> geoProbe: TWAMP continuously measures latency between the DoubleZero Device and the probe. DZDs have known, fixed geographic coordinates registered on the DZ Ledger.
- geoProbe <-> Target: RTT is measured between the probe and the device being located.
Offset results are cryptographically signed, and delivered via UDP to the target or a user-specified alternate destination.
Important: Geolocation reports RTT only — not inferred distance or coordinates. A common way to use this would be to divide the RTT by 2, and then multiply by the speed of light through glass (~200km/ms) to provide a radius around the DZD coordinates that the target is located within. How you interpret RTT (e.g., computing a maximum-distance radius) is up to you.
Probe flow types
There are three ways a probe can measure a target:
| Flow | Who initiates | Protocol | Use when |
|---|---|---|---|
| Outbound | Probe -> Target | TWAMP | Target has a public IP, open inbound port, and can run a TWAMP reflector |
| OutboundIcmp | Probe -> Target | ICMP echo | Target has a public IP but cannot run a TWAMP reflector (or TWAMP is blocked by firewall) |
| Inbound | Target -> Probe | Signed TWAMP | Target cannot accept inbound connections, or want to verify location of a signing key |
In all cases, the DZD <-> geoProbe measurement happens the same way. Only the direction and protocol of the geoProbe <-> target communication differs.
Technical Specification
For the full technical specification of the geolocation verification system, including cryptographic signing details and the measurement protocol, see RFC 16: Geolocation Verification.
Prerequisites
1. DoubleZero ID with credits
Geolocation users need a funded DoubleZero ID. You do not need to connect to the DoubleZero network (no access pass required), but your key needs credits on the DoubleZero ledger to create a user account and manage targets — each add/remove target operation costs credits.
If you don't have a DoubleZero ID:
doublezero keygen
doublezero address # get your pubkey
Contact the DoubleZero team with your pubkey to get your ID funded. Fund it to a higher-than-typical amount if you expect to add and remove targets dynamically.
2. 2Z token account
You need a 2Z token account. Service fees are deducted from this account on a per-epoch basis.
Installation
On a management computer:
curl -1sLf https://dl.cloudsmith.io/public/malbeclabs/doublezero/setup.deb.sh | sudo -E bash
sudo apt install doublezero
On a target for Inbound or TWAMP Outbound:
curl -1sLf https://dl.cloudsmith.io/public/malbeclabs/doublezero/setup.deb.sh | sudo -E bash
sudo apt install doublezero-geoprobe-target
doublezero-geoprobe-target (outbound) and doublezero-geoprobe-target-sender (inbound)
ICMP Outbound
outbound-icmp targets do not require any software installed.
Check your balance
doublezero balance
Setup
Step 1: Create a geolocation user
doublezero geolocation user create \
--env testnet \
--code <your-user-code> \
--token-account <your-2Z-token-account>
--code: a short, unique identifier for your account (e.g.myorg)--token-account: the public key of your 2Z token account — service fees are deducted from here
Account activation
After creating a user, contact the DoubleZero Foundation to activate your account. Payment status must be marked active before probing begins.
Step 2: List available probes
doublezero geolocation probe list
Note the code or public_ip, and the signing_pubkey (for inbound targets) of the probe you want to use.
Step 3: Add a target
Use this flow if your target has a public IP, an open inbound port, and can run a TWAMP reflector.
doublezero geolocation user add-target \
--user <your-user-code> \
--type outbound \
--probe <probe-code> \
--target-ip <target-public-ip>
--probe: the code of the geoProbe that will measure the target (e.g. ams-mn-gp1)
--ip-address: the public IPv4 address of the target device
Use this flow if your target has a public IP but cannot run a TWAMP reflector, or if TWAMP traffic is blocked by firewall. The target only needs to respond to ICMP echo (ping) requests — no additional software required.
doublezero geolocation user add-target \
--user <your-user-code> \
--type OutboundIcmp \
--probe <probe-code> \
--ip-address <target-public-ip>
--probe: the code of the geoProbe that will measure the target (e.g. ams-mn-gp1)
--ip-address: the public IPv4 address of the target device
Result Destination
Outbound ICMP targets only work if your user has an alternate result destination set. (See Step 3b)
Use this flow if your target is behind NAT or cannot accept inbound connections.
doublezero geolocation user add-target \
--user <your-user-code> \
--type inbound \
--probe <probe-code> \
--target-pk <target-keypair-pubkey>
--probe: the code of the geoProbe that will measure the target (e.g. ams-mn-gp1)
--target-pk: public key of the keypair the target will use to sign messages — the probe only accepts messages from registered public keys
Step 3b: Set a result destination (optional)
Configure an alternate host:port where composite LocationOffset results are delivered for any Outbound target types. This replaces sending the LocationOffset to the target and is configured on a per-user basis. If different per-target behavior is needed, it is required to set up two users, one for each desired behavior type.
The alternate destination is useful for aggregating results from multiple targets to a single endpoint. It is required for ICMP probing.
doublezero geolocation user set-result-destination \
--user <your-user-code> \
--destination <host:port>
--destination: a publicly routable IPv4 address or valid domain name with port (e.g., 203.0.113.10:9000 or results.example.com:9000). Pass an empty string to clear.
Use user get to verify your result destination:
doublezero geolocation user get --user <your-user-code>
Step 4: Run the target application
Both outbound and inbound flows require running an application on the target device. Reference implementations with examples are available in Go — you can run them directly or use them as a starting point for your own integration.
For outbound probing, the target device must run a TWAMP reflector so the geoProbe can measure RTT. Run the target application on the device being measured:
doublezero-geoprobe-target
For inbound probing, the target device must run software that sends signed messages to the probe.
On the device being measured:
doublezero-geoprobe-target-sender \
-probe-ip <probe-ip> \
-probe-pk <probe-pubkey> \
-keypair <path-to-keypair.json>
-probe-ip: IP address of the geoProbe (from probe list)
-probe-pk: public key of the geoProbe (from probe list)
-keypair: path to the keypair whose public key was registered as --target-pk in Step 3
The target sender uses a two-probe-pair mechanism: it sends two pre-signed TWAMP probes in quick succession. The probe's reply to the second packet includes SinceLastRxNs — the time between the probe sending reply 0 and receiving probe 1 — which serves as the probe-measured RTT. This paired approach provides an accurate RTT measurement even when the target cannot perform precise kernel-level timestamping.
Command reference
doublezero geolocation user
| Subcommand | Description |
|---|---|
create |
Create a new geolocation user account |
get |
Get details of a specific user |
list |
List all geolocation users |
delete |
Delete a user |
add-target |
Add a target to a user |
remove-target |
Remove a target from a user |
set-result-destination |
Set an alternate host:port for offset delivery |
update-payment |
Update payment status (foundation use) |
doublezero geolocation probe
| Subcommand | Description |
|---|---|
create |
Register a new geoProbe |
get |
Get details of a specific probe |
list |
List all probes |
update |
Update probe configuration |
delete |
Delete a probe |
add-parent |
Link a DZD as a parent of the probe |
remove-parent |
Remove a parent DZD |
Global flags
| Flag | Description |
|---|---|
--env |
Network environment: testnet, devnet, or mainnet-beta |
--rpc-url |
Custom DoubleZero RPC endpoint |
--keypair |
Path to signing keypair (required for write operations) |