esthlos-V Genesis, Or: Who Presses the Pressor?

Posted 2018-05-30
Edit on 2018-06-07: Modified the below vpatch to include a manifest, per the spec.


This item fulfills the request for a new V implementation.


If you're new here and don't know what V is, I suggest you glance at the canonical introduction by Benjamin Vulpes, and possibly glance my (now outdated by this post) older, flawed vtron.

Credit is due to

  • trinque for overall guidance,
  • phf for providing a mkdtemp interface for ccl,
  • asciilifeform for providing the original V,
  • Diana Coman for helping me get my shit together,

and others for general advice on vtronics and other matters.

Setup and Use

Per-System Configuration

As a user, you must take care to correctly set the global tuning parameters for your system. I've tried to set sensible defaults, but if something doesn't work, you should make sure that these parameters are set correctly. Here are the defaults:

(defparameter *default-vpatch-dir* "./patches/")
(defparameter *default-wot-dir* "./wot/")
(defparameter *default-seal-dir* "./seals/")
(defparameter *default-keyring-dir-location* "./")
(defparameter *default-keyring-dir-template* "gpgXXXXXX")
(defparameter *gpg-location* "/usr/bin/gpg")
(defparameter *patch-location* "/usr/bin/patch")
(defparameter *rm-location* "/bin/rm")


  • default-vpatch-dir is the directory where vpatches are looked for;
  • default-wot-dir is the directory where public keys are looked for;
  • default-seal-dir is the directory where seals are looked for;
  • default-keyring-dir-location is the location where gpg temporary keyring directory generation is attempted;
  • default-keyring-dir-template is the template used to name the temporary keyring directory. It must end with "XXXXXX" (six capital X's);
  • gpg-location is the location of your gpg executable;
  • patch-location is the location of your patch executable; and
  • rm-location is the location of your rm executable.

Note well: strings pointing to directories should end in a forward slash to ensure correct interpretation.

Setup Guide

Setting the thing up is simple:

  1. (n00b step): Ensure the following:
    1. You're on a decent Linux distribution (e.g. Gentoo).
    2. You have gpg 1.4.X installed. (2.x is banned.)
  2. Ensure at least one of the following is installed:
    1. sbcl (tested on version 1.4.4 x86_64).
    2. ccl (tested on version 1.11.5 x86_64).
  3. Press the thing with your current vtron.
  4. Move the files to a convenient location.
  5. Create (and possibly populate) the wot, seals, and vpatch directories.
  6. If you want to run interactively:
    1. In the directory with the files, run sbcl or ccl.
    2. In the REPL, run (load "v.lisp").
    3. Either:
      1. run (in-package "V"); or
      2. preface the main vtron commands with v:, and the internal vtron commands with v::. E.g., (v:flow) or (v::load-vpatches)
  7. If you want run as a portable executable:
    1. Either:
      1. run make sbcl to build with sbcl; or
      2. run make ccl to build with ccl.
    2. Invoke ./v to see your options


Of course, the user of this program is expected to read and understood before use, but you might want to test it, too. I've designed the program so that each piece can be tested independently. Here's something to get you started.

Open up your preferred (any color you like, as long it's sbcl or ccl) REPL, and load in the vtron with (load "v.lisp"). We're going to test the topological sorting capability by creating all directed 6-graphs, and trying to press each one. Exactly one of the graphs has a cycle, and should throw an error.

To make things easier, we will first redefine the vpatch class so that subpatches (patches for individual files) can be added post-instantiation:

(defclass vpatch ()
  ((name :initarg :name :reader name)
   (subpatches :initform '() :initarg :subpatches :accessor subpatches)
   (path :initarg :path :reader path)
   (seals :initarg :seals :reader seals))
  (:documentation "A representation of a vpatch."))

Next, we define a command to spit out three distinct vpatches, and another generally useful routine for establishing the parenthood relation between vpatches:

(defun new-vertex-set ()
  (list (make-instance 'vpatch :name "a")
        (make-instance 'vpatch :name "b")
        (make-instance 'vpatch :name "c")))

(defun set-parent (vpatch-list child parent)
  (let ((filename (symbol-name (gensym)))
        (pre-hash (symbol-name (gensym)))
        (post-hash (symbol-name (gensym)))
        (parent (find-if #'(lambda (vp) (string= parent (name vp)))
        (child (find-if #'(lambda (vp) (string= child (name vp)))
    (cl:setf (subpatches parent)
             (append (subpatches parent)
                     (list (make-instance 'subpatch
                                          :path filename
                                          :pre-hash "false"
                                          :post-hash pre-hash))))
    (cl:setf (subpatches child)
             (append (subpatches child)
                     (list (make-instance 'subpatch
                                          :path filename
                                          :pre-hash pre-hash
                                          :post-hash post-hash))))))

Now the following procedure should, upon evaluation, simply print "Cycle caught correctly.":

(defun make-and-test-3-graphs ()
  (let ((g1) (g2) (g3) (g4) (g5) (g6))
    ;; {}
    (setq g1 (new-vertex-set))

    ;; {(b,a)}
    (setq g2 (new-vertex-set))
    (set-parent g2 "b" "a")

    ;; {(b,a), (c,a)}
    (setq g3 (new-vertex-set))
    (set-parent g3 "b" "a")
    (set-parent g3 "c" "a")

    ;; {(b,a), (a,c)}
    (setq g4 (new-vertex-set))
    (set-parent g4 "b" "a")
    (set-parent g4 "a" "c")

    ;; {(b,a), (c,a), (c,b)}
    (setq g5 (new-vertex-set))
    (set-parent g5 "b" "a")
    (set-parent g5 "c" "a")
    (set-parent g5 "c" "b")

    ;; {(b,a), (a,c), (c,b)}
    (setq g6 (new-vertex-set))
    (set-parent g6 "b" "a")
    (set-parent g6 "a" "c")
    (set-parent g6 "c" "b")

    ;; this should execute without a problem
    (mapcar #'(lambda (vpatch-list)
                (toposort (generate-depgraph vpatch-list)))
            (list g1 g2 g3 g4 g5))

    ;; the error should be caught here
        (toposort (generate-depgraph g6))
      (cyclic () (format t "Cycle caught correctly.")))))

I encourage you to further play with the thing, especially if you believe it's broken in some way.

Concluding Remarks

I'm sure something is broken, so please: read and test!

Regardless, I hope it serves you well.

5 Responses to “esthlos-V Genesis, Or: Who Presses the Pressor?”

  1. PeterL says:
    Why did you not put in a manifest file for the genesis?
  2. esthlos says:
    I didn't think of it. If it's worthwhile, I'll regrind. See
  3. [...] of course, is the republican version control system. The latest client software can be found here. The new client lacks a manifest, and the manifest itself lacks a formal definition, so lets remedy [...]
  4. esthlos says:
    Peter, the vpatch has been updated with a manifest file.
  5. [...] reasons amply put in the logs, esthlos-v needs a hashing mechanism, and the standard is Keccak. How can Keccak be attached to the Common [...]

Leave a Reply (USE HTML! Space not preserved!)