mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 18:10:34 +01:00
lnwallet: ensure all channel state machine methods are thread-safe
This commit adds some necessary locking to ensure that all updates to the internal state of the commitment state machine are fully serial and thread-safe. This change is required to ensure future actions w.r.t taking action once a revoked commitment transaction has been broadcast are not carried out while the channel’s state is being updated.
This commit is contained in:
parent
e942e70651
commit
2d884618aa
@ -862,6 +862,9 @@ func processRemoveEntry(htlc *PaymentDescriptor, ourBalance,
|
|||||||
// call, the remote party's commitment chain is extended by a new commitment
|
// call, the remote party's commitment chain is extended by a new commitment
|
||||||
// which includes all updates to the HTLC log prior to this method invocation.
|
// which includes all updates to the HTLC log prior to this method invocation.
|
||||||
func (lc *LightningChannel) SignNextCommitment() ([]byte, uint32, error) {
|
func (lc *LightningChannel) SignNextCommitment() ([]byte, uint32, error) {
|
||||||
|
lc.Lock()
|
||||||
|
defer lc.Unlock()
|
||||||
|
|
||||||
// Ensure that we have enough unused revocation hashes given to us by the
|
// Ensure that we have enough unused revocation hashes given to us by the
|
||||||
// remote party. If the set is empty, then we're unable to create a new
|
// remote party. If the set is empty, then we're unable to create a new
|
||||||
// state unless they first revoke a prior commitment transaction.
|
// state unless they first revoke a prior commitment transaction.
|
||||||
@ -931,6 +934,9 @@ func (lc *LightningChannel) SignNextCommitment() ([]byte, uint32, error) {
|
|||||||
func (lc *LightningChannel) ReceiveNewCommitment(rawSig []byte,
|
func (lc *LightningChannel) ReceiveNewCommitment(rawSig []byte,
|
||||||
ourLogIndex uint32) error {
|
ourLogIndex uint32) error {
|
||||||
|
|
||||||
|
lc.Lock()
|
||||||
|
defer lc.Unlock()
|
||||||
|
|
||||||
theirCommitKey := lc.channelState.TheirCommitKey
|
theirCommitKey := lc.channelState.TheirCommitKey
|
||||||
theirMultiSigKey := lc.channelState.TheirMultiSigKey
|
theirMultiSigKey := lc.channelState.TheirMultiSigKey
|
||||||
|
|
||||||
@ -1000,6 +1006,9 @@ func (lc *LightningChannel) ReceiveNewCommitment(rawSig []byte,
|
|||||||
// indicates that either we have pending updates they need to commit, or vice
|
// indicates that either we have pending updates they need to commit, or vice
|
||||||
// versa.
|
// versa.
|
||||||
func (lc *LightningChannel) PendingUpdates() bool {
|
func (lc *LightningChannel) PendingUpdates() bool {
|
||||||
|
lc.RLock()
|
||||||
|
defer lc.RUnlock()
|
||||||
|
|
||||||
fullySynced := (lc.localCommitChain.tip().ourMessageIndex ==
|
fullySynced := (lc.localCommitChain.tip().ourMessageIndex ==
|
||||||
lc.remoteCommitChain.tip().ourMessageIndex)
|
lc.remoteCommitChain.tip().ourMessageIndex)
|
||||||
|
|
||||||
@ -1012,6 +1021,9 @@ func (lc *LightningChannel) PendingUpdates() bool {
|
|||||||
// chain is advanced by a single commitment. This now lowest unrevoked
|
// chain is advanced by a single commitment. This now lowest unrevoked
|
||||||
// commitment becomes our currently accepted state within the channel.
|
// commitment becomes our currently accepted state within the channel.
|
||||||
func (lc *LightningChannel) RevokeCurrentCommitment() (*lnwire.CommitRevocation, error) {
|
func (lc *LightningChannel) RevokeCurrentCommitment() (*lnwire.CommitRevocation, error) {
|
||||||
|
lc.Lock()
|
||||||
|
defer lc.Unlock()
|
||||||
|
|
||||||
theirCommitKey := lc.channelState.TheirCommitKey
|
theirCommitKey := lc.channelState.TheirCommitKey
|
||||||
|
|
||||||
// Now that we've accept a new state transition, we send the remote
|
// Now that we've accept a new state transition, we send the remote
|
||||||
@ -1071,6 +1083,10 @@ func (lc *LightningChannel) RevokeCurrentCommitment() (*lnwire.CommitRevocation,
|
|||||||
// commitment, and a log compaction is attempted. In addition, a slice of
|
// commitment, and a log compaction is attempted. In addition, a slice of
|
||||||
// HTLC's which can be forwarded upstream are returned.
|
// HTLC's which can be forwarded upstream are returned.
|
||||||
func (lc *LightningChannel) ReceiveRevocation(revMsg *lnwire.CommitRevocation) ([]*PaymentDescriptor, error) {
|
func (lc *LightningChannel) ReceiveRevocation(revMsg *lnwire.CommitRevocation) ([]*PaymentDescriptor, error) {
|
||||||
|
|
||||||
|
lc.Lock()
|
||||||
|
defer lc.Unlock()
|
||||||
|
|
||||||
// The revocation has a nil (zero) pre-image, then this should simply be
|
// The revocation has a nil (zero) pre-image, then this should simply be
|
||||||
// added to the end of the revocation window for the remote node.
|
// added to the end of the revocation window for the remote node.
|
||||||
if bytes.Equal(zeroHash[:], revMsg.Revocation[:]) {
|
if bytes.Equal(zeroHash[:], revMsg.Revocation[:]) {
|
||||||
@ -1231,6 +1247,9 @@ func (lc *LightningChannel) compactLogs(ourLog, theirLog *list.List,
|
|||||||
// increasing the number of new commitment updates the remote party can
|
// increasing the number of new commitment updates the remote party can
|
||||||
// initiate without our cooperation.
|
// initiate without our cooperation.
|
||||||
func (lc *LightningChannel) ExtendRevocationWindow() (*lnwire.CommitRevocation, error) {
|
func (lc *LightningChannel) ExtendRevocationWindow() (*lnwire.CommitRevocation, error) {
|
||||||
|
lc.Lock()
|
||||||
|
defer lc.Unlock()
|
||||||
|
|
||||||
/// TODO(roasbeef): error if window edge differs from tail by more than
|
/// TODO(roasbeef): error if window edge differs from tail by more than
|
||||||
// InitialRevocationWindow
|
// InitialRevocationWindow
|
||||||
|
|
||||||
@ -1258,6 +1277,9 @@ func (lc *LightningChannel) ExtendRevocationWindow() (*lnwire.CommitRevocation,
|
|||||||
// TODO(roasbeef): check for duplicates below? edge case during restart w/ HTLC
|
// TODO(roasbeef): check for duplicates below? edge case during restart w/ HTLC
|
||||||
// persistence
|
// persistence
|
||||||
func (lc *LightningChannel) AddHTLC(htlc *lnwire.HTLCAddRequest) uint32 {
|
func (lc *LightningChannel) AddHTLC(htlc *lnwire.HTLCAddRequest) uint32 {
|
||||||
|
lc.Lock()
|
||||||
|
defer lc.Unlock()
|
||||||
|
|
||||||
pd := &PaymentDescriptor{
|
pd := &PaymentDescriptor{
|
||||||
EntryType: Add,
|
EntryType: Add,
|
||||||
RHash: PaymentHash(htlc.RedemptionHashes[0]),
|
RHash: PaymentHash(htlc.RedemptionHashes[0]),
|
||||||
@ -1276,6 +1298,9 @@ func (lc *LightningChannel) AddHTLC(htlc *lnwire.HTLCAddRequest) uint32 {
|
|||||||
// method should be called in response to receiving a new HTLC from the remote
|
// method should be called in response to receiving a new HTLC from the remote
|
||||||
// party.
|
// party.
|
||||||
func (lc *LightningChannel) ReceiveHTLC(htlc *lnwire.HTLCAddRequest) uint32 {
|
func (lc *LightningChannel) ReceiveHTLC(htlc *lnwire.HTLCAddRequest) uint32 {
|
||||||
|
lc.Lock()
|
||||||
|
defer lc.Unlock()
|
||||||
|
|
||||||
pd := &PaymentDescriptor{
|
pd := &PaymentDescriptor{
|
||||||
EntryType: Add,
|
EntryType: Add,
|
||||||
RHash: PaymentHash(htlc.RedemptionHashes[0]),
|
RHash: PaymentHash(htlc.RedemptionHashes[0]),
|
||||||
@ -1295,6 +1320,9 @@ func (lc *LightningChannel) ReceiveHTLC(htlc *lnwire.HTLCAddRequest) uint32 {
|
|||||||
// creating the corresponding wire message. In the case the supplied pre-image
|
// creating the corresponding wire message. In the case the supplied pre-image
|
||||||
// is invalid, an error is returned.
|
// is invalid, an error is returned.
|
||||||
func (lc *LightningChannel) SettleHTLC(preimage [32]byte) (uint32, error) {
|
func (lc *LightningChannel) SettleHTLC(preimage [32]byte) (uint32, error) {
|
||||||
|
lc.Lock()
|
||||||
|
defer lc.Unlock()
|
||||||
|
|
||||||
var targetHTLC *list.Element
|
var targetHTLC *list.Element
|
||||||
|
|
||||||
// TODO(roasbeef): optimize
|
// TODO(roasbeef): optimize
|
||||||
@ -1336,6 +1364,9 @@ func (lc *LightningChannel) SettleHTLC(preimage [32]byte) (uint32, error) {
|
|||||||
// log, and error is returned. Similarly if the preimage is invalid w.r.t to
|
// log, and error is returned. Similarly if the preimage is invalid w.r.t to
|
||||||
// the referenced of then a distinct error is returned.
|
// the referenced of then a distinct error is returned.
|
||||||
func (lc *LightningChannel) ReceiveHTLCSettle(preimage [32]byte, logIndex uint32) error {
|
func (lc *LightningChannel) ReceiveHTLCSettle(preimage [32]byte, logIndex uint32) error {
|
||||||
|
lc.Lock()
|
||||||
|
defer lc.Unlock()
|
||||||
|
|
||||||
paymentHash := fastsha256.Sum256(preimage[:])
|
paymentHash := fastsha256.Sum256(preimage[:])
|
||||||
addEntry, ok := lc.ourLogIndex[logIndex]
|
addEntry, ok := lc.ourLogIndex[logIndex]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
Loading…
Reference in New Issue
Block a user