Change modifier name.

Change modifier name.

/**
 * @title BlobStore
 * @author Jonathan Brown <jbrown@bluedroplet.com>
 */
contract BlobStore {

    struct BlobInfo {               // Single slot.
        bool updatable;             // Can the blob be updated? Can be disabled.
        bool enforceRevisions;      // When updating, always make a new revision. Can be enabled.
        bool retractable;           // Can the blob be retracted? Can be disabled.
        bool transferable;          // Can the blob be transfered to another user or disowned? Can be disabled.
        uint32 blockNumber;         // Which block has revision 0 of this blob.
        uint32 numRevisions;        // Number of additional revisions.
        address owner;              // Who owns this blob.
    }

    mapping (bytes32 => BlobInfo) idBlobInfo;
    mapping (bytes32 => mapping (uint => bytes32)) idPackedRevisionBlockNumbers;
    mapping (bytes32 => mapping (address => bool)) enabledTransfers;

    event logBlob(bytes32 indexed id, uint indexed revisionId, bytes blob);     // Greatest revisionId for the blob at time of logging.
    event logRetractRevision(bytes32 indexed id, uint indexed revisionId);
    event logRetract(bytes32 indexed id);
    event logTransfer(bytes32 indexed id, address indexed sender, address indexed recipient);
    event logDisown(bytes32 indexed id);
    event logSetNotUpdatable(bytes32 indexed id);
    event logSetEnforceRevisions(bytes32 indexed id);
    event logSetNotRetractable(bytes32 indexed id);
    event logSetNotTransferable(bytes32 indexed id);

    // Create a 96-bit id for this contract. This is unique across all blockchains.
    // Wait a few minutes after deploying for this id to settle.
    bytes12 constant contractId = bytes12(sha3(this, block.blockhash(block.number - 1)));

    /**
     * @dev Throw if the current message is sending a payment.
     */
    modifier noValue() {
        if (msg.value > 0) {
            throw;      // Do not maintain a balance.
        }
        _
    }

    /**
     * @dev Throw if the blob has not been used before or it has been retracted.
     * @param id Id of the blob.
     */
    modifier exists(bytes32 id) {
        if (idBlobInfo[id].blockNumber == 0 || idBlobInfo[id].blockNumber == uint32(-1)) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the owner of the blob is not the message sender.
     * @param id Id of the blob.
     */
    modifier isOwner(bytes32 id) {
        if (idBlobInfo[id].owner != msg.sender) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob is not updatable.
     * @param id Id of the blob.
     */
    modifier isUpdatable(bytes32 id) {
        if (!idBlobInfo[id].updatable) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob is not enforcing revisions.
     * @param id Id of the blob.
     */
    modifier isNotEnforceRevisions(bytes32 id) {
        if (idBlobInfo[id].enforceRevisions) {
            throw;
        }
        _
    }

    /**
     * @dev Throw is the blob is not retractable.
     * @param id Id of the blob.
     */
    modifier isRetractable(bytes32 id) {
        if (!idBlobInfo[id].retractable) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob is not transferable.
     * @param id Id of the blob.
     */
    modifier isTransferable(bytes32 id) {
        if (!idBlobInfo[id].transferable) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob is not transferable to a specific user.
     * @param id Id of the blob.
     * @param recipient Address of the user.
     */
    modifier isTransferEnabled(bytes32 id, address recipient) {
        if (!enabledTransfers[id][recipient]) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob does not have revisions.
     * @param id Id of the blob.
     */
    modifier hasRevisions(bytes32 id) {
        if (idBlobInfo[id].numRevisions == 0) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if a specific blob revision does not exist.
     * @param id Id of the blob.
     * @param revisionId Id of the revision.
     */
    modifier revisionExists(bytes32 id, uint revisionId) {
        if (revisionId > idBlobInfo[id].numRevisions) {
            throw;
        }
        _
    }

    /**
     * @dev Stores new blob in the transaction log. It is guaranteed that each user will get a different id from the same nonce.
     * @param blob Blob that should be stored.
     * @param nonce Any value that the user has not used previously to create a blob.
     * @param updatable Should the blob be updatable?
     * @param enforceRevisions Should the blob enforce revisions when updating?
     * @param retractable Should the blob be retractable?
     * @param transferable Should the blob be transferable?
     * @param anon Should the blob be anonymous?
     * @return id Id of the blob.
     */
    function create(bytes blob, bytes32 nonce, bool updatable, bool enforceRevisions, bool retractable, bool transferable, bool anon) noValue external returns (bytes32 id) {
        // Determine the id.
        id = contractId | (sha3(msg.sender, nonce) & (2 ** 160 - 1));
        // Make sure this id has not been used before.
        if (idBlobInfo[id].blockNumber != 0) {
            throw;
        }
        // Store blob info in state.
        idBlobInfo[id] = BlobInfo({
            updatable: updatable,
            enforceRevisions: enforceRevisions,
            retractable: retractable,
            transferable: transferable,
            numRevisions: 0,
            blockNumber: uint32(block.number),
            owner: anon ? 0 : msg.sender,
        });
        // Store the blob in a log in the current block.
        logBlob(id, 0, blob);
    }

    /**
     * @dev Store a blob revision block number in a packed slot.
     * @param id Id of the blob.
     * @param offset The offset of the block number should be retreived.
     */
    function setPackedRevisionBlockNumber(bytes32 id, uint offset) internal {
        // Get the slot.
        bytes32 slot = idPackedRevisionBlockNumbers[id][offset / 8];
        // Wipe the previous block number.
        slot &= ~bytes32(uint32(-1) * 2 ** ((offset % 8) * 32));
        // Insert the current block number.
        slot |= bytes32(uint32(block.number) * 2 ** ((offset % 8) * 32));
        // Store the slot.
        idPackedRevisionBlockNumbers[id][offset / 8] = slot;
    }

    /**
     * @dev Create a new blob revision.
     * @param id Id of the blob.
     * @param blob Blob that should be stored as the new revision.
     * @return revisionId The new revisionId.
     */
    function createRevision(bytes32 id, bytes blob) noValue isOwner(id) isUpdatable(id) external returns (uint revisionId) {
        // Increment the number of revisions.
        revisionId = ++idBlobInfo[id].numRevisions;
        // Store the block number.
        setPackedRevisionBlockNumber(id, revisionId - 1);
        // Store the new blob in a log in the current block.
        logBlob(id, revisionId, blob);
    }

    /**
     * @dev Update a blob's latest revsion.
     * @param id Id of the blob.
     * @param blob Blob that should be stored as the latest revision.
     */
    function updateLatestRevision(bytes32 id,  bytes blob) noValue isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) external {
        if (idBlobInfo[id].numRevisions == 0) {
            idBlobInfo[id].blockNumber = uint32(block.number);
        }
        else {
            setPackedRevisionBlockNumber(id, idBlobInfo[id].numRevisions - 1);
        }
        // Store the new blob in a log in the current block.
        logBlob(id, idBlobInfo[id].numRevisions, blob);
    }

    /**
     * @dev Retract a blob's latest revision.
     * @param id Id of the blob.
     */
    function retractLatestRevision(bytes32 id) noValue isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) hasRevisions(id) external {
        // Delete slot if empty
        if (idBlobInfo[id].numRevisions % 8 == 1) {
            delete idPackedRevisionBlockNumbers[id][idBlobInfo[id].numRevisions / 8];
        }
        // Log the retraction.
        logRetractRevision(id, idBlobInfo[id].numRevisions--);
    }

    /**
     * @dev Delete all of a blob's packed revision block numbers.
     * @param id Id of the blob.
     */
    function deleteAllRevisionBlockNumbers(bytes32 id) internal {
        uint numSlots = (idBlobInfo[id].numRevisions + 7) / 8;
        for (uint i = 0; i < numSlots; i++) {
            delete idPackedRevisionBlockNumbers[id][i];
        }
    }

    /**
     * @dev Delete all a blob's revisions and replace it with a new blob.
     * @param id Id of the blob.
     * @param blob Blob that should be stored.
     */
    function restart(bytes32 id, bytes blob) noValue isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) external {
        // Try to get some gas refunds.
        deleteAllRevisionBlockNumbers(id);
        // Update the blob state info.
        idBlobInfo[id].blockNumber = uint32(block.number);
        idBlobInfo[id].numRevisions = 0;
        // Store the blob in a log in the current block.
        logBlob(id, 0, blob);
    }

    /**
     * @dev Retract a blob.
     * @param id Id of the blob.
     */
    function retract(bytes32 id) noValue isOwner(id) isRetractable(id) external {
        // Delete the packed revision block numbers.
        deleteAllRevisionBlockNumbers(id);
        // Mark this blob as retracted.
        idBlobInfo[id] = BlobInfo({
            updatable: false,
            enforceRevisions: false,
            retractable: false,
            transferable: false,
            numRevisions: 0,
            blockNumber: uint32(-1),
            owner: 0,
        });
        // Log that the blob has been retracted.
        logRetract(id);
    }

    /**
     * @dev Enable transfer of the blob to the current user.
     * @param id Id of the blob.
     */
    function transferEnable(bytes32 id) noValue isTransferable(id) external {
        // Record in state that the current user will accept this blob.
        enabledTransfers[id][msg.sender] = true;
    }

    /**
     * @dev Disable transfer of the blob to the current user.
     * @param id Id of the blob.
     */
    function transferDisable(bytes32 id) noValue external {
        // Record in state that the current user will not accept this blob.
        enabledTransfers[id][msg.sender] = false;
    }

    /**
     * @dev Transfer a blob to a new user.
     * @param id Id of the blob.
     * @param recipient Address of the user to transfer to blob to.
     */
    function transfer(bytes32 id, address recipient) noValue isOwner(id) isTransferable(id) isTransferEnabled(id, recipient) external {
        // Update ownership of the blob.
        idBlobInfo[id].owner = recipient;
        // Disable this transfer and free up the slot.
        enabledTransfers[id][recipient] = false;
        // Log the transfer.
        logTransfer(id, msg.sender, recipient);
    }

    /**
     * @dev Disown a blob.
     * @param id Id of the blob.
     */
    function disown(bytes32 id) noValue isOwner(id) isTransferable(id) external {
        // Remove the owner from the blob's state.
        delete idBlobInfo[id].owner;
        // Log as blob as disowned.
        logDisown(id);
    }

    /**
     * @dev Set a blob as not updatable.
     * @param id Id of the blob.
     */
    function setNotUpdatable(bytes32 id) noValue isOwner(id) external {
        // Record in state that the blob is not updatable.
        idBlobInfo[id].updatable = false;
        // Log that the blob is not updatable.
        logSetNotUpdatable(id);
    }

    /**
     * @dev Set a blob to enforce revisions.
     * @param id Id of the blob.
     */
    function setEnforceRevisions(bytes32 id) noValue isOwner(id) external {
        // Record in state that all changes to this blob must be new revisions.
        idBlobInfo[id].enforceRevisions = true;
        // Log that the blob now forces new revisions.
        logSetEnforceRevisions(id);
    }

    /**
     * @dev Set a blob to not be retractable.
     * @param id Id of the blob.
     */
    function setNotRetractable(bytes32 id) noValue isOwner(id) external {
        // Record in state that the blob is not retractable.
        idBlobInfo[id].retractable = false;
        // Log that the blob is not retractable.
        logSetNotRetractable(id);
    }

    /**
     * @dev Set a blob to not be transferable.
     * @param id Id of the blob.
     */
    function setNotTransferable(bytes32 id) noValue isOwner(id) external {
        // Record in state that the blob is not transferable.
        idBlobInfo[id].transferable = false;
        // Log that the blob is not transferable.
        logSetNotTransferable(id);
    }

    function getContractId() noValue constant external returns (bytes12 _contractId) {
        _contractId = contractId;
    }

    /**
     * @dev Get info about a blob.
     * @param id Id of the blob.
     * @return owner Owner of the blob.
     * @return updatable Is the blob updatable?
     * @return enforceRevisions Does the blob enforce revisions?
     * @return retractable Is the blob retractable?
     * @return transferable Is the blob transferable?
     * @return numRevisions How many revisions the blob has.
     * @return latestBlockNumber The block number of the latest revision.
     */
    function getInfo(bytes32 id) noValue exists(id) constant external returns (address owner, bool updatable, bool enforceRevisions, bool retractable, bool transferable, uint numRevisions, uint latestBlockNumber) {
        owner = idBlobInfo[id].owner;
        updatable = idBlobInfo[id].updatable;
        enforceRevisions = idBlobInfo[id].enforceRevisions;
        retractable = idBlobInfo[id].retractable;
        transferable = idBlobInfo[id].transferable;
        numRevisions = idBlobInfo[id].numRevisions;
        latestBlockNumber = getRevisionBlockNumber(id, numRevisions);
    }

    /**
     * @dev Get the owner of a blob.
     * @param id Id of the blob.
     * @return owner Owner of the blob.
     */
    function getOwner(bytes32 id) noValue exists(id) constant external returns (address owner) {
        owner = idBlobInfo[id].owner;
    }

    /**
     * @dev Is a blob updatable?
     * @param id Id of the blob.
     * @return updatable Is the blob updatable?
     */
    function getUpdatable(bytes32 id) noValue exists(id) constant external returns (bool updatable) {
        updatable = idBlobInfo[id].updatable;
    }

    /**
     * @dev Does a blob enforce revisions?
     * @param id Id of the blob.
     * @return enforceRevisions Does the blob enforce revisions?
     */
    function getEnforceRevisions(bytes32 id) noValue exists(id) constant external returns (bool enforceRevisions) {
        enforceRevisions = idBlobInfo[id].enforceRevisions;
    }

    /**
     * @dev Is a blob retractable?
     * @param id Id of the blob.
     * @return retractable Is the blob retractable?
     */
    function getRetractable(bytes32 id) noValue exists(id) constant external returns (bool retractable) {
        retractable = idBlobInfo[id].retractable;
    }

    /**
     * @dev Is a blob transferable.
     * @param id Id of the blob.
     * @return transferable Is the blob transferable?
     */
    function getTransferable(bytes32 id) noValue exists(id) constant external returns (bool transferable) {
        transferable = idBlobInfo[id].transferable;
    }

    /**
     * @dev Get the number of revisions a blob has.
     * @param id Id of the blob.
     * @return numRevisions How many revisions the blob has.
     */
    function getNumRevisions(bytes32 id) noValue exists(id) constant external returns (uint numRevisions) {
        numRevisions = idBlobInfo[id].numRevisions;
    }

    /**
     * @dev Get the block number for a specific blob revision.
     * @param id Id of the blob.
     * @param revisionId Id of the revision.
     * @return blockNumber Block number of the specified revision.
     */
    function getRevisionBlockNumber(bytes32 id, uint revisionId) noValue exists(id) revisionExists(id, revisionId) constant returns (uint blockNumber) {
        if (revisionId == 0) {
            blockNumber = idBlobInfo[id].blockNumber;
        }
        else {
            bytes32 slot = idPackedRevisionBlockNumbers[id][(revisionId - 1) / 8];
            blockNumber = uint32(uint256(slot) / 2 ** (((revisionId - 1) % 8) * 32));
        }
    }

    /**
     * @dev Default function.
     */
    function() {
        throw;      // Do not maintain a balance.
    }

}

/**
 * @title BlobStore
 * @author Jonathan Brown <jbrown@bluedroplet.com>
 */
contract BlobStore {

    struct BlobInfo {               // Single slot.
        bool updatable;             // Can the blob be updated? Can be disabled.
        bool enforceRevisions;      // When updating, always make a new revision. Can be enabled.
        bool retractable;           // Can the blob be retracted? Can be disabled.
        bool transferable;          // Can the blob be transfered to another user or disowned? Can be disabled.
        uint32 blockNumber;         // Which block has revision 0 of this blob.
        uint32 numRevisions;        // Number of additional revisions.
        address owner;              // Who owns this blob.
    }

    mapping (bytes32 => BlobInfo) idBlobInfo;
    mapping (bytes32 => mapping (uint => bytes32)) idPackedRevisionBlockNumbers;
    mapping (bytes32 => mapping (address => bool)) enabledTransfers;

    event logBlob(bytes32 indexed id, uint indexed revisionId, bytes blob);     // Greatest revisionId for the blob at time of logging.
    event logRetractRevision(bytes32 indexed id, uint indexed revisionId);
    event logRetract(bytes32 indexed id);
    event logTransfer(bytes32 indexed id, address indexed sender, address indexed recipient);
    event logDisown(bytes32 indexed id);
    event logSetNotUpdatable(bytes32 indexed id);
    event logSetEnforceRevisions(bytes32 indexed id);
    event logSetNotRetractable(bytes32 indexed id);
    event logSetNotTransferable(bytes32 indexed id);

    // Create a 96-bit id for this contract. This is unique across all blockchains.
    // Wait a few minutes after deploying for this id to settle.
    bytes12 constant contractId = bytes12(sha3(this, block.blockhash(block.number - 1)));

    /**
     * @dev Throw if the current message is sending a payment.
     */
    modifier noValue() {
        if (msg.value > 0) {
            throw;      // Do not maintain a balance.
        }
        _
    }

    /**
     * @dev Throw if the blob has not been used before or it has been retracted.
     * @param id Id of the blob.
     */
    modifier exists(bytes32 id) {
        if (idBlobInfo[id].blockNumber == 0 || idBlobInfo[id].blockNumber == uint32(-1)) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the owner of the blob is not the message sender.
     * @param id Id of the blob.
     */
    modifier isOwner(bytes32 id) {
        if (idBlobInfo[id].owner != msg.sender) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob is not updatable.
     * @param id Id of the blob.
     */
    modifier isUpdatable(bytes32 id) {
        if (!idBlobInfo[id].updatable) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob is not enforcing revisions.
     * @param id Id of the blob.
     */
    modifier isNotEnforceRevisions(bytes32 id) {
        if (idBlobInfo[id].enforceRevisions) {
            throw;
        }
        _
    }

    /**
     * @dev Throw is the blob is not retractable.
     * @param id Id of the blob.
     */
    modifier isRetractable(bytes32 id) {
        if (!idBlobInfo[id].retractable) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob is not transferable.
     * @param id Id of the blob.
     */
    modifier isTransferable(bytes32 id) {
        if (!idBlobInfo[id].transferable) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob is not transferable to a specific user.
     * @param id Id of the blob.
     * @param recipient Address of the user.
     */
    modifier transferEnabled(bytes32 id, address recipient) {
        if (!enabledTransfers[id][recipient]) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if the blob does not have revisions.
     * @param id Id of the blob.
     */
    modifier hasRevisions(bytes32 id) {
        if (idBlobInfo[id].numRevisions == 0) {
            throw;
        }
        _
    }

    /**
     * @dev Throw if a specific blob revision does not exist.
     * @param id Id of the blob.
     * @param revisionId Id of the revision.
     */
    modifier revisionExists(bytes32 id, uint revisionId) {
        if (revisionId > idBlobInfo[id].numRevisions) {
            throw;
        }
        _
    }

    /**
     * @dev Stores new blob in the transaction log. It is guaranteed that each user will get a different id from the same nonce.
     * @param blob Blob that should be stored.
     * @param nonce Any value that the user has not used previously to create a blob.
     * @param updatable Should the blob be updatable?
     * @param enforceRevisions Should the blob enforce revisions when updating?
     * @param retractable Should the blob be retractable?
     * @param transferable Should the blob be transferable?
     * @param anon Should the blob be anonymous?
     * @return id Id of the blob.
     */
    function create(bytes blob, bytes32 nonce, bool updatable, bool enforceRevisions, bool retractable, bool transferable, bool anon) noValue external returns (bytes32 id) {
        // Determine the id.
        id = contractId | (sha3(msg.sender, nonce) & (2 ** 160 - 1));
        // Make sure this id has not been used before.
        if (idBlobInfo[id].blockNumber != 0) {
            throw;
        }
        // Store blob info in state.
        idBlobInfo[id] = BlobInfo({
            updatable: updatable,
            enforceRevisions: enforceRevisions,
            retractable: retractable,
            transferable: transferable,
            numRevisions: 0,
            blockNumber: uint32(block.number),
            owner: anon ? 0 : msg.sender,
        });
        // Store the blob in a log in the current block.
        logBlob(id, 0, blob);
    }

    /**
     * @dev Store a blob revision block number in a packed slot.
     * @param id Id of the blob.
     * @param offset The offset of the block number should be retreived.
     */
    function setPackedRevisionBlockNumber(bytes32 id, uint offset) internal {
        // Get the slot.
        bytes32 slot = idPackedRevisionBlockNumbers[id][offset / 8];
        // Wipe the previous block number.
        slot &= ~bytes32(uint32(-1) * 2 ** ((offset % 8) * 32));
        // Insert the current block number.
        slot |= bytes32(uint32(block.number) * 2 ** ((offset % 8) * 32));
        // Store the slot.
        idPackedRevisionBlockNumbers[id][offset / 8] = slot;
    }

    /**
     * @dev Create a new blob revision.
     * @param id Id of the blob.
     * @param blob Blob that should be stored as the new revision.
     * @return revisionId The new revisionId.
     */
    function createRevision(bytes32 id, bytes blob) noValue isOwner(id) isUpdatable(id) external returns (uint revisionId) {
        // Increment the number of revisions.
        revisionId = ++idBlobInfo[id].numRevisions;
        // Store the block number.
        setPackedRevisionBlockNumber(id, revisionId - 1);
        // Store the new blob in a log in the current block.
        logBlob(id, revisionId, blob);
    }

    /**
     * @dev Update a blob's latest revsion.
     * @param id Id of the blob.
     * @param blob Blob that should be stored as the latest revision.
     */
    function updateLatestRevision(bytes32 id,  bytes blob) noValue isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) external {
        if (idBlobInfo[id].numRevisions == 0) {
            idBlobInfo[id].blockNumber = uint32(block.number);
        }
        else {
            setPackedRevisionBlockNumber(id, idBlobInfo[id].numRevisions - 1);
        }
        // Store the new blob in a log in the current block.
        logBlob(id, idBlobInfo[id].numRevisions, blob);
    }

    /**
     * @dev Retract a blob's latest revision.
     * @param id Id of the blob.
     */
    function retractLatestRevision(bytes32 id) noValue isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) hasRevisions(id) external {
        // Delete slot if empty
        if (idBlobInfo[id].numRevisions % 8 == 1) {
            delete idPackedRevisionBlockNumbers[id][idBlobInfo[id].numRevisions / 8];
        }
        // Log the retraction.
        logRetractRevision(id, idBlobInfo[id].numRevisions--);
    }

    /**
     * @dev Delete all of a blob's packed revision block numbers.
     * @param id Id of the blob.
     */
    function deleteAllRevisionBlockNumbers(bytes32 id) internal {
        uint numSlots = (idBlobInfo[id].numRevisions + 7) / 8;
        for (uint i = 0; i < numSlots; i++) {
            delete idPackedRevisionBlockNumbers[id][i];
        }
    }

    /**
     * @dev Delete all a blob's revisions and replace it with a new blob.
     * @param id Id of the blob.
     * @param blob Blob that should be stored.
     */
    function restart(bytes32 id, bytes blob) noValue isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) external {
        // Try to get some gas refunds.
        deleteAllRevisionBlockNumbers(id);
        // Update the blob state info.
        idBlobInfo[id].blockNumber = uint32(block.number);
        idBlobInfo[id].numRevisions = 0;
        // Store the blob in a log in the current block.
        logBlob(id, 0, blob);
    }

    /**
     * @dev Retract a blob.
     * @param id Id of the blob.
     */
    function retract(bytes32 id) noValue isOwner(id) isRetractable(id) external {
        // Delete the packed revision block numbers.
        deleteAllRevisionBlockNumbers(id);
        // Mark this blob as retracted.
        idBlobInfo[id] = BlobInfo({
            updatable: false,
            enforceRevisions: false,
            retractable: false,
            transferable: false,
            numRevisions: 0,
            blockNumber: uint32(-1),
            owner: 0,
        });
        // Log that the blob has been retracted.
        logRetract(id);
    }

    /**
     * @dev Enable transfer of the blob to the current user.
     * @param id Id of the blob.
     */
    function transferEnable(bytes32 id) noValue isTransferable(id) external {
        // Record in state that the current user will accept this blob.
        enabledTransfers[id][msg.sender] = true;
    }

    /**
     * @dev Disable transfer of the blob to the current user.
     * @param id Id of the blob.
     */
    function transferDisable(bytes32 id) noValue external {
        // Record in state that the current user will not accept this blob.
        enabledTransfers[id][msg.sender] = false;
    }

    /**
     * @dev Transfer a blob to a new user.
     * @param id Id of the blob.
     * @param recipient Address of the user to transfer to blob to.
     */
    function transfer(bytes32 id, address recipient) noValue isOwner(id) isTransferable(id) transferEnabled(id, recipient) external {
        // Update ownership of the blob.
        idBlobInfo[id].owner = recipient;
        // Disable this transfer and free up the slot.
        enabledTransfers[id][recipient] = false;
        // Log the transfer.
        logTransfer(id, msg.sender, recipient);
    }

    /**
     * @dev Disown a blob.
     * @param id Id of the blob.
     */
    function disown(bytes32 id) noValue isOwner(id) isTransferable(id) external {
        // Remove the owner from the blob's state.
        delete idBlobInfo[id].owner;
        // Log as blob as disowned.
        logDisown(id);
    }

    /**
     * @dev Set a blob as not updatable.
     * @param id Id of the blob.
     */
    function setNotUpdatable(bytes32 id) noValue isOwner(id) external {
        // Record in state that the blob is not updatable.
        idBlobInfo[id].updatable = false;
        // Log that the blob is not updatable.
        logSetNotUpdatable(id);
    }

    /**
     * @dev Set a blob to enforce revisions.
     * @param id Id of the blob.
     */
    function setEnforceRevisions(bytes32 id) noValue isOwner(id) external {
        // Record in state that all changes to this blob must be new revisions.
        idBlobInfo[id].enforceRevisions = true;
        // Log that the blob now forces new revisions.
        logSetEnforceRevisions(id);
    }

    /**
     * @dev Set a blob to not be retractable.
     * @param id Id of the blob.
     */
    function setNotRetractable(bytes32 id) noValue isOwner(id) external {
        // Record in state that the blob is not retractable.
        idBlobInfo[id].retractable = false;
        // Log that the blob is not retractable.
        logSetNotRetractable(id);
    }

    /**
     * @dev Set a blob to not be transferable.
     * @param id Id of the blob.
     */
    function setNotTransferable(bytes32 id) noValue isOwner(id) external {
        // Record in state that the blob is not transferable.
        idBlobInfo[id].transferable = false;
        // Log that the blob is not transferable.
        logSetNotTransferable(id);
    }

    function getContractId() noValue constant external returns (bytes12 _contractId) {
        _contractId = contractId;
    }

    /**
     * @dev Get info about a blob.
     * @param id Id of the blob.
     * @return owner Owner of the blob.
     * @return updatable Is the blob updatable?
     * @return enforceRevisions Does the blob enforce revisions?
     * @return retractable Is the blob retractable?
     * @return transferable Is the blob transferable?
     * @return numRevisions How many revisions the blob has.
     * @return latestBlockNumber The block number of the latest revision.
     */
    function getInfo(bytes32 id) noValue exists(id) constant external returns (address owner, bool updatable, bool enforceRevisions, bool retractable, bool transferable, uint numRevisions, uint latestBlockNumber) {
        owner = idBlobInfo[id].owner;
        updatable = idBlobInfo[id].updatable;
        enforceRevisions = idBlobInfo[id].enforceRevisions;
        retractable = idBlobInfo[id].retractable;
        transferable = idBlobInfo[id].transferable;
        numRevisions = idBlobInfo[id].numRevisions;
        latestBlockNumber = getRevisionBlockNumber(id, numRevisions);
    }

    /**
     * @dev Get the owner of a blob.
     * @param id Id of the blob.
     * @return owner Owner of the blob.
     */
    function getOwner(bytes32 id) noValue exists(id) constant external returns (address owner) {
        owner = idBlobInfo[id].owner;
    }

    /**
     * @dev Is a blob updatable?
     * @param id Id of the blob.
     * @return updatable Is the blob updatable?
     */
    function getUpdatable(bytes32 id) noValue exists(id) constant external returns (bool updatable) {
        updatable = idBlobInfo[id].updatable;
    }

    /**
     * @dev Does a blob enforce revisions?
     * @param id Id of the blob.
     * @return enforceRevisions Does the blob enforce revisions?
     */
    function getEnforceRevisions(bytes32 id) noValue exists(id) constant external returns (bool enforceRevisions) {
        enforceRevisions = idBlobInfo[id].enforceRevisions;
    }

    /**
     * @dev Is a blob retractable?
     * @param id Id of the blob.
     * @return retractable Is the blob retractable?
     */
    function getRetractable(bytes32 id) noValue exists(id) constant external returns (bool retractable) {
        retractable = idBlobInfo[id].retractable;
    }

    /**
     * @dev Is a blob transferable.
     * @param id Id of the blob.
     * @return transferable Is the blob transferable?
     */
    function getTransferable(bytes32 id) noValue exists(id) constant external returns (bool transferable) {
        transferable = idBlobInfo[id].transferable;
    }

    /**
     * @dev Get the number of revisions a blob has.
     * @param id Id of the blob.
     * @return numRevisions How many revisions the blob has.
     */
    function getNumRevisions(bytes32 id) noValue exists(id) constant external returns (uint numRevisions) {
        numRevisions = idBlobInfo[id].numRevisions;
    }

    /**
     * @dev Get the block number for a specific blob revision.
     * @param id Id of the blob.
     * @param revisionId Id of the revision.
     * @return blockNumber Block number of the specified revision.
     */
    function getRevisionBlockNumber(bytes32 id, uint revisionId) noValue exists(id) revisionExists(id, revisionId) constant returns (uint blockNumber) {
        if (revisionId == 0) {
            blockNumber = idBlobInfo[id].blockNumber;
        }
        else {
            bytes32 slot = idPackedRevisionBlockNumbers[id][(revisionId - 1) / 8];
            blockNumber = uint32(uint256(slot) / 2 ** (((revisionId - 1) % 8) * 32));
        }
    }

    /**
     * @dev Default function.
     */
    function() {
        throw;      // Do not maintain a balance.
    }

}


fixing vulnerability of state modification by send

contract MicropaymentsChannel {
    enum Stage {
        Empty,
        PartiallyConfirmed,
        Confirmed,
        Closing,
        Closed
    }

    uint public constant closingBlockDelay = 10;

    Stage public stage;
    uint public id;
    address public from;
    uint public fromBalance;
    address public to;
    uint public toBalance;
    uint public balanceTimestamp;

    uint public closingBlockNumber;

    function MicropaymentsChannel(address _from, address _to, uint _id) {
        stage = Stage.Empty;
        id  = _id;
        from = _from;
        fromBalance = 0;
        to = _to;
        toBalance = 0;
        balanceTimestamp = 0;
    }

    modifier onlyFrom {
        if (msg.sender != from) {
            throw;
        }
        _
    }

   modifier onlyTo {
        if (msg.sender != to) {
            throw;
        }
        _
    }

    modifier onlyParticipants {
        if ((msg.sender != from) && (msg.sender != to)) {
            throw;
        }
        _
    }

    modifier atStage(Stage _stage) {
        if (stage != _stage) {
            throw;
        }
        _
    }

    modifier atOneOfStages(Stage _stage1, Stage _stage2) {
        if ((stage != _stage1) && (stage != _stage2)) {
            throw;
        }
        _
    }

    modifier readyToClose() {
        if (block.number < closingBlockNumber) {
            throw;
        }
        _
    }

    function assertYoungerBalance(uint _balanceTimestamp) internal {
        if (_balanceTimestamp <= balanceTimestamp) {
            throw;
        }
    }

    function assertSaneBalance(uint _fromBalance, uint _toBalance) internal {
        if (fromBalance + toBalance < _fromBalance + _toBalance) {
            throw;
        }
    }

    function assertMessageHash(bytes32 _expected, bytes32 _sigHash) internal {
        if (_expected != _sigHash) {
            throw;
        }
    }

    function assertSignedByBoth(
        bytes32 _sigHash,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS
    ) internal {
        address receiver = ecrecover(_sigHash, _sigV, _sigR, _sigS);
        if (!(((from == msg.sender) && (to == receiver)) ||
              ((from == receiver) && (to == msg.sender)))) {
            throw;
        }
    }

    function getUpdateHash(
        uint _balanceTimestamp,
        uint _fromBalance,
        uint _toBalance
    ) constant returns(bytes32) {
        return sha3(id, _balanceTimestamp, _fromBalance, _toBalance);
    }

    function getSigner(
        bytes32 _sigHash,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS
    ) constant returns(address) {
        return ecrecover(_sigHash, _sigV, _sigR, _sigS);
    }

    function openChannel()
        onlyFrom
        atStage(Stage.Empty)
    {
        stage = Stage.PartiallyConfirmed;
        fromBalance = msg.value;
    }

    function confirmChannel()
        onlyTo
        atStage(Stage.PartiallyConfirmed)
    {
        stage = Stage.Confirmed;
        toBalance = msg.value;
    }

    function requestClosingChannel()
        onlyParticipants
        atOneOfStages(Stage.PartiallyConfirmed, Stage.Confirmed)
    {
        if (stage == Stage.PartiallyConfirmed) {
            suicide(from);
        } else {
            stage = Stage.Closing;
            closingBlockNumber = block.number + closingBlockDelay;
        }
    }

    function closeChannel()
        onlyParticipants
        atStage(Stage.Closing)
        readyToClose
    {
        stage = Stage.Closed;
        from.send(fromBalance);
        suicide(to);
    }

    function updateChannelState(
        uint _balanceTimestamp,
        uint _fromBalance,
        uint _toBalance,
        bytes32 _sigHash,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS
    )
        onlyParticipants
        atOneOfStages(Stage.Confirmed, Stage.Closing)
    {
        assertYoungerBalance(_balanceTimestamp);
        assertSaneBalance(_fromBalance, _toBalance);
        assertMessageHash(getUpdateHash(_balanceTimestamp, _fromBalance, _toBalance), _sigHash);
        assertSignedByBoth(_sigHash, _sigV, _sigR, _sigS);
        balanceTimestamp = _balanceTimestamp;
        fromBalance = _fromBalance;
        toBalance = _toBalance;
    }
}

contract MicropaymentsChannel {
    enum Stage {
        Empty,
        PartiallyConfirmed,
        Confirmed,
        Closing
    }

    uint public constant closingBlockDelay = 10;

    Stage public stage;
    uint public id;
    address public from;
    uint public fromBalance;
    address public to;
    uint public toBalance;
    uint public balanceTimestamp;

    uint public closingBlockNumber;

    function MicropaymentsChannel(address _from, address _to, uint _id) {
        stage = Stage.Empty;
        id  = _id;
        from = _from;
        fromBalance = 0;
        to = _to;
        toBalance = 0;
        balanceTimestamp = 0;
    }

    modifier onlyFrom {
        if (msg.sender != from) {
            throw;
        }
        _
    }

   modifier onlyTo {
        if (msg.sender != to) {
            throw;
        }
        _
    }

    modifier onlyParticipants {
        if ((msg.sender != from) && (msg.sender != to)) {
            throw;
        }
        _
    }

    modifier atStage(Stage _stage) {
        if (stage != _stage) {
            throw;
        }
        _
    }

    modifier atOneOfStages(Stage _stage1, Stage _stage2) {
        if ((stage != _stage1) && (stage != _stage2)) {
            throw;
        }
        _
    }

    modifier readyToClose() {
        if (block.number < closingBlockNumber) {
            throw;
        }
        _
    }

    function assertYoungerBalance(uint _balanceTimestamp) internal {
        if (_balanceTimestamp <= balanceTimestamp) {
            throw;
        }
    }

    function assertSaneBalance(uint _fromBalance, uint _toBalance) internal {
        if (fromBalance + toBalance < _fromBalance + _toBalance) {
            throw;
        }
    }

    function assertMessageHash(bytes32 _expected, bytes32 _sigHash) internal {
        if (_expected != _sigHash) {
            throw;
        }
    }

    function assertSignedByBoth(
        bytes32 _sigHash,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS
    ) internal {
        address receiver = ecrecover(_sigHash, _sigV, _sigR, _sigS);
        if (!(((from == msg.sender) && (to == receiver)) ||
              ((from == receiver) && (to == msg.sender)))) {
            throw;
        }
    }

    function openChannel()
        onlyFrom
        atStage(Stage.Empty)
    {
        stage = Stage.PartiallyConfirmed;
        fromBalance = msg.value;
    }

    function confirmChannel()
        onlyTo
        atStage(Stage.PartiallyConfirmed)
    {
        stage = Stage.Confirmed;
        toBalance = msg.value;
    }

    function requestClosingChannel()
        onlyParticipants
        atOneOfStages(Stage.PartiallyConfirmed, Stage.Confirmed)
    {
        if (stage == Stage.PartiallyConfirmed) {
            suicide(from);
        } else {
            stage = Stage.Closing;
            closingBlockNumber = block.number + closingBlockDelay;
        }
    }

    function closeChannel()
        onlyParticipants
        atStage(Stage.Closing)
        readyToClose
    {
        from.send(fromBalance);
        suicide(to);
    }

    function getUpdateHash(
        uint _balanceTimestamp,
        uint _fromBalance,
        uint _toBalance
    ) constant returns(bytes32) {
        return sha3(id, _balanceTimestamp, _fromBalance, _toBalance);
    }

    function getSigner(
        bytes32 _sigHash,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS
    ) constant returns(address) {
        return ecrecover(_sigHash, _sigV, _sigR, _sigS);
    }

    function updateChannelState(
        uint _balanceTimestamp,
        uint _fromBalance,
        uint _toBalance,
        bytes32 _sigHash,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS
    )
        onlyParticipants
        atOneOfStages(Stage.Confirmed, Stage.Closing)
    {
        assertYoungerBalance(_balanceTimestamp);
        assertSaneBalance(_fromBalance, _toBalance);
        assertMessageHash(getUpdateHash(_balanceTimestamp, _fromBalance, _toBalance), _sigHash);
        assertSignedByBoth(_sigHash, _sigV, _sigR, _sigS);
        balanceTimestamp = _balanceTimestamp;
        fromBalance = _fromBalance;
        toBalance = _toBalance;
    }
}


Added version pgrama in migration

Added version pgrama in migration

pragma solidity ^0.4.0;

contract Migrations {
  address public owner;

  // A function with the signature `last_completed_migration()`, returning a uint, is required.
  uint public last_completed_migration;

  modifier restricted() {
    if (msg.sender != owner) throw;
    _
  }

  function Migrations() {
    owner = msg.sender;
  }

  // A function with the signature `setCompleted(uint)` is required.
  function setCompleted(uint completed) restricted {
    last_completed_migration = completed;
  }

  function upgrade(address new_address) restricted {
    Migrations upgraded = Migrations(new_address);
    upgraded.setCompleted(last_completed_migration);
  }
}


Can not register as worker more than once.

contract WorkAgreement {
    address client;
    address worker;
    mapping (address => bool) testers;
    uint price;
    uint end;

    function WorkAgreement(address _client, address _worker, uint _price,
                           uint length) {
        client = _client;
        worker = _worker;
        price = _price;
        end = length;
    }

    function addTester(address tester) {
        testers[tester] = true;
    }
}

contract WorkerDispatcher {
    struct Worker {
        string32 name;
        uint maxLength;
        uint price;
    }
    mapping (address => Worker) public workersInfo;
    uint public numWorkers;
    mapping (uint => address) public workerList;

    function buyContract(address worker, uint redundancy, uint price,
                         uint length) returns (address addr) {
        if (msg.value < length * price &&
            workersInfo[worker].name == "" &&
            workersInfo[worker].maxLength < length) return;
        WorkAgreement wa = new WorkAgreement(msg.sender, worker,
                                             price, length);
        // TODO - create better way to asign testers
        for (uint i = 1; i < 3; i++) {
            uint n = uint(block.blockhash(block.number - i)) % numWorkers;
            if (workerList[n] == worker) continue;
            wa.addTester(workerList[n]);
        }
        return wa;
    }

    function registerWorker(uint maxLength, uint price, string32 name) {
        if (workersInfo[msg.sender].name == "") {
            workerList[numWorkers++] = msg.sender;
        }
        Worker w = workersInfo[msg.sender];
        w.name = name;
        w.maxLength = maxLength;
        w.price = price;
    }

    function changeWorkerPrice(uint newPrice) {
        workersInfo[msg.sender].price = newPrice;
    }
}

contract WorkAgreement {
    address client;
    address worker;
    mapping (address => bool) testers;
    uint price;
    uint end;

    function WorkAgreement(address _client, address _worker, uint _price,
                           uint length) {
        client = _client;
        worker = _worker;
        price = _price;
        end = length;
    }

    function addTester(address tester) {
        testers[tester] = true;
    }
}

contract WorkerDispatcher {
    struct Worker {
        string32 name;
        uint maxLength;
        uint price;
    }
    mapping (address => Worker) public workersInfo;
    uint public numWorkers;
    mapping (uint => address) public workerList;

    function buyContract(address worker, uint redundancy, uint price,
                         uint length) returns (address addr) {
        if (msg.value < length * price &&
            workersInfo[worker].name == "" &&
            workersInfo[worker].maxLength < length) return;
        WorkAgreement wa = new WorkAgreement(msg.sender, worker,
                                             price, length);
        // TODO - create better way to asign testers
        for (uint i = 1; i < 3; i++) {
            uint n = uint(block.blockhash(block.number - i)) % numWorkers;
            if (workerList[n] == worker) continue;
            wa.addTester(workerList[n]);
        }
        return wa;
    }

    function registerWorker(uint maxLength, uint price, string32 name) {
        workerList[numWorkers++] = msg.sender;
        Worker w = workersInfo[msg.sender];
        w.name = name;
        w.maxLength = maxLength;
        w.price = price;
    }

    function changeWorkerPrice(uint newPrice) {
        workersInfo[msg.sender].price = newPrice;
    }
}


Bug fixes

Bug fixes

import 'token/TokenEmission.sol';
import 'common/Mortal.sol';

/**
  @title Token ἄμβιξ

           .
          C..1
           fL
          GLi11
          if i11t11:
         ,.t. .  ;,:1i,t
       .,:i  .:1f..,  .,:i:1
      i.1f.  .    ,f .ftt...,i;;
     i.11 . . .   . ,     .f11..,i1:
     ,,1,   .     .  1         .ft1 ,11.
     :1Lf:::, ,,,,,..:              .tf;,:i.
     fCCCLffL ittCCCff                    Lf;1t
    .iGCCCLttLftCCCCCi.                       ,:
      t,GGGCCCLLCCGC                        ;i;1i:
     ,;  :ftttiit.::,                      Litf1fft1
     L       GC    LC                      1,. .. t,
    C        ;t    1.;                     t,.....1,
   t:        ;t     fC.11.                 1ti;;:;1,
  ;ftti1t1tfCLGfCCLCCfL1ft1i1i1t1fftfffftffCGCfttCC,
  ,i11ii;1;tC;CCCL1t1ft111t1tittii1i11i1ii;111LCLCC,

  @dev Ambix contract is used for morph Token set to another
  Token's by rule (recipe). In distillation process given
  Token's are burned and result generated by emission.

  The recipe presented as equation in form:
  (N1 * A1 | N'1 * A'1 | N''1 * A''1 ...)
  & (N2 * A2 | N'2 * A'2 | N''2 * A''2 ...) ...
  & (Nn * An | N'n * A'n | N''n * A''n ...)
  = M1 * B1 & M2 * B2 ... & Mm * Bm
    where A, B - input and output tokens
          N, M - token value coeficients
          n, m - input / output dimetion size
          | - is alternative operator (logical OR)
          & - is associative operator (logical AND)
  This says that `Ambix` should receive (approve) left
  part of equation and send (transfer) right part.
*/
contract Ambix is Mortal {
    /* Recipe fields */
    TokenEmission[][] public rSource;
    uint[][]          public rSourceCoef;
    TokenEmission[]   public rSink;
    uint[]            public rSinkCoef;
    /* Recipe end */

    /**
     * @dev Set source by index
     * @param _index is a source index
     * @param _source is a list of source alternatives
     * @param _coef is a list of source alternatives coeficients
     */
    function setSource(uint _index, TokenEmission[] _source, uint[] _coef) onlyOwner {
        if (_source.length != _coef.length) throw;

        // Lenght fix
        if (rSource.length < _index + 1) {
            rSource.length = _index + 1;
            rSourceCoef.length = _index + 1;
        }

        // Push values
        delete rSource[_index];
        delete rSourceCoef[_index];
        for (uint i = 0; i < _source.length; ++i) {
            rSource[_index].push(_source[i]);
            rSourceCoef[_index].push(_coef[i]);
        }
    }

    /**
     * @dev Set sink
     * @param _sink is a list of sink tokens
     * @param _coef is a list of sink coeficients
     */
    function setSink(TokenEmission[] _sink, uint[] _coef) onlyOwner {
        if (_sink.length != _coef.length) throw;

        delete rSink;
        delete rSource;
        for (uint i = 0; i < _sink.length; ++i) {
            rSink.push(_sink[i]);
            rSinkCoef.push(_coef[i]);
        }
    }

    /**
     * @dev Run distillation process
     * @notice Input tokens(any one of alternative) should be approved to this
     */
    function run() {
        TokenEmission token;
        uint value;
        uint i;
        uint j;

        // Take a source tokens
        for (i = 0; i < rSource.length; ++i) {
            bool tokenBurned = false;

            // Try to transfer alternatives and burn it
            for (j = 0; j < rSource[i].length; ++j) {
                token = rSource[i][j];
                value = rSourceCoef[i][j];
                if (token.transferFrom(msg.sender, this, value)) {
                    token.burn(value);
                    tokenBurned = true;
                    break;
                }
            }

            if (!tokenBurned) throw;
        }

        // Generate sink tokens
        for (i = 0; i < rSink.length; ++i) {
            token = rSink[i];
            value = rSinkCoef[i];
            token.emission(value);
            if (!token.transfer(msg.sender, value)) throw;
        }
    }
}

import 'token/TokenEmission.sol';
import 'common/Mortal.sol';

/**
  @title Token ἄμβιξ

           .
          C..1
           fL
          GLi11
          if i11t11:
         ,.t. .  ;,:1i,t
       .,:i  .:1f..,  .,:i:1
      i.1f.  .    ,f .ftt...,i;;
     i.11 . . .   . ,     .f11..,i1:
     ,,1,   .     .  1         .ft1 ,11.
     :1Lf:::, ,,,,,..:              .tf;,:i.
     fCCCLffL ittCCCff                    Lf;1t
    .iGCCCLttLftCCCCCi.                       ,:
      t,GGGCCCLLCCGC                        ;i;1i:
     ,;  :ftttiit.::,                      Litf1fft1
     L       GC    LC                      1,. .. t,
    C        ;t    1.;                     t,.....1,
   t:        ;t     fC.11.                 1ti;;:;1,
  ;ftti1t1tfCLGfCCLCCfL1ft1i1i1t1fftfffftffCGCfttCC,
  ,i11ii;1;tC;CCCL1t1ft111t1tittii1i11i1ii;111LCLCC,

  @dev Ambix contract is used for morph Token set to another
  Token's by rule (recipe). In distillation process given
  Token's are burned and result generated by emission.

  The recipe presented as equation in form:
  (N1 * A1 | N'1 * A'1 | N''1 * A''1 ...)
  & (N2 * A2 | N'2 * A'2 | N''2 * A''2 ...) ...
  & (Nn * An | N'n * A'n | N''n * A''n ...)
  = M1 * B1 & M2 * B2 ... & Mm * Bm
    where A, B - input and output tokens
          N, M - token value coeficients
          n, m - input / output dimetion size
          | - is alternative operator (logical OR)
          & - is associative operator (logical AND)
  This says that `Ambix` should receive (approve) left
  part of equation and send (transfer) right part.
*/
contract Ambix is Mortal {
    struct Recipe {
        TokenEmission[][] source;
        uint[][]          sourceCoef;
        TokenEmission[]   sink;
        uint[]            sinkCoef;
    }
    Recipe recipe;

    /**
     * @dev Set source by index
     * @param _index is a source index
     * @param _source is a list of source alternatives
     * @param _coef is a list of source alternatives coeficients
     */
    function setSource(uint _index, TokenEmission[] _source, uint[] _coef) onlyOwner {
        if (_source.length != _coef.length) throw;
        recipe.source[_index]     = _source;
        recipe.sourceCoef[_index] = _coef;
    }

    /**
     * @dev Set sink
     * @param _sink is a list of sink tokens
     * @param _coef is a list of sink coeficients
     */
    function setSink(TokenEmission[] _sink, uint[] _coef) onlyOwner {
        if (_sink.length != _coef.length) throw;
        recipe.sink     = _sink;
        recipe.sinkCoef = _coef;
    }

    /**
     * @dev Get source by index
     * @param _index is a source index
     * @return list of source alternatives and its coeficients
     */
    function getSource(uint _index) constant returns (address[], uint[]) {
        var source = recipe.source[_index];
        address[] memory sourceOut;
        for (uint i = 0; i < source.length; ++i)
            sourceOut[i] = source[i];
        return (sourceOut, recipe.sourceCoef[_index]);
    }

    /**
     * @dev Get sink
     * @return list of source alternatives and its coeficients
     */
    function getSink() constant returns (address[], uint[]) {
        address[] memory sinkOut;
        for (uint i = 0; i < recipe.sink.length; ++i)
            sinkOut[i] = recipe.sink[i];
        return (sinkOut, recipe.sinkCoef);
    }

    /**
     * @dev Run distillation process
     * @notice Input tokens(any one of alternative) should be approved to this
     */
    function run() {
        TokenEmission token;
        uint value;
        uint i;
        uint j;

        // Take a source tokens
        for (i = 0; i < recipe.source.length; ++i) {
            bool tokenBurned = false;

            // Try to transfer alternatives and burn it
            for (j = 0; j < recipe.source[i].length; ++j) {
                token = recipe.source[i][j];
                value = recipe.sourceCoef[i][j];
                if (token.transferFrom(msg.sender, this, value)) {
                    token.burn(value);
                    tokenBurned = true;
                    break;
                }
            }

            if (!tokenBurned) throw;
        }

        // Generate sink tokens
        for (i = 0; i < recipe.sink.length; ++i) {
            token = recipe.sink[i];
            value = recipe.sinkCoef[i];
            token.emission(recipe.sinkCoef[i]);
            if (!token.transfer(msg.sender, value)) throw;
        }
    }
}


- Made proposeSettlement to be able to be executed at Execution stage too

pragma solidity ^0.4.2;

import "./priced.sol";
import "./stateMachine.sol";
import "./accessRestricted.sol";

/// @title Brehon Contract
contract BrehonContract is
    priced,
    stateMachine,
    accessRestricted {

  struct Party {
    address addr;
    uint deposit;
    bool contractAccepted;
  }

  struct Brehon {
    address addr;
    bool contractAccepted;
    uint fixedFee;
    uint disputeFee;
  }

  struct Resolution {
    address proposerAddr;
    uint awardPartyA;
    uint awardPartyB;
    bool partyAAccepted;
    bool partyBAccepted;
  }

  int8 public appealLevel;
  uint public transactionAmount;
  bytes32 public contractTermsHash;
  Party public partyA;
  Party public partyB;
  Brehon public primaryBrehon;
  Brehon public secondaryBrehon;
  Brehon public tertiaryBrehon;
  Brehon public activeBrehon;

  mapping (address => uint) awards;
  Resolution public proposedSettlement;

  uint appealPeriodInDays = 5;
  uint public appealPeriodStartTime;

  event ExecutionStarted(address _caller, uint _totalDeposits);
  event ContractDisputed(address _disputingParty, address _activeBrehon);
  event AppealPeriodStarted(int8 _appealLevel, uint _startTime, address _activeBrehon, uint _awardPartyA, uint _awardPartyB);
  //TODO: Provide the information about the party which appaled
  event AppealRaised(int8 _appealLevel, address _activeBrehon);
  event SettlementProposed(address _proposingParty, uint _awardPartyA, uint _awardPartyB);
  event DisputeResolved(uint _awardPartyA, uint _awardPartyB);

  modifier eitherByParty(Party _party1, Party _party2)
  {
    if (msg.sender != _party1.addr &&
        msg.sender != _party2.addr)
        throw;
    _;
  }

  modifier afterContractStarts()
  {
    if(stage != Stages.Execution &&
       stage != Stages.Dispute &&
       stage != Stages.AppealPeriod &&
       stage != Stages.Appeal)
        throw;
    _;
  }

  modifier eitherByBrehon(Brehon _brehon1, Brehon _brehon2, Brehon _brehon3)
  {
    if (msg.sender != _brehon1.addr ||
        msg.sender != _brehon2.addr ||
        msg.sender != _brehon3.addr)
        throw;
    _;
  }

  modifier onlyByBrehon(Brehon _brehon) {
    if (msg.sender != _brehon.addr)
        throw;
    _;
  }

  function BrehonContract(
      address _partyA,
      address _partyB,
      uint _transactionAmount,
      bytes32 _contractTermsHash,
      address _primaryBrehon,
      uint _primaryBrehonFixedFee,
      uint _primaryBrehonDisputeFee,
      address _secondaryBrehon,
      uint _secondaryBrehonFixedFee,
      uint _secondaryBrehonDisputeFee,
      address _tertiaryBrehon,
      uint _tertiaryBrehonFixedFee,
      uint _tertiaryBrehonDisputeFee
  ) {
    partyA.addr = _partyA;
    transactionAmount = _transactionAmount;
    contractTermsHash = _contractTermsHash;

    partyB.addr = _partyB;

    primaryBrehon.addr = _primaryBrehon;
    primaryBrehon.fixedFee = _primaryBrehonFixedFee;
    primaryBrehon.disputeFee = _primaryBrehonDisputeFee;

    secondaryBrehon.addr = _secondaryBrehon;
    secondaryBrehon.fixedFee = _secondaryBrehonFixedFee;
    secondaryBrehon.disputeFee = _secondaryBrehonDisputeFee;

    tertiaryBrehon.addr = _tertiaryBrehon;
    tertiaryBrehon.fixedFee = _tertiaryBrehonFixedFee;
    tertiaryBrehon.disputeFee = _tertiaryBrehonDisputeFee;

    //Defaults
    stage = Stages.Negotiation;
    appealLevel = -1;
    partyA.contractAccepted = false;
    partyA.deposit = 0;

    partyB.contractAccepted = false;
    partyB.deposit = 0;

    primaryBrehon.contractAccepted = false;
    secondaryBrehon.contractAccepted = false;
    tertiaryBrehon.contractAccepted = false;
  }

  function acceptContract()
    atStage(Stages.Negotiation)
  {
      if (msg.sender == partyA.addr) {
          partyA.contractAccepted = true;
      } else if (msg.sender == partyB.addr) {
          partyB.contractAccepted = true;
      } else if(msg.sender == primaryBrehon.addr) {
          primaryBrehon.contractAccepted = true;
      } else if(msg.sender == secondaryBrehon.addr) {
          secondaryBrehon.contractAccepted = true;
      } else if(msg.sender == tertiaryBrehon.addr) {
          tertiaryBrehon.contractAccepted = true;
      } else throw;
  }

  function deposit()
    payable
  {
      if(msg.sender == partyA.addr) {
          partyA.deposit += msg.value;
      } else if (msg.sender == partyB.addr) {
          partyB.deposit += msg.value;
      } else throw;
  }

  function startContract()
    atStage(Stages.Negotiation)
    eitherByParty(partyA, partyB)
  {
      if(!partyA.contractAccepted ||
         !partyB.contractAccepted ||
         !primaryBrehon.contractAccepted ||
         !secondaryBrehon.contractAccepted ||
         !tertiaryBrehon.contractAccepted) throw;

      if ((partyA.deposit + partyB.deposit) >=
          (primaryBrehon.fixedFee + primaryBrehon.disputeFee +
          secondaryBrehon.fixedFee + secondaryBrehon.disputeFee +
          tertiaryBrehon.fixedFee + tertiaryBrehon.disputeFee +
          transactionAmount)
         ) {
             ExecutionStarted(msg.sender, partyA.deposit + partyB.deposit);
             stage = Stages.Execution;
      } else throw;
  }

  function raiseDispute()
    atStage(Stages.Execution)
    eitherByParty(partyA, partyB)
  {
    stage = Stages.Dispute;
    appealLevel = 0;
    activeBrehon = primaryBrehon;
    ContractDisputed(msg.sender, primaryBrehon.addr);
  }

  function adjudicate(uint _awardPartyA, uint _awardPartyB)
    atStage(Stages.Dispute)
    onlyByBrehon(activeBrehon)
  {
    if((_awardPartyA + _awardPartyB) > (partyA.deposit + partyB.deposit)) throw;

    stage = Stages.AppealPeriod;
    appealPeriodStartTime = now;

    awards[partyA.addr] = _awardPartyA;
    awards[partyB.addr] = _awardPartyB;

    AppealPeriodStarted(appealLevel, appealPeriodInDays, activeBrehon.addr, _awardPartyA, _awardPartyB);
  }

  function getActiveJudgmentByParty(address _partyAddress)
    returns (uint)
  {
      if(_partyAddress != partyA.addr &&
         _partyAddress != partyB.addr) throw;
    return awards[_partyAddress];
  }

  function claimFunds()
    timedTransition(appealPeriodStartTime, appealPeriodInDays, Stages.AppealPeriod, Stages.Completed)
    atStage(Stages.Completed)
    eitherByParty(partyA, partyB)
    returns (bool)
  {
    uint amount = awards[msg.sender];
    awards[msg.sender] = 0;
    if(msg.sender.send(amount)) {
      return true;
    } else {
      awards[msg.sender] = amount;
      return false;
    }
  }

  function raiseAppeal()
    atStage(Stages.AppealPeriod)
    eitherByParty(partyA, partyB)
  {
    stage = Stages.Dispute;
    appealLevel = 1;

    activeBrehon = secondaryBrehon;

    AppealRaised(appealLevel, activeBrehon.addr);
  }

  function raise2ndAppeal()
    atStage(Stages.AppealPeriod)
    eitherByParty(partyA, partyB)
  {
    stage = Stages.Dispute;
    appealLevel = 2;

    activeBrehon = tertiaryBrehon;

    AppealRaised(appealLevel, activeBrehon.addr);
  }

  function proposeSettlement(uint _awardPartyA, uint _awardPartyB)
    afterContractStarts()
    eitherByParty(partyA, partyB)
  {
      proposedSettlement.proposerAddr = msg.sender;
      proposedSettlement.awardPartyA = _awardPartyA;
      proposedSettlement.awardPartyB = _awardPartyB;
      if (msg.sender == partyA.addr) {
          proposedSettlement.partyAAccepted = true;
          proposedSettlement.partyBAccepted = false;
      } else if (msg.sender == partyB.addr) {
          proposedSettlement.partyAAccepted = false;
          proposedSettlement.partyBAccepted = true;
      }

      SettlementProposed(msg.sender, _awardPartyA, _awardPartyB);
  }

  function acceptSettlement(uint _awardPartyA, uint _awardPartyB)
    afterContractStarts()
    eitherByParty(partyA, partyB)
  {
      if((proposedSettlement.awardPartyA != _awardPartyA) ||
         (proposedSettlement.awardPartyB != _awardPartyB))
          throw;

      if(msg.sender == partyA.addr) {
        proposedSettlement.partyAAccepted = true;
      }

      if(msg.sender == partyB.addr) {
        proposedSettlement.partyBAccepted = true;
      }

      if(proposedSettlement.partyAAccepted && proposedSettlement.partyBAccepted) {
        stage = Stages.Completed;
        DisputeResolved(_awardPartyA, _awardPartyB);
      }
  }
}

pragma solidity ^0.4.2;

import "./priced.sol";
import "./stateMachine.sol";
import "./accessRestricted.sol";

/// @title Brehon Contract
contract BrehonContract is
    priced,
    stateMachine,
    accessRestricted {

  struct Party {
    address addr;
    uint deposit;
    bool contractAccepted;
  }

  struct Brehon {
    address addr;
    bool contractAccepted;
    uint fixedFee;
    uint disputeFee;
  }

  struct Resolution {
    address proposerAddr;
    uint awardPartyA;
    uint awardPartyB;
    bool partyAAccepted;
    bool partyBAccepted;
  }

  int8 public appealLevel;
  uint public transactionAmount;
  bytes32 public contractTermsHash;
  Party public partyA;
  Party public partyB;
  Brehon public primaryBrehon;
  Brehon public secondaryBrehon;
  Brehon public tertiaryBrehon;
  Brehon public activeBrehon;

  mapping (address => uint) awards;
  Resolution public proposedSettlement;

  uint appealPeriodInDays = 5;
  uint public appealPeriodStartTime;

  event ExecutionStarted(address _caller, uint _totalDeposits);
  event ContractDisputed(address _disputingParty, address _activeBrehon);
  event AppealPeriodStarted(int8 _appealLevel, uint _startTime, address _activeBrehon, uint _awardPartyA, uint _awardPartyB);
  //TODO: Provide the information about the party which appaled
  event AppealRaised(int8 _appealLevel, address _activeBrehon);
  event SettlementProposed(address _proposingParty, uint _awardPartyA, uint _awardPartyB);
  event DisputeResolved(uint _awardPartyA, uint _awardPartyB);

  modifier eitherByParty(Party _party1, Party _party2)
  {
    if (msg.sender != _party1.addr &&
        msg.sender != _party2.addr)
        throw;
    _;
  }

  modifier atConflictStages()
  {
    if(stage != Stages.Dispute &&
       stage != Stages.AppealPeriod &&
       stage != Stages.Appeal)
        throw;
    _;
  }

  modifier eitherByBrehon(Brehon _brehon1, Brehon _brehon2, Brehon _brehon3)
  {
    if (msg.sender != _brehon1.addr ||
        msg.sender != _brehon2.addr ||
        msg.sender != _brehon3.addr)
        throw;
    _;
  }

  modifier onlyByBrehon(Brehon _brehon) {
    if (msg.sender != _brehon.addr)
        throw;
    _;
  }

  function BrehonContract(
      address _partyA,
      address _partyB,
      uint _transactionAmount,
      bytes32 _contractTermsHash,
      address _primaryBrehon,
      uint _primaryBrehonFixedFee,
      uint _primaryBrehonDisputeFee,
      address _secondaryBrehon,
      uint _secondaryBrehonFixedFee,
      uint _secondaryBrehonDisputeFee,
      address _tertiaryBrehon,
      uint _tertiaryBrehonFixedFee,
      uint _tertiaryBrehonDisputeFee
  ) {
    partyA.addr = _partyA;
    transactionAmount = _transactionAmount;
    contractTermsHash = _contractTermsHash;

    partyB.addr = _partyB;

    primaryBrehon.addr = _primaryBrehon;
    primaryBrehon.fixedFee = _primaryBrehonFixedFee;
    primaryBrehon.disputeFee = _primaryBrehonDisputeFee;

    secondaryBrehon.addr = _secondaryBrehon;
    secondaryBrehon.fixedFee = _secondaryBrehonFixedFee;
    secondaryBrehon.disputeFee = _secondaryBrehonDisputeFee;

    tertiaryBrehon.addr = _tertiaryBrehon;
    tertiaryBrehon.fixedFee = _tertiaryBrehonFixedFee;
    tertiaryBrehon.disputeFee = _tertiaryBrehonDisputeFee;

    //Defaults
    stage = Stages.Negotiation;
    appealLevel = -1;
    partyA.contractAccepted = false;
    partyA.deposit = 0;

    partyB.contractAccepted = false;
    partyB.deposit = 0;

    primaryBrehon.contractAccepted = false;
    secondaryBrehon.contractAccepted = false;
    tertiaryBrehon.contractAccepted = false;
  }

  function acceptContract()
    atStage(Stages.Negotiation)
  {
      if (msg.sender == partyA.addr) {
          partyA.contractAccepted = true;
      } else if (msg.sender == partyB.addr) {
          partyB.contractAccepted = true;
      } else if(msg.sender == primaryBrehon.addr) {
          primaryBrehon.contractAccepted = true;
      } else if(msg.sender == secondaryBrehon.addr) {
          secondaryBrehon.contractAccepted = true;
      } else if(msg.sender == tertiaryBrehon.addr) {
          tertiaryBrehon.contractAccepted = true;
      } else throw;
  }

  function deposit()
    payable
  {
      if(msg.sender == partyA.addr) {
          partyA.deposit += msg.value;
      } else if (msg.sender == partyB.addr) {
          partyB.deposit += msg.value;
      } else throw;
  }

  function startContract()
    atStage(Stages.Negotiation)
    eitherByParty(partyA, partyB)
  {
      if(!partyA.contractAccepted ||
         !partyB.contractAccepted ||
         !primaryBrehon.contractAccepted ||
         !secondaryBrehon.contractAccepted ||
         !tertiaryBrehon.contractAccepted) throw;

      if ((partyA.deposit + partyB.deposit) >=
          (primaryBrehon.fixedFee + primaryBrehon.disputeFee +
          secondaryBrehon.fixedFee + secondaryBrehon.disputeFee +
          tertiaryBrehon.fixedFee + tertiaryBrehon.disputeFee +
          transactionAmount)
         ) {
             ExecutionStarted(msg.sender, partyA.deposit + partyB.deposit);
             stage = Stages.Execution;
      } else throw;
  }

  function raiseDispute()
    atStage(Stages.Execution)
    eitherByParty(partyA, partyB)
  {
    stage = Stages.Dispute;
    appealLevel = 0;
    activeBrehon = primaryBrehon;
    ContractDisputed(msg.sender, primaryBrehon.addr);
  }

  function adjudicate(uint _awardPartyA, uint _awardPartyB)
    atStage(Stages.Dispute)
    onlyByBrehon(activeBrehon)
  {
    if((_awardPartyA + _awardPartyB) > (partyA.deposit + partyB.deposit)) throw;

    stage = Stages.AppealPeriod;
    appealPeriodStartTime = now;

    awards[partyA.addr] = _awardPartyA;
    awards[partyB.addr] = _awardPartyB;

    AppealPeriodStarted(appealLevel, appealPeriodInDays, activeBrehon.addr, _awardPartyA, _awardPartyB);
  }

  function getActiveJudgmentByParty(address _partyAddress)
    returns (uint)
  {
      if(_partyAddress != partyA.addr &&
         _partyAddress != partyB.addr) throw;
    return awards[_partyAddress];
  }

  function claimFunds()
    timedTransition(appealPeriodStartTime, appealPeriodInDays, Stages.AppealPeriod, Stages.Completed)
    atStage(Stages.Completed)
    eitherByParty(partyA, partyB)
    returns (bool)
  {
    uint amount = awards[msg.sender];
    awards[msg.sender] = 0;
    if(msg.sender.send(amount)) {
      return true;
    } else {
      awards[msg.sender] = amount;
      return false;
    }
  }

  function raiseAppeal()
    atStage(Stages.AppealPeriod)
    eitherByParty(partyA, partyB)
  {
    stage = Stages.Dispute;
    appealLevel = 1;

    activeBrehon = secondaryBrehon;

    AppealRaised(appealLevel, activeBrehon.addr);
  }

  function raise2ndAppeal()
    atStage(Stages.AppealPeriod)
    eitherByParty(partyA, partyB)
  {
    stage = Stages.Dispute;
    appealLevel = 2;

    activeBrehon = tertiaryBrehon;

    AppealRaised(appealLevel, activeBrehon.addr);
  }

  function proposeSettlement(uint _awardPartyA, uint _awardPartyB)
    atConflictStages()
    eitherByParty(partyA, partyB)
  {
      proposedSettlement.proposerAddr = msg.sender;
      proposedSettlement.awardPartyA = _awardPartyA;
      proposedSettlement.awardPartyB = _awardPartyB;
      if (msg.sender == partyA.addr) {
          proposedSettlement.partyAAccepted = true;
          proposedSettlement.partyBAccepted = false;
      } else if (msg.sender == partyB.addr) {
          proposedSettlement.partyAAccepted = false;
          proposedSettlement.partyBAccepted = true;
      }

      SettlementProposed(msg.sender, _awardPartyA, _awardPartyB);
  }

  function acceptSettlement(uint _awardPartyA, uint _awardPartyB)
    atConflictStages()
    eitherByParty(partyA, partyB)
  {
      if((proposedSettlement.awardPartyA != _awardPartyA) ||
         (proposedSettlement.awardPartyB != _awardPartyB))
          throw;

      if(msg.sender == partyA.addr) {
        proposedSettlement.partyAAccepted = true;
      }

      if(msg.sender == partyB.addr) {
        proposedSettlement.partyBAccepted = true;
      }

      if(proposedSettlement.partyAAccepted && proposedSettlement.partyBAccepted) {
        stage = Stages.Completed;
        DisputeResolved(_awardPartyA, _awardPartyB);
      }
  }
}