2,600 lines of solidity later...

I've been very quiet on the Alarm front for quite a while.  One contributing factor to my silence is that the 0.7.0 version of the service has run largely without interruption for the last 8 months since it's release on January 31st of this year.  At the present time all of the execution servers I operate are offline due to the recent network attack that caused geth to crash from unbounded memory consumption.  Rather than spending effort getting those servers back online I've chosen to double down on my efforts to get the next version of the service released.

"Perfection is attained, not when there is nothing more to add, but when there is nothing more to take away."

The goal of the alarm service is to be the simplest thing that can serve as a base layer to the Ethereum ecosystem for scheduling transactions for execution at a later time with a high degree of confidence that they will in fact be executed.  For roughly the past 4 months I've been putting in a very large amount of work to establish a solid foundation to achieve this goal.

Sometime around a month ago all of the foundation level tooling that I use to develop the Alarm service hit a point where I could actually step back into the codebase.  I began with trying to iterate from where I left off but quickly found myself being crushed under what can only be described as a tangled web of contracts and libraries.   As the Alarm service evolved from 0.1.0 to 0.7.0 it grew somewhat organically.  Many of the language features available today did not exist at the time that I wrote the majority of that code.  The data model was awkward and spread out across contracts and library structs in hard to deal with ways.  The inheritance structure was hard to reason about and regularly lead to circular dependencies.

So here I am, 2,600 lines of solidity later with an entirely rewritten Alarm service that I'm extremely excited about and I'd like to take a moment to point out a few of the cool new bits.

Time and Block based scheduling

Block based scheduling has been around since the beginning of the service.  Starting with 0.8.0 you will be able to schedule transactions to be executed at a specific timestamp.

Libraries and more Libraries

I've loved using Solidity libraries since they were released but I never really got the opportunity to take advantage of the using syntax for adding library functions to types.  Here's an example of how I this is used with some of the custom structs that the service uses.

// The library function.
function sendTransaction(ExecutionData storage self) returns (bool) {
    return self.toAddress.call.value(self.callValue)
                              .gas(self.callGas)
                              (self.callData);
}
// and elsewhere where it is used
function execute(...) {
    bool wasSuccessful = txnData.sendTransaction();
}

Here you can see how the requested transaction is actually sent.  This makes for some extremely clean and easy to read code when dealing with complex structs and application logic.

However, the magic of libraries doesn't stop there.

library MathLib {
    function flooredSub(uint a, uint b) returns (uint) {...}
    function safeAdd(uint a, uint b) returns (uint) {...}
    function safeMultiply(uint a, uint b) returns (uint) {...}
}

With this simple library you can now make all of your math operations safe from overflows and underflows.

contract Wallet {
    using MathLib for uint;

    function deposit(uint value) {
        // This is safe.It will throw if this addition would cause an
        // overflow.
        accountBalances[msg.sender].safeAdd(value);
        ...
    }

    function transfer(uint value) {
        // This is safe.It will stop at 0 if value is greater than the
        // account balance.
        accountBalances[msg.sender].flooredSub(value);
        ...
    }
}

Given the amount of gas tracking and sending the right payments to the right addresses, this has allowed me to eliminate a huge number of possible bugs.

Deeper Abstraction

The previous version of the service was very opinionated about a number of things that you as the scheduler of the transaction may want to configure differently.  The service is now written as two primary layers. 

The scheduling layer should be familiar to anyone who has looked into the Alarm service in the past.  It aims to provide a high level interface for scheduling transactions.  It aims to find a balance between usability and configurability that should handle most any use case.

The factory layer sits under the scheduling layer as a low level interface for transaction scheduling.  It exposes the full data model allowing you to tune every parameter of the scheduled transaction.  The goal of this new factory layer is to provide an API that applications like Meta-Mask or the Mist Wallet could hook into.  I'm imagining another button on the transaction confirmation window that allows you to instead schedule the transaction for later.

No compulsory fees ever

One important aspect of the service is that it operates as an open market.  Both the payment and donation values are completely configurable meaning that they can be set to zero if you so choose in hopes that someone will execute your transaction with no compensation (which all of my execution servers are configured to do).  You do still always have to pay up front for your gas consumption.

I'm committed to this service being a foundational layer of the Ethereum ecosystem and ensuring that it is an open platform that anyone can build on is an important part of that goal.  While the scheduler layer has my address baked into it as the benefactor of the donation, the factory layer does not.  If for example the Mist team decided to add integration with the service they could very easily do it in a way that the donation went to the Ethereum Foundation, or so that there was no donation at all.

Forward Compatibility

All previous versions of the service have suffered from a forward compatibility problem.  This new version of the service comes with a new long lived database contract called the Request Tracker. Any transaction that is scheduled using the factory contract is tracked in this tracker.  The plan is for this tracker contract to be re-used across future deployments of the service to enable the execution client to more easily monitory historical versions of the service.

Finishing Thoughts

I'm excited to get this release out the door but I am not ready to make predictions about when it will be ready.  I'm expecting to push a version to the testnet within the next few weeks.  Once I've seen that running smoothly for a bit of time I'll plan on pushing out the mainnet version.

Hello, World!