upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorYour Name <you@example.com>2026-05-23 06:24:33 +0530
committerYour Name <you@example.com>2026-05-23 06:24:33 +0530
commit0642900ae44d84cfe24abe6911dbed4cd31ab8ad (patch)
tree01f960d54819133fe185ffe8d559bca9bdcf6bd9 /components
parent57e363fd30ef7715ac1dfb1484b8375e06160e1c (diff)
Phase 8a-8b: extract beacon_price and market into component
- tollgate_core_beacon.c/h: pure logic (hash_mint, hash_npub, build_ie) with platform-agnostic tollgate_beacon_config_t input struct - tollgate_core_market.c/h: market table logic (parse_ie, find_cheapest, update_ssid) with platform callbacks for time - main/beacon_price.c: thin shim delegates to component, WiFi IE start/stop - main/market.h: typedef aliases to component types - All 21 unit tests pass, ESP-IDF build passes - Hardware smoke test: 5/6 pass (AP, portal, grant/revoke, firewall) - Market scanner discovers other TollGates via vendor IEs on hardware
Diffstat (limited to 'components')
-rw-r--r--components/tollgate_core/CMakeLists.txt2
-rw-r--r--components/tollgate_core/src/tollgate_core_beacon.c48
-rw-r--r--components/tollgate_core/src/tollgate_core_beacon.h53
-rw-r--r--components/tollgate_core/src/tollgate_core_market.c121
-rw-r--r--components/tollgate_core/src/tollgate_core_market.h49
5 files changed, 273 insertions, 0 deletions
diff --git a/components/tollgate_core/CMakeLists.txt b/components/tollgate_core/CMakeLists.txt
index 1b7d84a..3cd5e85 100644
--- a/components/tollgate_core/CMakeLists.txt
+++ b/components/tollgate_core/CMakeLists.txt
@@ -6,6 +6,8 @@ idf_component_register(
6 "src/tollgate_core_session.c" 6 "src/tollgate_core_session.c"
7 "src/tollgate_core_mining.c" 7 "src/tollgate_core_mining.c"
8 "src/tollgate_core_stratum_proxy.c" 8 "src/tollgate_core_stratum_proxy.c"
9 "src/tollgate_core_beacon.c"
10 "src/tollgate_core_market.c"
9 INCLUDE_DIRS "include" "src" 11 INCLUDE_DIRS "include" "src"
10 REQUIRES lwip json esp_http_client mbedtls log esp_netif 12 REQUIRES lwip json esp_http_client mbedtls log esp_netif
11 PRIV_REQUIRES esp_wifi) 13 PRIV_REQUIRES esp_wifi)
diff --git a/components/tollgate_core/src/tollgate_core_beacon.c b/components/tollgate_core/src/tollgate_core_beacon.c
new file mode 100644
index 0000000..927aa03
--- /dev/null
+++ b/components/tollgate_core/src/tollgate_core_beacon.c
@@ -0,0 +1,48 @@
1#include "tollgate_core_beacon.h"
2#include "mbedtls/sha256.h"
3#include <string.h>
4
5void tollgate_core_beacon_hash_mint(const char *mint_url, uint8_t hash_out[4])
6{
7 uint8_t full_hash[32];
8 mbedtls_sha256((const unsigned char *)mint_url, strlen(mint_url), full_hash, 0);
9 memcpy(hash_out, full_hash, 4);
10}
11
12void tollgate_core_beacon_hash_npub(const char *npub_hex, uint8_t hash_out[4])
13{
14 uint8_t full_hash[32];
15 mbedtls_sha256((const unsigned char *)npub_hex, strlen(npub_hex), full_hash, 0);
16 memcpy(hash_out, full_hash, 4);
17}
18
19void tollgate_core_beacon_build_ie(const tollgate_beacon_config_t *cfg, tollgate_price_ie_t *ie)
20{
21 memset(ie, 0, sizeof(*ie));
22 ie->element_id = TOLLGATE_IE_ELEMENT_ID;
23 ie->length = 4 + TOLLGATE_IE_PAYLOAD_SIZE;
24 ie->vendor_oui[0] = TOLLGATE_OUI_0;
25 ie->vendor_oui[1] = TOLLGATE_OUI_1;
26 ie->vendor_oui[2] = TOLLGATE_OUI_2;
27 ie->vendor_oui_type = TOLLGATE_IE_TYPE;
28
29 tollgate_price_payload_t *p = &ie->payload;
30 p->version = TOLLGATE_IE_VERSION;
31 p->metric = (strcmp(cfg->metric, "bytes") == 0) ? 1 : 0;
32 p->price_per_step = (uint16_t)cfg->price_per_step;
33
34 bool is_bytes = (strcmp(cfg->metric, "bytes") == 0);
35 p->step_size = is_bytes ? (uint32_t)cfg->step_size_bytes : (uint32_t)cfg->step_size_ms;
36
37 tollgate_core_beacon_hash_mint(cfg->mint_url, p->mint_hash);
38
39 p->geohash_len = (uint8_t)strnlen(cfg->geohash, TOLLGATE_IE_GEOHASH_MAX);
40 memcpy(p->geohash, cfg->geohash, p->geohash_len);
41 if (p->geohash_len < TOLLGATE_IE_GEOHASH_MAX) {
42 memset(p->geohash + p->geohash_len, 0, TOLLGATE_IE_GEOHASH_MAX - p->geohash_len);
43 }
44
45 if (cfg->identity_initialized && cfg->npub_hex) {
46 tollgate_core_beacon_hash_npub(cfg->npub_hex, p->npub_hash);
47 }
48}
diff --git a/components/tollgate_core/src/tollgate_core_beacon.h b/components/tollgate_core/src/tollgate_core_beacon.h
new file mode 100644
index 0000000..27ad3fe
--- /dev/null
+++ b/components/tollgate_core/src/tollgate_core_beacon.h
@@ -0,0 +1,53 @@
1#ifndef TOLLGATE_CORE_BEACON_H
2#define TOLLGATE_CORE_BEACON_H
3
4#include <stdint.h>
5#include <stdbool.h>
6
7#define TOLLGATE_OUI_0 0xC0
8#define TOLLGATE_OUI_1 0xFF
9#define TOLLGATE_OUI_2 0xEE
10#define TOLLGATE_IE_TYPE 0x01
11#define TOLLGATE_IE_VERSION 1
12#define TOLLGATE_IE_ELEMENT_ID 0xDD
13
14#define TOLLGATE_IE_GEOHASH_MAX 9
15
16typedef struct __attribute__((packed)) {
17 uint8_t version;
18 uint8_t metric;
19 uint16_t price_per_step;
20 uint32_t step_size;
21 uint8_t mint_hash[4];
22 uint8_t geohash_len;
23 char geohash[TOLLGATE_IE_GEOHASH_MAX];
24 uint8_t npub_hash[4];
25} tollgate_price_payload_t;
26
27#define TOLLGATE_IE_PAYLOAD_SIZE sizeof(tollgate_price_payload_t)
28#define TOLLGATE_IE_TOTAL_SIZE (6 + TOLLGATE_IE_PAYLOAD_SIZE)
29
30typedef struct __attribute__((packed)) {
31 uint8_t element_id;
32 uint8_t length;
33 uint8_t vendor_oui[3];
34 uint8_t vendor_oui_type;
35 tollgate_price_payload_t payload;
36} tollgate_price_ie_t;
37
38typedef struct {
39 const char *mint_url;
40 const char *metric;
41 int price_per_step;
42 int step_size_ms;
43 int step_size_bytes;
44 const char *geohash;
45 const char *npub_hex;
46 bool identity_initialized;
47} tollgate_beacon_config_t;
48
49void tollgate_core_beacon_hash_mint(const char *mint_url, uint8_t hash_out[4]);
50void tollgate_core_beacon_hash_npub(const char *npub_hex, uint8_t hash_out[4]);
51void tollgate_core_beacon_build_ie(const tollgate_beacon_config_t *cfg, tollgate_price_ie_t *ie);
52
53#endif
diff --git a/components/tollgate_core/src/tollgate_core_market.c b/components/tollgate_core/src/tollgate_core_market.c
new file mode 100644
index 0000000..8530212
--- /dev/null
+++ b/components/tollgate_core/src/tollgate_core_market.c
@@ -0,0 +1,121 @@
1#include "tollgate_core_market.h"
2#include <string.h>
3
4static tollgate_market_t s_market;
5static tollgate_market_get_time_ms_fn s_get_time_ms;
6
7static int find_entry_by_bssid(const uint8_t bssid[6])
8{
9 for (int i = 0; i < TG_MARKET_MAX_ENTRIES; i++) {
10 if (s_market.entries[i].valid && memcmp(s_market.entries[i].bssid, bssid, 6) == 0) {
11 return i;
12 }
13 }
14 return -1;
15}
16
17static int find_free_slot(void)
18{
19 for (int i = 0; i < TG_MARKET_MAX_ENTRIES; i++) {
20 if (!s_market.entries[i].valid) return i;
21 }
22 int oldest = 0;
23 int64_t oldest_time = s_market.entries[0].discovered_ms;
24 for (int i = 1; i < TG_MARKET_MAX_ENTRIES; i++) {
25 if (s_market.entries[i].discovered_ms < oldest_time) {
26 oldest_time = s_market.entries[i].discovered_ms;
27 oldest = i;
28 }
29 }
30 return oldest;
31}
32
33void tollgate_core_market_init(tollgate_market_get_time_ms_fn get_time_ms)
34{
35 memset(&s_market, 0, sizeof(s_market));
36 s_get_time_ms = get_time_ms;
37}
38
39void tollgate_core_market_parse_ie(const uint8_t sa[6], const tollgate_vendor_ie_t *ie, int rssi,
40 const uint8_t *self_npub_hash)
41{
42 if (!ie || ie->payload_len < TOLLGATE_IE_PAYLOAD_SIZE) return;
43
44 static const uint8_t oui[3] = { TOLLGATE_OUI_0, TOLLGATE_OUI_1, TOLLGATE_OUI_2 };
45 if (memcmp(ie->vendor_oui, oui, 3) != 0) return;
46 if (ie->vendor_oui_type != TOLLGATE_IE_TYPE) return;
47
48 const tollgate_price_payload_t *payload = (const tollgate_price_payload_t *)ie->payload;
49 if (payload->version != TOLLGATE_IE_VERSION) return;
50
51 if (self_npub_hash && memcmp(payload->npub_hash, self_npub_hash, 4) == 0) return;
52
53 int idx = find_entry_by_bssid(sa);
54 if (idx < 0) {
55 idx = find_free_slot();
56 if (s_market.count < TG_MARKET_MAX_ENTRIES) s_market.count++;
57 }
58
59 tollgate_market_entry_t *entry = &s_market.entries[idx];
60 memcpy(entry->bssid, sa, 6);
61 entry->rssi = (int8_t)rssi;
62 entry->price_per_step = payload->price_per_step;
63 entry->step_size = payload->step_size;
64 entry->metric = payload->metric;
65 memcpy(entry->mint_hash, payload->mint_hash, 4);
66 memcpy(entry->npub_hash, payload->npub_hash, 4);
67
68 uint8_t gh_len = payload->geohash_len;
69 if (gh_len > TOLLGATE_IE_GEOHASH_MAX) gh_len = TOLLGATE_IE_GEOHASH_MAX;
70 memcpy(entry->geohash, payload->geohash, gh_len);
71 entry->geohash[gh_len] = '\0';
72
73 entry->discovered_ms = s_get_time_ms ? s_get_time_ms() : 0;
74 entry->valid = true;
75 entry->ssid[0] = '\0';
76}
77
78int tollgate_core_market_find_cheapest(const tollgate_market_t *market)
79{
80 int cheapest = -1;
81 uint32_t best_eff_price = UINT32_MAX;
82
83 for (int i = 0; i < TG_MARKET_MAX_ENTRIES; i++) {
84 if (!market->entries[i].valid) continue;
85 if (market->entries[i].ssid[0] == '\0') continue;
86
87 uint32_t step = market->entries[i].step_size;
88 if (step == 0) continue;
89
90 uint32_t eff;
91 if (market->entries[i].metric == 0) {
92 eff = (uint32_t)market->entries[i].price_per_step * 60000 / step;
93 } else {
94 eff = (uint32_t)market->entries[i].price_per_step * 1048576 / step;
95 }
96
97 if (eff < best_eff_price) {
98 best_eff_price = eff;
99 cheapest = i;
100 }
101 }
102 return cheapest;
103}
104
105const tollgate_market_t *tollgate_core_market_get(void)
106{
107 return &s_market;
108}
109
110void tollgate_core_market_update_ssid(const uint8_t bssid[6], const char *ssid, int8_t rssi)
111{
112 for (int i = 0; i < TG_MARKET_MAX_ENTRIES; i++) {
113 if (!s_market.entries[i].valid) continue;
114 if (memcmp(s_market.entries[i].bssid, bssid, 6) == 0) {
115 memcpy(s_market.entries[i].ssid, ssid, 32);
116 s_market.entries[i].ssid[32] = '\0';
117 s_market.entries[i].rssi = rssi;
118 break;
119 }
120 }
121}
diff --git a/components/tollgate_core/src/tollgate_core_market.h b/components/tollgate_core/src/tollgate_core_market.h
new file mode 100644
index 0000000..a89a1db
--- /dev/null
+++ b/components/tollgate_core/src/tollgate_core_market.h
@@ -0,0 +1,49 @@
1#ifndef TOLLGATE_CORE_MARKET_H
2#define TOLLGATE_CORE_MARKET_H
3
4#include "tollgate_core_beacon.h"
5#include <stdint.h>
6#include <stddef.h>
7#include <stdbool.h>
8
9#define TG_MARKET_MAX_ENTRIES 10
10
11typedef struct {
12 uint8_t bssid[6];
13 char ssid[33];
14 int8_t rssi;
15 uint16_t price_per_step;
16 uint32_t step_size;
17 uint8_t metric;
18 uint8_t mint_hash[4];
19 uint8_t npub_hash[4];
20 char geohash[TOLLGATE_IE_GEOHASH_MAX + 1];
21 int64_t discovered_ms;
22 bool valid;
23} tollgate_market_entry_t;
24
25typedef struct {
26 tollgate_market_entry_t entries[TG_MARKET_MAX_ENTRIES];
27 int count;
28 int64_t last_scan_ms;
29 bool scanning;
30 int consecutive_failures;
31} tollgate_market_t;
32
33typedef struct {
34 const uint8_t *vendor_oui;
35 uint8_t vendor_oui_type;
36 const uint8_t *payload;
37 size_t payload_len;
38} tollgate_vendor_ie_t;
39
40typedef int64_t (*tollgate_market_get_time_ms_fn)(void);
41
42void tollgate_core_market_init(tollgate_market_get_time_ms_fn get_time_ms);
43void tollgate_core_market_parse_ie(const uint8_t sa[6], const tollgate_vendor_ie_t *ie, int rssi,
44 const uint8_t *self_npub_hash);
45int tollgate_core_market_find_cheapest(const tollgate_market_t *market);
46const tollgate_market_t *tollgate_core_market_get(void);
47void tollgate_core_market_update_ssid(const uint8_t bssid[6], const char *ssid, int8_t rssi);
48
49#endif