upleb.uk

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

summaryrefslogtreecommitdiff
path: root/tollgate_core/src/tollgate_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'tollgate_core/src/tollgate_core.c')
-rw-r--r--tollgate_core/src/tollgate_core.c466
1 files changed, 0 insertions, 466 deletions
diff --git a/tollgate_core/src/tollgate_core.c b/tollgate_core/src/tollgate_core.c
deleted file mode 100644
index c7c2902..0000000
--- a/tollgate_core/src/tollgate_core.c
+++ /dev/null
@@ -1,466 +0,0 @@
1#include "tollgate_core.h"
2#include "tollgate_platform.h"
3#include "tollgate_cashu.h"
4#include "tollgate_session.h"
5#include "tollgate_firewall.h"
6#include "tollgate_mining.h"
7#include <string.h>
8#include <stdlib.h>
9#include <stdio.h>
10
11static const char *TAG = "tg_core";
12static const tollgate_platform_t *s_platform;
13static uint32_t s_ap_ip;
14
15static uint32_t s_owner_ip;
16static uint8_t s_owner_mac[6];
17static bool s_owner_connected;
18
19const tollgate_platform_t *tollgate_core_get_platform(void)
20{
21 return s_platform;
22}
23
24uint32_t tollgate_core_get_ap_ip(void)
25{
26 return s_ap_ip;
27}
28
29int tollgate_core_init(const tollgate_platform_t *platform, uint32_t ap_ip)
30{
31 if (!platform) return -1;
32
33 s_platform = platform;
34 s_ap_ip = ap_ip;
35 s_owner_connected = false;
36 memset(s_owner_mac, 0, sizeof(s_owner_mac));
37
38 tg_session_init();
39 tg_firewall_init(ap_ip);
40 tg_mining_init();
41
42 if (platform->log_info) {
43 char ip_str[16];
44 snprintf(ip_str, sizeof(ip_str), "%d.%d.%d.%d",
45 (int)((ap_ip >> 0) & 0xFF), (int)((ap_ip >> 8) & 0xFF),
46 (int)((ap_ip >> 16) & 0xFF), (int)((ap_ip >> 24) & 0xFF));
47 platform->log_info(TAG, "TollGate core initialized, AP IP=%s", ip_str);
48 }
49 return 0;
50}
51
52void tollgate_core_tick(void)
53{
54 tg_session_tick();
55}
56
57int tollgate_core_process_payment(uint32_t client_ip, const char *token_str)
58{
59 if (!s_platform || !token_str) return -1;
60
61 const char *accepted_mint = s_platform->get_mint_url ? s_platform->get_mint_url() : NULL;
62 if (!accepted_mint || accepted_mint[0] == '\0') {
63 if (s_platform->log_error) s_platform->log_error(TAG, "No mint URL configured");
64 return -1;
65 }
66
67 tg_cashu_token_t token;
68 if (tg_cashu_decode_token(token_str, &token) != 0) {
69 if (s_platform->log_error) s_platform->log_error(TAG, "Token decode failed");
70 return -1;
71 }
72
73 bool mint_ok = false;
74 if (s_platform->get_accepted_mint_count && s_platform->get_accepted_mint) {
75 int count = s_platform->get_accepted_mint_count();
76 for (int i = 0; i < count; i++) {
77 if (tg_cashu_is_mint_accepted(token.mint_url, s_platform->get_accepted_mint(i))) {
78 mint_ok = true;
79 break;
80 }
81 }
82 } else {
83 mint_ok = tg_cashu_is_mint_accepted(token.mint_url, accepted_mint);
84 }
85 if (!mint_ok) {
86 if (s_platform->log_error) s_platform->log_error(TAG, "Token mint not accepted");
87 return -1;
88 }
89
90 tg_cashu_proof_state_t states[TG_CASHU_MAX_PROOFS];
91 int state_count = 0;
92 if (tg_cashu_check_proof_states(token.mint_url, &token, states, &state_count) != 0) {
93 if (s_platform->log_error) s_platform->log_error(TAG, "Proof state check failed (continuing)");
94 } else {
95 for (int i = 0; i < state_count; i++) {
96 if (states[i].spent) {
97 if (s_platform->log_error) s_platform->log_error(TAG, "Proof %d is SPENT", i);
98 return -1;
99 }
100 }
101 }
102
103 if (s_platform->wallet_receive) {
104 if (!s_platform->wallet_receive(token_str)) {
105 if (s_platform->log_error) s_platform->log_error(TAG, "wallet_receive rejected token");
106 return -1;
107 }
108 }
109
110 const char *metric = (s_platform->get_metric) ? s_platform->get_metric() : "milliseconds";
111 uint64_t price = (s_platform->get_price_sats) ? s_platform->get_price_sats() : 21;
112 uint64_t step_size;
113
114 if (strcmp(metric, "bytes") == 0) {
115 step_size = (s_platform->get_step_bytes) ? (uint64_t)s_platform->get_step_bytes() : 22020096;
116 } else {
117 step_size = (s_platform->get_step_ms) ? (uint64_t)s_platform->get_step_ms() : 60000;
118 }
119
120 uint64_t allotment = tg_cashu_calculate_allotment(token.total_amount, price, step_size);
121 if (allotment == 0) {
122 if (s_platform->log_error) s_platform->log_error(TAG, "Token amount too small");
123 return -1;
124 }
125
126 if (strcmp(metric, "bytes") == 0) {
127 if (!tg_session_create_bytes(client_ip, allotment)) return -1;
128 } else {
129 if (!tg_session_create(client_ip, allotment)) return -1;
130 }
131
132 if (s_platform->log_info) s_platform->log_info(TAG, "Payment: %llu sats -> %llu %s",
133 (unsigned long long)token.total_amount, (unsigned long long)allotment, metric);
134 return 0;
135}
136
137int tollgate_core_process_share(uint32_t client_ip, const char *job_id,
138 const char *nonce, const char *ntime, const char *version)
139{
140 (void)job_id; (void)nonce; (void)ntime; (void)version;
141 if (!s_platform) return -1;
142
143 tg_mining_update_hashrate(client_ip, true);
144 const tg_mining_client_stats_t *stats = tg_mining_get_client_stats(client_ip);
145 if (!stats) return -1;
146
147 double hashprice = tg_mining_get_current_hashprice();
148 uint64_t override = (s_platform->get_hashprice_override) ? s_platform->get_hashprice_override() : 0;
149 if (override > 0) hashprice = tg_mining_calculate_hashprice_override(override);
150
151 const char *metric = (s_platform->get_metric) ? s_platform->get_metric() : "milliseconds";
152 int price = (s_platform->get_price_sats) ? s_platform->get_price_sats() : 21;
153
154 tg_session_t *existing = tg_session_find_by_ip(client_ip);
155 if (existing && existing->payment_method == TG_PAYMENT_MINING) {
156 uint64_t allotment;
157 if (strcmp(metric, "bytes") == 0) {
158 int step_bytes = (s_platform->get_step_bytes) ? (int)s_platform->get_step_bytes() : 22020096;
159 allotment = tg_mining_shares_to_allotment_bytes(stats->hashrate_ghs, hashprice, price, step_bytes);
160 existing->allotment_bytes += allotment;
161 } else {
162 int step_ms = (s_platform->get_step_ms) ? s_platform->get_step_ms() : 60000;
163 allotment = tg_mining_shares_to_allotment_ms(stats->hashrate_ghs, hashprice, price, step_ms);
164 tg_session_extend(existing, allotment);
165 }
166 return 0;
167 }
168
169 uint64_t allotment;
170 if (strcmp(metric, "bytes") == 0) {
171 int step_bytes = (s_platform->get_step_bytes) ? (int)s_platform->get_step_bytes() : 22020096;
172 allotment = tg_mining_shares_to_allotment_bytes(stats->hashrate_ghs, hashprice, price, step_bytes);
173 tg_session_t *s = tg_session_create_bytes(client_ip, allotment);
174 if (s) s->payment_method = TG_PAYMENT_MINING;
175 } else {
176 int step_ms = (s_platform->get_step_ms) ? s_platform->get_step_ms() : 60000;
177 allotment = tg_mining_shares_to_allotment_ms(stats->hashrate_ghs, hashprice, price, step_ms);
178 tg_session_t *s = tg_session_create(client_ip, allotment);
179 if (s) s->payment_method = TG_PAYMENT_MINING;
180 }
181
182 return 0;
183}
184
185void tollgate_core_client_connected(const uint8_t *mac, uint32_t client_ip)
186{
187 if (!s_owner_connected) {
188 s_owner_connected = true;
189 s_owner_ip = client_ip;
190 if (mac) memcpy(s_owner_mac, mac, 6);
191 if (s_platform && s_platform->log_info) {
192 char ip_str[16];
193 snprintf(ip_str, sizeof(ip_str), "%d.%d.%d.%d",
194 (int)((client_ip >> 0) & 0xFF), (int)((client_ip >> 8) & 0xFF),
195 (int)((client_ip >> 16) & 0xFF), (int)((client_ip >> 24) & 0xFF));
196 s_platform->log_info(TAG, "First client = owner: %s", ip_str);
197 }
198 return;
199 }
200 if (s_platform && s_platform->log_info) s_platform->log_info(TAG, "Client connected (non-owner)");
201}
202
203void tollgate_core_client_disconnected(const uint8_t *mac)
204{
205 if (!s_owner_connected) return;
206 if (mac && memcmp(s_owner_mac, mac, 6) == 0) {
207 s_owner_connected = false;
208 memset(s_owner_mac, 0, sizeof(s_owner_mac));
209 if (s_platform && s_platform->log_info) s_platform->log_info(TAG, "Owner disconnected");
210 }
211}
212
213bool tollgate_core_is_client_allowed(uint32_t client_ip)
214{
215 return tg_firewall_is_allowed(client_ip);
216}
217
218bool tollgate_core_is_dns_running(void)
219{
220 return false;
221}
222
223char *tollgate_core_get_status_json(void)
224{
225 const int BUFSIZE = 512;
226 char *json = malloc(BUFSIZE);
227 if (!json) return NULL;
228 snprintf(json, BUFSIZE,
229 "{\"ownerConnected\":%s,\"activeSessions\":%d,\"allowedClients\":%d,\"dnsRunning\":%s}",
230 s_owner_connected ? "true" : "false",
231 tg_session_active_count(),
232 tg_firewall_client_count(),
233 tollgate_core_is_dns_running() ? "true" : "false");
234 return json;
235}
236
237char *tollgate_core_get_config_json(void)
238{
239 const int BUFSIZE = 512;
240 char *json = malloc(BUFSIZE);
241 if (!json) return NULL;
242 int pos = 0;
243 pos += snprintf(json + pos, BUFSIZE - pos, "{");
244 if (s_platform) {
245 if (s_platform->get_price_sats)
246 pos += snprintf(json + pos, BUFSIZE - pos, "\"priceSats\":%d,", (int)s_platform->get_price_sats());
247 if (s_platform->get_step_ms)
248 pos += snprintf(json + pos, BUFSIZE - pos, "\"stepMs\":%d,", (int)s_platform->get_step_ms());
249 if (s_platform->get_mint_url)
250 pos += snprintf(json + pos, BUFSIZE - pos, "\"mintUrl\":\"%s\",", s_platform->get_mint_url());
251 if (s_platform->get_metric)
252 pos += snprintf(json + pos, BUFSIZE - pos, "\"metric\":\"%s\"", s_platform->get_metric());
253 }
254 pos += snprintf(json + pos, BUFSIZE - pos, "}");
255 return json;
256}
257
258int tollgate_core_active_session_count(void)
259{
260 return tg_session_active_count();
261}
262
263int tollgate_core_allowed_client_count(void)
264{
265 return tg_firewall_client_count();
266}
267
268int tollgate_core_firewall_revoke_all(void)
269{
270 tg_session_revoke_all();
271 return tg_firewall_revoke_all();
272}
273
274void tollgate_core_firewall_set_mining_port(uint16_t port)
275{
276 tg_firewall_set_mining_port(port);
277}
278
279void tollgate_core_firewall_set_sandbox_mint_access(bool enable)
280{
281 tg_firewall_set_sandbox_mint_access(enable);
282}
283
284bool tollgate_core_is_owner(uint32_t client_ip)
285{
286 return s_owner_connected && s_owner_ip == client_ip;
287}
288
289bool tollgate_core_is_owner_connected(void)
290{
291 return s_owner_connected;
292}
293
294double tollgate_core_get_hashprice(void)
295{
296 return tg_mining_get_current_hashprice();
297}
298
299void tollgate_core_set_nbits(uint32_t nbits)
300{
301 tg_mining_set_current_nbits(nbits);
302}
303
304const void *tollgate_core_get_current_job(void) { return NULL; }
305void tollgate_core_set_job(const void *job) { (void)job; }
306int tollgate_core_stratum_client_start(void) { return -1; }
307void tollgate_core_stratum_client_stop(void) { }
308int tollgate_core_stratum_proxy_init(uint16_t port) { (void)port; return -1; }
309void tollgate_core_stratum_proxy_get_stats(void *out) { (void)out; }
310void tollgate_core_beacon_start(void) { }
311void tollgate_core_market_init(void) { }
312void tollgate_core_market_on_scan_result(const void *ie_data, int ie_len, const uint8_t *bssid, int rssi)
313{
314 (void)ie_data; (void)ie_len; (void)bssid; (void)rssi;
315}
316
317const void *tollgate_core_get_sessions_array(void)
318{
319 return tg_session_get_array();
320}
321
322int tollgate_core_get_sessions_array_size(void)
323{
324 return tg_session_get_array_size();
325}
326
327void *tollgate_core_find_session_by_ip(uint32_t ip)
328{
329 return tg_session_find_by_ip(ip);
330}
331
332void *tollgate_core_find_session_by_mac(const char *mac)
333{
334 return tg_session_find_by_mac(mac);
335}
336
337void tollgate_core_session_extend(void *session, uint64_t additional_ms)
338{
339 tg_session_extend((tg_session_t *)session, additional_ms);
340}
341
342int tollgate_core_session_add_bytes(uint32_t client_ip, uint64_t bytes)
343{
344 tg_session_add_bytes(client_ip, bytes);
345 return 0;
346}
347
348void *tollgate_core_session_create(uint32_t client_ip, uint64_t allotment_ms)
349{
350 return tg_session_create(client_ip, allotment_ms);
351}
352
353void *tollgate_core_session_create_bytes(uint32_t client_ip, uint64_t allotment_bytes)
354{
355 return tg_session_create_bytes(client_ip, allotment_bytes);
356}
357
358void tollgate_core_session_revoke(void *session)
359{
360 tg_session_revoke((tg_session_t *)session);
361}
362
363bool tollgate_core_session_is_expired(const void *session)
364{
365 return tg_session_is_expired((const tg_session_t *)session);
366}
367
368void tollgate_core_firewall_grant(uint32_t client_ip)
369{
370 tg_firewall_grant(client_ip);
371}
372
373void tollgate_core_firewall_revoke(uint32_t client_ip)
374{
375 tg_firewall_revoke(client_ip);
376}
377
378int tollgate_core_firewall_get_mac_for_ip(uint32_t client_ip, char *mac_out, int mac_out_size)
379{
380 return tg_firewall_get_mac_for_ip(client_ip, mac_out, mac_out_size);
381}
382
383int tollgate_core_cashu_decode(const char *token_str, void *out)
384{
385 return tg_cashu_decode_token(token_str, (tg_cashu_token_t *)out);
386}
387
388int tollgate_core_cashu_check_states(const char *mint_url, const void *token,
389 void *states, int *state_count)
390{
391 return tg_cashu_check_proof_states(mint_url, (const tg_cashu_token_t *)token,
392 (tg_cashu_proof_state_t *)states, state_count);
393}
394
395uint64_t tollgate_core_cashu_allotment(uint64_t amount, uint64_t price, uint64_t step_size)
396{
397 return tg_cashu_calculate_allotment(amount, price, step_size);
398}
399
400bool tollgate_core_cashu_is_mint_accepted(const char *mint_url)
401{
402 if (!s_platform) return false;
403 const char *accepted = s_platform->get_mint_url ? s_platform->get_mint_url() : NULL;
404 if (!accepted) return false;
405 if (s_platform->get_accepted_mint_count && s_platform->get_accepted_mint) {
406 int count = s_platform->get_accepted_mint_count();
407 for (int i = 0; i < count; i++) {
408 if (tg_cashu_is_mint_accepted(mint_url, s_platform->get_accepted_mint(i)))
409 return true;
410 }
411 return false;
412 }
413 return tg_cashu_is_mint_accepted(mint_url, accepted);
414}
415
416const char *tollgate_core_cashu_token_mint(const void *token)
417{
418 const tg_cashu_token_t *t = (const tg_cashu_token_t *)token;
419 return t->mint_url;
420}
421
422uint64_t tollgate_core_cashu_token_amount(const void *token)
423{
424 const tg_cashu_token_t *t = (const tg_cashu_token_t *)token;
425 return t->total_amount;
426}
427
428void tollgate_core_mining_update_hashrate(uint32_t client_ip, bool accepted)
429{
430 tg_mining_update_hashrate(client_ip, accepted);
431}
432
433const void *tollgate_core_mining_get_client_stats(uint32_t client_ip)
434{
435 return tg_mining_get_client_stats(client_ip);
436}
437
438double tollgate_core_mining_get_hashprice(void)
439{
440 return tg_mining_get_current_hashprice();
441}
442
443uint64_t tollgate_core_mining_shares_to_allotment_ms(double hashrate, double hashprice,
444 int price, int step_ms)
445{
446 return tg_mining_shares_to_allotment_ms(hashrate, hashprice, price, step_ms);
447}
448
449uint64_t tollgate_core_mining_shares_to_allotment_bytes(double hashrate, double hashprice,
450 int price, int step_bytes)
451{
452 return tg_mining_shares_to_allotment_bytes(hashrate, hashprice, price, step_bytes);
453}
454
455void tollgate_core_mining_set_nbits(uint32_t nbits)
456{
457 tg_mining_set_current_nbits(nbits);
458}
459
460int tollgate_core_dns_start(uint32_t upstream_dns)
461{
462 (void)upstream_dns;
463 return -1;
464}
465
466void tollgate_core_dns_stop(void) { }