Category Archives: technology

Behind the magic of the blockchain

This entry is part 2 of 2 in the series The magic of the blockchain

[Cross-posted at blog.chain.com.]

This is part two in a series. In part one, we learned that the big idea behind blockchains is this:

I don’t give you digital data as payment. I give the rest of the world a signed statement saying I paid you.

In this article we’ll take a closer look at just how this is done. That is, we’ll look at how:

  • I give the rest of the world
  • A signed statement
  • Saying I paid you

Let’s take these one at a time, in reverse order.

Step 3: …Saying I paid you

Suppose I want to pay you ten dollars on a blockchain. To “say” that I paid you, I have to construct a message called a transaction that combines information about what I’m paying with where I’m sending it.

what “ten dollars”
where “to you”

The ten dollars is called the input to the transaction. Where it’s going is called the output. Ultimately this message will be incorporated into a blockchain, which we learned last time is a ledger – a record of transactions – that is immutable, distributed, and cryptographically secure. More about this below.

Of course I have to have ten dollars before I can pay it to you. It has to come from somewhere. So the input needs to be some earlier transaction saying that someone paid me ten dollars.1 This means each transaction has to have some sort of unique name, or number, or other identifier, so later transactions can refer back to earlier ones.

transaction-id “unique identifier for this transaction”
input “unique identifier for some earlier ten-dollar transaction”
output “you”

What if the only earlier transaction I have is one where I received twelve dollars? Since I only want to send you ten, and since I have to use up all of the earlier transaction (for reasons that will become clear), my new transaction must send you your ten dollars and must also send me two dollars as change. This means that a transaction must be able to have multiple outputs.

transaction-id “unique identifier for this transaction”
input “unique identifier for some earlier $12 transaction”
output1 “$10 to you”
output2 “$2 to me”

Now that we’ve decided transactions can have multiple outputs, it’s necessary to say which output of an earlier transaction you’re using as the input.

transaction-id “unique identifier for this transaction”
input “unique identifier for output1 of some earlier $12 transaction”
output1 “$10 to you”
output2 “$2 to me”

And what if I don’t have a single $10 or $12 transaction to draw on, but I do have a $5 one and a $7 one? Let’s let transactions have multiple inputs as well as multiple outputs.

transaction-id “unique identifier for this transaction”
input1 “unique identifier for output1 of some earlier $5 transaction”
input2 “unique identifier for output1 of some earlier $7 transaction”
output1 “$10 to you”
output2 “$2 to me”

Let’s now focus on those unique transaction identifiers. How should they be chosen so that:

  • Distinct transactions have distinct identifiers, and
  • Anyone in the world can construct his or her own transaction, and
  • No one needs to coordinate with anyone else, or with any central authority, in order to construct a transaction?

The main problem is to prevent “collisions” – two different transactions having the same identifier. If you and I both construct a transaction at the same time, on opposite sides of the world, and don’t coordinate with each other or anyone else, what’s to stop us from accidentally choosing MYCOOLTRANSACTION17 as the identifier for both transactions?

Blockchains solve this problem using a technique called hashing. This is a process that transforms a message of any length, such as the transactions we’re constructing, into a single number of a predetermined size, called a hash. There are several different recipes for computing the hash of a message; they have names like MD5 and SHA1. But good hashing recipes all have the same goals:

  • Given a message, it must be easy to compute the hash (well, easy for a computer);
  • Given only the hash, it must be close to impossible to come up with a message that produces it (even for a computer!);
  • Two identical messages always produce the same hash;
  • Even a tiny difference between two messages must produce wildly different hashes.

The ease of going from message to hash, and the difficulty of going from hash to message, makes this a so-called one-way function, an idea that will be important a little later on.

Now, when squashing a long message down to a number of a predetermined size, it’s unavoidable that different messages will collide – i.e., produce the same hash. But if the predetermined size is big enough – 32 bytes, say – and if the recipe is very good at scattering hashes evenly throughout all 232×8 possible values (that’s 100 quadrillion-quadrillion-quadrillion-quadrillion-quadrillion, give or take a few quadrillion-quadrillion-quadrillion-quadrillion-quadrillions), then the odds of a collision are so low as to be effectively impossible.2

So when you and I construct our transactions, we don’t choose identifiers at all. Instead, we compute identifiers that are nothing more or less than a hash of each transaction’s contents.

input1
  • transaction hash of some earlier $5 transaction
  • output1
input2
  • transaction hash of some earlier $7 transaction
  • output1
output1 $10 to you
output2 $2 to me

When you are deciding whether to accept this transaction as payment for something, you can consult the complete history of transactions on the blockchain to make sure that the inputs of this transaction really do exist, and that they haven’t already been spent in some other transaction. Later on, when you want to spend this money you’re now receiving, someone else will look at this transaction to make sure you own it.

Using a transaction’s hash as its unique identifier also explains why one must consume all of a transaction’s output at the same time (as when, in an earlier example above, I had to consume a $12 transaction output and return $2 to myself as change). If I could consume only part of an old transaction, that would alter the amount available from that old transaction. Altering the transaction would change its hash, which cannot be allowed if hashes are permanent, unchanging unique identifiers for transactions. Once published on a blockchain, a transaction can never change, it can only be referenced by newer transactions.

Step 2: …A signed statement…

Remember that this transaction, like all others on a blockchain, is a message that’s going to everyone in the world. My earlier $5 and $7 transactions, the source of the funds I’m paying to you, are sitting out there on the blockchain for everyone to see, like all unspent transaction outputs, just waiting to be used. What prevents someone else from using them in a payment of their own?

This is where the “to you” and “to me” part of the transaction outputs come into play. I need to be able to write “to you” in such a way that no one but you can construct a new transaction claiming that $10.

This is done using so-called public-private keypairs. You choose a very (very, very) large random number and keep it secret. This is your “private key.” This number can be transformed with some fancy arithmetic into another number, the “public key,” that you publish for everyone to see. The fancy arithmetic is a one-way function akin to hashing, so no one with only your public key can figure out your private key.

Public-private keypairs have some amazing superpowers. One of them is that you can digitally sign a message so that everyone in the world can be sure it’s you signing it. You do this by combining your private key in a particular way with the message you’re signing (or, more typically, a hash of the message you’re signing). The resulting “signature” has some special properties:

  • It was created using another one-way function, so no one looking at just the signature can discover either your private key or the message you’ve signed;
  • There remains a mathematical relationship between the signature and your public key, so if someone has that and the message you signed, they can verify that the signature is genuine. Even without knowing your private key, they can be sure the signature was made from it, and from that particular message and no other. (So no one can take your valid signature from one transaction and stick it on another one in the hope that it’ll be valid there – it won’t.)

So to make sure that only you can access the $10 I’m paying you, I secure the output of my transaction by attaching your public key. I also secure the $2 in change that I’m paying to myself by attaching my public key.

input1
  • transaction hash of some earlier $5 transaction
  • output1
input2
  • transaction hash of some earlier $7 transaction
  • output1
output1
  • $10
  • to your public key
output2
  • $2
  • to my public key

In order to redeem one transaction’s output for use as the input to another transaction, the payee supplies a digital signature made from the new transaction’s hash and his or her private key. My transaction paying you $10 redeems $5 and $7 from two earlier transactions, which were paid to my public key, so I redeem them like so:

input1
  • transaction hash of some earlier $5 transaction
  • output1
  • signature made from this transaction’s hash and my private key
input2
  • transaction hash of some earlier $7 transaction
  • output1
  • signature made from this transaction’s hash and my private key
output1
  • $10
  • to your public key
output2
  • $2
  • to my public key

Anyone can look at this transaction and verify that my signature on the inputs matches the public key attached to the earlier transactions’ outputs. As long as I’ve kept my private key secret, no one else can produce a valid signature that matches both this transaction and my public key.

The balance of money that I own on the blockchain is simply the sum of all unspent transaction outputs that have my public key attached.

Step 1: I give the rest of the world…

These transactions must be distributed to be useful, meaning that everyone in the world has, or can get, the data they need to validate transactions.3 If I create a transaction sending you $10, in principle you’ll need the entire history of earlier transactions leading up to that one in order to validate it (i.e., to believe that you’re really receiving $10), including all the unrelated transactions in the system to ensure I haven’t spent that same $10 somewhere else. When you want to spend the $10 I send you, your payee will need the same thing.4

It’s easy to imagine a system in which each new transaction is broadcast to all blockchain participants that are somehow subscribed to new-transaction notices. But the reality of network delays means that different subscribers will receive these notices in different orders. (Transactions that originate closer on the network will arrive sooner, in general, than transactions that need more “hops” to get to you.) The system only works if everyone has a consistent view of the transaction history: if I see A, then B, and you see B, then A, we might disagree about the validity of C, and a distributed ledger (or any ledger, really) can’t work if there’s disagreement about a transaction’s validity. Here’s why: if I were dishonest,5 I might try to exploit network delays to spend the same $10 twice, to two different people, each of whom might believe (thanks to differences in ordering) that theirs is the valid $10 and the other is the invalid double-spend. No one would be willing to accept either person’s (purported) $10 as payment for anything, and confidence in the whole scheme goes out the window.

What’s needed is some authority that everyone can trust to put a stamp on the official correct ordering of transactions; and once the order is set, to publish the sequence for all to see. The published sequence could, in principle, consist of a list of individual, timestamped transactions, digitally signed by the timestamping authority; but if there are more than just a few transactions each second, the processing and communication overhead of this approach is prohibitive. For efficiency, it’s better to group transactions into blocks, certifying and publishing a block containing many transactions every so often, with each block linked to the block before it (by including the earlier block’s unchangeable hash, in the same way transactions refer to other transactions by their hashes) in an ever-lengthening blockchain.

Whom to trust for generating blocks in the chain? That depends on how a particular blockchain is going to be used. If it’s for managing an anti-authoritarian global cryptocurrency, the answer is “no one.” If it’s for managing the loyalty-reward points of a national coffee-shop chain, the answer is probably the corporate parent of the coffee shops. Other use cases require in-between levels of trust.

There are techniques for concentrating trust or spreading it around to match different use cases. The just-trust-headquarters case is easy, of course: everyone sends their proposed transactions there, and listens for the blocks that occasionally emerge, confirming their transactions. The trust-no-one case has everyone broadcasting their proposed transactions to as many others as they can, and everyone racing to collect them up and be the one that produces the next valid block in exchange for some small reward (a process called “mining,” designed so no one person or group can control the contents of the blockchain). The in-between case of trusting a group of independent authorities can require that, if one of that group proposes a block, all or a majority of the others must endorse it by adding their digital signatures.

In most cases, the simple existence of a transaction in a block of the blockchain is the transfer of money: final and authoritative, with no further steps required before the recipient can spend what they’ve just received – by adding a transaction of their own.

Sounds great but

Transferring money (or other kinds of value) on a blockchain is as fast and easy as handing someone cash – easier, since you don’t have to be in the same place to do it.

But cash isn’t the right answer for every type of transaction. Sometimes you need a delay, and sometimes you need to cancel or reclaim your payment. And what about this everyone-can-see-every-transaction business? Do you really want to give everyone in the world the ability to look at your whole purchase history?6

There are ways to preserve privacy on a blockchain, as well as ways to delay payment until a certain time elapses or other conditions are met, and even ways to eliminate “counterparty risk” (the risk that you pay for something and then don’t get what you paid for), but I’ve gone on long enough for now and discussion of those will have to wait until part three.

[My thanks to my Chain colleagues Adam Ludwin, Nadia Ali, and Zarya Faraj for their input on early drafts of this article.]
  1. And that transaction had to have a source too, and so on, and so on. Where do the dollars on a blockchain ultimately come from? It’s a good question with a complicated answer that we won’t get to in this article. The short version is that participants can “buy in” to a blockchain in the same way one converts dollars to chips in order to play at a casino (among other options). []
  2. Many newcomers to hashing worry about the difference between “effectively impossible” and “actually impossible” and waste a lot of energy in a vain attempt to eliminate even the tiny remaining possibility of a hash collision. But that’s only because our ape brains are bad at understanding really, really, really tiny possibilities. When it’s likelier that your blockchain system will be disrupted by simultaneous drunken-rhinoceros stampedes at multiple datacenters than by even one hash collision, your efforts are better directed elsewhere (like putting up rhino fencing). []
  3. Who is “everyone in the world”? It would be more accurate to say “everyone participating in a particular blockchain.” A blockchain managing consumer dollars, as in the examples in this article, would necessarily be global, and “everyone in the world” would literally mean everyone in the world. Other blockchains managing other kinds of asset might confine participants to particular companies’ customers, or particular traders, investors, or institutions. []
  4. If you’re thinking that’s a tremendous data requirement, you’re not wrong. In a future article we’ll discuss clever ways to mitigate this and even make it fast. []
  5. I’m not. But if I were, that’s just what I would say. []
  6. Millennials: this is a rhetorical question. The answer is “no.” []

The magic of the blockchain

This entry is part 1 of 2 in the series The magic of the blockchain

[Cross-posted at blog.chain.com.]

You may have heard that the world of finance is getting excited about the potential of the blockchain (Economist, Financial Times, Forbes) and wondered:

What is the blockchain? What problem does it solve?

The blockchain is the technology behind the digital currency Bitcoin, but it has wider applicability. It is a collection of mathematical, recordkeeping, and communication procedures that makes it possible to trade digital assets securely.

Why is that a big deal?

Think of how useful it has been to digitize all kinds of information over the past generation or two.1 Digital information can be transmitted from place to place at lightning speed (literally), stored indefinitely, duplicated endlessly, and analyzed, processed, and transformed automatically, all without any loss of fidelity. This was all flatly impossible until quite recently. When it became possible, it didn’t just make things faster and more efficient. It enabled the creation of entirely new ways to produce and consume information that never existed before, and new industries built on top of them. Think Twitter, YouTube, Uber.

But money hasn’t been digitized – and has therefore been left out of all the dramatic innovation that has happened elsewhere in the economy – because digital information can be duplicated endlessly, which is at odds with the key feature of money: namely, that once you trade it away, you no longer have it. Think about it: without that feature, money would be useless.

If you have something valuable to sell, and I want to pay you with some digital data that I call “money,” what’s to stop me from keeping a copy of that data and then spending it again with someone else?

The blockchain, that’s what.

That’s impossible

You may now be thinking, “There’s no way to prevent the copying of digital data,” and you’d be right. Even so-called copy-protected data, such as a movie on DVD, doesn’t work on the principle of actually preventing copying. (It works by scrambling the data and refusing to descramble it unless the playback conditions are kosher. You can copy the scrambled data as many times as you like.)

And yet the blockchain does manage to prevent “double-spending.” You might now expect to hear an explanation of how it does so in terms of prime numbers, one-way functions, asymmetric encryption, and other arcana. But those are merely the implementation details, which we’ll save for another article. The main idea is this:

I don’t give you digital data as payment. I give the rest of the world a signed statement saying I paid you.

This is a fundamental and surprising insight into the nature of money: the token of exchange doesn’t matter as much as that everyone agrees an exchange took place. When everyone agrees on that, then I can’t double-spend that token, even if I’ve made a copy of it, because whoever I try to spend it with will know that token is no longer mine to spend. And they’ll know that you can spend it… and you’ll know that they know it.

The money at the bottom of the sea

Here it’s worth taking a little digression into the story of the Yapese and their Rai stones.

The Yapese live on Yap, an island in Micronesia in the South Pacific. You may have heard of the giant stone discs that they use as a traditional form of money. Hewn out of limestone rocks on Palau, some 200 miles away, and standing on edge, they tower over their owners, who sometimes have to stand on tiptoe just to peer through the holes drilled in their centers.

These coins weigh thousands of pounds each. They can’t be kept in a coin purse or even stored indoors, so they are propped up for display in public places. When it is time to spend one, the coin never moves – that would be too difficult, and might damage the coin (or the mover!). Instead, news of the transfer filters out to the Yapese, who maintain an oral history of the ownership of each coin. This shared “ledger” of trades ensures that only the current owner of a coin can spend it, no matter where it’s physically situated.

In fact, a rai stone being transported from Palau to Yap by outrigger canoe once famously sank to the bottom of the sea in a storm. When the sailors got home without their cargo, the Yapese did not doubt the fact of its existence, and since its location didn’t matter, they proceeded to trade it just like their other giant coins.

Imagine that an earthquake strikes the island of Yap. No one is hurt, fortunately, but all the stone discs are dislodged and they all roll downhill into the sea. No problem – the rai economy could still continue! Now imagine that, instead of an earthquake, collective amnesia strikes the Yapese. No one can remember who owns what! In that case the rai economy is destroyed and actual economic value is irretrievably lost. This illustrates that, in a very real sense, the record of trades is the money.

That kinda makes sense

Right?

Think about depositing money in the bank. You go to the bank and hand the teller some cash. Does the teller put the cash in a box with your name on it? No. Some of it goes into a vault, mixed with everyone else’s money. Some of it is put to work in the form of loans. In what sense is your money still in the bank? In the sense that the bank maintains a record of what it owes you if you ever come asking for it.

(To keep the bank honest, you also maintain your own records – deposit receipts, a checkbook register, etc. Occasionally your records and the bank’s may disagree. We’ll come back to this idea.)

Don’t we already have secure digital asset trading?

In a word, no.

The problem is that there are multiple recordkeeping systems that have to be reconciled with one another. When you swipe your debit card at a gas station (say), you initiate a series of steps in which you, your bank, the gas station, the gas station’s bank, and the card-processing network all have to make updates to their records. For efficiency, those updates are usually batched together with others, and they happen at different times for different participants in this transaction. The updates get transmitted between and among the participants, and those transmissions produce acknowledgements that also get transmitted. Each party has to incorporate the others’ details into its own recordkeeping, and if everything doesn’t agree, there may need to be some sort of dispute-resolution step, unless the cumulative error is small enough that it’s not worth it and someone just eats the loss.

All of this transaction clearing and settlement is comparatively slow and expensive and happens long after you drive away from the pump. The gas station has some “counterparty risk”: it has let you have its gasoline without being sure that it will get your money. (But that risk is small compared to the value of letting customers pay this way, which is why the gas station accepts it.)

This is all because no one involved – not you, not the banks, not the gas station or the card network – can be quite sure at any given moment where the money is,2 only that if they follow these procedures, it usually ends up in the right place. Each entity therefore does its own recordkeeping as a check and balance on the others – just the same way that you keep all your deposit receipts (you do, don’t you?) in case your bank ever shows the wrong balance on your account.

How does the blockchain help?

The blockchain is a ledger that is immutable, distributed, and cryptographically secure.

  • Ledger means that it’s a historical record of trades;
  • Immutable means that once a trade is added to the ledger, it is permanent and unchangeable;
  • Distributed means that everyone gets a copy of it (and keeps getting updates as they happen); and
  • Cryptographically secure means that that everyone can trust what’s in it.

If the parties in the gas-station example were all on the blockchain, what would be the steps by which the gas station gets paid?

  1. You add a transaction to the blockchain stating that some funds that you control (because in an earlier transaction, someone else transferred them to you) now belong to the gas station.

That’s all! When you commit to the idea that the record of trades is the money, there is no separate clearing or settlement step needed. The trade is its own settlement. As soon as you add that transaction to the blockchain, you lose control over those funds and the gas station gets control over them. The gas station can now add its own transaction to the blockchain transferring those funds to someone else – and you can’t.3

Would you like to know more?

In the original Bitcoin blockchain, there is one type of asset – bitcoin – and a predefined way in which new bitcoins can be “minted.” It is possible to generalize the idea of the blockchain, however, so that it can encompass many different kinds of asset (dollars, airline miles, corporate securities, loyalty reward points) with differing rules for issuing units of those assets onto the network. The next article in this series will take a closer look at the mechanisms behind the blockchain (including explaining why it’s called a “blockchain”) and describe some reasons and ways to alter the Bitcoin blockchain to make it suitable for other uses.

  1. I like to think of that scene in All The President’s Men when Woodward and Bernstein have to thumb through thousands of Library of Congress call slips one by one by one, hour after hour after hour. Today a few tap-tap-taps at a computer terminal are all that’s needed. []
  2. To say nothing of what the money is – which, as we’ve seen, is the record of who has paid what to whom. In this example (and in the economy at large) that record is a kaleidoscopic agglomeration of many differing and overlapping records, some of which lag behind others, some of which will never agree. It’s no wonder people are confused about money. []
  3. Of course it isn’t quite that simple. To achieve the cryptographic security that allows everyone to trust the contents of the blockchain, it takes a little time for the transaction to propagate across the network and for other participants on the network to certify it. []

Remembering the past no guarantee of not repeating it

In February of 1992, Apple Computer flew me from Pittsburgh to California and put me up at the Cupertino Inn for a series of job interviews over a couple of days. I extended my stay in order to visit a few other companies too.

One of the companies on my list was a tiny e-mail startup in San Rafael called Z-Code. I was planning to visit them in the afternoon after spending the morning at a prominent computer magazine, interviewing for an editorial position. That visit went very well, and so had the interviews at Apple; and having driven from Cupertino to San Francisco for that interview, I now had a sense for how long the return drive would be, and how much farther out of the way a visit to Z-Code would take me.

If I hadn’t been such a Star Wars nerd I might have skipped it altogether. But I knew that Skywalker Ranch and Industrial Light and Magic were in San Rafael somewhere and I harbored a secret hope of spotting them as I navigated to my Z-Code visit. I visited Z-Code and, to my surprise, found that opportunity more compelling than the ones at Apple and at the magazine. Two months later I was living in California and working at Z-Code and the rest is history.

Now, almost a quarter century later, I’ve had a very similar experience. I interviewed successfully at a number of well-known medium-to-large-sized companies over the past several weeks but found a tiny startup – that I had almost dismissed, at first, as not worth my time – to be the most compelling. Tomorrow I begin at Chain.com.

Kill Ralphie! saved!

[Cross-posted at kill-ralphie.blogspot.com/2015/06/kill-ralphie-saved.html.]

In the 1980’s, students and faculty at Carnegie Mellon University were on the Internet, but there was no World Wide Web yet – no browsers, no websites, no Google, Facebook, or YouTube; in fact, no video and almost no graphics, just text. But there still existed social communities online, organized into discussion forums on numerous topics. Usenet was the biggest of these. Carnegie Mellon had its own internal collection of discussion forums called bboards.

One bboard was called “Kill Ralphie!” When someone posted to Kill Ralphie, they were contributing a chapter to an ongoing story about a hapless lad who is alternately placed in immediate mortal danger, then rescued, both in the most creative and entertaining ways possible. I was an enthusiastic participant back then, along with many others at CMU. Writing for an audience of fellow contributors was a formative experience for me that improved my prose and humor skills from “immature” to “slightly less immature.”

Well, guess what? Kill Ralphie! lives again! I’ve taken that old pastime and turned it into a fun new website. Please check it out, contribute chapters, and enjoy: kill-ralphie.com.

When you click a YouTube link

Earlier today I gave a presentation about YouTube to seventh graders for “career day” at Jonah’s middle school. (Actually I gave it six times in a row to rotating classroomsful of kids, with the result that (a) I’m totally shredded and (b) I have even more respect for what teachers do all day every day.) Coincidentally it’s the tenth anniversary of the first YouTube video.

I thought fifth grade would be my last chance to appear cool to Jonah’s classmates on his behalf (and I’ve now given that presentation to Archer’s class too), but it looks like I have some coolness left after all. He even allowed me to walk to school with him and his neighborhood friends this morning:

Me: OK if I walk to school with you in the morning?
Jonah, shrugging: Sure.
Me: OK. Just wanted to make sure I wasn’t cramping your style or anything.
Jonah: What style?

Maybe YouTube lends me a little extra middle-school cred. Anyway, the presentation was well-received by most of the kids. It involved soliciting sixteen volunteers per class to read different parts aloud in a short little play I wrote. Each volunteer got a copy of the script with his or her part individually highlighted (which I did by hand earlier this week for all ninety-six copies I needed to hand out – eight pages each – and this in the middle of April, because I’m a glutton for punishment). I was a little worried about getting enough volunteers in each class, but I need not have been; the kids were down with whatever the YouTube guy wanted to do. I gave out my bribes anyway: YouTube stickers and pens.

I was the narrator. Everyone in the class who didn’t volunteer for one of the other parts became “All the buttons and menus.” After we performed the scene, the teacher displayed a web page I had prepared containing a YouTube link and we watched – hopefully with a little better understanding now of what was going on behind the scenes – as she clicked it and Dramatic Chipmunk played. It took a split second to perform all the actions we’d just spent eight minutes dramatizing.

We didn’t get to the song I included at the end of the script. I didn’t expect to but included it anyway as a little lagniappe for the kids. I hope some of them are singing it now; I know I am.

After the sixth presentation, I thanked the teacher for hosting me. She complimented me on the scene I had written. “Thanks,” I said, “but after six repetitions the words have lost all meaning.” She replied, “Welcome to the world of teaching.”

We’re not fledgling

THIS ASSET PURCHASE AGREEMENT (this “Agreement”) is made and entered into as of and shall take effect on March 1, 2015 (the “Closing Date”), by and among [company that may not wish to be named quite yet], a California corporation (“Buyer”), ZANSHIN, a California corporation (“Seller”), and Seller’s principal shareholders, BARTON SCHAEFER, STEVE WEBSTER, GREGORY FOX, and ROBERT GLICKSTEIN (collectively the “Majority Shareholders”).

Thus ends, for all intents and purposes, the story of Zanshin, the company that my friends and I started in 1996 after resigning en masse from Z-Code. It will continue to exist in name and in certain administrative functions, but [unnamed company] is buying substantially all its assets and hiring away most of its employees.

Z-Code was the producer of an award-winning cross-platform e-mail client, Z-Mail. In 1994 Z-Code’s owner Dan Heller sold the company to Network Computing Devices (NCD), a hardware company. Much of Z-Code’s staff was baffled by the sale and considered it ill-advised. Indeed there followed a corporate comedy of errors as first Dan was let go and then NCD’s top leaders, Judy Estrin and Bill Carrico, were fired. As we’d predicted, NCD’s sales staff had no idea how to sell software. As the World Wide Web started gaining traction, we were alarmed when NCD’s clueless new CEO, Ed Marinaro, tried to repurpose Z-Code’s staff of e-mail software experts as developers of a new Windows-only web browser called Mariner. Meanwhile, we were denied opportunities to make badly needed improvements to Z-Mail, and finally, after a number of grassroots efforts to turn things around had failed, a bunch of us gave up and quit to start our own e-mail software company.

After considering and rejecting several names we settled on Zanshin, a Japanese word meaning some badass combination of “emotional intensity” and “follow-through.” We discovered it in this passage in Neal Stephenson’s novel Snow Crash, describing a swordfight between avatars in the high-resolution virtual reality called the “Metaverse”:

The businessman reaches across his body with his right hand, grips the handle of his sword just below the guard, draws it out, snaps it forward so it’s pointing at Hiro, then places his left hand on the grip just below the right. […]

The businessman turns out to have a lot of zanshin. Translating this concept into English is like translating “fuckface” into Nipponese, but it might translate into “emotional intensity” in football lingo. He charges directly at Hiro, hollering at the top of his lungs. […]

“Emotional intensity” doesn’t convey the half of it, of course. It is the kind of coarse and disappointing translation that makes the dismembered bodies of samurai warriors spin in their graves. The word “zanshin” is larded down with a lot of other folderol that you have to be Nipponese to understand.

And Hiro thinks, frankly, that most of it is pseudomystical crap, on the same level as his old high school football coach exhorting his men to play at 110 percent.

We incorporated with our own money (proceeds from selling NCD stock) and the help of a fancy Sand Hill Road lawyer. We rented a house in Petaluma where some of us lived and all of us worked on bringing to life our vision of a beautiful and functional e-mail manager built on the theory that, done right, e-mail could serve as the repository for all one’s private information and communications. In hindsight our plan was not sufficiently well-defined, and neither was our project development timeline. More than two years passed of writing code together every day, grappling with the early web and our ever-problematic dialup Internet access, pushing the boundaries of the IMAP e-mail protocol and the fledgling GNU C++ compiler, and taking turns cooking for one another, watching The Simpsons together, and generally not operating with an adequate sense of purpose or urgency. By the time our e-mail client, code-named Lawndart, finally began sparking to life, the entire e-mail landscape had changed beneath our feet. Free clients like Outlook Express and Eudora had become ubiquitous and were good enough for most people, and free web-based mail from Microsoft and Yahoo was starting to take off. Even if we had gotten Lawndart to market, no one would have cared.

The only software we ever released was a Lisp-like text-markup language called Latte (“Language for Transforming Text”) and its followup, Blatte (“Better Language for Transforming Text”), which we open-sourced and gave away as a kind of corporate calling card. Somehow or other this led to Zanshin getting an extended consulting gig with Amazon.com, for which a couple of us ended up traveling back and forth to Seattle a lot. Things I remember from that time:

  • Checking in and out and in and out of the Residence Inn on Lake Union week after week;
  • The offices in which we did our work, and several of the people we worked with;
  • Various meetings and meals;
  • Keeping in touch with my new wife via the late-90’s-vintage phone I carried on a belt clip;
  • Being extra fastidious about tracking my time, reporting my progress, and keeping expenses down

but I’m damned if I can remember the nature of any actual work we did for them. Nevertheless, the gig went so well that Amazon offered to relocate us all to Seattle and hire us. Andrea flew up to Seattle to get the vibe of the place. Together we decided it was definitely doable.

Back in California we had a few long talks about Zanshin’s prospects and how we all felt about packing it in and moving to Seattle. Some of us were in favor, some were opposed and felt that Zanshin had some life left in it. We recognized that our dream of a high-tech e-mail client was dead; but in those long-overdue discussions we started to conceive of some exciting new ideas for the server side of e-mail and, in the end, convinced ourselves to stick it out as a software startup. We turned Amazon down.

We began describing to ourselves, and then to some business consultants, a collection of server-side e-mail features that collectively we called “MSpace.” Zanshin moved out of rented houses and into actual offices, and we took a little extra investment to keep us going (including from the notorious Gary Kremen, owner of the sex.com domain).

One way and another, our plans for MSpace took a detour into the realm of e-mail marketing — spamming, essentially, but ethical spamming as we were always quick to point out, for reputable marketers only, never sharing e-mail lists, and always providing no-hassle opt-out. I wrote a high-performance e-mail delivery engine and the aforementioned Blatte language for creating dynamic customizable templates, and Zanshin, operating its e-mail marketing service under the name iPost, finally started earning money.

This whole time I had been moonlighting as a founding member of the Internet Movie Database. In 1998 Amazon.com bought the IMDb (a coincidence not related to Zanshin’s consulting gig) and early in 2001 they asked me to join full-time. Five years of earning first no salary and later only a token amount had taken its toll, particularly since Andrea and I were planning to start a family; and the e-mail marketing business, though it was taking off, failed to move me. After consulting with my partners we agreed that I’d wrap up work on iPost’s delivery engine and then be done.

However, Andrea had joined Zanshin a couple of years earlier herself and she remained even as I went on to work full-time for the IMDb, and later for other companies. The e-mail marketing business amassed a surprisingly healthy client list and collected enough revenue to pay competitive salaries to a growing staff of developers and salespeople. I returned for a couple of short contract gigs from time to time. But as the years passed, the margins got slimmer and slimmer and the industry consolidated behind a few ever-larger players. Two of the other original founders had also left. New-product ideas always came second to dealing with never-ending customer issues. There was still momentum in the business, but it was unclear for how much longer. The time for a change had come, and I am grateful to Andrea and my Zanshin partners for making it happen.


Postscript. The title of this post comes from an episode at Z-Code. When a magazine, in its review of our product, Z-Mail, called our company a fledgling startup, we bristled, having by then grown quite a bit and able to count companies like Chevron and Silicon Graphics among our business partners. I undertook to make a sign for the office reading, “Z-Code Software: We’re Not Fledgling,” and it became a frequently heard catchphrase.

A little of Andy lives on in me

In 1978, it was rare ever to encounter a computer, much less someone who had one at home. The “personal computer revolution” was only about a year old, with Apple, Commodore, and Radio Shack all introducing their first consumer models in 1977.

Of the people who did have computers at home, surely only a small fraction were so generous with them as to allow their sons’ twelve-year-old friends to spend afterschool hour after hour, day after day, month after month sitting at them, tapping in and trying out dumb little programs; and an even smaller fraction were also seasoned programming experts with the desire, ability, and patience to impart some of that expertise to receptive but very green ears.

This weekend I, one of those twelve-year-old friends in 1978, mourn the passing of Andy Kane, one of those generous and patient computer owners. Andy was one of the many reasons I was lucky to befriend his son Chuck in the seventh grade. He was a living example of the ability to make a career out of writing software and he contributed significantly to nurturing the then-embryonic skills that today support me and my family. My condolences to his; I will always be grateful.

Counting the bits at YouTube

Jonah is nearly done with fifth grade. In the fall he begins middle school. For years I’ve known that if I’m ever going to visit his classroom for a “what my dad does at work” presentation, it would have to be before middle school, which is when the coolness of “what my dad does at work” presentations falls off a cliff.

I made it just under the wire. For a long time all I had were good intentions and a half-started slide deck, work on which always took a backseat to this and that. Finally, a few weeks ago I gave his classroom the presentation below.

It was a hit. YouTube has a lot of cachet with 10-year-olds. It helped that I made some of the presentation interactive; there was a novelty factor to having the class work out some simple but enormous numbers. They stayed engaged for the full forty-five minutes, volunteering answers, laughing in the right places, and asking smart questions.

At the end I distributed light-up YouTube yo-yos to everyone, which was an even bigger hit. Hopefully it cemented Jonah’s reputation as the coolest kid to know. But his classmates were into the talk even before they knew there was swag coming.

I invite you to reuse or repurpose the slides below. I plan to give the talk again in two years when Archer is in fifth grade, so any constructive feedback that I can incorporate before then would be welcome.

How (and why) to program, part 2

This entry is part 2 of 2 in the series How (and why) to program

It’s National Computer Science Education Week! That must mean it’s time for part 2 of my How (And Why) To Program series. Today I will discuss a tricky but powerful concept in computer science: recursion.

Briefly, recursion means accomplishing a task by performing it in terms of smaller versions of the same task. For example, each morning I execute my “drive to work” routine, which is really my “drive from point A to point B” routine, where point A is home and point B is work. To do that, I first do “drive from point A to point B” where point A is home and point B is the Golden Gate Bridge (which is about halfway to work for me), followed by “drive from point A to point B” where point A is now the Golden Gate Bridge and point B is work. Each of those steps, of course, can be decomposed into smaller “drive from point A to point B” tasks.

One classic example for illustrating recursion in computer code is the Fibonacci sequence — the mathematical sequence in which each number is the sum of the two before it. You might already see the weakness in that definition: what can the first and second numbers in the sequence be, if they don’t have two numbers before them that can be added together? This is a key feature of recursive functions: at some point they reduce the problem into parts so small that they reach the “base case,” where the recursive rule breaks down. It happens that the base case of the Fibonacci sequence says the first two numbers are 0 and 1. From there, the recursive rule takes over to give the numbers that follow: 1, 2, 3, 5, 8, 13, 21, 34, and so on.

Let’s look at a “function,” which is the computer programming equivalent of a recipe: you give it some inputs, and it gives you an output, the result of processing the inputs in specific ways. Our function is called fibonacci and it takes one input, or “argument”: a number, which we’ll call n. The result of fibonacci(n) will be the nth number in the Fibonacci sequence, where the first two numbers — fibonacci(0) and fibonacci(1) (recall that in programming, lists and sequences of things are almost always numbered beginning at zero) — are 0 and 1.

As before, code samples are presented in the Python programming language, though the same concepts we’re discussing apply to most other programming languages too.

def fibonacci(n):
  if n == 0 or n == 1:
    return n
  else:
    return fibonacci(n-1) + fibonacci(n-2)

We start with “def fibonacci(n),” which simply means “define a function named fibonacci taking one argument called n.” The body of the function follows. First it checks for the base case: does the caller (whoever is invoking this function) want one of the first two Fibonacci numbers? If so, the function simply “returns” (or hands back to the caller) the value of n, since by coincidence the value of fibonacci(n) is n when n is 0 or 1.

If it’s not the base case, the function returns a different value: the sum of invoking fibonacci first on n-1 and then on n-2. Those recursive calls give the two prior Fibonacci numbers. For instance, if we invoke fibonacci(9), then n is 9 and fibonacci(n-1) is fibonacci(8), which is 21; and fibonacci(n-2) is fibonacci(7), which is 13. Adding those together gives 34, which is the correct result for fibonacci(9).

Enough about the Fibonacci sequence. It’s a contrived example and, though it explains recursion pretty well, it doesn’t demonstrate the real-world applicability of the technique. (It also happens that, for reasons I won’t go into here, recursion is a terribly inefficient way to compute Fibonacci numbers compared to other possibilities like iteration.)

A few days ago, my Mensa Puzzle-a-Day Calendar presented this riddle:

The letters of a certain three-letter word can be added in sequential order (though not necessarily with all three letters together in the same place) to each of the letter strings below to form common, uncapitalized English words. You don’t need to rearrange any of the letters below. Simply add the three needed letters in sequential order. What is the three-letter word, and what are the nine new words formed?

1. alp 2. wl 3. marit 4. ealus 5. urneman 6. cke 7. disintedl 8. traectr 9. epard

(To illustrate the puzzle: the letters of what three-letter word can be inserted in both “hoyde” and “ckear” to produce common English words? The answer is “new,” to produce “honeydew” and “neckwear.”)

Staring at the puzzle for a while, I was unable to solve it. So I sat down and wrote a program to solve it for me. How’s that for real-world applicability?

Once again I relied on the file /usr/share/dict/words (or sometimes /usr/dict/words, or /usr/lib/dict/words) that is a standard feature of some operating systems; it’s simply a list of many common English words (and many uncommon ones, plus some frankly questionable ones), one per line. Reading that file, I produced two sets of words: one set of all the words, and one set of all three-letter words. Here’s how that looks:

three_letter_words = set()
all_words = set()
wordlist = open('/usr/share/dict/words')
for word in wordlist:
  word = word[:-1]
  all_words.add(word)
  if len(word) == 3:
    three_letter_words.add(word)
wordlist.close()

(Very similar code is explained in detail in part 1 of this series.)

With those two word sets in hand, and the nine letter-strings from the puzzle, this was my strategy: try all possible ways of inserting the letters of all the three-letter words in each of the letter-strings. For any three-letter word, if none of its combinations with a given letter-string produces a valid word, remove the three-letter word from further consideration. In other words, beginning with all possible three-letter words, we whittle them away as they become disqualified. In the end, the only three-letter words left should be ones that combine, one way or another, with all of the nine letter-strings to produce valid words.

So, for example, the three-letter words “see” and “era” both can be added to the letter-string “alp” to produce valid words (“asleep” and “earlap”). But the three-letter word “new” can’t be, so after running through all the three-letter words on the letter-string “alp,” “see” and “era” will still be in the set three_letter_words, but “new” won’t be.

Here’s how that strategy looks:

for string in ("alp", "wl", "marit", "ealus",
               "urneman", "cke", "disintedl",
               "traectr", "epard"):

This starts a loop that will run nine times, once for each letter-string, giving each letter-string the name “string” on its turn through the body of the loop.

  three_letter_words_to_discard = list()

This creates an empty list called three_letter_words_to_discard. It’s empty now but as we progress we will fill it with words to remove from the three_letter_words set.

(If you’re wondering why I sometimes use lists for collections of things, and sometimes use sets, gold star! The answer is that they are two different kinds of data structure, each one good at some things and bad at others. A set is very fast at telling you whether a certain item is in it or not; a list is slow at that. On the other hand, a list keeps things in the same order in which you added them; a set doesn’t do that at all.)

  for three_letter_word in three_letter_words:

This starts a nested loop. It’ll run through the complete list of three_letter_words each of the nine times that the outer loop runs.

    combinations = combine(three_letter_word, string)

Here we presume there’s a function called combine that takes the current three-letter word and the current letter string, and produces the complete list of ways that the letters of three_letter_word can be interspersed with the letters of string. For example, combine(“abc”, “def”) should produce the list [“abcdef”, “abdcef”, “abdecf”, “abdefc”, “adbcef”, “adbecf”, “adbefc”, “adebcf”, “adebfc”, “adefbc”, “dabcef”, “dabecf”, “dabefc”, “daebcf”, “daebfc”, “daefbc”, “deabcf”, “deabfc”, “deafbc”, “defabc”]. That’s where recursion is going to come into play. We’ll get to writing the combine function in a moment.

    good_combinations = list()
    for combination in combinations:
      if combination in all_words:
        good_combinations.append(combination)

With the list of combinations in hand, we now look through them to see which of them are valid words, if any. We set good_combinations to be a new empty list where we’ll accumulate the valid words we find. We loop through the combinations, testing each one to see if it’s a member of the set all_words. If one is, we add it to the list good_combinations.

    if good_combinations:
      print three_letter_word, "+", string, "=", good_combinations
    else:
      three_letter_words_to_discard.append(three_letter_word)

After the “for combination in combinations” loop, we check to see whether good_combinations has anything in it. (“If good_combinations” is true if the list has something in it, and false otherwise.) If it does, we print out the current three-letter word, the current letter-string, and the list of valid words they make. If it doesn’t, then three_letter_word goes into our list of three-letter words to discard.

  for word in three_letter_words_to_discard:
    three_letter_words.remove(word)

After the “for three_letter_word in three_letter_words” loop, this small loop does the discarding of disqualified three-letter words.

Why not simply discard those words from three_letter_words in the preceding loop, as we run across them? Why save them up to remove them later? The answer is that when you’re looping through the contents of a data structure, it’s a bad idea to add to or remove from the data structure. The loop can get confused and lose its place in the structure. It may end up running twice with the same list member, or skip a member entirely. It’s safe to make changes to the membership of the data structure only after the loop finishes.

Finally, after the outermost loop has finished, it’s time to see which three-letter words remain in our set:

print three_letter_words

And that’s all! All except the tricky part: the combine function. Here is how it starts:

def combine(string1, string2):

It takes two strings. We’ll give them generic names, string1 and string2, so as not to assume that either one is a three-letter word. As you’ll see, often neither one is.

Now, how to approach writing a recursive function? It’s usually a safe bet to start with the base case, the conditions under which combine isn’t recursive. The recursive step will involve passing shorter and shorter strings to combine, so the base case is when one or both of the strings is empty. Obviously if either string is empty, the result should be the other string — or more precisely, the list containing the other string as its one member (since we’ve already stipulated that the result of combine is a list of strings). In other words, combine(“”, “def”) should produce the list [“def”] — which after all is the result of interspersing the letters of “” among the letters of “def” — and combine(“abc”, “”) should produce [“abc”].

So here’s the body of combine so far. It’s just the base case:

  if len(string1) == 0:
    return [string2]
  elif len(string2) == 0:
    return [string1]

(Recall that “elif” is Python’s abbreviation for “else if.”)

Now for the case where string1 and string2 are both non-empty; the recursive case. The key to writing the recursive step of a function like this is figuring out (a) how to make the problem the same but smaller, and then (b) what to do with the result of computing the smaller solution.

One way to make the problem smaller is to lop off the first letter of string1. So if combine were originally invoked with the strings “abc” and “def,” the recursive call would invoke it with “bc” and “def.” Presuming combine works correctly — which is the counterintuitive assumption you must always make about the recursive step in a function like this — we’ll get back the list [“bcdef”, “bdcef”, “bdecf”, “bdefc”, “dbcef”, “dbecf”, “dbefc”, “debcf”, “debfc”, “defbc”]. None of those belongs in the result list of combine(“abc”, “def”); but if we now restore to the beginning of each of those strings the same letter we lopped off, we get [“abcdef”, “abdcef”, “abdecf”, “abdefc”, “adbcef”, “adbecf”, “adbefc”, “adebcf”, “adebfc”, “adefbc”]. This is halfway to the complete answer: it’s all the strings in the result list that begin with the first letter of string1. We only need to add all the strings in the result list that begin with the first letter of string2, and we’re done. We do this by treating string2 the same way we just treated string1: we lop off its first letter in another recursive call to combine, then paste it back on to each string in the result. Continuing the example, this means calling combine(“abc”, “ef”), which produces [“abcef”, “abecf”, “abefc”, “aebcf”, “aebfc”, “aefbc”, “eabcf”, “eabfc”, “eafbc”, “efabc”]. Sticking the “d” back onto the beginning of each of those strings gives [“dabcef”, “dabecf”, “dabefc”, “daebcf”, “daebfc”, “daefbc”, “deabcf”, “deabfc”, “deafbc”, “defabc”], and adding this list to the list from the first recursive call gives the complete solution.

In Python, the first letter of string is denoted string[0]. The rest of string, without its first letter, is denoted string[1:]. So here’s the complete version of combine, with the (double) recursive step added in.

def combine(string1, string2):
  if len(string1) == 0:
    return [string2]
  elif len(string2) == 0:
    return [string1]
  else:
    recursive_result1 = combine(string1[1:], string2)
    recursive_result2 = combine(string1, string2[1:])
    result = []
    for string in recursive_result1:
      result.append(string1[0] + string)
    for string in recursive_result2:
      result.append(string2[0] + string)
    return result

This is the crazy magic of recursion: at each step, you simply assume the next-smaller step is going to work and give you the result you need. All you have to get right is the base case and the way to process the recursive result, and — well, look:

hol + alp = ['alphol']
has + alp = ['alphas']
sae + alp = ['salpae']
her + alp = ['halper']
see + alp = ['asleep']
eta + alp = ['aletap']
era + alp = ['earlap']
soe + alp = ['aslope']
yin + alp = ['alypin']
pus + alp = ['palpus']
een + alp = ['alpeen']
kas + alp = ['kalpas']
ecu + alp = ['alecup']
ist + alp = ['alpist']
doh + alp = ['adolph']
pal + alp = ['palpal']
cul + alp = ['calpul']
ped + alp = ['palped']
Moe + alp = ['Malope']
clo + alp = ['callop', 'callop']
gos + alp = ['galops']
tid + alp = ['talpid']
yum + alp = ['alypum']
pon + alp = ['palpon']
hin + alp = ['alphin']
joy + alp = ['jalopy']
hol + wl = ['wholl', 'wholl']
sae + wl = ['swale']
soe + wl = ['sowel', 'sowle']
joy + wl = ['jowly']
joy + marit = ['majority']
joy + ealus = ['jealousy']
joy + urneman = ['journeyman']
joy + cke = ['jockey']
joy + disintedl = ['disjointedly']
joy + traectr = ['trajectory']
joy + epard = ['jeopardy']
set(['joy'])

Predicting the present

One day long ago, when the IBM PC was still new, my friend Mike asked me to imagine my ideal computer. I described something very like the IBM PC, but with more memory and a bigger hard drive — 50 megabytes, say, instead of 10 or 20. I couldn’t imagine any use for much more than that. (Today of course you can’t even buy a thumb drive that tiny.) I grudgingly allowed that a bitmap display might be more useful than the 80-column-by-24-line character terminal that PC’s had, but that was all I would consider adopting from the then-brand-new Apple Macintosh, which I dismissed as a silly toy unworthy of Real Programmers.

“Why?” I asked Mike. “What’s your ideal computer?”

Mike described something no bigger than an 8.5×11 sheet of paper and no more than an inch or so thick, whose entire surface was a full-color display. It could be carried in the hand or slipped into a backpack. “What about the CPU, where would that go?” I asked. I wasn’t getting it. Mike patiently explained that the whole system — CPU, RAM, video driver, power supply — was inside that little slab. I scoffed. Cramming everything into such a small space was obviously impossible, and no battery that could fit in such a thing would ever have enough power to spin a floppy disk drive for long. “Anyway, even if you could build it,” I told him, “it wouldn’t be as convenient as you’d like. You’d have to carry around a keyboard too and plug it in every time you wanted to use it.” No you wouldn’t, said Mike. The display could be touch-sensitive. The keyboard could be rendered on the screen as needed and input accepted that way.

This was 1984. What Mike described was pure science fiction. (In 1987 that became literally true, when the touch-controlled “padd” became a staple prop on Star Trek: The Next Generation.) Yet here I am, the proud new owner of a Nexus 7, the latest in high-powered touch-sensitive computing slabs that put even Mike’s audacious vision to shame.

It wasn’t the first time I’d had a failure of technological vision, nor was it the last.

Several years earlier, before even the IBM PC, I was spending a lot of afterschool hours at my friend Chuck’s house, and a lot of those hours on his dad’s home computer, one of the only ones then available: the beloved but now mostly forgotten Sol-20. (The TRS-80 and the Apple ][ were brand new and just about to steal the thunder from hobbyist models like the Sol-20.) It had a small black-and-white monitor that could display letters, numbers, typographical marks, and a few other special characters at a single intensity (i.e., it really was “black and white,” not greyscale). It looked like this:

The display was so adequate for my meager computing needs there in the late 1970’s that when the computer magazines I read started advertising things like Radio Shack’s new Color Computer (that’s what it was called — the “Color Computer”), I dismissed them as children’s toys.

Once, Chuck and I entertained the idea of making a little science fiction movie. A scene in Chuck’s script had a person’s face appearing on a computer monitor and speaking to the user. It was his plan to film this scene using his father’s computer. I said, “How are we going to make a face appear on a computer monitor?” I had only ever seen letters and numbers blockily rendered on it. Chuck pointed out that the monitor was really just a small TV. “Oh yeah,” I said, feeling stupid. It ought to be able to display anything a TV could. Of course we’d have to hook it up to a different source; obviously no computer could handle rendering full-motion video. Yet here I am, a software engineer at YouTube.

There’s more. In the mid 80’s, my sometime boss Gerald Zanetti, the commercial food photographer and computing technophile, once described his vision for composing and editing photographs on a high-resolution computer display. If a photograph included a bowl of fruit, he explained, he wanted to be able to adjust the position of an orange separately from the grapes and the bananas surrounding it. I said that such technology was far in the future. I’d seen graphics-editing programs by then, but they treated the image as a grid of undifferentiated pixels. Separating out a foreground piece of fruit from other items in the background simply was not feasible. Yet just a couple of years later Photoshop exactly realized Zanetti’s vision.

In the mid 90’s, when the web was new, my friend and mentor Nathaniel founded a new company, First Virtual, to handle credit card payments for Internet commerce. At the time there was no Internet commerce. Nathaniel and company invented some very clever mechanisms for keeping sensitive credit-card information entirely off the Internet while still enabling online payments. But I felt their system was too complicated to explain and to use, that people would prefer the familiarity and convenience of credit cards (turns out I was right about that), and that since no one would (or should!) ever trust the Internet with their credit card information, Internet commerce could never amount to much. Yet here I am, receiving a new shipment of something or other from Amazon.com every week or two.

Oh well. At least I’m in good company. I’m sensible enough finally to have learned that however gifted I may be as a technologist, I’m no visionary. Now when someone describes some fantastical new leap they imagine, I shut up and listen.