Reseller Bootstrap: Zero-Float Mesh Formation (Implementation Plan)
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 25/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Ít trao đổi
- Công nghệ
- go, playwright, react
- Lĩnh vực
- backend, frontend, networking
Hướng nghiên cứu
This is a multi-phase plan; start with Phase 1 in config_manager_config.go, config_schema.go, upstream_manager.go, vendor_element_manager.go, main.go, and upstream_session_manager/types.go. Read PR #235 first, since the vendor IE work depends on its TLV format, then add unit coverage for hop-count derivation and check the balance JSON and vendor IE tests. Done means hop_count is propagated as specified; the later phases require separate backend and captive-portal work.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Reseller Bootstrap: Zero-Float Mesh Formation
Problem
A freshly configured TollGate in reseller mode has no internet, no upstream
session, and no ecash balance. When a customer pays, the reseller cannot
grant internet access because it has none to grant. The network cannot
bootstrap without pre-funding or trust.
Solution
The first customer's first proof is forwarded in full to the upstream
TollGate. No split, no swap, no margin on the first transaction. The
upstream authorizes the reseller's STA MAC, granting a data session. The
reseller now has internet. Every subsequent payment earns margin normally.
This works recursively — a reseller-of-a-reseller bootstraps the same way.
Each hop adds latency only on the first transaction (5-15s for payment
forwarding). After that, the reseller can reach the mint directly for
proof swaps.
No walled gardens. No whitelists. No pre-funding. No trust. The first
proof is the spark that lights the network.
Bootstrap Flow
First customer transaction (cold start)
- Customer connects to reseller WiFi, sees captive portal, pays 2 sats
- Reseller detects: no active upstream session → bootstrap mode
- Reseller forwards the ENTIRE proof to upstream via Nostr payment
- Upstream receives proof, validates at mint, authorizes reseller STA MAC
- Reseller's upstream session begins (2 MB at 1 sat/MB upstream rate)
- Reseller opens valve for customer: 1 MB (what 2 sats buys at reseller rate)
- Reseller retains 1 MB of prepaid upstream bandwidth as float
Customer UX during cold start (5-15s):
- "Payment received"
- "Establishing internet link..."
- "Link established — N hops to gateway"
- "Access granted!"
Second transaction (warm path)
- Customer pays 2 sats (renewal or new customer)
- Reseller HAS internet — reaches mint directly
- Reseller swaps proof at mint, splits: 1 sat upstream + 1 sat profit
- Sends 1 sat to upstream for 1 MB more
- Customer gets 1 MB
Every subsequent transaction: normal margin. The "cost" of cold start
was zero — the reseller didn't lose money, it just didn't earn margin
on transaction #1, and gained 1 MB of prepaid float.
Recursive multi-hop
A chain of TollGates A → B → C:
- Customer pays C (hop 2 reseller)
- C has no internet → forwards proof to B
- B has no internet → forwards proof to A
- A is the gateway → has internet, validates proof, authorizes B's MAC
- B now has internet → authorizes C's MAC
- C now has internet → opens valve for customer
Each hop adds one payment round-trip (~5-8s). A 3-hop chain cold-starts
in ~20s on the first transaction only.
Hop Count Propagation
Each TollGate advertises its hop distance from the internet gateway:
- Direct gateway (has its own internet):
hop_count = 0 - Reseller of a gateway:
hop_count = upstream.hop_count + 1
Propagated via:
- Vendor IE (802.11, for router-to-router discovery)
- NostR details event (kind 21023, for client-facing portal)
- Balance JSON (
/balanceendpoint, for status display)
Customer sees on balance page:
Connection active
2 hops to internet
0.8 MB remaining
Implementation Phases
Phase 1: Hop Count Propagation (backend)
Scope: Add hop_count field end-to-end through the backend.
- Add
hop_countint field toUpstreamManagerConfigand config schema - Add
hop_countbyte to vendor IE encoding (#235's TLV format, new type0x03) - Add
hop_counttag to NostR details event (kind 21023) - Add
hop_counttobalanceResponseJSON struct in main.go - UpstreamManager: when connecting to upstream, read its hop_count from
vendor IE or probe response, set local = upstream + 1 - Direct gateway: hop_count = 0 when reseller_mode = false
- Config default: hop_count = 0 (updated at runtime by UpstreamManager)
Files touched: config_manager_config.go, config_schema.go,
upstream_manager.go, vendor_element_manager.go, main.go,
upstream_session_manager/types.go
Dependencies: PR #235 (vendor IE) must merge first (for the TLV encoding)
Testing: Unit test hop_count derivation logic. Router test: verify
hop_count appears in balance JSON and vendor IE on real hardware.
Estimate: 2-3 tasks
Phase 2: Bootstrap Passthrough Logic (backend)
Scope: First-proof-forward bootstrap in the merchant payment flow.
- Add
bootstrap_modestate to merchant/upstream session manager - Detect cold start: no active upstream session + reseller_mode = true
- In bootstrap mode: forward entire received proof to upstream via Nostr
- After upstream session established: set bootstrap_mode = false
- Subsequent payments: normal proof swap + split flow
- Add
/bootstrap-statusendpoint (or extend/balance):bootstrap_phase: idle | forwarding | establishing | complete | errorhop_count: derived from upstream
Files touched: merchant/merchant.go, upstream_session_manager/session.go,
main.go (new endpoint or extended balance response)
Dependencies: Phase 1 (hop_count field exists in response structs)
Testing: Unit test bootstrap state machine. Integration test: mock
upstream, verify first proof forwarded whole, second proof split.
Estimate: 3-4 tasks
Phase 3: Bootstrap Status UI (frontend)
Scope: Customer-facing UI for bootstrap progress + hop count display.
- New processing states in captive portal during bootstrap:
- "Payment received"
- "Establishing internet link..." (with hop count if >1)
- "Link established — N hops to gateway"
- "Access granted!"
- Poll
/balance(or/bootstrap-status) during bootstrap for phase updates - Balance page: add hop count display alongside remaining/usage
- i18n strings for all new status messages
Files touched: captive portal React app (separate repo:
OpenTollGate/tollgate-captive-portal-site), locale files
Dependencies: Phase 2 (backend serves bootstrap phase data)
Testing: Playwright/visual test of bootstrap UI states
Estimate: 2 tasks
Phase 4: Pre-connect, Post-pay (optimization)
Scope: Eliminate cold-start latency for subsequent network formations.
- Upstream TollGate: add
reseller_grace_secondsconfig (default: 0 = off) - When grace > 0: upstream allows identified reseller STAs to connect and
get a local IP without payment, for N seconds - Reseller: pre-connects to upstream WiFi immediately on boot
- When first customer pays: upstream session already established,
payment flows instantly - Grace window expires → upstream disconnects unpaid STA
- Reseller can reconnect (grace restarts) but must pay to stay
Files touched: upstream_session_manager/, config_manager/,
nodogsplash configuration in packaging/
Dependencies: Phases 1-3 (bootstrap flow works end-to-end first)
Testing: Two-router test: cold start with grace enabled, verify
first customer experiences <2s latency instead of 5-15s
Estimate: 3-4 tasks
Key Design Decisions
-
No walled gardens. The upstream does not whitelist mint URLs.
The first proof goes directly to the upstream TollGate via Nostr,
which has internet and can validate it. -
No proof splitting on cold start. The entire first proof is
forwarded. Splitting requires a mint swap, which requires internet,
which requires paying the upstream — circular dependency. Forwarding
the whole proof breaks the cycle. -
Hop count is informational, not control. Display only. No
automatic chain-depth limiting in v1. Operators can configure
max_reseller_hopslater if abuse becomes a concern. -
Vendor IE carries hop count. This lets scanning resellers see
the hop depth before connecting, enabling price calculation
(markup compounds per hop). -
Phase 4 is the goal, Phases 1-3 are stepping stones. The
pre-connect grace window is the optimal UX, but the passthrough
bootstrap must work first as the fallback when grace is not
available or expires.
Open Questions
- Should the reseller calculate its price dynamically from upstream
price + configured markup, or keep static pricing? (Dynamic is
correct but adds complexity.) - Should hop count be capped? (e.g., refuse to resell beyond hop 5)
- What happens if the upstream rejects the forwarded proof (wrong mint)?
Error message to customer: "This mint is not accepted by the upstream
gateway. Try a different token."
Related PRs
- #235 (vendor IE) — provides the TLV encoding framework
- #232 / #231 (identity) — reseller identity is derived from merchant key
- Ngôn ngữ chính
- Go
- Star
- 12
- Fork
- 14
- Merge trung bình
- 3 ngày 20 giờ
- Pull request đã merge (30 ngày)
- 261
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của OpenTollGate/tollgate-module-basic-go
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 85/100
OpenTollGate/tollgate-module-basic-go#1159 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Degraded-mode hygiene follow-ups: dead walletNotInitializedError() + main.go's startup log still over-promises mint recoveryCó thể đã có người làm @Amperstrand đã nhận 1 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
OpenTollGate/tollgate-module-basic-go#1135 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
setup_uhttpd_portal hardcodes the GUEST portal docroot to the TollGate path — the brand token cannot select a re-brand guest portalCó thể đã có người làm @Amperstrand đã nhận 1 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
OpenTollGate/tollgate-module-basic-go#1122 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
changelog: dependency-security sweep missing from [Unreleased] [Amperstrand fork #105 review debt]Đang mở
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 72/100
OpenTollGate/tollgate-module-basic-go#1055 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
OpenTollGate/tollgate-module-basic-go#1027 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của OpenTollGate/tollgate-module-basic-go
Issue tương tự
-
agent-butler-finding chore
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 78/100
jordansmall/spindrift#6318 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Eyevinn/moqlivemock#166 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
JakeChampion/lang#14091 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
hyperledger/fabric-x-orderer#1409 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
get actions doesn't show the approval flag, and describe action shows it unformattedCó thể đã có người làm @kenokech đã nhận hôm nay. Đang mởbug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
Maintainer thường phản hồi trong vòng 1 ngày