From 51d617e70f90a972185917ea0096c1ecef2bfa8b Mon Sep 17 00:00:00 2001 From: Bitflash-sh Date: Fri, 24 Jul 2026 11:18:11 -0300 Subject: Bitflash: fair-launch release Satoshi's bitcoin-0.1.0 reborn with RandomX CPU proof of work, anonymous .btf addressing over Nostr with CGNAT rendezvous, automatic peer discovery, a headless Linux node, and Windows GUI wallet. Fair launch, no premine, 21M cap. --- src/btftunnel.cpp | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 src/btftunnel.cpp (limited to 'src/btftunnel.cpp') diff --git a/src/btftunnel.cpp b/src/btftunnel.cpp new file mode 100644 index 0000000..65c4b89 --- /dev/null +++ b/src/btftunnel.cpp @@ -0,0 +1,161 @@ +// Copyright (c) 2026 Bitflash developers +// Distributed under the MIT/X11 software license. +// +// Transparent anonymous tunnel. See btftunnel.h. + +#include "btftunnel.h" +#include "btfchan.h" + +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#include +typedef int SOCKET; +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (-1) +#endif +#define closesocket(s) ::close(s) +#ifndef SD_BOTH +#define SD_BOTH SHUT_RDWR +#endif +#endif +#include +#include +#include + +namespace btf +{ + +bool TunnelInit() +{ + return RvInit() && ChanInit(); +} + +// Create a connected loopback socket pair (no socketpair() on Windows). +// Returns app end and pump end; both are ordinary full-duplex TCP sockets. +static bool MakeLocalPair(btf_socket_t& appEnd, btf_socket_t& pumpEnd) +{ + SOCKET listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (listener == INVALID_SOCKET) return false; + + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr.sin_port = 0; // ephemeral + if (bind(listener, (struct sockaddr*)&addr, sizeof(addr)) != 0) { closesocket(listener); return false; } + if (listen(listener, 1) != 0) { closesocket(listener); return false; } + +#ifdef _WIN32 + int len = sizeof(addr); +#else + socklen_t len = sizeof(addr); +#endif + if (getsockname(listener, (struct sockaddr*)&addr, &len) != 0) { closesocket(listener); return false; } + + SOCKET a = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (a == INVALID_SOCKET) { closesocket(listener); return false; } + if (connect(a, (struct sockaddr*)&addr, sizeof(addr)) != 0) { closesocket(a); closesocket(listener); return false; } + + SOCKET b = accept(listener, NULL, NULL); + closesocket(listener); + if (b == INVALID_SOCKET) { closesocket(a); return false; } + + appEnd = a; + pumpEnd = b; + return true; +} + +static bool SockReadN(SOCKET s, void* buf, int n) +{ + char* p = (char*)buf; int off = 0; + while (off < n) { int r = recv(s, p + off, n - off, 0); if (r <= 0) return false; off += r; } + return true; +} +static bool SockWriteN(SOCKET s, const void* buf, int n) +{ + const char* p = (const char*)buf; int off = 0; + while (off < n) { int r = send(s, p + off, n - off, 0); if (r <= 0) return false; off += r; } + return true; +} + +// Outbound pump: plaintext from the app -> echan frame -> rendezvous socket. +static void PumpOut(SOCKET pumpEnd, RvSocket rv, std::vector key) +{ + char buf[16 * 1024]; + for (;;) + { + int r = recv(pumpEnd, buf, sizeof(buf), 0); + if (r <= 0) break; + std::vector frame = ChanEncryptFrame(key.data(), (const unsigned char*)buf, r); + if (!RvWriteN(rv, frame.data(), (int)frame.size())) break; + } + // Tear down: unblock the inbound pump and the app. + shutdown((SOCKET)rv, SD_BOTH); + shutdown(pumpEnd, SD_BOTH); +} + +// Inbound pump: echan frames from the rendezvous socket -> plaintext to the app. +static void PumpIn(SOCKET pumpEnd, RvSocket rv, std::vector key) +{ + for (;;) + { + unsigned char len[4]; + if (!RvReadN(rv, len, 4)) break; + size_t n = ((size_t)len[0]<<24)|((size_t)len[1]<<16)|((size_t)len[2]<<8)|len[3]; + if (n < (size_t)(CHAN_NONCEBYTES + CHAN_MACBYTES) || n > (1u<<20)) break; + std::vector body(n); + if (!RvReadN(rv, body.data(), (int)n)) break; + std::vector pt; + if (!ChanDecryptBody(key.data(), body.data(), (int)n, pt)) break; // auth fail -> drop + if (!pt.empty() && !SockWriteN(pumpEnd, pt.data(), (int)pt.size())) break; + } + shutdown(pumpEnd, SD_BOTH); + shutdown((SOCKET)rv, SD_BOTH); +} + +// Start the two pumps and hand back the app-facing socket. When both pumps +// finish, close the pump end and the rendezvous socket. +static btf_socket_t StartTunnel(RvSocket rv, const unsigned char shared[32]) +{ + btf_socket_t appEnd, pumpEnd; + if (!MakeLocalPair(appEnd, pumpEnd)) { RvClose(rv); return INVALID_SOCKET; } + + std::vector key(shared, shared + 32); + std::thread(PumpOut, pumpEnd, rv, key).detach(); + std::thread([pumpEnd, rv, key]() { + PumpIn(pumpEnd, rv, key); + closesocket(pumpEnd); + RvClose(rv); + }).detach(); + return appEnd; +} + +btf_socket_t BtfClientTunnel(const char* meeting_host, unsigned short port, + const unsigned char target_pubkey[32], + const unsigned char service_enc_pub[32]) +{ + if (!TunnelInit()) return INVALID_SOCKET; + RvSocket rv = RvClientConnect(meeting_host, port, target_pubkey); + if (rv == RV_INVALID) return INVALID_SOCKET; + + unsigned char eph_pub[32], shared[32]; + if (!ChanClientHandshake(service_enc_pub, eph_pub, shared)) { RvClose(rv); return INVALID_SOCKET; } + if (!RvWriteN(rv, eph_pub, 32)) { RvClose(rv); return INVALID_SOCKET; } + return StartTunnel(rv, shared); +} + +btf_socket_t BtfServiceWrap(RvSocket rv, const unsigned char my_enc_sk[32]) +{ + if (!TunnelInit()) { RvClose(rv); return INVALID_SOCKET; } + unsigned char eph_pub[32], shared[32]; + if (!RvReadN(rv, eph_pub, 32)) { RvClose(rv); return INVALID_SOCKET; } + if (!ChanEndpointHandshake(eph_pub, my_enc_sk, shared)) { RvClose(rv); return INVALID_SOCKET; } + return StartTunnel(rv, shared); +} + +} // namespace btf -- cgit v1.2.3