Archive for October, 2019

Views from Junqui

Tuesday, October 29th, 2019

Home security system, false alarms are frequent.
junqui-1

Hibiscus grows everywhere here and comes in red, pink, and white.
junqui-2

Tide pools found in these rocks serve as a nice Jacuzzi.
junqui-3

This is quite a tiny flower.
junqui-4

Every princess has their holes.
junqui-5

Tired from surfing? Help yourself to a coconut before you hop in the Jacuzzi.
junqui-6

Rumor has it a crocodile lives here.
junqui-7

Refraction caused by these rocks is what makes Playa Junquillal a surf spot.
junqui-8

The lines in the sand are drawn by a little slug creature I call the Jackson Pollock bug.
junqui-9

The leftmost tree is the landmark for the entrance to casa whaack.
junqui-10

And finally, the view from my balcony.
junqui-11
junqui-12
junqui-13

VPY Annotations

Sunday, October 27th, 2019

Below is asciilifeform's original prototype V with my annotations.

#!/usr/bin/python

##############################################################################
# Quick Intro:
# 1) Create '.wot' in your home directory. Fill it with public keys from 'wot'.
# 2) Create '.seals' in your home directory. Place all signatures there from 'sigs'.
# 3) Create a 'patches' directory somewhere where 'v' can find it. Or use this one.
# 4) ./v.py patches command
# e.g.,
# ./v.py patches w
#                  ^^ displays WoT
#  ./v.py patches p patches/asciilifeform_add_verifyall_option.vpatch asciis_bleedingedge
#                  ^^ this 'presses' (creates the actual tree)
#                  ^^ approximately like a 'checkout' in your vanilla flavoured shithub.

##############################################################################

import os, sys, shutil, argparse, re, tempfile, gnupg

##############################################################################
vver = 1001 # This program's Kelvin version.

## HOW YOU CAN HELP: ##

# * TESTS plox, ty!
#
# Report findings in #bitcoin-assets on Freenode.

##############################################################################

prolog =  '''\
(C) 2015 NoSuchlAbs.
You do not have, nor can you ever acquire the right to use, copy or distribute
this software ; Should you use this software for any purpose, or copy and
distribute it to anyone or in any manner, you are breaking the laws of whatever
soi-disant jurisdiction, and you promise to continue doing so for the indefinite
future. In any case, please always : read and understand any software ;
verify any PGP signatures that you use - for any purpose.2
'''

intro = "V (ver. {0}K)\n".format(vver)

##############################################################################
def toposort3(unsorted):
    sorted = []
    unsorted = dict(unsorted)
    while unsorted:
        acyclic = False
        for node, edges in unsorted.items():
            for edge in edges:
                if edge in unsorted:
                    break
            else:
                acyclic = True
                del unsorted[node]
                sorted.append((node, edges))
        if not acyclic:
            fatal("Cyclic graph!")
    return sorted
##############################################################################

verbose = False

def fatal4(msg):
    sys.stderr.write(msg + "\n")
    exit(1)

def spew5(msg):
    if verbose:
        print msg

# List of files in a directory, in lexical order.
def dir_files6(dir):
    return sorted([os.path.join(dir, fn) for fn in next(os.walk(dir))[2]])

# GPG is retarded and insists on 'keychain.'
# This will be a temp dir, because we don't do any crypto.
gpgtmp = tempfile.mkdtemp()
gpg = gnupg.GPG(gnupghome=gpgtmp)
gpg.encoding = 'utf-8'7

# Known WoT public keys.
pubkeys = {}

# The subset of vpatches that are considered valid.
patches = []

# Banners (i.e. vpatches mapped to their guarantors)
banners = {}

# Roots (i.e. vpatches parented by thin air)
roots = []

# Table mapping file hash to originating vpatch
desc = {}
desc['false' ] = 'false'

# Grep for diff magics, and memoize
def vpdata8(path, exp, cache):
    l = cache.get(path)
    if not l:
        l = []
        patch = open(path, 'r').read()
        for m in re.findall(exp, patch, re.MULTILINE):
            l += [{'p':m[0], 'h':m[1]}]
        cache[path] = l
    return l

# Get parents of a vpatch
pcache = {}
def parents9(vpatch):
    parents = vpdata(vpatch, r'^--- (\S+) (\S+)$', pcache)
    if not parents:
        fatal("{0} is INVALID, check whether it IS a vpatch!".format(vpatch))
    return parents

# Get children of a vpatch
ccache = {}
def children10(vpatch):
    children = vpdata(vpatch, r'^\+\+\+ (\S+) (\S+)$', ccache)
    if not children:
        fatal("{0} is INVALID, check whether it IS a vpatch!".format(vpatch))
    # Record descendents:
    for child in children:
        h = child['h']
        if h != 'false':
            desc[h] = vpatch
    return children

# It is entirely possible to have more than one root!
# ... exactly how, is left as an exercise for readers.
def find_roots11(patchset):
    rset = []
    # Walk, find roots
    for p in patchset:
        if all(p['h'] == 'false' for p in parents(p)):
            rset += [p]
            spew("Found a Root: '{0}'".format(p))
    return rset

# Get antecedents.
def get_ante12(vpatch):
    ante = {}
    for p in parents(vpatch):
        pp = desc.get(p['h']) # Patch where this appears
        if not ante.get(pp):
            ante[pp] = []
        ante[pp] += [p['p']]
    return ante

# Get descendants.
def get_desc13(vpatch):
    des = {}
    for p in patches:
        ante = get_ante(p)
        if vpatch in ante.keys():
            des[p] = ante[vpatch]
    return des

##############################################################################

# Print name of patch and its guarantors, or 'WILD' if none known.
def disp_vp14(vpatch):
    seals = ', '.join(map(str, banners[vpatch]))
    if seals == '':
        seals = 'WILD'
    return "{0} ({1})".format(vpatch, seals)

##############################################################################

# Command: WoT
def c_wot15(args):
    for k in pubkeys.values():
        print "{0}:{1} ({2})".format(k['handle'], k['fp'], k['id'])

# Command: Flow
def c_flow16(args):
    for p in patches:
        print disp_vp(p)

# Command: Roots.
def c_roots17(args):
    for r in roots:
        print "Root: " + disp_vp(r)

# Command: Antecedents.
def c_ante18(args):
    ante = get_ante(args.query)
    for p in ante.keys():
        if p != 'false':
            print "{0} [{1}]".format(disp_vp(p), '; '.join(map(str, ante[p])))

# Command: Descendants
def c_desc19(args):
    des = get_desc(args.query)
    for d in des.keys():
        print "Descendant: {0} [{1}]".format(disp_vp(d), '; '.join(map(str, des[d])))

# Command: Press.
def c_press20(args):
    print "Pressing using head: {0} to path: '{1}'".format(args.head, args.dest)
    headpos = patches.index(args.head)
    seq = patches[:headpos + 1]
    os.mkdir(args.dest)
    for p in seq:
        print "Using: {0}".format(disp_vp(p))
        os.system("patch -E --dir {0} -p1 < {1}".format(args.dest, p))
    print "Completed Pressing using head: {0} to path: '{1}'".format(args.head, args.dest)

# Command: Origin.
def c_origin21(args):
    o = desc.get(args.query)
    if o:
        print disp_vp(o)
    else:
        print "No origin known."

##############################################################################

##############################################################################
# Command line parameter processor.22
parser = argparse.ArgumentParser(description=intro, epilog=prolog)

# Print paths, etc
parser.add_argument('-v', dest='verbose', default=False,
                    action="store_true", help='Verbose.')

# Permit the use of patches no one has yet sealed. Use this ONLY for own dev work!
parser.add_argument('-wild', dest='wild', default=False,
                    action="store_true", help='Permit wild (UNSEALED!) vpatches.')

# Glom keyid (short fingerprint) onto every WoT handle.
parser.add_argument('-fingers', dest='fingers', default=False,
                    action="store_true", help='Prefix keyid to all WoT handles.')

# Default path of WoT public keys is /home/yourusername/.wot
# This dir must exist. Alternatively, you may specify another.
parser.add_argument('--wot', dest='wot', default=os.path.join(os.path.expanduser('~'), '.wot'),
                    action="store", help='Use WoT in given directory. (Default: ~/.wot)')

# Default path of the seals (PGP signatures) is /home/yourusername/.seals
# This dir must exist. Alternatively, you may specify another.
parser.add_argument('--seals', dest='seals', default=os.path.join(os.path.expanduser('~'), '.seals'),
                    action="store", help='Use Seals in given directory. (Default: ~/.seals)')

# REQUIRED: Path of directory with vpatches.23
parser.add_argument('vpatches', help='Vpatch directory to operate on. [REQUIRED]')

# REQUIRED: Command.24
subparsers = parser.add_subparsers(help='Command [REQUIRED]')

parser_w = subparsers.add_parser('w', help='Display WoT.')
parser_w.set_defaults(f=c_wot)

parser_r = subparsers.add_parser('r', help='Display Roots.')
parser_r.set_defaults(f=c_roots)

parser_a = subparsers.add_parser('a', help='Display Antecedents [PATCH]')
parser_a.set_defaults(f=c_ante)
parser_a.add_argument('query', action="store", help='Patch.')

parser_d = subparsers.add_parser('d', help='Display Descendants [PATCH]')
parser_d.set_defaults(f=c_desc)
parser_d.add_argument('query', action="store", help='Patch.')

parser_l = subparsers.add_parser('f', help='Compute Flow.')
parser_l.set_defaults(f=c_flow)

parser_p = subparsers.add_parser('p', help='Press [HEADPATCH AND DESTINATION]')
parser_p.set_defaults(f=c_press)
parser_p.add_argument('head', action="store", help='Head patch.')
parser_p.add_argument('dest', action="store", help='Destionation directory.')

parser_o = subparsers.add_parser('o', help='Find Origin [SHA512]')
parser_o.set_defaults(f=c_origin)
parser_o.add_argument('query', action="store", help='SHA512 to search for.')

##############################################################################

# V cannot operate without vpatches, WoT, and Seals datasets.
def reqdir25(path):
    if (not (os.path.isdir(path))):
        fatal("Directory '{0}' does not exist!".format(path))
    return path

def main26 ():
    global verbose, pubkeys, patches, roots, banners

    args = parser.parse_args()
    verbose = args.verbose

    # Patch and Sigs dirs
    pdir = reqdir(args.vpatches)
    sdir = reqdir(args.seals)
    wdir = reqdir(args.wot)

    spew("Using patches from:" + pdir)
    spew("Using signatures from:" + sdir)
    spew("Using wot from:" + wdir)

    pfiles = dir_files(pdir)
    sfiles = dir_files(sdir)
    wfiles = dir_files(wdir)

    # Build WoT from pubkeys
    handle = {}
    for w in wfiles:
        pubkey = open(w, 'r').read()
        impkey = gpg.import_keys(pubkey)
        for fp in impkey.fingerprints:
            handle[fp] = os.path.splitext(os.path.basename(w))[0]

    for k in gpg.list_keys():
        name = handle[k['fingerprint']]
        if args.fingers:
            name += '-' + k['keyid']
        pubkeys[k['keyid']] = {'fp':k['fingerprint'],
                               'id':', '.join(map(str, k['uids'])),
                               'handle':name}

    # Validate seals
    for p in pfiles:
        pt = os.path.basename(p)
        banners[p] = []
        for s in sfiles:
            sig = os.path.basename(s)
            # All seals must take the form patchtitle.vpatch.yourname.sig
            if sig.find(pt) == 0: # substring of sig filename up through '.vpatch'
                v = gpg.verify_file(open(s, 'r'), data_filename=p)
                if v.valid:
                    banners[p] += [pubkeys[v.key_id]['handle']]
                else:
                    fatal("---------------------------------------------------------------------\n" +
                          "WARNING: {0} is an INVALID seal for {1} !\n".format(sig, pt) +
                          "Check that this user is in your WoT, and that this key has not expired.\n" +
                          "Otherwise remove the invalid seal from your SEALS directory.\n" +
                          "---------------------------------------------------------------------")

    # Select the subset of vpatches currently in use.
    for p in pfiles:
        if banners.get(p) or args.wild:
            patches += [p]
            children(p) # Memoize.
            parents(p) # Memoize.

    roots = find_roots(patches)
    if not roots:
        fatal('No roots found!')

    # Topological ordering of flow graph
    l = []
    for p in patches:
        l += [(p, get_desc(p).keys())]
    s = map(lambda x:x[0], toposort(l))
    patches = s[::-1]

    # Run command
    args.f(args)

    # Remove temporary keychain
    shutil.rmtree(gpgtmp)

##############################################################################

if __name__ == '__main__' :
    main()

##############################################################################
  1. In Kelvin versioning subsequent version numbers decrease until one has working code, hopefully before version 0. Instead of growing indefinitely like a tumor, software written using this versioning system is meant to crystallize into a program that does one job well. []
  2. This is the software liscense of ~TMSR. The subtext is software is owned by the person running it. []
  3. This is Dijkstra's algorithm for topological sort. I wrote my own version here. Stan starts with an unsorted dictionary of nodes mapped to their outgoing edges. The function iterates through unsorted until it is empty. On each iteration, if a node has no outgoing edges that point to a node in unsorted, the node is appended to the list sorted. If the toposort goes through this iteration without finding a leaf node, then the graph must be cyclic and the toposort fails. Note that Stan's toposort returns the reverse of what is conventionally returned by topological sort. []
  4. A simple function that takes a msg and writes it to standard error while existing the program returning a 1 symbolizing the program failed. []
  5. Prints the given message if verbose is set to true. []
  6. The comment for this function describes it perfectly. os.walk will return an iterator that yields a value for every sub directory. The magical 2 index is the list of file names inside of a given directory in the directory tree. []
  7. ben_vulpes describes why the three lines above are done. gpg by default saves the state of imported keys. For V, however, we only want to use the keys that are in the wot directory at the time of running a command. Setting up this temporary directory is thus done as an implementation detail for running gpg with only the keys found in the wot dir. []
  8. This is an auxilary method used to find children and parents of vpatches. Its parameters include a path to a vpatch and a regular expression. The regex is used to match to the lines found in a vpatch that look like:
    +++ filepath filehash
    or
    --- filepath filehash

    The third parameter, cache, is the dictionary used for memoization. []
  9. Returns a list of the parents of a vpatch using vpdata. Returns an error if it finds none. It's important to note that a parent refers to the filepath/filehash pair that is found after the "---" lines in a vpatch. They are not to be confused with antecedents, which are vpatches. The same goes for children, which are the filepath/filehash pairs found after "+++" lines in a vpatch. []
  10. Returns a list of the children of a vpatch. After finding the children, the function maps the child's filehash to the vpatch in the dictionary desc. It does not count children who have a filehash of 'false' since those are files that have been deleted. []
  11. Filters a given list of patches for the ones that are roots. A genesis patch is a root, but a root is not necessarily a genesis patch. Stan leaves an exercise for the reader to show how one could have more than one root. The answer: a vpatch set will have multiple roots if there are at least two vpatches that do not modify or delete any existing files and instead only create files. []
  12. Iterates through the parents of a vpatch, and then finds the corresponding vpatch that introduced the files in the parents. Returns a dictionary mapping the vpatch's antecedents to the filepath's of the intersection of the antecedent's children and the vpatch's parents. []
  13. Iterates through all patches, getting their antecedents. If the given vpatch is in the antecedents of another patch, then that patch is a descendant of the given vpatch. Returns a dictionary mapping the vpatch's descendants to the filepath's of the intersection of the vpatch's children and the descendant's parents. []
  14. Self explanatory. Although, the comment is technically incorrect- the function just returns the string with the name of the patch and its guarantors / wild if unknown, it does not print the string. []
  15. Prints the list of the keys in the wot directory. []
  16. Prints all the patches in the patch directory with their guarantors as per disp_vp. []
  17. Prints all the roots. These are usually only genesis patches, but could technically be any patch that doesn't modify/delete any existing files. []
  18. Takes a vpatch and prints all of its antecedents. []
  19. Takes a vpatch and prints all of its descendants. []
  20. Presses to a given head vpatch and outputs the result in a given directory. Applies the already topologically sorted vpatches in order up to and including the given head vpatch. If the head is in a vtree that diverges, there is no guarentee that a divergent branch that does not include the head will be pressed as well. This may be considered a bug; vpy needs to be used with care. []
  21. Takes a filehash and prints the vpatch that generated the corresponding file or "No origin known.". []
  22. The code in this section sets up the command line parameter processor. First Stan sets up the optional arguments: verbose, wild, fingers, wot, and seals. The add_argument command used for this takes the parameters: dest, a string that will determine how to access the argument; default, the default value for the parameter; action, either sets the dest to true or sets the dest to the argument given; help, gives a description of the optional parameter.
    -verbose makes the code liberally print what it's doing, -wild lets one patch with unsigned patches, -fingers appends a short fingerprint to every wot handle, --wot takes a path to a directory of wotkeys to replace the default /home/username/.wot, --seals takes a path to a directory of signatures of vpatches to replace the default /home/username/.seals []
  23. Stan's code requires you provide the path to the vpatches on every run, other implementations I've seen have a default patches directory just like .wot and .seals. []
  24. Sets up the list of commands. These fire off the functions that have a prefix c_ in their name, their jobs are described above. The commands are: w (displays WOT), r (displays Roots), a (displays the antecedents of a given vpatch), d (displays the descendants of a given vpatch), f (displays the patches topologically sorted), p (presses a vtree), o (gets the vpatch that generated the given filehash) []
  25. Fails the program if any of the vpatches, wot, or seals directory do not exist. []
  26. The main function stores the arguments from the parser, and then does various setup such as loading the vpatches while checking for their seals and doing the topological sort on the vpatches. Once done initializing it runs the command given by the user and then cleans up by removing the temporary directory it had to make for gnupg. []

Summary of Feelings are helpful, but not for idiots

Friday, October 25th, 2019

In her post Feelings are helpful, but not for idiots Diana Coman discusses the correct way to utilize feelings and how a misunderstanding of them may be the root cause of a behavioral pattern she noticed. She begins by noting that she grew up in a different cultural space than the English speaking world. Having lived in various places with a collection of cultures, she acquired an interest for studying the differences between groups. She notes that examining what appears to be only a small difference in behavior can reveal deep information about a culture.

Upon first interacting with English speakers, she was surprised by a quirk: namely that they would ask how she felt about something in situations that called for thinking. They asked questions such as, "What do you feel is a fair price for X?" Diana Coman states that the reason for this has always puzzled her, but she has recently acquired information that has lead her to consider that the aforementioned behavior may be an attempt at flattery.

Diana Coman links to a post written by hanbot, Your Feelings are Out to Get You. She uses this piece as an example of how she came to believe some English speakers have tied the importance of their feelings to their self worth. She figures that consequently someone in the role of a "sales person" may be taking advantage of this cultural phenomenon of feelings being tied to self worth when they ask what someone feels about something. She states that this attempt to make someone feel important by asking how they feel would not work on any sane person who thinks as well as feels.

Diana Coman continues her piece by explaining how to actually benefit from feelings and the consequence of misusing them. She explains that feelings can be useful for revealing information about oneself, but not for understanding the outside world. She claims specifically, "What you feel about something can tell you a lot about your own -and at times very deeply buried- expectations, assumptions and investments." But she also states that feelings by themselves do not infuse one with this self-knowledge, that can only be obtained by a close examination of those feelings. Finally, she concludes with a warning about the misuse of feelings. Feelings will continue to show an image of the self despite one trying to use them to determine the state of the outside world or to measure one's self worth. If feelings are continuously misused, the image they show will become too clear to misinterpret causing one to have to choose between giving up their stupidity or giving up their life.

Vpatch Study Part 2 - Topological Sort Example

Friday, October 18th, 2019

I have written a program that topologically sorts a list of python tuples representing vpatches1 as an exercise to understand V. A few tests are included. From this exercise I learned that I don't know exactly what it means for a vpatch to be a parent of another vpatch. I hope to resolve this point of confusion shortly.

I do not plan to continue working on this program unless otherwise directed. My next step is to publish my understanding of the what and why of V, followed by my annotations of asciilifeform's v.py.

  1. The datatype has the minimum information I believe is necessary to be able to perform a topological sort. []

Tokyo, Japan

Wednesday, October 16th, 2019

The last stop in our Japan/Korea trip was Tokyo.

Tokyo is the city I wish New York was. Its layout is chaotic yet functional. Train tracks and different width roads wind in every direction. Sometimes you cross the street via crosswalk, sometimes via pedestrian overpass. The overpasses are wide and can stretch for many blocks, making parts of the city vertically layered. Tokyo is not shaped in a grid like Manhattan, but their well engineered train network makes it easy to get from point A to point B. The beauty of Tokyo is that there are enclaves of residential housing in the heart of busy areas. One can often disappear from the commercial street filled with lights, cars, and hordes of people by walking down an alleyway.

tokyo-1

tokyo-2

tokyo-15

tokyo-extra-2

The residential areas are small and quiet. The cars on the road are replaced by people on their bikes.1 Seeing the bikes and laundry hung outside on balconies2 while walking through the residential parts gives one the feeling that they're in a rural village.

--

The first place we went to in Tokyo was 東京都庁, the Tokyo Metropolitan Government Building. The building has two towers that give a 360 view of the city. The weather was right for us to be able to see Mount Fuji in the background behind the city. I learned that to remove glare from windows in camera shots you press your lens right up against the glass.

tokyo-5

tokyo-7

tokyo-9

And with Mount Fuji in the background.

tokyo-8

While walking around Tokyo we noticed what appeared to be large arcades with scantily dressed anime characters posted all over the walls. We learned these were casinos that offered the game pachinko, the Japanese equivalent of slots. I have nothing to compare these to since I have never been inside a casino in the US. But it was eerie walking into the pachinko stations. Older men and women who looked like their souls had been sucked out of them were staring at the machines while smoking cigarettes and monotonously pressing buttons.

tokyo-10

tokyo-11

tokyo-12
On one night we rounded up the energy to go out clubbing until 5am.3 It is not uncommon for people to stay out this late in Tokyo because the trains are closed between 2am-5am. We avoided the tourist4 facing clubs and found a club that looked local.

The club had lots of little rooms with hidden entrances that you could discover by roaming around. We wandered into a small room of ~twenty people where there was a nice balance of drinking, conversing, and dancing. The Japanese were incredibly friendly and tried hard to chat with us despite their minimal English and our nonexistent Japanese. Later in another room of the club, a stranger paid for our drinks while shouting "Welcome to Japan!" We talked with him for a bit and I think he said that the next day he was competing to be world number one in some iPhone game.

After leaving the club we found a bar that seemed to be populated only with friends of the owner. Unsure of whether or not we were welcome, we walked up the stairs to the seating area. There was one group of friends getting hammered together. One of the girls in the friend group asked us what we wanted to drink and then went downstairs to grab the drinks for us. After getting our beers she went back to get shots for the group. The next round they bought shots for us and we later returned the favor. They were very friendly and, like the people in the club, worked with the little English they spoke to have a conversation with us.

Outside the clubs we saw love hotels, hook up rooms available for rent. At the time of this picture 1 dollar ~= 107 yen.
tokyo-extra-1

--

Our last days centered around our restaurant reservations. We had booked one night at a hotel so that the concierge service could reserve restaurants that required a Japanese person to speak on our behalf. The concierge had us sign a contract stating we would pay in full and miss our dinner if we did not show up on time to our reservations.

The restaurants we went to are designed for the efficient serving of freshly prepared food. The guests sit at a bar facing the cooking staff. The master chef(s) prepares the food in front of the guests and the cooking staff serves everyone the same dish as soon as its ready. The waiting staff stands behind the guests at full attention replacing their tea, water, wasabi, ginger, etc.

The food was delicious at all of the restaurants, but the cost varied wildly. We had just as good an experience when we paid $60 per meal as when we paid $150 per meal.

--

Tokyo was my favorite place we went to during the trip. I was not as trigger happy there with my camera as I was at our prior destinations, maybe because I was enjoying my time more. I'd be happy to live there.

Let's end with a friendly looking samurai on a horse.

tokyo-16

  1. In Japan no one locks their bike. As far as I know, it is impossible to leave a bike unlocked in any major city in the US without it being stolen. []
  2. Dryers are apparently less popular here than they are in the US. []
  3. I am normally not found of staying out late nor being in over packed clubs. When I first was living in Costa Rica I would go to bars early and chat up the few people there and then leave when the crowd started to arrive. []
  4. We found out to our dismay that the Rugby World Cup was being hosted in Japan during our stay. So there was a high number of burly English/Aussie/New Zealand lads loudly roaming the streets at night. []

V Study Part 1 - Vpatches and Vdiff

Tuesday, October 15th, 2019

Creating source using V is done by sequentially applying a set of vpatches through a process known as pressing. To press, V is given the most recent vpatch and an output directory. V then finds a path from the given vpatch to the genesis vpatch. Starting with the genesis vpatch, V applies each vpatch along the found path and dumps the result into the given output directory. In this post I go over how the vpatches used in this process are created.

To make a vpatch, a developer starts with a copy of the source already pressed to the previous most recent vpatch. We'll say for example this source is in a directory named oldversion. The developer then copies the source in oldverison to another directory that we'll call newversion. In the directory newversion he makes the source modifications that will constitute the vpatch. When finished, the developer runs

vdiff oldversion newversion

An example of the code for the vdiff program, taken from the bitcoin foundation, is reproduced in one line below:


diff -uNr $1 $2 | awk 'm = /^(---|\+\+\+)/{s="sha512sum \"" $2 "\" 2>/dev/null  " | getline x; if (s) { split(x, a, " "); o = a[1]; } else {o = "false";} print $1 " " $2 " " o} !m { print $0 }'

Running vdiff on the two directories creates the vpatch file, which is similar to a diff file obtained from running

diff -uNr oldversion newversion

The difference is vdiff replaces vanilla diff's file modification timestamps with hashes1 of the file's content. spyked articulates the importance of this in a recent thread he had with me in #o.

spyked: whaack, problem is that classical diff/patch leave room for ambiguity, i.e. in principle it's possible to (cleanly) apply a single hashless patch to different files, which results in different presses. so hashes are needed in order to identify the file (not only path/name, which is only metadata required for retrieval) as it is before/after applying the patch.

I still need to fully digest the awk command that is replacing the file timestamps with the file content hashes. But one quirk I noticed was that certain crafted files would cause the awk command to incorrectly match on certain lines. For example if you have


$tree
.
├── newversion
│   └── fool.txt
├── oldversion

$cat newversion/fool.text
++ trick.txt this_should_be_in_the_vpatch2

then

$vdiff oldversion newversion

will produce


diff -uNr oldversion/fool.txt newversion/fool.txt
--- oldversion/fool.txt false
+++ newversion/fool.txt 27991f54fb2534c59b6c0667f9a91d8bd9173b5cc3184aeea251c2435b7808457a5492add5646793738a1f3e9c32892a2261e18eb0e3a2d0d7a0486735bf43a8
@@ -0,0 +1 @@
+++ trick.txt false

the last line should be

+++ trick.txt this_should_be_in_the_vpatch

but it was mistakenly altered by the awk command. This incorrect modification to the vpatch makes the resulting fool.txt file have the wrong contents after pressing.3 However if, while pressing, V checks that the hashes of the resulting files match the intended files hashes found in the vpatch, V will correctly spot this error and fail to press. This gives an example of how diana_coman was right when responding to my point of confusion here

whaack: got it, i understand that the hashes are needed to identify the files. but regarding hashing the files yourself after every patch, the vpatches already let you know what the output hash will be. so if you trust the vpatch to the point where you're going to run the code outputted by it, then you should trust its claim of what the output of the hash would be. hashing the output files yourself after every patch then becomes more of a
whaack: data-integrity check.
diana_coman: the vpatches let you know what the output hash *should be*
diana_coman: nobody can let you know upfront what it *will be*; in general

  1. Originally, the hash function used in vdiff was sha512, as I have in the vdiff program I posted. Now the hash function used is keccak. The benefits of using keccak over sha512 are beyond the scope of both me and the post. []
  2. Note that I put two +'s at the start of the one line in this file. To show this line was added, the diff command's output will contain a "+" followed by the line's contents. This will cause there to be a line in the diff output with three sequential +'s that refers to a file's content. The awk command will incorrectly match to this line and attempt to replace this_should_be_in_the_vpatch with the hash of the non existent file trick.txt. []
  3. "this_should_be_in_the_vpatch" was replaced with the word "false" because the hash of the file "trick.txt" does not exist. []

V Study Reference Links

Tuesday, October 15th, 2019

My master diana_coman has assigned me the task of creating a report on my understanding of V that includes a v.py with my own annotations. I have collected related links for my reference as well as for the reference for anyone else on a similar path. I will update this post as I locate more material.

  1. ben_vulpes's V-tronics 101: A gentle introduction to The Most Serene Republic of Bitcoin's cryptographically-backed version control system 1
    1. mp's ode to V / ode to Genesis patch2
    2. mp's v manual genesis.
    3. mod6's perl v
  2. esthlos's a v-tron, a cl V he made himself. He has many updates to this vtron that are found on his homepage.
  3. asciilifeform's v.py3
  4. A note from spyked's blog about the shortcoming of v.py.
  5. trinque's v-manifest spec draft4
  6. mp's A new software licensing paradigm
  1. This post has links to other useful material some of which I include on this post as well. []
  2. link dead at time of writing mod6 has fixed the link. []
  3. This was written by asciilifeform but I only have found phf's signature. There is a patch by phf to have asciilifeform's v.py use vtools. []
  4. Linking archived version until trinque recovers his blog. []

Differences Between English-Spanish Pronunciation Part 3 - Diphthongs

Sunday, October 13th, 2019

This is my notes from the information found on 123teachme. There they also list example words with sound files.

A diphthong1 is formed in Spanish when the unaccented vowel i or u proceeds or follows another vowel, or a y follows a vowel. Attaching an i adds a "y" sound, attaching u adds a "w" sound.2

No diphthong is formed during a combination of two of the following vowels: a, e, o.

  1. two vowels glided together and pronounced within the same syllable []
  2. The Spanish y is said, i believe, with putting the tip of your tongue towards the bottom of your mouth by the gum of your bottom teeth. This is in contrast to English where the tip stays neutral or even goes up towards the roof of the mouth when making the "y" sound. []

What I Find Worthy of My Time

Sunday, October 13th, 2019

whaack: asciilifeform: following from http://logs.nosuchlabs.com/log/ossasepia/2019-09-23#1003544 I am considering submitting to training under diana_coman, but before I pulled the trigger I thought I should stop here and ask if you feel it would be wiser for me to submit to training under you. Is this something you are interested in, and if so what would be required of me for you to take me?

asciilifeform: whaack: i can't answer this w/out knowing ~something~ about your interests1

whaack: asciilifeform: Okay, I think that itself deserves a blog post. The short answer is: programming ( have enjoyed going through SICP quite a bit, although its on hold, I want to learn how to program faster to eat through lots of saltmine work quickly), cryptography (i want to have trb "fit in head"), learning 2nd language (Spanish) , playing the guitar

And now for the long(er) answer. My six main interests are:

(1) Academic and TMSR Related - programming, cryptography,2 Spanish, and reading
(2) Non-Academic / Non-TMSR Related - guitar and surfing

For each of these I describe:

i) My relevant history.
ii) Why i want to pursue the interest.
iii) My related future goals.

I Programming

i) History

I first started programming when I was twelve-years-old. Since then I have done a number of personal projects, learned a few programming languages, got a bachelors at MIT, worked in the startup circus, and interned at various USG corps (including Goolag.) There is more detail I can go into with my programming history than my other interests, so I will save the expanded CV for another post.

ii) Why

I like the problem solving aspect of programming as well as the rewards of automation. It is incredible to be able to construct strings that can affect the physical universe.

Another reason I program is it is a way to whore out for cash. I sometimes enjoy programming for saltmines work, just like an actual whore might enjoy sleeping with some of her clients. But the goal is to get a large slice of the easy credit pie.

iii) Future Goals

I want to develop my programming ability in two different areas. One is improving my understanding of programming related topics by getting the CS education I should have received while at MIT. A good start for this would be: reading through the great books, completing the FFA series, and writing my own V. The other separate skill I want to develop is the ability to prostitute myself efficiently. I would like to learn how to make big bucks by quickly putting together websites/apps/what have you. This has to do with self-marketing and entrepreneurship as much as it does with programming.

II Cryptography

i) History

I first learned about the field of cryptography through reading a magazine called 2600. I read about RSA, but the math behind the algorithm was an enigma to me. I knew only that it had something to do with prime numbers and modular arithmetic.

Later in my discrete math course3 at MIT we went through the entirety of the algorithm. The same year I learned RSA in college, I got my first bitcoins. After successfully transacting with them, I figured that the blockchain4 was an important discovery5 and started investigating. Not too long after MtGox collapsed I learned about bitcoin-assets. I read How to airgap. A practical Guide. as well as a qntra post The Hard Fork Missle Crisis.6 It became clear that tmsr was the only place where anyone knew wtf they were talking about regarding bitcoin. Thus the logs became my source of information for everything related to cryptography.

ii) Why

One, cryptography gives the tools that allow a human to be an individual rather than a cell of neoplasm. I don’t want to be a helpless dependent to the person who programs the tools i use - be it gpg or my bitcoin wallet.

Two, bitcoin is what is important in our world. And true to the younghands.club slogan, I want to work on what matters, so I matter too.

iii) Future Goals

Much of my goals with cryptography are the same as my goals with programming. I would like to better understand the cryptography tools that I use by doing the relevant reading and writing my own versions of RSA, V, SHA256, and ECDSA. This knowledge would then be used to contribute to tmsr by being less of a liability while creating new tools.

III Spanish

i) History

I took Spanish from 6th grade of middle school up until junior year of high school. Throughout that time, I and most of my teachers did not intend for me to ever actually learn the language. Like most I would only plan to memorize a week’s worth of ~20 vocabulary cards and a new grammar rule for the week's test. I didn’t quite grok how in civilized society being monolingual stamps one as uneducated.

My quest to not be ESLtarded began in my last year at MIT. I signed up for a Spanish class with the intention of actually trying to learn the language. I started using Duolingo and went through all of their exercises multiple times. I lived in Tamarindo, Costa Rica for a year.

I set out goals for myself for learning Spanish, but I have been far from steadfast in completing them. Currently, I am reading Por Quien Doblan Las Campañas by Hemingway and adding words I don’t know to Anki.7 When I’m in routine mode I try to add 30 words a day, and review all my past words. I have made about 1,200 flashcards this way.

ii) Why

I began learning Spanish for the sake of being bilingual. I want to expand the capacity of my mind by allowing it to model situations in a language other than English. I also want to develop the discipline that is necessary to learn a second language.

Of course there is an appreciation of the social benefit of learning a second language. The apartment I am renting in Costa Rica would have been unavailable to me had I been unable to converse with the Spanish speaking owners. It costs about half the price I would pay for an equivalent apartment through a gringo facing website like airbnb.

iii) Future Goals

My study goals are laid out in my fixing my affliction of monoligiusm post. There I detail specific time commitments I would like to give each day to vocab, grammar, etc. I have fallen behind on those goals, but it may not be too late for me to repent and catch up. One major change that should occur from moving to my move to CR is having my mechanical vocab study become secondary to having real world interactions in Spanish.

After reaching an acceptable level of fluency in Spanish, I would like to learn a third language. I will most likely choose a language that uses a different alphabet, such as Japanese or Russian.

IV Reading

i) History

Growing up I read little more than Harry Potter and the books required for school. Like most dumb children in usaschwitz, I believed that skimming articles on the internet8 sufficed for reading. Luckily for me, I eventually stumbled upon trilema. I saw for myself the ability that a superior intellect could obtain from reading copious numbers of books.

I began to read somewhat regularly. I learned how slow a reader I was and how much trouble I had with concentration. My wpm reading was low and I usually could only go ~fifteen minutes without my mind wandering off. But I started to push through more and more books. I got a lot of pleasure through reading. It became easier, and a 200 page book turned into a one day rather than one week endeavor.

ii) Why

The rewards of reading are clear so I won't belabor the obvious but instead just mention the important points. Reading allows one to learn much faster than one can learn from a lecture in a classroom. In terms of raw data transfer, a speaker can only talk at roughly 100wpm while an average reader can digest a book at 400wpm. Reading lots of different material helps one fight against the 'you don't know what you don't know' problem. Going through a few books on an activity before doing it can, in just a few hours, give one the knowledge a previous expert spent their lifetime obtaining.

iii) Future Goals

I would like to read more and comprehend better through the following means. First, by keeping a list of books I have read and writing a summary for each one. The summary could include whether or not I believe that this book is worth rereading, and then if it is, a timeline for rereading the book. Second, by improving my system for choosing my next book. Lastly, by improving my reading technique. I still sound out the majority of words I read; perhaps killing that bad habit and building other ones could help me read more books.

V Guitar

i) History

I picked up the guitar in Costa Rica because my neighbor had one lying around. The guitar quickly began my preferred way to waste time. I've been playing now for about a year and a half, and for a decent amount of that time I was practicing for an hour daily. I have given two abysmal live performances during open mics in Tamarindo. I play fingerstyle on an acoustic guitar with an appreciation for all genres but a preference for classical and flamenco.

ii) Why

Playing the guitar gets me more out of my leisure time. It gives a road to travel down where I can always improve myself. It teaches myself self-discipline and muscle control. Performing in front of people gives me a way to train handling my nerves. And jamming with others is a great way to have fun and make friends.

iii) Future Goals

I would like to learn how to site read music, this is a skill that every other musician learns but is often neglected for the guitar. Other than that, my goal is to use the guitar as a device for training my ability to focus. So my goal for the guitar is simply to create a practice regiment and stick to it. I hope that as I improve my self discipline with the guitar my discipline will increase in other areas of life.

VI Surfing

i) History

I have been swimming in the ocean for as long as I can remember. My parents had a tiny beach house on Fire Island, a barrier island in New York off the coast of Long Island. I learned to body surf and boogied board there. For a short period I also surfed, although the waves mostly broke on the sand so this was not so feasible.

When I first arrived in Costa Rica, I had a lot of free time. I was in Tamarindo, where the economy is based around surf tourism. So I started surfing everyday and became amigos with arguably the best surfers in town. I spent a year enjoying the hedonism. I made new friends and girlfriends and traveled to spots all along the west coast of Costa Rica as well as to Peru and Nicaragua.

ii) Why

Surfing is one of the most enjoyable activities I've done in my life. The time between catching waves spaces dopamine kicks obtained from riding them into nice intervals. Surfing stays entertaining because every wave is a different experience. It also keeps me in great shape.

iii) Future Goals

My goals with surfing are more based around aspects of surfing to avoid. There is a dark side of surfing. It's an easy way to escape from problems in life. You have to do this important job X? Oh well the waves are calling, there's a swell and it may not be here again for months, btw why don't you smoke a joint before and after? The other problem with surfing is that the sun takes quite a toll on your skin. I visually aged during the year I spent surfing, and if I'm not careful I could wind up with skin cancer. Thus my aim with surfing is to use it as a meditative exercise that I do during sunrise or sunset.

*****

These are the main areas I enjoy and I'd like to develop myself in.9 The next step after this post is to evaluate the amount of time I should invest in my different interests and create concrete goals with timelines for them.

  1. I was surprised that while looking for a master to train under my interests were considered. There's ample writing in the republicsphere on how learning comes from being forced to do what's uncomfortable instead of from following your feelings. Why should an educator care about what their student is interested in? []
  2. I considered combining this category with programming. There is a lot of overlap between the two, since having control of your computer is a necessary requirement for doing work with crytography. I decided to keep them separate since there are aspects of programming separate from cryptography, and I didn't want to create an entire new category for those aspects. []
  3. taught by Albert Meyer []
  4. the blockchain. not blockchain technologees []
  5. Since at least high school I was dubious about the legitimacy of the USG’s financial system. I have always been shocked how heathens spend their lives chasing money without putting a drop of effort to learn about money itself. []
  6. Unavailable at the time of writing. []
  7. Anki is a flash card app that claims to have an optimal algorithm for spacing out cards you are learning to minimize the amount of time you need to memorize a large set []
  8. from USG spamsites, as I would later learn []
  9. Another one that I didn't mention is writing, which perhaps could be categorized with reading. []

Seoul, Korea

Saturday, October 12th, 2019

The airport in Seoul was inconvenient. We tried to buy train tickets to our place in Donggyo-Dong, but the machines only accepted cash in Won. We looked for a bank or a currency exchange booth, but they were all closed (it was ~10pm) So we were forced to take a cab.

koreanew-1

Our taxi drivers in Seoul varied in style. Some cab drivers were patient, always stopping before yellow lights and staying within the speed limit. But one cab driver that took us home from a club treated red lights as merely suggestions.

Seoul had more of a night life compared to Kyoto. There is a culture of beauty there based around plastic surgery and generous use of makeup. The popular look for Korean women is an application of makeup that creates snow white skin and red lips. Yes, the Koreans look photoshopped. But they embrace their superficial culture. They have a term in Korean, aegyo (애교), for when a person pretends to be cute.

I ate a lot of meat in Seoul. There are many restaurants where either you cook the food yourselves or it is cooked right in front of you. This one had an ugly tube that sucked up the heat and smoke from the grill.

koreanew-23

They have a horrible system here where tables have buttons you press to call the waiter. When you press them a loud beep sounds and your table number appears on a screen. The waiter, who always looks pissed off, comes over to take your order. They will not come to your table to refill water or for any other circumstance other than you having pressed the button.

You will be waiting for a while for your check if you forget to press this.
koreanew-9

We saw posters for this 17-year-old emo pop idol Billie Eilish everywhere.

koreanew-2

We wandered into what appeared to be a children’s toy store. They had multiple floors of weird shit with huge screens playing cartoon ads for the store.

koreanew-29

koreanew-30

koreanew-31

koreanew-32

The toystore had an "adult" section upstairs. Seeing as we were in a toy store, we figured this may be a mistranslation, but we went upstairs to investigate. We were prompted for our IDs when we reached the top floor.

Here we have standard equipment.

koreanew-28

And comfort for the lonely anime enthusiast.

koreanew-24

A helpful diagram.

koreanew-10

Later we indulged in the traditional Korean dish of ice cream waffles.

koreanew-33

koreanew-34

After stuffing ourselves with those waffles we went on a food tour throughout a street market where we met some German ladies and a sign interpreter1 from Minnesota.

We ate some live octopus. Chop sticks are difficult to use when your food is using its suckers to stick itself to the plate.

koreanew-25
Afterwards we went with the Germans to karaoke. We found an alcohol free teenager spot. Almost everything there was written in Korean and the person working desk spoke ~no English. But we managed to figure out how to rent a room for an hour. The room had two microphones and this hand held device that let you pick songs, change effects on the mic, etc. Everything on the device was written in Korean. We clicked around and eventually found the section with pop songs in English. Among others we found Bad Guy by Billie Eilish.

koreanew-19

The next day we journeyed to the Gyeongbokgung Palace.

koreanew-11
koreanew-12
koreanew-13
koreanew-14
koreanew-15
koreanew-16

Then to an old village with traditional architecture.

koreanew-26
koreanew-27

That night we went out drinking. Beware of the sweet soju. On our last day there I woke up at 2:30pm.2. We went on a tour of Gangnam.

Here is a bookstore. True to the superficial Korean culture, the books on the shelves are merely frames of books and not actual books.

koreanew-3

We walked by a pop up Kpop concert. No one but the performers were dancing. We also saw a monument to one of Youtube’s most watch videos.

koreanew-17

Only a few hundred meters away from the kpop concert was a tranquil Buddhist temple.
koreanew-4
koreanew-5
koreanew-6
koreanew-7
koreanew-8

We got a view of the Han river and the Lotte World Tower.

koreanew-18

They have a street with a monument to all the biggest kpop bands.

koreanew-20
koreanew-21

And one for Psy, Gangnam's king.

koreanew-22

Next up, Tokyo!

  1. I learned that different countries have different sign languages. And sign languages do not directly correspond to a spoken language, they're languages with their own grammar. []
  2. I normally wake up at 6am and have been waking up in Asia at around 7:30am. Thank you soju. []