Files
ssmithxandClaude Opus 5.5 7322b07442 TollGate: expand short v2 keyset IDs before swapping received ecash
Payments failed on the Pi and the MT6000 with "NUT02: ID length invalid":
cashuB tokens carry v2 keyset IDs in their 8-byte short form, and
gonuts-tollgate v0.7.1 swapped with it instead of looking the full ID up
at the mint.  Patch its Receive/ReceiveHTLC; the package builds the
daemon against a patched local copy of the module.  Tested against
minibits' live keysets; deployed to the MT6000 (generation 4).
PITFALLS #54.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 12:13:05 -04:00

184 lines
9.1 KiB
Scheme

;;; TollGate (OpenTollGate's tollgate-module-basic-go): pay-per-use network
;;; access over Nostr and Cashu, on top of nodogsplash. The Go binaries
;;; here; its OpenWrt files (init script, uci-defaults, rpcd plugin, portal
;;; site) are installed under share/tollgate-wrt for the service.
(define-module (tollgate)
;; Same cross toolchain as rpi4.scm (PITFALLS #35).
#:use-module (cross-libc-fix)
#:use-module (guix packages)
#:use-module (guix git-download)
#:use-module (guix gexp)
#:use-module (guix utils)
#:use-module (guix base32)
#:use-module ((guix licenses) #:prefix license:)
#:use-module (guix build-system gnu)
#:use-module ((gnu packages golang) #:select (go-1.24))
#:use-module ((gnu packages nss) #:select (nss-certs)))
(define %tollgate-version "0.5.0")
(define %tollgate-source
(origin
(method git-fetch)
(uri (git-reference
(url "https://github.com/OpenTollGate/tollgate-module-basic-go")
(commit (string-append "v" %tollgate-version))))
(file-name (git-file-name "tollgate-module-basic-go" %tollgate-version))
(sha256
(base32 "18qk422khrrngg2vcdr790wxlavv22zkxv7hnyraz4rf7i0w2llm"))))
;; Its Go module dependencies, as the module cache's download/ part (the
;; canonical zips, .mod and .info files from the proxy): a fixed-output
;; derivation, the one kind of build allowed network access. go.sum pins
;; every module, so the result is reproducible; GOSUMDB is off so the
;; ever-changing checksum-database tiles stay out. Update the hash when the
;; version changes (build it, take the hash Guix reports). It runs on the
;; build machine: refer to it, and in it to Go and the certificates, with
;; #+ -- with #$ a cross build would cross-compile Go (and GCC) first.
(define %tollgate-go-modules
(computed-file
(string-append "tollgate-go-modules-" %tollgate-version)
(with-imported-modules '((guix build utils))
#~(begin
(use-modules (guix build utils))
(setenv "HOME" "/tmp")
(setenv "GOMODCACHE" "/tmp/modcache")
(setenv "GOCACHE" "/tmp/gocache")
(setenv "GOPROXY" "https://proxy.golang.org")
(setenv "GOSUMDB" "off")
(setenv "GOTOOLCHAIN" "local")
(setenv "GOFLAGS" "-modcacherw")
(setenv "SSL_CERT_DIR" #+(file-append nss-certs "/etc/ssl/certs"))
(for-each (lambda (dir)
(with-directory-excursion (string-append #$%tollgate-source
"/" dir)
(invoke #+(file-append go-1.24 "/bin/go")
"mod" "download")))
'("src" "src/cmd/tollgate-cli"))
(copy-recursively "/tmp/modcache/cache/download" #$output)))
#:options
(list #:hash-algo 'sha256
#:hash (nix-base32-string->bytevector
"1qy8b8v5l8zh60m0aybxi2ni4wmj6mdkn3cfdr2n3aay0n4akpci")
#:recursive? #t)))
(define (go-arch target)
;; GOARCH for a GNU triplet.
(cond ((string-prefix? "aarch64" target) "arm64")
((string-prefix? "x86_64" target) "amd64")
((string-prefix? "arm" target) "arm")
((string-prefix? "mips" target) "mips")
(else (error "unsupported target" target))))
(define-public tollgate-wrt
(package
(name "tollgate-wrt")
(version %tollgate-version)
(source %tollgate-source)
(build-system gnu-build-system)
(arguments
(list
#:tests? #f ;tests want a router and the network
#:strip-binaries? #f ;static Go binaries, already -s -w
#:phases
#~(modify-phases %standard-phases
;; Keep its scripts' #!/bin/sh: in a cross build these phases
;; would point them at the build host's bash (PITFALLS #39).
(delete 'patch-source-shebangs)
(delete 'patch-shebangs)
(delete 'configure)
(replace 'build
;; As its scripts/repro-test.sh: static, trimmed, no VCS stamp,
;; modules from the cache above only.
(lambda _
(let ((ldflags
(string-append
"-s -w"
" -X 'github.com/OpenTollGate/tollgate-module-basic-go/src/cli.Version=v"
#$version "'"
" -X 'github.com/OpenTollGate/tollgate-module-basic-go/src/cli.GitCommit=v"
#$version "'"
" -X 'github.com/OpenTollGate/tollgate-module-basic-go/src/cli.BuildTime=1970-01-01T00:00:00Z'"
" -X 'github.com/OpenTollGate/tollgate-module-basic-go/src/config_manager.GitBranch=v"
#$version "'")))
(setenv "HOME" "/tmp")
(setenv "GOCACHE" "/tmp/gocache")
(setenv "GOMODCACHE" "/tmp/modcache")
;; #+: built by and for the build machine (Go, certs), even
;; when cross-compiling.
(copy-recursively #+%tollgate-go-modules
"/tmp/modcache/cache/download")
;; Go opens the cache's .lock files for writing.
(for-each make-file-writable
(find-files "/tmp/modcache" #:directories? #t))
(setenv "GOPROXY" "off")
(setenv "GOSUMDB" "off")
(setenv "GOTOOLCHAIN" "local")
(setenv "GOFLAGS" "-mod=mod -modcacherw")
(setenv "CGO_ENABLED" "0")
(setenv "GOOS" "linux")
(setenv "GOARCH"
#$(go-arch (or (%current-target-system)
(%current-system))))
;; Its Cashu library (the daemon's), patched: a local copy
;; replaces the module (a patched zip would fail go.sum).
(with-directory-excursion "src"
(invoke "go" "mod" "download"
"github.com/OpenTollGate/gonuts-tollgate@v0.7.1"))
(copy-recursively
"/tmp/modcache/github.com/!open!toll!gate/gonuts-tollgate@v0.7.1"
"/tmp/gonuts-tollgate")
(for-each make-file-writable
(find-files "/tmp/gonuts-tollgate" #:directories? #t))
(invoke "patch" "-p1" "-d" "/tmp/gonuts-tollgate" "-i"
#$(local-file
"patches/gonuts-tollgate-short-keyset-ids.patch"))
(with-directory-excursion "src"
(invoke "go" "mod" "edit" "-replace"
"github.com/Origami74/gonuts-tollgate=/tmp/gonuts-tollgate"))
(invoke "go" "build" "-C" "src" "-o" "../tollgate-wrt"
"-trimpath" "-buildvcs=false"
(string-append "-ldflags=" ldflags) ".")
(invoke "go" "build" "-C" "src/cmd/tollgate-cli"
"-o" "../../../tollgate"
"-trimpath" "-buildvcs=false"
(string-append "-ldflags=" ldflags
" -X 'main.version=v" #$version "'")))))
(replace 'install
(lambda _
(let ((bin (string-append #$output "/bin"))
(share (string-append #$output "/share/tollgate-wrt")))
(for-each (lambda (f) (install-file f bin))
'("tollgate-wrt" "tollgate"))
;; The OpenWrt side (init script, uci-defaults, hotplug,
;; helper scripts, portal site), for the service.
(copy-recursively "packaging/files" share)
(let ((scripts (append
(find-files (string-append share "/usr"))
(find-files (string-append share "/etc")
(lambda (f st)
(not (string-contains
f "/config/")))))))
(substitute* scripts
(("/usr/bin/tollgate-wrt")
(string-append bin "/tollgate-wrt"))
(("/usr/local/bin/first-login-setup")
(string-append share "/usr/local/bin/first-login-setup")))
(for-each (lambda (f) (chmod f #o755))
(find-files (string-append share "/usr")))
;; Its helpers (check_package_path, tollgate-apply-ssl,
;; ...) on PATH, as in /usr/bin.
(for-each (lambda (f)
(symlink f (string-append bin "/" (basename f))))
(find-files (string-append share "/usr/bin"))))))))))
(native-inputs (list go-1.24))
(home-page "https://github.com/OpenTollGate/tollgate-module-basic-go")
(synopsis "Pay-per-use network access over Nostr and Cashu")
(description
"TollGate sells network access: clients pay with Cashu ecash, the
router announces itself and its prices over Nostr, and paid clients are let
through the nodogsplash captive portal. This package has the
@command{tollgate-wrt} daemon, the @command{tollgate} command-line tool and
TollGate's OpenWrt files.")
(license license:gpl3)))