aboutsummaryrefslogtreecommitdiff
;;; Whispers --- Stealth VPN and ssh tunneler
;;; Copyright © 2023 Runciter <runciter@whispers-vpn.org>
;;;
;;; This file is part of Whispers.
;;;
;;; Whispers is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; Whispers is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with Whispers.  If not, see <http://www.gnu.org/licenses/>.

(define-module (whispers services finance)
  #:use-module (guix gexp)
  #:use-module (guix records)
  #:use-module (gnu services)
  #:use-module (gnu services shepherd)
  #:use-module (gnu services admin)
  #:use-module (gnu packages finance)
  #:export (bitcoin-configuration
            bitcoin-service-type
            bitcoin-configuration?
            bitcoin-service-type
            monero-configuration
            monero-service-type
            monero-configuration?
            monero-service-type))

(define-record-type* <bitcoin-configuration>
  bitcoin-configuration make-bitcoin-configuration
  bitcoin-configuration?
  this-bitcoin-configuration
  ;; A file-like object
  (bitcoin-package      bitcoin-configuration-bitcoin-package
                        (default bitcoin-core))
  ;; A string
  (user                 bitcoin-configuration-user
                        (default "johndoe"))
  ;; A boolean value
  (walletdir-opt?       bitcoin-configuration-walletdir-opt?
                        (default #f))
  ;; A string
  (walletdir            bitcoin-configuration-walletdir
                        (default ""))
  ;; A boolean value
  (proxy-opt?           bitcoin-configuration-proxy-opt?
                        (default #f))
  ;; A string
  (proxy                bitcoin-configuration-proxy
                        (default ""))
  ;; A string
  (pid                  bitcoin-configuration-pid
                        (default ""))
  ;; A string
  (log-folder           bitcoin-configuration-log-folder
                        (default "/var/run"))
  ;; A string
  (log-file-name        bitcoin-configuration-log-file-name
                        (default "bitcoin.log"))
  ;; A boolean value
  (%auto-start?         bitcoin-configuration-auto-start?
                        (default #t)))

(define-record-type* <monero-configuration>
  monero-configuration make-monero-configuration
  monero-configuration?
  this-monero-configuration
  ;; A file-like object
  (monero-package        monero-configuration-monero-package
                         (default monero))
  ;; A string
  (user                  monero-configuration-user
                         (default "johndoe"))
  ;; A boolean value
  (proxy-opt?            monero-configuration-proxy-opt?
                         (default #f))
  ;; A string
  (proxy                 monero-configuration-proxy
                         (default ""))
  ;; A boolean value
  (tx-proxy-opt?         monero-configuration-tx-proxy-opt?
                         (default #f))
  ;; A string
  (tx-proxy              monero-configuration-tx-proxy
                         (default ""))
  ;; A boolean value
  (prune-blockchain-opt? monero-configuration-prune-blockchain-opt?
                         (default #f))
  ;; A string
  (pidfile               monero-configuration-pidfile
                         (default ""))
  ;; An integer
  (pid-file-timeout      monero-configuration-pid-file-timeout
                         (default 5))
  ;; A string
  (log-folder            monero-configuration-log-folder
                         (default "/var/run"))
  ;; A string
  (stdout-log-file-name  monero-configuration-stdout-log-file-name
                         (default "monero.log"))
  ;; A string
  (monero-log-file-name  monero-configuration-monero-log-file-name
                         (default "bitmonero.log"))
  ;; A boolean value
  (%auto-start?          monero-configuration-auto-start?
                         (default #t)))

(define (bitcoin-log-file-path config)
  "Returns a string specifying the path to the log file of a bitcoin
node service configurable by CONFIG, a record of the
<bitcoin-configuration> type."
  (string-append (bitcoin-configuration-log-folder config)
                 "/"
                 (bitcoin-configuration-log-file-name config)))

(define (bitcoin-log-rotation config)
  "Returns a list of log-rotation records specifying how to rotate the
logs of a bitvoin node service configurable by CONFIG, a record of the
<bitcoin-configuration> type."
  (list (log-rotation (frequency 'daily)
                      (files `(,(bitcoin-log-file-path config))))))

(define (bitcoin-constructor-gexp config)
  "Returns a G-exp to a procedure starting a bitcoin node daemon,
configurable by CONFIG, a record of the <bitcoin-configuration> type."
  (let ((bitcoin-package (bitcoin-configuration-bitcoin-package config))
        (user (bitcoin-configuration-user config))
        (walletdir-opt? (bitcoin-configuration-walletdir-opt? config))
        (walletdir (bitcoin-configuration-walletdir config))
        (proxy-opt? (bitcoin-configuration-proxy-opt? config))
        (proxy (bitcoin-configuration-proxy config))
        (pid-file-path (bitcoin-configuration-pid config))
        (log-file-path (bitcoin-log-file-path config)))
    #~(make-forkexec-constructor
       (append (list #$(file-append bitcoin-package
                                    "/bin/bitcoind")
                     (string-append "-datadir="
                                    (passwd:dir (getpwnam #$user))
                                    "/.bitcoin"))
               (if #$walletdir-opt?
                   (list (string-append "-walletdir="
                                        #$walletdir))
                   (list))
               (if #$proxy-opt?
                   (list (string-append "-proxy="
                                        #$proxy))
                   (list))
               (list (string-append "-pid="
                                        #$pid-file-path)))
       #:pid-file
       #$pid-file-path
       #:log-file
       #$log-file-path)))

(define (bitcoin-shepherd-services config)
  "Returns a list of shepherd services handling a bitcoin node
configured by CONFIG, a record of the <bitcoin-configuration> type."
  (let ((auto-start? (bitcoin-configuration-auto-start? config)))
    (list
     (shepherd-service
      (documentation "Bitcoin node")
      (provision '(bitcoin))
      (requirement '())
      (start (bitcoin-constructor-gexp config))
      (stop #~(make-kill-destructor))
      (auto-start? auto-start?)))))

(define bitcoin-service-type
  (service-type
   (name 'bitcoin)
   (description "Bitcoin node service")
   (extensions
    (list (service-extension shepherd-root-service-type
                             bitcoin-shepherd-services)
          (service-extension rottlog-service-type
                             bitcoin-log-rotation)
          (service-extension
           profile-service-type
           (lambda (config)
             (list (bitcoin-configuration-bitcoin-package config))))))
   (default-value (bitcoin-configuration))))

(define (stdout-monero-log-file-path config)
  "Returns a string specifying the path to the log file of the standard
output of a monero node service configurable by CONFIG, a record of the
<monero-configuration> type."
  (string-append (monero-configuration-log-folder config)
                 "/"
                 (monero-configuration-stdout-log-file-name config)))

(define (monero-log-file-path config)
  "Returns a string specifying the path to the log file of a monero node
service configurable by CONFIG, a record of the <monero-configuration>
type."
  (string-append (monero-configuration-log-folder config)
                 "/"
                 (monero-configuration-monero-log-file-name config)))

(define (monero-log-rotation config)
  "Returns a list of log-rotation records specifying how to rotate the
logs of a monero node service configurable by CONFIG, a record of
the <monero-configuration> type."
  (list (log-rotation (frequency 'daily)
                      (files `(,(monero-log-file-path config))))
        (log-rotation (frequency 'daily)
                      (files `(,(stdout-monero-log-file-path config))))))

(define (monero-constructor-gexp config)
  "Returns a G-exp to a procedure starting a monero node daemon,
configurable by CONFIG, a record of the <monero-configuration> type."
  (let ((monero-package (monero-configuration-monero-package config))
        (user (monero-configuration-user config))
        (proxy-opt? (monero-configuration-proxy-opt? config))
        (proxy (monero-configuration-proxy config))
        (tx-proxy-opt? (monero-configuration-tx-proxy-opt? config))
        (tx-proxy (monero-configuration-tx-proxy config))
        (pid-file-path (monero-configuration-pidfile config))
        (prune? (monero-configuration-prune-blockchain-opt? config))
        (pid-file-timeout (monero-configuration-pid-file-timeout config))
        (log-file-path ( monero-log-file-path config))
        (stdout-log-file-path (stdout-monero-log-file-path config)))
    #~(make-forkexec-constructor
       (append (list #$(file-append monero-package
                                    "/bin/monerod")
                     "--data-dir"
                     (string-append (passwd:dir (getpwnam #$user))
                                    "/.bitmonero"))
               (if #$proxy-opt?
                   (list "--proxy"
                         #$proxy)
                   (list))
               (if #$tx-proxy-opt?
                   (list "--tx-proxy"
                         #$tx-proxy)
                   (list))
               (if #$prune?
                   (list "--prune-blockchain")
                   (list))
               (list "--detach"
                     "--pid"
                     #$pid-file-path
                     "--log-file"
                     #$log-file-path))
       #:pid-file
       #$pid-file-path
       #:pid-file-timeout
       #$pid-file-timeout
       #:log-file
       #$stdout-log-file-path)))

(define (monero-shepherd-services config)
  "Returns a list of shepherd services handling a monero node
configured by CONFIG, a record of the <monero-configuration> type."
  (let ((auto-start? (monero-configuration-auto-start? config)))
    (list
     (shepherd-service
      (documentation "Monero node")
      (provision '(monero))
      (requirement '())
      (start (monero-constructor-gexp config))
      (stop #~(make-kill-destructor))
      (auto-start? auto-start?)))))

(define monero-service-type
  (service-type
   (name 'monero)
   (description "Monero node service")
   (extensions
    (list (service-extension shepherd-root-service-type
                             monero-shepherd-services)
          (service-extension rottlog-service-type
                             monero-log-rotation)
          (service-extension
           profile-service-type
           (lambda (config)
             (list (monero-configuration-monero-package config))))))
   (default-value (monero-configuration))))