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 intendWithdrawMockSet(byte[] _channelId, BigInteger _amount, byte[] _recipientChannelId, byte[] _receiver)
        {
            BasicMethods.assert(BasicMethods._isByte32(_channelId), "_channelId illegal");
            BasicMethods.assert(_amount >= 0, "_amount smaller than zero");
            BasicMethods.assert(BasicMethods._isByte32(_recipientChannelId), "_recipientChannelId illegal");
            BasicMethods.assert(BasicMethods._isLegalAddress(_receiver), "_receiver illegal");

            LedgerStruct.Channel        c = LedgerStruct.getChannelMap(_channelId);
            LedgerStruct.WithdrawIntent withdrawIntent = c.withdrawIntent;

            withdrawIntent.receiver           = _receiver;
            withdrawIntent.amount             = _amount;
            withdrawIntent.requestTime        = Blockchain.GetHeight();
            withdrawIntent.recipientChannelId = _recipientChannelId;
            c.withdrawIntent = withdrawIntent;
            setTmpChannelId(_channelId);
            LedgerStruct.setChannelMap(_channelId, c);
            return(true);
        }
        public static bool confirmWithdraw(byte[] _channelId)
        {
            BasicMethods.assert(BasicMethods._isByte32(_channelId), "_channelId illegal");

            LedgerStruct.Channel        c = LedgerStruct.getChannelMap(_channelId);
            LedgerStruct.WithdrawIntent withdrawIntent = c.withdrawIntent;
            byte[]     receiver = BasicMethods.clone(withdrawIntent.receiver);
            BigInteger amount   = withdrawIntent.amount;

            byte[] recipientChannelId = BasicMethods.clone(withdrawIntent.recipientChannelId);
            withdrawIntent.receiver           = null;
            withdrawIntent.amount             = 0;
            withdrawIntent.requestTime        = 0;
            withdrawIntent.recipientChannelId = null;
            c.withdrawIntent = withdrawIntent;
            c = LedgerChannel._addWithdrawal(c, receiver, amount);
            LedgerStruct.setChannelMap(_channelId, c);
            LedgerStruct.BalanceMap balanceMap = LedgerChannel.getBalanceMapInner(c);
            ConfirmWithdrawEvent(_channelId, amount, receiver, recipientChannelId, balanceMap.deposits, balanceMap.withdrawals);

            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);
        }