private static LedgerStruct.Channel _resetDuplexState(LedgerStruct.Channel c)
        {
            c.settleFinalizedTime = 0;
            LedgerStruct.ChannelStatus channelStatus = LedgerStruct.getStandardChannelStatus();
            c = _updateChannelStatus(c, channelStatus.Operable);
            LedgerStruct.PeerProfile[] peerProfiles = c.peerProfiles;
            LedgerStruct.PeerProfile   peerProfile0 = peerProfiles[0];
            LedgerStruct.PeerProfile   peerProfile1 = peerProfiles[1];
            LedgerStruct.PeerState     state        = peerProfile0.state;
            state.seqNum                 = 0;
            state.transferOut            = 0;
            state.nextPayIdListHash      = null;
            state.lastPayResolveDeadline = 0;
            state.pendingPayOut          = 0;
            peerProfile0.state           = state;
            state                        = peerProfile1.state;
            state.seqNum                 = 0;
            state.transferOut            = 0;
            state.nextPayIdListHash      = null;
            state.lastPayResolveDeadline = 0;
            state.pendingPayOut          = 0;
            peerProfile1.state           = state;
            peerProfiles[0]              = peerProfile0;
            peerProfiles[1]              = peerProfile1;
            c.peerProfiles               = peerProfiles;

            // reset possibly remaining WithdrawIntent freezed by previous intendSettle()
            LedgerStruct.WithdrawIntent intent = c.withdrawIntent;
            intent.receiver           = null;
            intent.amount             = 0;
            intent.requestTime        = 0;
            intent.recipientChannelId = null;
            c.withdrawIntent          = intent;
            return(c);
        }
 public static bool confirmSettle(byte[] _channelId)
 {
     BasicMethods.assert(BasicMethods._isByte32(_channelId), "_channelId illegal");
     LedgerStruct.Channel       c       = LedgerStruct.getChannelMap(_channelId);
     LedgerStruct.SettleBalance balance = LedgerChannel._validateSettleBalance(c);
     if (balance.isSettled != 1)
     {
         c = _resetDuplexState(c);
         ConfirmSettleFailEvent(_channelId);
         return(false);
     }
     LedgerStruct.ChannelStatus channelStatus = LedgerStruct.getStandardChannelStatus();
     c = _updateChannelStatus(c, channelStatus.Closed);
     LedgerStruct.setChannelMap(_channelId, c);
     ConfirmSettleEvent(_channelId, balance.balance);
     return(true);
 }
        private static LedgerStruct.Channel _updateChannelStatus(LedgerStruct.Channel _c, byte _newStatus)
        {
            if (_c.status == _newStatus)
            {
                return(_c);
            }
            LedgerStruct.ChannelStatus channelStatus = LedgerStruct.getStandardChannelStatus();
            // update counter of old status
            if (_c.status != channelStatus.Uninitialized)
            {
                LedgerStruct.setChannelStatusNums(_c.status, LedgerStruct.getChannelStatusNums(_c.status) - 1);
            }

            // update counter of new status
            LedgerStruct.setChannelStatusNums(_newStatus, LedgerStruct.getChannelStatusNums(_newStatus) + 1);

            _c.status = _newStatus;

            return(_c);
        }
    public static byte[] migrateChannelToInner(byte[] sender, LedgerStruct.Ledger _self, byte[][] pubKeys, byte[] _migrationRequest)
    {
        BasicMethods.assert(BasicMethods._isLegalAddress(sender), "sender illegal");
        PbChain.ChannelMigrationRequest migrationRequest =
            (PbChain.ChannelMigrationRequest)Neo.SmartContract.Framework.Helper.Deserialize(_migrationRequest);
        PbEntity.ChannelMigrationInfo migrationInfo =
            (PbEntity.ChannelMigrationInfo)Neo.SmartContract.Framework.Helper.Deserialize(migrationRequest.channelMigrationInfo);
        byte[] channelId = migrationInfo.channelId;
        BasicMethods.assert(BasicMethods._isByte32(channelId), "channelId illegal");
        LedgerStruct.Channel c = LedgerStruct.getChannelMap(channelId);
        byte[] toLedgerAddr    = migrationInfo.toLedgerAddress;

        LedgerStruct.ChannelStatus channelStatus = LedgerStruct.getStandardChannelStatus();
        BasicMethods.assert(
            c.status == channelStatus.Operable ||
            c.status == channelStatus.Settling, "status illegal"
            );
        byte[] h = Hash256(migrationRequest.channelMigrationInfo);
        // use Channel Library instead

        BasicMethods.assert(LedgerChannel._checkCoSignatures(c, h, pubKeys, migrationRequest.sigs), "Check co-sigs failed");
        BasicMethods.assert(migrationInfo.fromLedgerAddress.Equals(ExecutionEngine.ExecutingScriptHash), "From ledger address is not this");
        BasicMethods.assert(toLedgerAddr.Equals(sender), "To ledger address is not msg.sender");
        BasicMethods.assert(Blockchain.GetHeight() <= migrationInfo.migrationDeadline, "Passed migration deadline");

        c            = LedgerOperation._updateChannelStatus(c, channelStatus.Migrated);
        c.migratedTo = toLedgerAddr;
        LedgerStruct.setChannelMap(channelId, c);
        MigrateChannelToEvent(channelId, toLedgerAddr);

        byte[] celerWallet = _self.celerWallet;

        NEP5Contract dyncall = (NEP5Contract)celerWallet.ToDelegate();

        Object[] args = new object[] { channelId, toLedgerAddr };
        dyncall("transferOperatorship", args);

        return(channelId);
    }
        public static bool openChannelMockSet(byte[] _channelId, BigInteger _disputeTimeout, byte[] _tokenAddress, byte _tokenType, byte[][] _peerAddrs, BigInteger[] _deposits)
        {
            BasicMethods.assert(BasicMethods._isByte32(_channelId), "_channelId illegal");
            BasicMethods.assert(BasicMethods._isLegalAddress(_tokenAddress), "_channelId illegal");
            BasicMethods.assert(_tokenType >= 0 && _tokenType <= 3, "_tokenType illegal");
            BasicMethods.assert(_peerAddrs.Length == 2, "_peerAddrs length illegal");
            BasicMethods.assert(BasicMethods._isLegalAddress(_peerAddrs[0]), "_peerAddrs 0 illegal");
            BasicMethods.assert(BasicMethods._isLegalAddress(_peerAddrs[1]), "_peerAddrs 1 illegal");
            BasicMethods.assert(_deposits.Length == 2, "_deposits length illegal");
            BasicMethods.assert(_deposits[0] >= 0, "_deposits 0 illegal");
            BasicMethods.assert(_deposits[1] >= 0, "_deposits 1 illegal");

            setTmpChannelId(_channelId);

            LedgerStruct.Channel c = LedgerStruct.getChannelMap(_channelId);
            c.disputeTimeout = _disputeTimeout;
            LedgerStruct.ChannelStatus channelStatus = LedgerStruct.getStandardChannelStatus();
            c = LedgerOperation._updateChannelStatus(c, channelStatus.Operable);
            PbEntity.TokenInfo token = new PbEntity.TokenInfo()
            {
                address   = _tokenAddress,
                tokenType = _tokenType
            };
            c.token = token;

            LedgerStruct.PeerProfile[] peerProfiles = c.peerProfiles;
            LedgerStruct.PeerProfile   peerProfile0 = peerProfiles[0];
            LedgerStruct.PeerProfile   peerProfile1 = peerProfiles[1];
            peerProfile0.peerAddr = _peerAddrs[0];
            peerProfile0.deposit  = _deposits[0];
            peerProfile1.peerAddr = _peerAddrs[1];
            peerProfile1.deposit  = _deposits[1];
            peerProfiles[0]       = peerProfile0;
            peerProfiles[1]       = peerProfile1;
            c.peerProfiles        = peerProfiles;
            LedgerStruct.setChannelMap(_channelId, c);
            return(true);
        }
        public static bool vetoWithdraw(byte[] _channelId, byte[] _sender)
        {
            BasicMethods.assert(BasicMethods._isByte32(_channelId), "_channelId illegal");
            BasicMethods.assert(BasicMethods._isLegalAddress(_sender), "_sender illegal");
            BasicMethods.assert(Runtime.CheckWitness(_sender), "_sender check witness failed");

            LedgerStruct.Channel       c             = LedgerStruct.getChannelMap(_channelId);
            LedgerStruct.ChannelStatus channelStatus = LedgerStruct.getStandardChannelStatus();
            BasicMethods.assert(c.status == channelStatus.Operable, "Channel status error");
            LedgerStruct.WithdrawIntent withdrawIntent = c.withdrawIntent;
            byte[] receiver = withdrawIntent.receiver;
            BasicMethods.assert(receiver.ToBigInteger() != 0, "No pending withdraw intent");
            BasicMethods.assert(LedgerChannel._isPeer(c, _sender), "msg.sender is not peer");

            withdrawIntent.receiver           = null;
            withdrawIntent.amount             = 0;
            withdrawIntent.requestTime        = 0;
            withdrawIntent.recipientChannelId = null;
            c.withdrawIntent = withdrawIntent;
            LedgerStruct.setChannelMap(_channelId, c);
            VetoWithdrawEvent(_channelId);
            return(true);
        }
    public static bool migrateChannelFromInner(LedgerStruct.Ledger _self, byte[] _fromLedgerAddr, byte[] _migrationRequest, byte[][] pubKeys)
    {
        BasicMethods.assert(BasicMethods._isLegalAddress(_fromLedgerAddr), "_fromLedgerAddr illegal");

        // TODO: latest version of openzeppelin Address.sol provide this api toPayable()
        byte[] fromLedgerAddrPayable = _fromLedgerAddr;

        NEP5Contract dyncall = (NEP5Contract)fromLedgerAddrPayable.ToDelegate();

        Object[] args      = new object[] { _migrationRequest, pubKeys };
        byte[]   channelId = (byte[])dyncall("migrateChannelTo", args);

        LedgerStruct.Channel       c             = LedgerStruct.getChannelMap(channelId);
        LedgerStruct.ChannelStatus channelStatus = LedgerStruct.getStandardChannelStatus();
        BasicMethods.assert(c.status == channelStatus.Uninitialized, "Immigrated channel already exists");

        byte[] celerWallet = _self.celerWallet;
        args    = new object[] { channelId };
        dyncall = (NEP5Contract)celerWallet.ToDelegate();
        byte[] oper = (byte[])dyncall("getOperator", args);
        BasicMethods.assert(
            oper.Equals(ExecutionEngine.ExecutingScriptHash),
            "Operatorship not transferred"
            );

        c = LedgerOperation._updateChannelStatus(c, channelStatus.Operable);
        // Do not migrate WithdrawIntent, in other words, migration will implicitly veto
        // pending WithdrawIntent if any.
        c = LedgerChannel._importChannelMigrationArgs(c, fromLedgerAddrPayable, channelId);
        c = LedgerChannel._importPeersMigrationInfo(c, fromLedgerAddrPayable, channelId);
        LedgerStruct.setChannelMap(channelId, c);

        MigrateChannelFromEvent(channelId, _fromLedgerAddr);

        return(true);
    }
 private static LedgerStruct.Channel _updateOverallStatesByIntendState(LedgerStruct.Channel c)
 {
     c.settleFinalizedTime = Blockchain.GetHeight() + c.disputeTimeout;
     LedgerStruct.ChannelStatus channelStatus = LedgerStruct.getStandardChannelStatus();
     return(_updateChannelStatus(c, channelStatus.Settling));
 }