|
@ -77,10 +77,11 @@ class ChannelState(IntEnum): |
|
|
# - Non-funding node: has sent the funding_signed message. |
|
|
# - Non-funding node: has sent the funding_signed message. |
|
|
FUNDED = 2 # Funding tx was mined (requires min_depth and tx verification) |
|
|
FUNDED = 2 # Funding tx was mined (requires min_depth and tx verification) |
|
|
OPEN = 3 # both parties have sent funding_locked |
|
|
OPEN = 3 # both parties have sent funding_locked |
|
|
CLOSING = 4 # shutdown has been sent, and closing tx is unconfirmed. |
|
|
SHUTDOWN = 4 # shutdown has been sent. |
|
|
FORCE_CLOSING = 5 # we force-closed, and closing tx is unconfirmed. (otherwise we remain OPEN) |
|
|
CLOSING = 5 # closing negotiation done. we have a fully signed tx. |
|
|
CLOSED = 6 # closing tx has been mined |
|
|
FORCE_CLOSING = 6 # we force-closed, and closing tx is unconfirmed. (otherwise we remain OPEN) |
|
|
REDEEMED = 7 # we can stop watching |
|
|
CLOSED = 7 # closing tx has been mined |
|
|
|
|
|
REDEEMED = 8 # we can stop watching |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PeerState(IntEnum): |
|
|
class PeerState(IntEnum): |
|
@ -95,18 +96,25 @@ state_transitions = [ |
|
|
(cs.PREOPENING, cs.OPENING), |
|
|
(cs.PREOPENING, cs.OPENING), |
|
|
(cs.OPENING, cs.FUNDED), |
|
|
(cs.OPENING, cs.FUNDED), |
|
|
(cs.FUNDED, cs.OPEN), |
|
|
(cs.FUNDED, cs.OPEN), |
|
|
(cs.OPENING, cs.CLOSING), |
|
|
(cs.OPENING, cs.SHUTDOWN), |
|
|
(cs.FUNDED, cs.CLOSING), |
|
|
(cs.FUNDED, cs.SHUTDOWN), |
|
|
(cs.OPEN, cs.CLOSING), |
|
|
(cs.OPEN, cs.SHUTDOWN), |
|
|
|
|
|
(cs.SHUTDOWN, cs.SHUTDOWN), # if we reestablish |
|
|
|
|
|
(cs.SHUTDOWN, cs.CLOSING), |
|
|
|
|
|
(cs.CLOSING, cs.CLOSING), |
|
|
|
|
|
# we can force close almost any time |
|
|
(cs.OPENING, cs.FORCE_CLOSING), |
|
|
(cs.OPENING, cs.FORCE_CLOSING), |
|
|
(cs.FUNDED, cs.FORCE_CLOSING), |
|
|
(cs.FUNDED, cs.FORCE_CLOSING), |
|
|
(cs.OPEN, cs.FORCE_CLOSING), |
|
|
(cs.OPEN, cs.FORCE_CLOSING), |
|
|
|
|
|
(cs.SHUTDOWN, cs.FORCE_CLOSING), |
|
|
(cs.CLOSING, cs.FORCE_CLOSING), |
|
|
(cs.CLOSING, cs.FORCE_CLOSING), |
|
|
|
|
|
# we can get force closed almost any time |
|
|
(cs.OPENING, cs.CLOSED), |
|
|
(cs.OPENING, cs.CLOSED), |
|
|
(cs.FUNDED, cs.CLOSED), |
|
|
(cs.FUNDED, cs.CLOSED), |
|
|
(cs.OPEN, cs.CLOSED), |
|
|
(cs.OPEN, cs.CLOSED), |
|
|
(cs.CLOSING, cs.CLOSING), # if we reestablish |
|
|
(cs.SHUTDOWN, cs.CLOSED), |
|
|
(cs.CLOSING, cs.CLOSED), |
|
|
(cs.CLOSING, cs.CLOSED), |
|
|
|
|
|
# |
|
|
(cs.FORCE_CLOSING, cs.FORCE_CLOSING), # allow multiple attempts |
|
|
(cs.FORCE_CLOSING, cs.FORCE_CLOSING), # allow multiple attempts |
|
|
(cs.FORCE_CLOSING, cs.CLOSED), |
|
|
(cs.FORCE_CLOSING, cs.CLOSED), |
|
|
(cs.FORCE_CLOSING, cs.REDEEMED), |
|
|
(cs.FORCE_CLOSING, cs.REDEEMED), |
|
@ -174,11 +182,11 @@ class AbstractChannel(Logger, ABC): |
|
|
return self.get_state() == ChannelState.OPEN |
|
|
return self.get_state() == ChannelState.OPEN |
|
|
|
|
|
|
|
|
def is_closing(self): |
|
|
def is_closing(self): |
|
|
return self.get_state() in [ChannelState.CLOSING, ChannelState.FORCE_CLOSING] |
|
|
return ChannelState.SHUTDOWN <= self.get_state() <= ChannelState.FORCE_CLOSING |
|
|
|
|
|
|
|
|
def is_closed(self): |
|
|
def is_closed(self): |
|
|
# the closing txid has been saved |
|
|
# the closing txid has been saved |
|
|
return self.get_state() >= ChannelState.CLOSED |
|
|
return self.get_state() >= ChannelState.CLOSING |
|
|
|
|
|
|
|
|
def is_redeemed(self): |
|
|
def is_redeemed(self): |
|
|
return self.get_state() == ChannelState.REDEEMED |
|
|
return self.get_state() == ChannelState.REDEEMED |
|
@ -707,8 +715,6 @@ class Channel(AbstractChannel): |
|
|
# and the constraints are the ones imposed by their config |
|
|
# and the constraints are the ones imposed by their config |
|
|
ctn = self.get_next_ctn(htlc_receiver) |
|
|
ctn = self.get_next_ctn(htlc_receiver) |
|
|
chan_config = self.config[htlc_receiver] |
|
|
chan_config = self.config[htlc_receiver] |
|
|
if self.is_closed(): |
|
|
|
|
|
raise PaymentFailure('Channel closed') |
|
|
|
|
|
if self.get_state() != ChannelState.OPEN: |
|
|
if self.get_state() != ChannelState.OPEN: |
|
|
raise PaymentFailure('Channel not open', self.get_state()) |
|
|
raise PaymentFailure('Channel not open', self.get_state()) |
|
|
if htlc_proposer == LOCAL: |
|
|
if htlc_proposer == LOCAL: |
|
@ -777,7 +783,7 @@ class Channel(AbstractChannel): |
|
|
return True |
|
|
return True |
|
|
|
|
|
|
|
|
def should_try_to_reestablish_peer(self) -> bool: |
|
|
def should_try_to_reestablish_peer(self) -> bool: |
|
|
return ChannelState.PREOPENING < self._state < ChannelState.FORCE_CLOSING and self.peer_state == PeerState.DISCONNECTED |
|
|
return ChannelState.PREOPENING < self._state < ChannelState.CLOSING and self.peer_state == PeerState.DISCONNECTED |
|
|
|
|
|
|
|
|
def get_funding_address(self): |
|
|
def get_funding_address(self): |
|
|
script = funding_output_script(self.config[LOCAL], self.config[REMOTE]) |
|
|
script = funding_output_script(self.config[LOCAL], self.config[REMOTE]) |
|
|