Confirming ownership of on-chain assets off the chain

Quick Updates

A few of updates this week before we get into the meat of this post about ‘Confirming ownership of on-chain assets off the chain.’ 

  1. Looks like we won the auction for catallax.eth. Woot! Unless I’m vastly misunderstanding the process we were the only ones that placed a bid and so far the only to reveal.  So...two points to us for not getting much attention before the launch of the ethereum name services.

  2. Gas prices seem to be more under control.  We used 2Gwei(as opposed to the normal 20Gwei) gas price on our auction transactions and they seemed to get picked up, so yeah, for now, it is only 0.007 cents to store a variable in the blockchain. Therefore some of the costs from my post a couple of weeks ago[http://catallax.info/news/2017/5/5/a-week-with-ethereum] is somewhat mitigated, but we still have a problem if we need to update thousands of account balances because of a catch up.

  3. TokenCard.io looks to be a good contender to help me stop having to worry about issuing the credit / debit card.  I think I get the idea:  You’ll be able to spend your erc20 tokens on the card.  So if we issue a catallax token and tokencard is successful, you could spend your catallax tokens with their card.  I have a feeling that a decaying token may jack with their reward algorithm.  I’m going to do some looking into it.  It turns out that they just announced a partnership with wavecrest which is who I was looking at using as well.  More than happy to let someone else handle the overhead there.

  4. I think I’ve mapped out the token that we’ll be offering to raise money to build this crazy thing out.  I’m designing as a utility token to help other tokens as well.  It will run a utility that we need and be a great first step to getting Catallax off the ground.  I’m hoping to run it by some ‘in the know’ people this week.

Now onto the beef of this week’s post:  Confirming ownership of on chain assets off the chain.

Off the chain

It is clear that Catallax Bank is going to be in the business of doing some off the chain things based on on the chain transactions.  Some of these I’ve laid out in past articles like paying out pref payments.  It would just be too expensive to update running balances on the chain.

There are also going to be some auctions involved in the ecosystem and while we can do most of the auction on-chain(more on that in a future blog), there will be some off chain stuff that we will need to do.  For example, implementing the results of an auction.  I see the workflow going something like this:

OnChainTX:  close_auction() [signed by winner]

  • Sets a winner address variable to the winning address

OffChainTX:  MoveAsset(winner, bank info{bank name, address, routing, account}, signature)

  • Based on the winner we need to move money to a real live out in the world bank account(not on the chain)

  • We need to prove that this info was sent from the owner of the destination account

  • We do this by requiring them to send a signature of the bank account info

  • This signature must be signed with the private key of the winner's address

  • If they match, move the asset to the account

Crypto Basics

I get that this should be crypto 101 and that this is probably not rocket science for people who have been around the crypto world for a while.  That being said, there are very few actual tutorials on how to do this out there that deal with modern ethereum(circa mid-2017).  I realize this tutorial may have a very limited shelf life.  Just today I was reading Vitalik’s update saying that they are going to add wallet generation to web3.  That alone would have saved me some significant time figuring this stuff out.  Given that, let’s go over some basics so that the newbies(me included) won’t be lost:

Web3 [https://github.com/ethereum/wiki/wiki/JavaScript-API] - A javascript based ethereum api that does a bunch of etherumy stuff(technical term). It can run in the browser or in node.js.

Eth-lightwallet[https://github.com/ConsenSys/eth-lightwallet] - A javascript based wallet generator that can generate valid ethereum wallets and store them in a browser local storage.  I think metamask(the chrome plugin that helps link ethereum dApps to the browser).  I’m going to use it from node to generate a temporary wallet for testing. 

ethereumjs-util[https://github.com/ethereumjs/ethereumjs-util] - A bunch of crypto and ethereum related tools that can be used in javascript.

(I’m wading in to no expert territory in the next few definitions so your milage may vary)

Sha3 - As best I can tell this is a function that you can feed a string into and it will spit out a short(relatively) hash that is probabilistically unique for the message pass in.  It also has the quality that if I sha3 something and you sha3 the same string of text, the output hash will be the same.

Signing a Message - So what happens here is you take a sha3 hash that you’ve generated and you ‘sign’ it with your private key.  Ethereum’s tools take care of most of the inner workings for you.  What you get out is another long string of bits that can be pulled apart in a way that can recover the public key(not the private key) that is associated with the private key that signed the message. 

Ecrecover - This is the function that does the work of pulling the public key off of a signed transaction.  When you pull a public key(also called an address in ethereum) you have proven that that address signed the message. Yeah! 

The Plan

So the plan is that we’re going to have our auction winner sign a message with their private key that containing the parameters for the function.  We are going to erecover the message and only proceed with the off chain execution if the winner address matches the erecover address.  We can pull the winner address of the blockchain by running a full node of ethereum and checking the storage value of our auction contract.  You’d want a few blocks to pass before you did this. 

The Code

The code provided is simpler.  We aren’t confirming bank routing info.  We are confirming that an address sent us the text ‘foobar.’  The full code can be found in a gist here and if you want to pull it down and run it yourself it is on my ethereum proof of ownership project on github.It is also at the bottom of this post.

It turns out it is pretty simple to prove the ownership of an ethereum address once you know all the tools.  One issue to consider is what happens if a private key is compromised, but that is an issue for another day.  Let me know if you think I've missed something major.

If you have any comments or questions, please leave them below or send them to me on twitter at @hypercatallax. If you’d like to see more of this kind of stuff and help us build this new economy please consider supporting the "Catallax Code " patreon.

If this is interesting to you and you'd like to see where we are going with Catallax, please pick up my book Immortality.

Donations always accepted at:

BTC: 1AAfkhg1NEQwGmwW36dwDZjSAvNLtKECas

ETH and Tokens: 0x148311c647ec8a584d896c04f6492b5d9cb3a9b0

 The full test code is below:

// copy this file into a directory as index.js
// from that directory run the following:
// npm install q
// npm install eth-lightwallet
// npm install ethereumjs-util
// npm install web3
//
// node index.js

var Q = require('q');  //I'm doing promises old school
var wal = require('eth-lightwallet'); //we will use this to generate some silly addresses
var utils = require('ethereumjs-util');  //we will use this to recover the address from our message
var Web3 = require('web3'); //we will use this to sha3 something

var web3 = new Web3();

var password = 'zzzzzzzzz'; //the password we will use to generate an ethereum address
var message = 'foobar';  //the message that we want to send

var keystore = null; //object created that holds our ethereum address that can sign things
var key = null; //the derived key from our wallet.
var addr1 = null; //the address of our account
var addr2 = null;
var sgnmsg = null; // the signed message

var createKeystore = function(){
 return Q.Promise(function (resolve,reject){
    //use eth-lightwallet to create a new ethererum address
    wal.keystore.createVault({password:password}, function(err,ks){
        keystore = ks;
        resolve(ks);
    });

  });
}

var generateKey = function(){
  return Q.Promise(function (resolve,reject){

    //get the key for the account.
    keystore.keyFromPassword(password,
      function (err, pwDerivedKey) {
          key = pwDerivedKey;
          if (err) throw err;

          //this gets us a valid address that matches our key
          // we get two addresses so we can test failure as well
          keystore.generateNewAddress(pwDerivedKey, 2);
          addr1 = keystore.getAddresses()[0];
          addr2 = keystore.getAddresses()[1];
          resolve();


          });
  });
}


var signSomething = function(the_addr){

  //use our keystore to sign a message with the address we created
  //this function sha3s our message for us and then signs it with our private key
  var foo = wal.signing.signMsg(keystore, key, message, the_addr);
  sgnmsg = foo;
}

var confirmAddress = function(the_addr){

  //these are variables that make sense to the encrption algo
  var r = sgnmsg.r;
  var s = sgnmsg.s;
  var v = sgnmsg.v;

  //we are going to re sha3 our message with a different library
  var m = utils.toBuffer(web3.sha3(message));


  var pub = utils.ecrecover(m, v, r, s);
  var sourceaddr = utils.pubToAddress(pub).toString('hex')
  if(sourceaddr == the_addr){
    console.log('Address 0x' + the_addr + ' owns this message.');
  } else {
    console.log('get out of town.  you dont own this');
  }



}

var run = function(){

  //our application

  createKeystore().then(generateKey).then( function(){
    //sign with address 1
    signSomething(addr1);

    //confirm that address 1 signed
    confirmAddress(addr1);

    //sign with address 2
    signSomething(addr2);

    //confirm that they don't match
    confirmAddress(addr1);
  });

}

run();