Monthly Archives: August 2016

An Ethereum Project (6) – Automating the draws

So, now that we have a draw and a lottery orchestrator to keep track of it all, the next task was to put this all together so that, at regular intervals (say once a week), the draw is drawn and either winners paid or the pot rolled over to next week’s draw. To do that you have to execute the following actions in sequence:

  1. Create a new draw for next week
  2. Run the current draw, i.e. select a winning number and pay the winners if there are any
  3. Transfer the pot (if there are no winners) to next week’s draw
  4. Add the address of the new draw to the lottery orchestrator
  5. Sleep until next week and do it all again!

All of the above are asynchronous operations on the Ethereum Blockchain, so it is necessary to wait for confirmation of one thing to execute the next one. In the following code, we do step 1, but only execute step 2 when the callback comes with confirmation that the contract has been created. And steps 3 and 4 are inside an Event callback that confirms that a winning number has been selected and the winners paid:

var draw = drawContract.new(30,100000000000000000,theorganiser,latestDrawAddress,
  {
    from: theminer,
    data: drawSrcCompiled.draw.code, 
    gas: 3000000
  }, function(e, contract){
       if(!e) { 
	 if(!contract.address) {
           console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined...");
         } else {
           console.log("Contract mined! New draw Address: " + contract.address);
           var event = latestDraw.Log_WinningNumberSelected();
           event.watch(function(e,r) {
             console.log("Winning  Number Selected!",r);
             latestDraw.transferPot(contract.address, {from: theminer, gas: 3000000}, function(e, d2) {
                 console.log("transferPot",e,JSON.stringify(d2));  
                 if (!e) {
                   console.log("Pot transferred to ", contract.address);
                   lottereo.addDraw(contract.address, {from: theminer, gas: 3000000}, function(e, d3) {
                     console.log("addDraw",e,JSON.stringify(d3));
                     if (!e) {
                       console.log("Lottereo updated");
                     }
                   });
                 }
               });
           });
           latestDraw.doDraw({from: theminer, gas: 3000000}, function(e, d) { 
             console.log("dodraw",e,JSON.stringify(d)); 
           }); 
         } 
       }
});

Automating it all

So how do you get this to happen without having to remember to do it yourself, and bearing in mind that it requires you to run code from within a geth console? To solve that problem we put all the code we wanted to run in a script and then used Expect to run it. Expect is a programme that “talks” to other interactive programmes according to a script. Our script is:

#!/usr/bin/expect
set timeout 1000   //long timeout - the blockchain is slow!
spawn /usr/bin/geth attach    //make a geth console
expect ">"
send "loadScript('/home/path/to/weekly_deploy.js')\r"  //run script!
expect "Lottereo updated"
set results $expect_out(buffer)   //print it out
send "exit\r"   log out 
expect eof   //finish!

Finally, all you do is add a line to your crontab to execute the script once a week at midnight (or whenever)

0 0 * * 0 /home/path/to/weekly_deploy.exp >> /tmp/expect.txt

Why this is OK, but not perfect

This works fine but a confession is required: When we set out we wanted to create a totally trust-less lottery, i.e. one where you did not have to trust any third party to ensure that the lottery would run according to the rules.
By doing the above, you need to trust us that this script will run at the appointed time. And we need to trust that the people who supply the server where we keep the script will continue to supply it.
So it does somewhat break the rules.
But the alternative, to have contracts that knew when to run themselves and that knew how to spawn copies of themselves in order to transfer the pot and keep the thing going, was too hard for our current abilities. So it will have to wait, for now…
Once Lottereo is live we will run the scripts, we promise!