updated event

updated event

import "HumanStandardToken.sol";

contract NettingChannelContract {
    uint public lockedTime;
    address public assetAddress;
    uint public opened;
    uint public closed;
    uint public settled;
    address public closingAddress;
    HumanStandardToken public assetToken;

    struct Participant
    {
        address addr;
        uint deposit;
        uint netted;
        uint transferedAmount;
        bytes merkleProof;
        bytes32 hashlock;
        bytes32 secret;
        uint expiration;
        address sender;
        uint nonce;
        address asset;
        uint balance;
        address recipient;
        bytes32 locksroot;
    }
    Participant[2] public participants; // We only have two participants at all times

    event ChannelOpened(address assetAdr, address participant1, address participant2); // TODO
    event ChannelClosed(); // TODO
    event ChannelSettled(); // TODO
    event ChannelSecretRevealed(); //TODO

    /// @dev modifier ensuring that on a participant of the channel can call a function
    modifier inParticipants {
        if (msg.sender != participants[0].addr &&
            msg.sender != participants[1].addr) throw;
        _
    }

    function NettingChannelContract(address assetAdr, address participant1, address participant2, uint lckdTime) {
        opened = 0;
        closed = 0;
        settled = 0;
        assetAddress = HumanStandardToken(assetAdr);
        participants[0].addr = participant1;
        participants[1].addr = participant2;
        lockedTime = lckdTime;
    }

    /// @notice atIndex(address) to get the index of an address (0 or 1)
    /// @dev get the index of an address
    /// @param addr (address) the address you want the index of
    function atIndex(address addr) private returns (uint index) {
        if (addr == participants[0].addr) return 0;
        else return 1;
    }

    /// @notice deposit(uint) to deposit amount to channel.
    /// @dev Deposit an amount to the channel. At least one of the participants
    /// must deposit before the channel is opened.
    /// @param amount (uint) the amount to be deposited to the address
    function deposit(uint amount) inParticipants {
        if (assetAddress.balanceOf(msg.sender) < amount) throw;
        bool s = assetAddress.transfer(this, amount);
        if (s == true) participants[atIndex(msg.sender)].deposit += amount;
        if(isOpen() && opened == 0) open();
    }

    /// @notice open() to set the opened to be the current block and triggers
    /// the event ChannelOpened()
    /// @dev Sets the value of `opened` to be the value of the current block.
    /// param none
    /// returns none, but changes the value of `opened` and triggers the event ChannelOpened.
    function open() private {
        opened = block.number;
        // trigger event
        ChannelOpened(assetAddress, participants[0].addr, participants[1].addr);
    }

    /// @notice partner() to get the partner or other participant of the channel
    /// @dev Get the other participating party of the channel
    /// @return p (address) the partner of the calling party
    function partner(address a) private returns (address p) {
        if (a == participants[0].addr) return participants[1].addr;
        else return participants[0].addr;
    }

    /// @notice isOpen() to check if a channel is open
    /// @dev Check if a channel is open and both parties have deposited to the channel
    /// @return open (bool) the status of the channel
    function isOpen() private returns (bool open) {
        if (closed == 0) throw;
        if (participants[0].deposit > 0 || participants[1].deposit > 0) return true;
        else return false;
    }

    /// @notice addrAndDep() to get the addresses and deposits of the participants
    /// @dev get the addresses and deposits of the participants
    /// @return par1 (address) address of one of the participants
    /// @return par2 (address) address of the the other participant
    /// @return dep1 (uint) the deposit of the first participant
    /// @return dep2 (uint) the deposit of the second participant
    function addrAndDep() returns (address par1, uint dep1, address par2, uint dep2) {
        par1 = participants[0].addr;
        dep1 = participants[0].deposit;
        par2 = participants[1].addr;
        dep2 = participants[1].deposit;
    }

    /// @notice close(bytes, bytes) to close a channel between to parties
    /// @dev Close the channel between two parties
    /// @param firstEncoded (bytes) the last sent transfer of the msg.sender
    function close(bytes firstEncoded) inParticipants {
        if (settled > 0) throw; // channel already settled
        if (closed > 0) throw; // channel is closing

        // check if sender of message is a participant
        if (getSender(firstEncoded) != participants[0].addr &&
            getSender(firstEncoded) != participants[1].addr) throw;

        uint partnerId = atIndex(partner(msg.sender));
        uint senderId = atIndex(msg.sender);

        decode(firstEncoded);

        // mark closed
        closed = block.number;
        closingAddress = msg.sender;

        uint amount1 = participants[senderId].transferedAmount;
        uint amount2 = participants[partnerId].transferedAmount;

        uint allowance = participants[senderId].deposit + participants[partnerId].deposit;
        uint difference;
        if(amount1 > amount2) {
            difference = amount1 - amount2;
        } else {
            difference = amount2 - amount1;
        }

        // TODO
        // if (difference > allowance) penalize();

        // trigger event
        //TODO
        ChannelClosed();
    }

    /// @notice close(bytes, bytes) to close a channel between to parties
    /// @dev Close the channel between two parties
    /// @param firstEncoded (bytes) the last sent transfer of the msg.sender
    /// @param secondEncoded (bytes) the last sent transfer of the msg.sender
    function close(bytes firstEncoded, bytes secondEncoded) inParticipants {
        if (settled > 0) throw; // channel already settled
        if (closed > 0) throw; // channel is closing

        // check if the sender of either of the messages is a participant
        if (getSender(firstEncoded) != participants[0].addr &&
            getSender(firstEncoded) != participants[1].addr) throw;
        if (getSender(secondEncoded) != participants[0].addr &&
            getSender(secondEncoded) != participants[1].addr) throw;

        // Don't allow both transfers to be from the same sender
        if (getSender(firstEncoded) == getSender(secondEncoded)) throw;

        uint partnerId = atIndex(partner(msg.sender));
        uint senderId = atIndex(msg.sender);

        decode(firstEncoded);
        decode(secondEncoded);

        // mark closed
        closed = block.number;
        closingAddress = msg.sender;

        uint amount1 = participants[senderId].transferedAmount;
        uint amount2 = participants[partnerId].transferedAmount;

        uint allowance = participants[senderId].deposit + participants[partnerId].deposit;
        uint difference;
        if(amount1 > amount2) {
            difference = amount1 - amount2;
        } else {
            difference = amount2 - amount1;
        }

        // TODO
        // if (difference > allowance) penalize();

        // trigger event
        //TODO
        ChannelClosed();
    }

    /// @notice updateTransfer(bytes) to update last known transfer
    /// @dev Allow the partner to update the last known transfer
    /// @param message (bytes) the encoded transfer message
    function updateTransfer(bytes message) inParticipants {
        if (settled > 0) throw; // channel already settled
        if (closed == 0) throw; // channel is open
        if (msg.sender == closingAddress) throw; // don't allow closer to update
        if (closingAddress == getSender(message)) throw;

        decode(message);

        // TODO check if tampered and penalize
        // TODO check if outdated and penalize

    }

    /// @notice unlock(bytes, bytes, bytes32) to unlock a locked transfer
    /// @dev Unlock a locked transfer
    /// @param lockedEncoded (bytes) the lock
    /// @param merkleProof (bytes) the merkle proof
    /// @param secret (bytes32) the secret
    function unlock(bytes lockedEncoded, bytes merkleProof, bytes32 secret) inParticipants{
        if (settled > 0) throw; // channel already settled
        if (closed == 0) throw; // channel is open

        uint partnerId = atIndex(partner(msg.sender));
        uint senderId = atIndex(msg.sender);

        if (participants[partnerId].nonce == 0) throw;

        bytes32 h = sha3(lockedEncoded);

        for (uint i = 0; i < merkleProof.length; i += 64) {
            bytes32 left;
            left = bytesToBytes32(slice(merkleProof, i, i + 32), left);
            bytes32 right;
            right = bytesToBytes32(slice(merkleProof, i + 32, i + 64), right);
            if (h != left && h != right) throw;
            h = sha3(left, right);
        }

        if (participants[partnerId].locksroot != h) throw;

        // TODO decode lockedEncoded into a Unlocked struct and append

        //participants[partnerId].unlocked.push(lock);
    }

    /// @notice settle() to settle the balance between the two parties
    /// @dev Settles the balances of the two parties fo the channel
    /// @return participants (Participant[]) the participants with netted balances
    /*
    function settle() returns (Participant[] participants) {
        if (settled > 0) throw;
        if (closed == 0) throw;
        if (closed + lockedTime > block.number) throw; //if locked time has expired throw

        for (uint i = 0; i < participants.length; i++) {
            uint otherIdx = atIndex(partner(participants[i].addr));
            participants[i].netted = participants[i].deposit;
            if (participants[i].lastSentTransfer != 0) {
                participants[i].netted = participants[i].lastSentTransfer.balance;
            }
            if (participants[otherIdx].lastSentTransfer != 0) {
                participants[i].netted = participants[otherIdx].lastSentTransfer.balance;
            }
        }

        //for (uint j = 0; j < participants.length; j++) {
            //uint otherIdx = atIndex(partner(participants[j].addr));
        //}

        // trigger event
        //ChannelSettled();
    }
    */

    // Get the nonce of the last sent transfer
    function getNonce(bytes message) private returns (uint8 non) {
        // Direct Transfer
        if (message[0] == 5) {
            (non, , , , , , ) = decodeTransfer(message);
        }
        // Locked Transfer
        if (message[0] == 6) {
            (non, , , ) = decodeLockedTransfer1(message);
        }
        // Mediated Transfer
        if (message[0] == 7) {
            (non, , , , ) = decodeMediatedTransfer1(message);
        }
        // Cancel Transfer
        if (message[0] == 8) {
            (non, , , ) = decodeCancelTransfer1(message);
        }
        else throw;
    }

    // Gets the sender of a last sent transfer
    function getSender(bytes message) private returns (address sndr) {
        // Secret
        if (message[0] == 4) {
            sndr = dsec(message);
        }
        // Direct Transfer
        if (message[0] == 5) {
            sndr = ddtran(message);
        }
        // Locked Transfer
        if (message[0] == 6) {
            sndr = dltran(message);
        }
        // Mediated Transfer
        if (message[0] == 7) {
            sndr = dmtran(message);
        }
        // Cancel Transfer
        if (message[0] == 8) {
            sndr = dctran(message);
        }
        else throw;
    }

    function dsec(bytes message) private returns (address sndr) {
        var(sec, sig) = decodeSecret(message);
        bytes32 h = sha3(sec);
        sndr = ecrecovery(h, sig);
    }
    function ddtran(bytes message) private returns (address sndr) {
        var(non, ass, rec, bal, olo, , sig) = decodeTransfer(message);
        bytes32 h = sha3(non, ass, bal, rec, olo); //need the optionalLocksroot
        sndr = ecrecovery(h, sig);
    }
    function dltran(bytes message) private returns (address sndr) {
        bytes32 lock;
        var(non, , ass, rec) = decodeLockedTransfer1(message);
        var(loc, bal, , has, sig) = decodeLockedTransfer2(message);
        bytes32 h = sha3(non, ass, bal, rec, loc, lock ); //need the lock
        sndr = ecrecovery(h, sig);
    }
    function dmtran(bytes message) private returns (address sndr) {
        bytes32 lock;
        var(non, , ass, rec, tar) = decodeMediatedTransfer1(message);
        var(ini, loc, bal, , , fee, sig) = decodeMediatedTransfer2(message);
        bytes32 h = sha3(non, ass, bal, rec, loc, lock, tar, ini, fee); //need the lock
        sndr = ecrecovery(h, sig);
    }
    function dctran(bytes message) private returns (address sndr) {
        bytes32 lock;
        var(non, , ass, rec) = decodeCancelTransfer1(message);
        var(loc, bal, , , sig) = decodeCancelTransfer2(message);
        bytes32 h = sha3(non, ass, bal, rec, loc, lock); //need the lock
        sndr = ecrecovery(h, sig);
    }

    function decode(bytes message) private {
        bytes32 hash;
        // Secret
        uint i;
        if (message[0] == 4) {
            decsec(message);
        }
        // Direct Transfer
        if (message[0] == 5) {
            decdir(message);
        }
        // Locked Transfer
        if (message[0] == 6) {
            hash = decloc1(message);
            decloc2(message, hash);
        }
        // Mediated Transfer
        if (message[0] == 7) {
            hash = decmed1(message);
            decmed2(message, hash);
        }
        // Cancel Transfer
        if (message[0] == 8) {
            hash = deccan1(message);
            deccan2(message, hash);
        }
        else throw;
    }

    function decsec(bytes message) private {
        uint i = atIndex(getSender(message));
        var(sec, sig) = decodeSecret(message);
        participants[atIndex(msg.sender)].secret = sec;
        bytes32 h = sha3(sec);
        participants[i].sender = ecrecovery(h, sig);
    }
    function decdir(bytes message) private {
        bytes32 lock;
        uint i = atIndex(getSender(message));
        var(non, ass, rec, bal, loc, sec, sig) = decodeTransfer(message);
        participants[i].nonce = non;
        participants[i].asset = ass;
        participants[i].recipient = rec;
        participants[i].balance = bal;
        bytes32 h = sha3(non, ass, bal, rec, loc);
        participants[i].sender = ecrecovery(h, sig);
    }
    function decloc1(bytes message) private returns (bytes32 hh) {
        uint i = atIndex(getSender(message));
        var(non, exp, ass, rec) = decodeLockedTransfer1(message);
        participants[i].nonce = non;
        lockedTime = exp;
        participants[i].asset = ass;
        participants[i].recipient = rec;
        hh = sha3(non, ass, rec);
    }
    function decloc2(bytes message, bytes32 hh) private {
        bytes32 lock;
        uint i = atIndex(getSender(message));
        var(loc, bal, amo, has, sig) = decodeLockedTransfer2(message);
        participants[i].locksroot = loc;
        participants[i].balance = bal;
        participants[i].transferedAmount = amo;
        participants[i].hashlock = has;
        bytes32 h = sha3(hh, bal, loc, lock ); //need the lock
        participants[i].sender = ecrecovery(h, sig);
    }
    function decmed1(bytes message) private returns (bytes32 hh) {
        uint i = atIndex(getSender(message));
        var(non, exp, ass, rec, tar) = decodeMediatedTransfer1(message);
        participants[i].nonce = non;
        lockedTime = exp;
        participants[i].asset = ass;
        participants[i].recipient = rec;
        hh = sha3(non, ass, rec, tar);
    }
    function decmed2(bytes message, bytes32 hh) private {
        bytes32 lock;
        uint i = atIndex(getSender(message));
        var(ini, loc, has, bal, amo, fee, sig) = decodeMediatedTransfer2(message);
        participants[i].locksroot = loc;
        participants[i].hashlock = has;
        participants[i].balance = bal;
        participants[i].transferedAmount = amo;
        bytes32 h = sha3(hh, bal, loc, lock, ini, fee); //need the lock
        participants[i].sender = ecrecovery(h, sig);
    }
    function deccan1(bytes message) private returns (bytes32 hh) {
        uint i = atIndex(getSender(message));
        var(non, exp, ass, rec) = decodeCancelTransfer1(message);
        participants[i].nonce = non;
        lockedTime = exp;
        participants[i].asset = ass;
        participants[i].recipient = rec;
        hh = sha3(non, ass, rec);
    }
    function deccan2(bytes message, bytes32 hh) private {
        bytes32 lock;
        uint i = atIndex(getSender(message));
        var(loc, bal, amo, has, sig) = decodeCancelTransfer2(message);
        participants[i].locksroot = loc;
        participants[i].balance = bal;
        participants[i].transferedAmount = amo;
        participants[i].hashlock = has;
        bytes32 h = sha3(hh, bal, loc, lock); //need the lock
        participants[i].sender = ecrecovery(h, sig);
    }

    // Written by Alex Beregszaszi (@axic), use it under the terms of the MIT license.
    function ecrecovery(bytes32 hash, bytes sig) private returns (address) {
        bytes32 r;
        bytes32 s;
        uint8 v;

        // FIXME: Should this throw, or return 0?
        if (sig.length != 65)
          return 0;

        // The signature format is a compact form of:
        //   {bytes32 r}{bytes32 s}{uint8 v}
        // Compact means, uint8 is not padded to 32 bytes.
        assembly {
            r := mload(add(sig, 32))
            s := mload(add(sig, 64))
            // Here we are loading the last 32 bytes, including 31 bytes
            // of 's'. There is no 'mload8' to do this.
            //
            // 'byte' is not working due to the Solidity parser, so lets
            // use the second best option, 'and'
            v := and(mload(add(sig, 65)), 1)
        }

        // old geth sends a `v` value of [0,1], while the new, in line with the YP sends [27,28]
        if (v < 27) v += 27;

        return ecrecover(hash, v, r, s);
    }

    function ecverify(bytes32 hash, bytes sig, address signer) private returns (bool) {
        return ecrecovery(hash, sig) == signer;
    }

    function slice(bytes a, uint start, uint end) private returns (bytes n) {
        if (a.length < end) throw;
        if (start < 0) throw;
        if (start > end) throw;
        n = new bytes(end-start);
        for ( uint i = start; i < end; i ++) { //python style slice
            n[i-start] = a[i];
        }
    }

    function decodeSecret(bytes m) private returns (bytes32 secret, bytes signature) {
        if (m.length != 101) throw;
        secret = bytesToBytes32(slice(m, 4, 36), secret);
        signature = slice(m, 36, 101);
    }

    function decodeTransfer(bytes m) private
        returns
        (uint8 nonce,
        address asset,
        address recipient,
        uint balance,
        bytes32 optionalLocksroot,
        bytes32 optionalSecret,
        bytes signature)
    {
        if (m.length != 213) throw;
        nonce = bytesToIntEight(slice(m, 4, 12), nonce);
        uint160 ia;
        asset = bytesToAddress(slice(m, 12, 32), ia);
        uint160 ir;
        recipient = bytesToAddress(slice(m, 32, 52), ir);
        balance = bytesToInt(slice(m, 52, 84), balance);
        optionalLocksroot = bytesToBytes32(slice(m, 84, 116), optionalLocksroot);
        optionalSecret = bytesToBytes32(slice(m, 116, 148), optionalSecret);
        signature = slice(m, 148, 213);

    }

    function decodeLockedTransfer1(bytes m) private
        returns
        (uint8 nonce,
        uint8 expiration,
        address asset,
        address recipient)
    {
        if (m.length != 253) throw;
        nonce = bytesToIntEight(slice(m, 4, 12), nonce);
        expiration = bytesToIntEight(slice(m, 12, 20), expiration);
        uint160 ia;
        asset = bytesToAddress(slice(m, 20, 40), ia);
        uint160 ir;
        recipient = bytesToAddress(slice(m, 40, 60), ir);
    }

    function decodeLockedTransfer2(bytes m) private
        returns
        (bytes32 locksroot,
        uint balance,
        uint amount,
        bytes32 hashlock,
        bytes signature)
    {

        locksroot = bytesToBytes32(slice(m, 60, 92), locksroot);
        balance = bytesToInt(slice(m, 92, 124), balance);
        amount = bytesToInt(slice(m, 124, 156), amount);
        hashlock = bytesToBytes32(slice(m, 156, 188), hashlock);
        signature = slice(m, 188, 253);
    }

    function decodeMediatedTransfer1(bytes m) private
        returns
        (uint8 nonce,
        uint8 expiration,
        address asset,
        address recipient,
        address target)
    {
        if (m.length != 325) throw;
        nonce = bytesToIntEight(slice(m, 4, 12), nonce);
        expiration = bytesToIntEight(slice(m, 12, 20), expiration);
        uint160 ia;
        asset = bytesToAddress(slice(m, 20, 40), ia);
        uint160 ir;
        recipient = bytesToAddress(slice(m, 40, 60), ir);
        uint160 it;
        target = bytesToAddress(slice(m, 60, 80), it);
    }

    function decodeMediatedTransfer2(bytes m) private
        returns
        (address initiator,
        bytes32 locksroot,
        bytes32 hashlock,
        uint balance,
        uint amount,
        uint fee,
        bytes signature)
    {
        uint160 ii;
        initiator = bytesToAddress(slice(m, 80, 100), ii);
        locksroot = bytesToBytes32(slice(m, 100, 132), locksroot);
        hashlock = bytesToBytes32(slice(m, 132, 164), hashlock);
        balance = bytesToInt(slice(m, 164, 196), balance);
        amount = bytesToInt(slice(m, 196, 228), amount);
        fee = bytesToInt(slice(m, 228, 260), fee);
        signature = slice(m, 260, 325);
    }

    function decodeCancelTransfer1(bytes m) private
        returns
        (uint8 nonce,
        uint8 expiration,
        address asset,
        address recipient)
    {
        if (m.length != 253) throw;
        nonce = bytesToIntEight(slice(m, 4, 12), nonce);
        expiration = bytesToIntEight(slice(m, 12, 20), expiration);
        uint160 ia;
        asset = bytesToAddress(slice(m, 20, 40), ia);
        uint160 ir;
        recipient = bytesToAddress(slice(m, 40, 60), ir);
    }

    function decodeCancelTransfer2(bytes m) private
    returns
    (bytes32 locksroot,
    uint balance,
    uint amount,
    bytes32 hashlock,
    bytes signature)
    {
        locksroot = bytesToBytes32(slice(m, 60, 92), locksroot);
        balance = bytesToInt(slice(m, 92, 124), balance);
        amount = bytesToInt(slice(m, 124, 156), amount);
        hashlock = bytesToBytes32(slice(m, 156, 188), hashlock);
        signature = slice(m, 188, 253);
    }

    /* HELPER FUNCTIONS */

    function bytesToIntEight(bytes b, uint8 i) private returns (uint8 res) {
        assembly { i := mload(add(b, 0x8)) }
        res = i;
    }

    function bytesToInt(bytes b, uint i) private returns (uint res) {
        assembly { i := mload(add(b, 0x20)) }
        res = i;
    }

    function bytesToAddress(bytes b, uint160 i) private returns (address add) {
        assembly { i := mload(add(b, 0x14)) }
        uint160 a = uint160(i);
        add = address(i);
    }

    function bytesToBytes32(bytes b, bytes32 i) private returns (bytes32 bts) {
        assembly { i := mload(add(b, 0x20)) }
        bts = i;
    }

    // empty function to handle wrong calls
    function () { throw; }
}

import "HumanStandardToken.sol";

contract NettingChannelContract {
    uint public lockedTime;
    address public assetAddress;
    uint public opened;
    uint public closed;
    uint public settled;
    address public closingAddress;
    HumanStandardToken public assetToken;

    struct Participant
    {
        address addr;
        uint deposit;
        uint netted;
        uint transferedAmount;
        bytes merkleProof;
        bytes32 hashlock;
        bytes32 secret;
        uint expiration;
        address sender;
        uint nonce;
        address asset;
        uint balance;
        address recipient;
        bytes32 locksroot;
    }
    Participant[2] public participants; // We only have two participants at all times

    event ChannelOpened(address assetAdr); // TODO
    event ChannelClosed(); // TODO
    event ChannelSettled(); // TODO
    event ChannelSecretRevealed(); //TODO

    /// @dev modifier ensuring that on a participant of the channel can call a function
    modifier inParticipants {
        if (msg.sender != participants[0].addr &&
            msg.sender != participants[1].addr) throw;
        _
    }

    function NettingChannelContract(address assetAdr, address participant1, address participant2, uint lckdTime) {
        opened = 0;
        closed = 0;
        settled = 0;
        assetAddress = HumanStandardToken(assetAdr);
        participants[0].addr = participant1;
        participants[1].addr = participant2;
        lockedTime = lckdTime;
    }

    /// @notice atIndex(address) to get the index of an address (0 or 1)
    /// @dev get the index of an address
    /// @param addr (address) the address you want the index of
    function atIndex(address addr) private returns (uint index) {
        if (addr == participants[0].addr) return 0;
        else return 1;
    }

    /// @notice deposit(uint) to deposit amount to channel.
    /// @dev Deposit an amount to the channel. At least one of the participants
    /// must deposit before the channel is opened.
    /// @param amount (uint) the amount to be deposited to the address
    function deposit(uint amount) inParticipants {
        if (assetAddress.balanceOf(msg.sender) < amount) throw;
        bool s = assetAddress.transfer(this, amount);
        if (s == true) participants[atIndex(msg.sender)].deposit += amount;
        if(isOpen() && opened == 0) open();
    }

    /// @notice open() to set the opened to be the current block and triggers
    /// the event ChannelOpened()
    /// @dev Sets the value of `opened` to be the value of the current block.
    /// param none
    /// returns none, but changes the value of `opened` and triggers the event ChannelOpened.
    function open() private {
        opened = block.number;
        // trigger event
        ChannelOpened(assetAddress);
    }

    /// @notice partner() to get the partner or other participant of the channel
    /// @dev Get the other participating party of the channel
    /// @return p (address) the partner of the calling party
    function partner(address a) private returns (address p) {
        if (a == participants[0].addr) return participants[1].addr;
        else return participants[0].addr;
    }

    /// @notice isOpen() to check if a channel is open
    /// @dev Check if a channel is open and both parties have deposited to the channel
    /// @return open (bool) the status of the channel
    function isOpen() private returns (bool open) {
        if (closed == 0) throw;
        if (participants[0].deposit > 0 || participants[1].deposit > 0) return true;
        else return false;
    }

    /// @notice addrAndDep() to get the addresses and deposits of the participants
    /// @dev get the addresses and deposits of the participants
    /// @return par1 (address) address of one of the participants
    /// @return par2 (address) address of the the other participant
    /// @return dep1 (uint) the deposit of the first participant
    /// @return dep2 (uint) the deposit of the second participant
    function addrAndDep() returns (address par1, uint dep1, address par2, uint dep2) {
        par1 = participants[0].addr;
        dep1 = participants[0].deposit;
        par2 = participants[1].addr;
        dep2 = participants[1].deposit;
    }

    /// @notice close(bytes, bytes) to close a channel between to parties
    /// @dev Close the channel between two parties
    /// @param firstEncoded (bytes) the last sent transfer of the msg.sender
    function close(bytes firstEncoded) inParticipants {
        if (settled > 0) throw; // channel already settled
        if (closed > 0) throw; // channel is closing

        // check if sender of message is a participant
        if (getSender(firstEncoded) != participants[0].addr &&
            getSender(firstEncoded) != participants[1].addr) throw;

        uint partnerId = atIndex(partner(msg.sender));
        uint senderId = atIndex(msg.sender);

        decode(firstEncoded);

        // mark closed
        closed = block.number;
        closingAddress = msg.sender;

        uint amount1 = participants[senderId].transferedAmount;
        uint amount2 = participants[partnerId].transferedAmount;

        uint allowance = participants[senderId].deposit + participants[partnerId].deposit;
        uint difference;
        if(amount1 > amount2) {
            difference = amount1 - amount2;
        } else {
            difference = amount2 - amount1;
        }

        // TODO
        // if (difference > allowance) penalize();

        // trigger event
        //TODO
        ChannelClosed();
    }

    /// @notice close(bytes, bytes) to close a channel between to parties
    /// @dev Close the channel between two parties
    /// @param firstEncoded (bytes) the last sent transfer of the msg.sender
    /// @param secondEncoded (bytes) the last sent transfer of the msg.sender
    function close(bytes firstEncoded, bytes secondEncoded) inParticipants {
        if (settled > 0) throw; // channel already settled
        if (closed > 0) throw; // channel is closing

        // check if the sender of either of the messages is a participant
        if (getSender(firstEncoded) != participants[0].addr &&
            getSender(firstEncoded) != participants[1].addr) throw;
        if (getSender(secondEncoded) != participants[0].addr &&
            getSender(secondEncoded) != participants[1].addr) throw;

        // Don't allow both transfers to be from the same sender
        if (getSender(firstEncoded) == getSender(secondEncoded)) throw;

        uint partnerId = atIndex(partner(msg.sender));
        uint senderId = atIndex(msg.sender);

        decode(firstEncoded);
        decode(secondEncoded);

        // mark closed
        closed = block.number;
        closingAddress = msg.sender;

        uint amount1 = participants[senderId].transferedAmount;
        uint amount2 = participants[partnerId].transferedAmount;

        uint allowance = participants[senderId].deposit + participants[partnerId].deposit;
        uint difference;
        if(amount1 > amount2) {
            difference = amount1 - amount2;
        } else {
            difference = amount2 - amount1;
        }

        // TODO
        // if (difference > allowance) penalize();

        // trigger event
        //TODO
        ChannelClosed();
    }

    /// @notice updateTransfer(bytes) to update last known transfer
    /// @dev Allow the partner to update the last known transfer
    /// @param message (bytes) the encoded transfer message
    function updateTransfer(bytes message) inParticipants {
        if (settled > 0) throw; // channel already settled
        if (closed == 0) throw; // channel is open
        if (msg.sender == closingAddress) throw; // don't allow closer to update
        if (closingAddress == getSender(message)) throw;

        decode(message);

        // TODO check if tampered and penalize
        // TODO check if outdated and penalize

    }

    /// @notice unlock(bytes, bytes, bytes32) to unlock a locked transfer
    /// @dev Unlock a locked transfer
    /// @param lockedEncoded (bytes) the lock
    /// @param merkleProof (bytes) the merkle proof
    /// @param secret (bytes32) the secret
    function unlock(bytes lockedEncoded, bytes merkleProof, bytes32 secret) inParticipants{
        if (settled > 0) throw; // channel already settled
        if (closed == 0) throw; // channel is open

        uint partnerId = atIndex(partner(msg.sender));
        uint senderId = atIndex(msg.sender);

        if (participants[partnerId].nonce == 0) throw;

        bytes32 h = sha3(lockedEncoded);

        for (uint i = 0; i < merkleProof.length; i += 64) {
            bytes32 left;
            left = bytesToBytes32(slice(merkleProof, i, i + 32), left);
            bytes32 right;
            right = bytesToBytes32(slice(merkleProof, i + 32, i + 64), right);
            if (h != left && h != right) throw;
            h = sha3(left, right);
        }

        if (participants[partnerId].locksroot != h) throw;

        // TODO decode lockedEncoded into a Unlocked struct and append

        //participants[partnerId].unlocked.push(lock);
    }

    /// @notice settle() to settle the balance between the two parties
    /// @dev Settles the balances of the two parties fo the channel
    /// @return participants (Participant[]) the participants with netted balances
    /*
    function settle() returns (Participant[] participants) {
        if (settled > 0) throw;
        if (closed == 0) throw;
        if (closed + lockedTime > block.number) throw; //if locked time has expired throw

        for (uint i = 0; i < participants.length; i++) {
            uint otherIdx = atIndex(partner(participants[i].addr));
            participants[i].netted = participants[i].deposit;
            if (participants[i].lastSentTransfer != 0) {
                participants[i].netted = participants[i].lastSentTransfer.balance;
            }
            if (participants[otherIdx].lastSentTransfer != 0) {
                participants[i].netted = participants[otherIdx].lastSentTransfer.balance;
            }
        }

        //for (uint j = 0; j < participants.length; j++) {
            //uint otherIdx = atIndex(partner(participants[j].addr));
        //}

        // trigger event
        //ChannelSettled();
    }
    */

    // Get the nonce of the last sent transfer
    function getNonce(bytes message) private returns (uint8 non) {
        // Direct Transfer
        if (message[0] == 5) {
            (non, , , , , , ) = decodeTransfer(message);
        }
        // Locked Transfer
        if (message[0] == 6) {
            (non, , , ) = decodeLockedTransfer1(message);
        }
        // Mediated Transfer
        if (message[0] == 7) {
            (non, , , , ) = decodeMediatedTransfer1(message);
        }
        // Cancel Transfer
        if (message[0] == 8) {
            (non, , , ) = decodeCancelTransfer1(message);
        }
        else throw;
    }

    // Gets the sender of a last sent transfer
    function getSender(bytes message) private returns (address sndr) {
        // Secret
        if (message[0] == 4) {
            sndr = dsec(message);
        }
        // Direct Transfer
        if (message[0] == 5) {
            sndr = ddtran(message);
        }
        // Locked Transfer
        if (message[0] == 6) {
            sndr = dltran(message);
        }
        // Mediated Transfer
        if (message[0] == 7) {
            sndr = dmtran(message);
        }
        // Cancel Transfer
        if (message[0] == 8) {
            sndr = dctran(message);
        }
        else throw;
    }

    function dsec(bytes message) private returns (address sndr) {
        var(sec, sig) = decodeSecret(message);
        bytes32 h = sha3(sec);
        sndr = ecrecovery(h, sig);
    }
    function ddtran(bytes message) private returns (address sndr) {
        var(non, ass, rec, bal, olo, , sig) = decodeTransfer(message);
        bytes32 h = sha3(non, ass, bal, rec, olo); //need the optionalLocksroot
        sndr = ecrecovery(h, sig);
    }
    function dltran(bytes message) private returns (address sndr) {
        bytes32 lock;
        var(non, , ass, rec) = decodeLockedTransfer1(message);
        var(loc, bal, , has, sig) = decodeLockedTransfer2(message);
        bytes32 h = sha3(non, ass, bal, rec, loc, lock ); //need the lock
        sndr = ecrecovery(h, sig);
    }
    function dmtran(bytes message) private returns (address sndr) {
        bytes32 lock;
        var(non, , ass, rec, tar) = decodeMediatedTransfer1(message);
        var(ini, loc, bal, , , fee, sig) = decodeMediatedTransfer2(message);
        bytes32 h = sha3(non, ass, bal, rec, loc, lock, tar, ini, fee); //need the lock
        sndr = ecrecovery(h, sig);
    }
    function dctran(bytes message) private returns (address sndr) {
        bytes32 lock;
        var(non, , ass, rec) = decodeCancelTransfer1(message);
        var(loc, bal, , , sig) = decodeCancelTransfer2(message);
        bytes32 h = sha3(non, ass, bal, rec, loc, lock); //need the lock
        sndr = ecrecovery(h, sig);
    }

    function decode(bytes message) private {
        bytes32 hash;
        // Secret
        uint i;
        if (message[0] == 4) {
            decsec(message);
        }
        // Direct Transfer
        if (message[0] == 5) {
            decdir(message);
        }
        // Locked Transfer
        if (message[0] == 6) {
            hash = decloc1(message);
            decloc2(message, hash);
        }
        // Mediated Transfer
        if (message[0] == 7) {
            hash = decmed1(message);
            decmed2(message, hash);
        }
        // Cancel Transfer
        if (message[0] == 8) {
            hash = deccan1(message);
            deccan2(message, hash);
        }
        else throw;
    }

    function decsec(bytes message) private {
        uint i = atIndex(getSender(message));
        var(sec, sig) = decodeSecret(message);
        participants[atIndex(msg.sender)].secret = sec;
        bytes32 h = sha3(sec);
        participants[i].sender = ecrecovery(h, sig);
    }
    function decdir(bytes message) private {
        bytes32 lock;
        uint i = atIndex(getSender(message));
        var(non, ass, rec, bal, loc, sec, sig) = decodeTransfer(message);
        participants[i].nonce = non;
        participants[i].asset = ass;
        participants[i].recipient = rec;
        participants[i].balance = bal;
        bytes32 h = sha3(non, ass, bal, rec, loc);
        participants[i].sender = ecrecovery(h, sig);
    }
    function decloc1(bytes message) private returns (bytes32 hh) {
        uint i = atIndex(getSender(message));
        var(non, exp, ass, rec) = decodeLockedTransfer1(message);
        participants[i].nonce = non;
        lockedTime = exp;
        participants[i].asset = ass;
        participants[i].recipient = rec;
        hh = sha3(non, ass, rec);
    }
    function decloc2(bytes message, bytes32 hh) private {
        bytes32 lock;
        uint i = atIndex(getSender(message));
        var(loc, bal, amo, has, sig) = decodeLockedTransfer2(message);
        participants[i].locksroot = loc;
        participants[i].balance = bal;
        participants[i].transferedAmount = amo;
        participants[i].hashlock = has;
        bytes32 h = sha3(hh, bal, loc, lock ); //need the lock
        participants[i].sender = ecrecovery(h, sig);
    }
    function decmed1(bytes message) private returns (bytes32 hh) {
        uint i = atIndex(getSender(message));
        var(non, exp, ass, rec, tar) = decodeMediatedTransfer1(message);
        participants[i].nonce = non;
        lockedTime = exp;
        participants[i].asset = ass;
        participants[i].recipient = rec;
        hh = sha3(non, ass, rec, tar);
    }
    function decmed2(bytes message, bytes32 hh) private {
        bytes32 lock;
        uint i = atIndex(getSender(message));
        var(ini, loc, has, bal, amo, fee, sig) = decodeMediatedTransfer2(message);
        participants[i].locksroot = loc;
        participants[i].hashlock = has;
        participants[i].balance = bal;
        participants[i].transferedAmount = amo;
        bytes32 h = sha3(hh, bal, loc, lock, ini, fee); //need the lock
        participants[i].sender = ecrecovery(h, sig);
    }
    function deccan1(bytes message) private returns (bytes32 hh) {
        uint i = atIndex(getSender(message));
        var(non, exp, ass, rec) = decodeCancelTransfer1(message);
        participants[i].nonce = non;
        lockedTime = exp;
        participants[i].asset = ass;
        participants[i].recipient = rec;
        hh = sha3(non, ass, rec);
    }
    function deccan2(bytes message, bytes32 hh) private {
        bytes32 lock;
        uint i = atIndex(getSender(message));
        var(loc, bal, amo, has, sig) = decodeCancelTransfer2(message);
        participants[i].locksroot = loc;
        participants[i].balance = bal;
        participants[i].transferedAmount = amo;
        participants[i].hashlock = has;
        bytes32 h = sha3(hh, bal, loc, lock); //need the lock
        participants[i].sender = ecrecovery(h, sig);
    }

    // Written by Alex Beregszaszi (@axic), use it under the terms of the MIT license.
    function ecrecovery(bytes32 hash, bytes sig) private returns (address) {
        bytes32 r;
        bytes32 s;
        uint8 v;

        // FIXME: Should this throw, or return 0?
        if (sig.length != 65)
          return 0;

        // The signature format is a compact form of:
        //   {bytes32 r}{bytes32 s}{uint8 v}
        // Compact means, uint8 is not padded to 32 bytes.
        assembly {
            r := mload(add(sig, 32))
            s := mload(add(sig, 64))
            // Here we are loading the last 32 bytes, including 31 bytes
            // of 's'. There is no 'mload8' to do this.
            //
            // 'byte' is not working due to the Solidity parser, so lets
            // use the second best option, 'and'
            v := and(mload(add(sig, 65)), 1)
        }

        // old geth sends a `v` value of [0,1], while the new, in line with the YP sends [27,28]
        if (v < 27) v += 27;

        return ecrecover(hash, v, r, s);
    }

    function ecverify(bytes32 hash, bytes sig, address signer) private returns (bool) {
        return ecrecovery(hash, sig) == signer;
    }

    function slice(bytes a, uint start, uint end) private returns (bytes n) {
        if (a.length < end) throw;
        if (start < 0) throw;
        if (start > end) throw;
        n = new bytes(end-start);
        for ( uint i = start; i < end; i ++) { //python style slice
            n[i-start] = a[i];
        }
    }

    function decodeSecret(bytes m) private returns (bytes32 secret, bytes signature) {
        if (m.length != 101) throw;
        secret = bytesToBytes32(slice(m, 4, 36), secret);
        signature = slice(m, 36, 101);
    }

    function decodeTransfer(bytes m) private
        returns
        (uint8 nonce,
        address asset,
        address recipient,
        uint balance,
        bytes32 optionalLocksroot,
        bytes32 optionalSecret,
        bytes signature)
    {
        if (m.length != 213) throw;
        nonce = bytesToIntEight(slice(m, 4, 12), nonce);
        uint160 ia;
        asset = bytesToAddress(slice(m, 12, 32), ia);
        uint160 ir;
        recipient = bytesToAddress(slice(m, 32, 52), ir);
        balance = bytesToInt(slice(m, 52, 84), balance);
        optionalLocksroot = bytesToBytes32(slice(m, 84, 116), optionalLocksroot);
        optionalSecret = bytesToBytes32(slice(m, 116, 148), optionalSecret);
        signature = slice(m, 148, 213);

    }

    function decodeLockedTransfer1(bytes m) private
        returns
        (uint8 nonce,
        uint8 expiration,
        address asset,
        address recipient)
    {
        if (m.length != 253) throw;
        nonce = bytesToIntEight(slice(m, 4, 12), nonce);
        expiration = bytesToIntEight(slice(m, 12, 20), expiration);
        uint160 ia;
        asset = bytesToAddress(slice(m, 20, 40), ia);
        uint160 ir;
        recipient = bytesToAddress(slice(m, 40, 60), ir);
    }

    function decodeLockedTransfer2(bytes m) private
        returns
        (bytes32 locksroot,
        uint balance,
        uint amount,
        bytes32 hashlock,
        bytes signature)
    {

        locksroot = bytesToBytes32(slice(m, 60, 92), locksroot);
        balance = bytesToInt(slice(m, 92, 124), balance);
        amount = bytesToInt(slice(m, 124, 156), amount);
        hashlock = bytesToBytes32(slice(m, 156, 188), hashlock);
        signature = slice(m, 188, 253);
    }

    function decodeMediatedTransfer1(bytes m) private
        returns
        (uint8 nonce,
        uint8 expiration,
        address asset,
        address recipient,
        address target)
    {
        if (m.length != 325) throw;
        nonce = bytesToIntEight(slice(m, 4, 12), nonce);
        expiration = bytesToIntEight(slice(m, 12, 20), expiration);
        uint160 ia;
        asset = bytesToAddress(slice(m, 20, 40), ia);
        uint160 ir;
        recipient = bytesToAddress(slice(m, 40, 60), ir);
        uint160 it;
        target = bytesToAddress(slice(m, 60, 80), it);
    }

    function decodeMediatedTransfer2(bytes m) private
        returns
        (address initiator,
        bytes32 locksroot,
        bytes32 hashlock,
        uint balance,
        uint amount,
        uint fee,
        bytes signature)
    {
        uint160 ii;
        initiator = bytesToAddress(slice(m, 80, 100), ii);
        locksroot = bytesToBytes32(slice(m, 100, 132), locksroot);
        hashlock = bytesToBytes32(slice(m, 132, 164), hashlock);
        balance = bytesToInt(slice(m, 164, 196), balance);
        amount = bytesToInt(slice(m, 196, 228), amount);
        fee = bytesToInt(slice(m, 228, 260), fee);
        signature = slice(m, 260, 325);
    }

    function decodeCancelTransfer1(bytes m) private
        returns
        (uint8 nonce,
        uint8 expiration,
        address asset,
        address recipient)
    {
        if (m.length != 253) throw;
        nonce = bytesToIntEight(slice(m, 4, 12), nonce);
        expiration = bytesToIntEight(slice(m, 12, 20), expiration);
        uint160 ia;
        asset = bytesToAddress(slice(m, 20, 40), ia);
        uint160 ir;
        recipient = bytesToAddress(slice(m, 40, 60), ir);
    }

    function decodeCancelTransfer2(bytes m) private
    returns
    (bytes32 locksroot,
    uint balance,
    uint amount,
    bytes32 hashlock,
    bytes signature)
    {
        locksroot = bytesToBytes32(slice(m, 60, 92), locksroot);
        balance = bytesToInt(slice(m, 92, 124), balance);
        amount = bytesToInt(slice(m, 124, 156), amount);
        hashlock = bytesToBytes32(slice(m, 156, 188), hashlock);
        signature = slice(m, 188, 253);
    }

    /* HELPER FUNCTIONS */

    function bytesToIntEight(bytes b, uint8 i) private returns (uint8 res) {
        assembly { i := mload(add(b, 0x8)) }
        res = i;
    }

    function bytesToInt(bytes b, uint i) private returns (uint res) {
        assembly { i := mload(add(b, 0x20)) }
        res = i;
    }

    function bytesToAddress(bytes b, uint160 i) private returns (address add) {
        assembly { i := mload(add(b, 0x14)) }
        uint160 a = uint160(i);
        add = address(i);
    }

    function bytesToBytes32(bytes b, bytes32 i) private returns (bytes32 bts) {
        assembly { i := mload(add(b, 0x20)) }
        bts = i;
    }

    // empty function to handle wrong calls
    function () { throw; }
}


Finish Challenge-Response in BC

Finish Challenge-Response in BC

/**
 * Chess contract
 * Stores any amount of games with two players and current state.
 * State encoding:
 *    positive numbers for white, negative numbers for black
 *    for details, see
 *    https://github.com/ise-ethereum/on-chain-chess/wiki/Chess-board-representation
 */

import "TurnBasedGame.sol";
import "ChessLogic.sol";
import "Auth.sol";

contract Chess is TurnBasedGame, Auth {
    using ChessLogic for ChessLogic.State;
    mapping (bytes32 => ChessLogic.State) gameStates;

    event GameInitialized(bytes32 indexed gameId, address indexed player1, string player1Alias, address playerWhite, uint pot);
    event GameJoined(bytes32 indexed gameId, address indexed player1, string player1Alias, address indexed player2, string player2Alias, address playerWhite, uint pot);
    event GameStateChanged(bytes32 indexed gameId, int8[128] state);
    event GameTimeoutStarted(bytes32 indexed gameId,uint timeoutStarted, int8 timeoutState);
    // GameDrawOfferRejected: notification that a draw of the currently turning player
    //                        is rejected by the waiting player
    event GameDrawOfferRejected(bytes32 indexed gameId);
    event Move(bytes32 indexed gameId, address indexed player, uint256 fromIndex, uint256 toIndex);

    function Chess(bool enableDebugging) TurnBasedGame(enableDebugging) {
    }

    /**
     * Initialize a new game
     * string player1Alias: Alias of the player creating the game
     * bool playAsWhite: Pass true or false depending on if the creator will play as white
     */
    function initGame(string player1Alias, bool playAsWhite) public returns (bytes32) {
        bytes32 gameId = super.initGame(player1Alias, playAsWhite);

        // Setup game state
        int8 nextPlayerColor = int8(1);
        gameStates[gameId].setupState(nextPlayerColor);
        if (playAsWhite) {
            // Player 1 will play as white
            gameStates[gameId].playerWhite = msg.sender;

            // Game starts with White, so here player 1
            games[gameId].nextPlayer = games[gameId].player1;
        }

        // Sent notification events
        GameInitialized(gameId, games[gameId].player1, player1Alias, gameStates[gameId].playerWhite, games[gameId].pot);
        GameStateChanged(gameId, gameStates[gameId].fields);
        return gameId;
    }

    /**
     * Join an initialized game
     * bytes32 gameId: ID of the game to join
     * string player2Alias: Alias of the player that is joining
     */
    function joinGame(bytes32 gameId, string player2Alias) public {
        super.joinGame(gameId, player2Alias);

        // If the other player isn't white, player2 will play as white
        if (gameStates[gameId].playerWhite == 0) {
            gameStates[gameId].playerWhite = msg.sender;
            // Game starts with White, so here player2
            games[gameId].nextPlayer = games[gameId].player2;
        }

        GameJoined(gameId, games[gameId].player1, games[gameId].player1Alias, games[gameId].player2, player2Alias, gameStates[gameId].playerWhite, games[gameId].pot);
    }

    /**
    *
    * verify signature of state
    * verify signature of move
    * apply state, verify move
    */
    function moveFromState(bytes32 gameId, int8[128] state, uint256 fromIndex,
                           uint256 toIndex, bytes sigState) notEnded(gameId) public {
        // check whether sender is a member of this game
        if (games[gameId].player1 != msg.sender && games[gameId].player2 != msg.sender) {
            throw;
        }

        // find opponent to msg.sender
        address opponent;
        if (msg.sender == games[gameId].player1) {
            opponent = games[gameId].player2;
        } else {
            opponent = games[gameId].player1;
        }

        // verify state - should be signed by the other member of game - not mover
        if (!verifySig(opponent, sha3(state), sigState)) {
            throw;
        }

        // check move count. New state should have a higher move count.
        if ((state[8] * int8(128) + state[9]) < (gameStates[gameId].fields[8] * int8(128) + gameStates[gameId].fields[9])) {
            throw;
        }

        int8 playerColor = msg.sender == gameStates[gameId].playerWhite ? int8(1) : int8(-1);

        // apply state
        gameStates[gameId].setState(state, playerColor);
        games[gameId].nextPlayer =  msg.sender;

        // apply and verify move
        move(gameId, fromIndex, toIndex);
    }

    function move(bytes32 gameId, uint256 fromIndex, uint256 toIndex) notEnded(gameId) public {
        if (games[gameId].nextPlayer != msg.sender) {
            throw;
        }
        if(games[gameId].timeoutState != 0) {
            games[gameId].timeoutState = 0;
        }
        // Chess move validation
        gameStates[gameId].move(fromIndex, toIndex);

        // Set nextPlayer
        if (msg.sender == games[gameId].player1) {
            games[gameId].nextPlayer = games[gameId].player2;
        } else {
            games[gameId].nextPlayer = games[gameId].player1;
        }

        // Send events
        Move(gameId, msg.sender, fromIndex, toIndex);
        GameStateChanged(gameId, gameStates[gameId].fields);
    }

    /* Explicit set game state. Only in debug mode */
    function setGameState(bytes32 gameId, int8[128] state, address nextPlayer) debugOnly public {
        int8 playerColor = nextPlayer == gameStates[gameId].playerWhite ? int8(1) : int8(-1);
        gameStates[gameId].setState(state, playerColor);
        games[gameId].nextPlayer = nextPlayer;
        GameStateChanged(gameId, gameStates[gameId].fields);
    }

    function getCurrentGameState(bytes32 gameId) constant returns (int8[128]) {
       return gameStates[gameId].fields;
    }

    function getWhitePlayer(bytes32 gameId) constant returns (address) {
       return gameStates[gameId].playerWhite;
    }

    /* The sender claims he has won the game. Starts a timeout. */
    function claimWin(bytes32 gameId) notEnded(gameId) public {

        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        // only if timeout has not started
        if (game.timeoutState != 0)
            throw;
        // you can only claim draw / victory in the enemies turn
        if (msg.sender == game.nextPlayer)
            throw;
        // get the color of the player that wants to claim win
        int8 otherPlayerColor = gameStates[gameId].playerWhite == msg.sender ? int8(-1) : int8(1);
        // the one not sending is white -> the sending player is Black

        // We get the king position of that player
        uint256 kingIndex = uint256(gameStates[gameId].getOwnKing(otherPlayerColor));
        // if he is in check the request is legal
        if (gameStates[gameId].checkForCheck(kingIndex, otherPlayerColor)){
            game.timeoutStarted = now;
            game.timeoutState = 1;
            GameTimeoutStarted(gameId, game.timeoutStarted, game.timeoutState);
        // else it is not
        } else {
            throw;
        }

    }

    /* The sender offers the other player a draw. Starts a timeout. */
    function offerDraw(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        // only if timeout has not started or state = timeout and 2*timeoutTime is over
        if (game.timeoutState != 0 && (game.timeoutState != 2 || now < game.timeoutStarted + 20 minutes))
            throw;

        game.timeoutStarted = now;
        if (msg.sender == game.nextPlayer) {
            game.timeoutState = -2;
        } else {
            game.timeoutState = -1;
        }
        GameTimeoutStarted(gameId, game.timeoutStarted, game.timeoutState);
    }

    /*
     * The sender claims that the other player is not in the game anymore.
     * Starts a Timeout that can be claimed
     */
    function claimTimeout(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        // only if timeout has not started
        if (game.timeoutState != 0)
            throw;
        // you can only claim draw / victory in the enemies turn
        if (msg.sender == game.nextPlayer)
            throw;
        game.timeoutStarted = now;
        game.timeoutState = 2;
        GameTimeoutStarted(gameId, game.timeoutStarted, game.timeoutState);
    }

    /*
     * The sender (currently waiting player) rejects the draw offered by the
     * other (turning) player.
     */
    function rejectCurrentPlayerDraw(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        // only if timeout is present
        if (game.timeoutState != -2)
            throw;
        // only not playing player is able to reject a draw offer of the nextPlayer
        if (msg.sender == game.nextPlayer)
            throw;
        game.timeoutState = 0;
        GameDrawOfferRejected(gameId);
    }

    /*
     * The sender (currently waiting player) claims that the other (turning)
     * player timed out and has to provide a move, the other player could
     * have done to prevent the timeout.
     */
    function claimTimeoutEndedWithMove(bytes32 gameId, uint256 fromIndex, uint256 toIndex) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        if (now < game.timeoutStarted + 10 minutes)
            throw;
        if (msg.sender == game.nextPlayer)
            throw;
        if (game.timeoutState != 2)
            throw;

        // TODO we need other move function
        // move is valid if it does not throw
        move(gameId, fromIndex, toIndex);

        game.ended = true;
        game.winner = msg.sender;
        if(msg.sender == game.player1) {
            games[gameId].player1Winnings = games[gameId].pot;
            games[gameId].pot = 0;
        } else {
            games[gameId].player2Winnings = games[gameId].pot;
            games[gameId].pot = 0;
        }
        GameEnded(gameId);
    }

    /* The sender claims a previously started timeout. */
    function claimTimeoutEnded(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        if (game.timeoutState == 0 || game.timeoutSate == 2)
            throw;
        if (now < game.timeoutStarted + 10 minutes)
            throw;
        if (msg.sender == game.nextPlayer) {
            if (game.timeoutState == -2) { // draw
                game.ended = true;
                games[gameId].player1Winnings = games[gameId].pot / 2;
                games[gameId].player2Winnings = games[gameId].pot / 2;
                games[gameId].pot = 0;
                GameEnded(gameId);
            } else {
                throw;
            }
        } else {
            if (game.timeoutState == -1) { // draw
                game.ended = true;
                games[gameId].player1Winnings = games[gameId].pot / 2;
                games[gameId].player2Winnings = games[gameId].pot / 2;
                games[gameId].pot = 0;
                GameEnded(gameId);
            } else if (game.timeoutState == 1){ // win
                game.ended = true;
                game.winner = msg.sender;
                if(msg.sender == game.player1) {
                    games[gameId].player1Winnings = games[gameId].pot;
                    games[gameId].pot = 0;
                } else {
                    games[gameId].player2Winnings = games[gameId].pot;
                    games[gameId].pot = 0;
                }
                GameEnded(gameId);
            } else {
                throw;
            }
        }
    }

    /* A timeout can be confirmed by the non-initializing player. */
    function confirmGameEnded(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        if (game.timeoutState == 0)
            throw;
        if (msg.sender != game.nextPlayer) {
            if (game.timeoutState == -2) { // draw
                game.ended = true;
                games[gameId].player1Winnings = games[gameId].pot / 2;
                games[gameId].player2Winnings = games[gameId].pot / 2;
                games[gameId].pot = 0;
                GameEnded(gameId);
            } else {
                throw;
            }
        } else {
            if (game.timeoutState == -1) { // draw
                game.ended = true;
                games[gameId].player1Winnings = games[gameId].pot / 2;
                games[gameId].player2Winnings = games[gameId].pot / 2;
                games[gameId].pot = 0;
                GameEnded(gameId);
            } else if (game.timeoutState == 1 || game.timeoutState == 2) { // win
                // TODO: do we want to allow this for timeoutState == 2 ?
                game.ended = true;
                if(msg.sender == game.player1) {
                    game.winner = game.player2;
                    games[gameId].player2Winnings = games[gameId].pot;
                    games[gameId].pot = 0;
                } else {
                    game.winner = game.player1;
                    games[gameId].player1Winnings = games[gameId].pot;
                    games[gameId].pot = 0;
                }
                GameEnded(gameId);
            } else {
                throw;
            }
        }
    }

    /* This unnamed function is called whenever someone tries to send ether to the contract */
    function () {
        throw; // Prevents accidental sending of ether
    }
}

/**
 * Chess contract
 * Stores any amount of games with two players and current state.
 * State encoding:
 *    positive numbers for white, negative numbers for black
 *    for details, see
 *    https://github.com/ise-ethereum/on-chain-chess/wiki/Chess-board-representation
 */

import "TurnBasedGame.sol";
import "ChessLogic.sol";
import "Auth.sol";

contract Chess is TurnBasedGame, Auth {
    using ChessLogic for ChessLogic.State;
    mapping (bytes32 => ChessLogic.State) gameStates;

    event GameInitialized(bytes32 indexed gameId, address indexed player1, string player1Alias, address playerWhite, uint pot);
    event GameJoined(bytes32 indexed gameId, address indexed player1, string player1Alias, address indexed player2, string player2Alias, address playerWhite, uint pot);
    event GameStateChanged(bytes32 indexed gameId, int8[128] state);
    event GameTimeoutStarted(bytes32 indexed gameId,uint timeoutStarted, int8 timeoutState);
    // GameDrawOfferRejected: notification that a draw of the currently turning player
    //                        is rejected by the waiting player
    event GameDrawOfferRejected(bytes32 indexed gameId);
    event Move(bytes32 indexed gameId, address indexed player, uint256 fromIndex, uint256 toIndex);

    function Chess(bool enableDebugging) TurnBasedGame(enableDebugging) {
    }

    /**
     * Initialize a new game
     * string player1Alias: Alias of the player creating the game
     * bool playAsWhite: Pass true or false depending on if the creator will play as white
     */
    function initGame(string player1Alias, bool playAsWhite) public returns (bytes32) {
        bytes32 gameId = super.initGame(player1Alias, playAsWhite);

        // Setup game state
        int8 nextPlayerColor = int8(1);
        gameStates[gameId].setupState(nextPlayerColor);
        if (playAsWhite) {
            // Player 1 will play as white
            gameStates[gameId].playerWhite = msg.sender;

            // Game starts with White, so here player 1
            games[gameId].nextPlayer = games[gameId].player1;
        }

        // Sent notification events
        GameInitialized(gameId, games[gameId].player1, player1Alias, gameStates[gameId].playerWhite, games[gameId].pot);
        GameStateChanged(gameId, gameStates[gameId].fields);
        return gameId;
    }

    /**
     * Join an initialized game
     * bytes32 gameId: ID of the game to join
     * string player2Alias: Alias of the player that is joining
     */
    function joinGame(bytes32 gameId, string player2Alias) public {
        super.joinGame(gameId, player2Alias);

        // If the other player isn't white, player2 will play as white
        if (gameStates[gameId].playerWhite == 0) {
            gameStates[gameId].playerWhite = msg.sender;
            // Game starts with White, so here player2
            games[gameId].nextPlayer = games[gameId].player2;
        }

        GameJoined(gameId, games[gameId].player1, games[gameId].player1Alias, games[gameId].player2, player2Alias, gameStates[gameId].playerWhite, games[gameId].pot);
    }

    /**
    *
    * verify signature of state
    * verify signature of move
    * apply state, verify move
    */
    function moveFromState(bytes32 gameId, int8[128] state, uint256 fromIndex,
                           uint256 toIndex, bytes sigState) notEnded(gameId) public {
        // check whether sender is a member of this game
        if (games[gameId].player1 != msg.sender && games[gameId].player2 != msg.sender) {
            throw;
        }

        // find opponent to msg.sender
        address opponent;
        if (msg.sender == games[gameId].player1) {
            opponent = games[gameId].player2;
        } else {
            opponent = games[gameId].player1;
        }

        // verify state - should be signed by the other member of game - not mover
        if (!verifySig(opponent, sha3(state), sigState)) {
            throw;
        }

        // check move count. New state should have a higher move count.
        if ((state[8] * int8(128) + state[9]) < (gameStates[gameId].fields[8] * int8(128) + gameStates[gameId].fields[9])) {
            throw;
        }

        int8 playerColor = msg.sender == gameStates[gameId].playerWhite ? int8(1) : int8(-1);

        // apply state
        gameStates[gameId].setState(state, playerColor);
        games[gameId].nextPlayer =  msg.sender;

        // apply and verify move
        move(gameId, fromIndex, toIndex);
    }

    function move(bytes32 gameId, uint256 fromIndex, uint256 toIndex) notEnded(gameId) public {
        if (games[gameId].nextPlayer != msg.sender) {
            throw;
        }
        if(games[gameId].timeoutState != 0) {
            games[gameId].timeoutState = 0;
        }
        // Chess move validation
        gameStates[gameId].move(fromIndex, toIndex);

        // Set nextPlayer
        if (msg.sender == games[gameId].player1) {
            games[gameId].nextPlayer = games[gameId].player2;
        } else {
            games[gameId].nextPlayer = games[gameId].player1;
        }

        // Send events
        Move(gameId, msg.sender, fromIndex, toIndex);
        GameStateChanged(gameId, gameStates[gameId].fields);
    }

    /* Explicit set game state. Only in debug mode */
    function setGameState(bytes32 gameId, int8[128] state, address nextPlayer) debugOnly public {
        int8 playerColor = nextPlayer == gameStates[gameId].playerWhite ? int8(1) : int8(-1);
        gameStates[gameId].setState(state, playerColor);
        games[gameId].nextPlayer = nextPlayer;
        GameStateChanged(gameId, gameStates[gameId].fields);
    }

    function getCurrentGameState(bytes32 gameId) constant returns (int8[128]) {
       return gameStates[gameId].fields;
    }

    function getWhitePlayer(bytes32 gameId) constant returns (address) {
       return gameStates[gameId].playerWhite;
    }

    /* The sender claims he has won the game. Starts a timeout. */
    function claimWin(bytes32 gameId) notEnded(gameId) public {

        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        // only if timeout has not started
        if (game.timeoutState != 0)
            throw;
        // you can only claim draw / victory in the enemies turn
        if (msg.sender == game.nextPlayer)
            throw;
        // get the color of the player that wants to claim win
        int8 otherPlayerColor = gameStates[gameId].playerWhite == msg.sender ? int8(-1) : int8(1);
        // the one not sending is white -> the sending player is Black

        // We get the king position of that player
        uint256 kingIndex = uint256(gameStates[gameId].getOwnKing(otherPlayerColor));
        // if he is in check the request is legal
        if (gameStates[gameId].checkForCheck(kingIndex, otherPlayerColor)){
            game.timeoutStarted = now;
            game.timeoutState = 1;
            GameTimeoutStarted(gameId, game.timeoutStarted, game.timeoutState);
        // else it is not
        } else {
            throw;
        }

    }

    /* The sender offers the other player a draw. Starts a timeout. */
    function offerDraw(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        // only if timeout has not started
        if (game.timeoutState != 0)
            throw;

        game.timeoutStarted = now;
        if (msg.sender == game.nextPlayer) {
            game.timeoutState = -2;
        } else {
            game.timeoutState = -1;
        }
        GameTimeoutStarted(gameId, game.timeoutStarted, game.timeoutState);
    }

    /*
     * The sender (currently turning player) offers the other player (waiting)
     * a draw. Starts a timeout.
     */
    function rejectCurrentPlayerDraw(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        // only if timeout is present
        if (game.timeoutState != -2)
            throw;
        // only not playing player is able to reject a draw offer of the nextPlayer
        if (msg.sender == game.nextPlayer)
            throw;
        game.timeoutState = 0;
        GameDrawOfferRejected(gameId);
    }

    /*
     * The sender claims that the other player is not in the game anymore.
     * Starts a Timeout that can be claimed
     */
    function claimTimeout(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        // only if timeout has not started
        if (game.timeoutState != 0)
            throw;
        // you can only claim draw / victory in the enemies turn
        if (msg.sender == game.nextPlayer)
            throw;
        game.timeoutStarted = now;
        game.timeoutState = 2;
        GameTimeoutStarted(gameId, game.timeoutStarted, game.timeoutState);
    }

    /*
     * The sender rejects the previously claimed timeout of the other player.
     * This will NOT reset the timeout.
     * Timeout will 'degrade' to a draw timeout.
     */
    function rejectTimeout(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        // only if timeout has not started
        if (game.timeoutState != 2)
            throw;
        // you can only reject a timeout if you are the next player
        if (msg.sender != game.nextPlayer)
            throw;
        game.timeoutState = 1;
        GameTimeoutStarted(gameId, game.timeoutStarted, game.timeoutState);
    }

    /* The sender claims a previously started timeout. */
    function claimTimeoutEnded(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        if (game.timeoutState == 0)
            throw;
        if (now < game.timeoutStarted + 10 minutes)
            throw;
        if (msg.sender == game.nextPlayer) {
            if (game.timeoutState == -2) { // draw
                game.ended = true;
                games[gameId].player1Winnings = games[gameId].pot / 2;
                games[gameId].player2Winnings = games[gameId].pot / 2;
                games[gameId].pot = 0;
                GameEnded(gameId);
            } else {
                throw;
            }
        } else {
            // Game is a draw, transfer ether back
            if (game.timeoutState == -1) {
                game.ended = true;
                games[gameId].player1Winnings = games[gameId].pot / 2;
                games[gameId].player2Winnings = games[gameId].pot / 2;
                games[gameId].pot = 0;
                GameEnded(gameId);
            } else if (game.timeoutState == 1 || game.timeoutState == 2){
                game.ended = true;
                game.winner = msg.sender;
                if(msg.sender == game.player1) {
                    games[gameId].player1Winnings = games[gameId].pot;
                    games[gameId].pot = 0;
                } else {
                    games[gameId].player2Winnings = games[gameId].pot;
                    games[gameId].pot = 0;
                }
                GameEnded(gameId);
            } else {
                throw;
            }
        }
    }

    /* A timeout can be confirmed by the non-initializing player. */
    function confirmGameEnded(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        if (game.timeoutState == 0)
            throw;
        if (msg.sender != game.nextPlayer) {
            if (game.timeoutState == -2) { // draw
                game.ended = true;
                games[gameId].player1Winnings = games[gameId].pot / 2;
                games[gameId].player2Winnings = games[gameId].pot / 2;
                games[gameId].pot = 0;
                GameEnded(gameId);
            } else {
                throw;
            }
        } else {
            // Game is a draw, transfer ether back
            if (game.timeoutState == -1) {
                game.ended = true;
                games[gameId].player1Winnings = games[gameId].pot / 2;
                games[gameId].player2Winnings = games[gameId].pot / 2;
                games[gameId].pot = 0;
                GameEnded(gameId);
            } else if (game.timeoutState == 1 || game.timeoutState == 2) {
                // TODO: do we want to allow this for timeoutState == 2 ?
                game.ended = true;
                // other player won
                if(msg.sender == game.player1) {
                    game.winner = game.player2;
                    games[gameId].player2Winnings = games[gameId].pot;
                    games[gameId].pot = 0;
                } else {
                    game.winner = game.player1;
                    games[gameId].player1Winnings = games[gameId].pot;
                    games[gameId].pot = 0;
                }
                GameEnded(gameId);
            } else {
                throw;
            }
        }
    }

    /* This unnamed function is called whenever someone tries to send ether to the contract */
    function () {
        throw; // Prevents accidental sending of ether
    }
}


fix: smart contract using worng address for the event ChannelNew

import "Token.sol";
import "ChannelManagerLibrary.sol";

// for each asset a manager will be deployed, to reduce gas usage for manager
// deployment the logic is moved into a library and this contract will work
// only as a proxy/state container.
contract ChannelManagerContract {
    using ChannelManagerLibrary for ChannelManagerLibrary.Data;
    ChannelManagerLibrary.Data data;

    event ChannelNew(
        address nettingChannel,
        address participant1,
        address participant2,
        uint settleTimeout
    );

    function ChannelManagerContract(address tokenAddress) {
        data.token = Token(tokenAddress);
    }

    // XXX: move this to the library, if possible
    // variable length arrays from inside the evm is not supported
    // function getAllChannels() constant returns (address[]) {
    //     return data.getAllChannels();
    // }
    // function getChannelsForNode(address nodeAddress) constant returns (address[]) {
    //     return data.getChannelsForNode(nodeAddress);
    // }
    // function getChannelsParticipants() constant returns (address[]) {
    //     return data.getChannelsParticipants();
    // }
    function getChannelsAddresses() constant returns (address[]) {
        return data.all_channels;
    }

    function getChannelsParticipants() constant returns (address[] channels) {
        uint i;
        uint pos;
        address channel;
        address participant1;
        address participant2;
        address[] memory result;

        result = new address[](data.all_channels.length * 2);

        pos = 0;
        for (i=0; i<data.all_channels.length; i++) {
            channel = data.all_channels[i];

            (participant1, , participant2, ) = NettingChannelContract(channel).addressAndBalance();

            result[pos] = participant1;
            pos += 1;
            result[pos] = participant2;
            pos += 1;
        }

        return result;
    }

    function nettingContractsByAddress(address node_address) constant returns (address[]){
        uint i;
        uint count;
        address channel;
        address participant1;
        address participant2;
        address[] memory result;

        count = 0;
        for (i=0; i<data.all_channels.length; i++) {
            channel = data.all_channels[i];

            (participant1, , participant2, ) = NettingChannelContract(channel).addressAndBalance();

            if (participant1 == node_address) {
                count += 1;
            } else if (participant2 == node_address) {
                count += 1;
            }
        }

        result = new address[](count);
        count -= 1;
        for (i=0; i<data.all_channels.length; i++) {
            channel = data.all_channels[i];

            (participant1, , participant2, ) = NettingChannelContract(channel).addressAndBalance();

            if (participant1 == node_address) {
                result[count] = channel;
                count -= 1;
            } else if (participant2 == node_address) {
                result[count] = channel;
                count -= 1;
            }
        }

        return result;
    }

    function tokenAddress () constant returns (address) {
        return data.token;
    }

    function getChannelsForNode(address nodeAddress) constant returns (address[]) {
        return data.nodeChannels[nodeAddress];
    }

    function getChannelWith(address partner) constant returns (address) {
        return data.getChannelWith(partner);
    }

    function newChannel(address partner, uint settleTimeout) returns (address channel) {
        channel = data.newChannel(partner, settleTimeout);
        ChannelNew(channel, msg.sender, partner, settleTimeout);
    }

    function () { throw; }
}

import "Token.sol";
import "ChannelManagerLibrary.sol";

// for each asset a manager will be deployed, to reduce gas usage for manager
// deployment the logic is moved into a library and this contract will work
// only as a proxy/state container.
contract ChannelManagerContract {
    using ChannelManagerLibrary for ChannelManagerLibrary.Data;
    ChannelManagerLibrary.Data data;

    event ChannelNew(
        address nettingChannel,
        address participant1,
        address participant2,
        uint settleTimeout
    );

    function ChannelManagerContract(address tokenAddress) {
        data.token = Token(tokenAddress);
    }

    // XXX: move this to the library, if possible
    // variable length arrays from inside the evm is not supported
    // function getAllChannels() constant returns (address[]) {
    //     return data.getAllChannels();
    // }
    // function getChannelsForNode(address nodeAddress) constant returns (address[]) {
    //     return data.getChannelsForNode(nodeAddress);
    // }
    // function getChannelsParticipants() constant returns (address[]) {
    //     return data.getChannelsParticipants();
    // }
    function getChannelsAddresses() constant returns (address[]) {
        return data.all_channels;
    }

    function getChannelsParticipants() constant returns (address[] channels) {
        uint i;
        uint pos;
        address channel;
        address participant1;
        address participant2;
        address[] memory result;

        result = new address[](data.all_channels.length * 2);

        pos = 0;
        for (i=0; i<data.all_channels.length; i++) {
            channel = data.all_channels[i];

            (participant1, , participant2, ) = NettingChannelContract(channel).addressAndBalance();

            result[pos] = participant1;
            pos += 1;
            result[pos] = participant2;
            pos += 1;
        }

        return result;
    }

    function nettingContractsByAddress(address node_address) constant returns (address[]){
        uint i;
        uint count;
        address channel;
        address participant1;
        address participant2;
        address[] memory result;

        count = 0;
        for (i=0; i<data.all_channels.length; i++) {
            channel = data.all_channels[i];

            (participant1, , participant2, ) = NettingChannelContract(channel).addressAndBalance();

            if (participant1 == node_address) {
                count += 1;
            } else if (participant2 == node_address) {
                count += 1;
            }
        }

        result = new address[](count);
        count -= 1;
        for (i=0; i<data.all_channels.length; i++) {
            channel = data.all_channels[i];

            (participant1, , participant2, ) = NettingChannelContract(channel).addressAndBalance();

            if (participant1 == node_address) {
                result[count] = channel;
                count -= 1;
            } else if (participant2 == node_address) {
                result[count] = channel;
                count -= 1;
            }
        }

        return result;
    }

    function tokenAddress () constant returns (address) {
        return data.token;
    }

    function getChannelsForNode(address nodeAddress) constant returns (address[]) {
        return data.nodeChannels[nodeAddress];
    }

    function getChannelWith(address partner) constant returns (address) {
        return data.getChannelWith(partner);
    }

    function newChannel(address partner, uint settleTimeout) returns (address channel) {
        channel = data.newChannel(partner, settleTimeout);
        ChannelNew(this, msg.sender, partner, settleTimeout);
    }

    function () { throw; }
}