You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
3.2 KiB
123 lines
3.2 KiB
package lnd |
|
|
|
import ( |
|
"sync" |
|
|
|
"github.com/lightningnetwork/lnd/channeldb" |
|
"github.com/lightningnetwork/lnd/contractcourt" |
|
"github.com/lightningnetwork/lnd/lntypes" |
|
) |
|
|
|
// preimageSubscriber reprints an active subscription to be notified once the |
|
// daemon discovers new preimages, either on chain or off-chain. |
|
type preimageSubscriber struct { |
|
updateChan chan lntypes.Preimage |
|
|
|
quit chan struct{} |
|
} |
|
|
|
// preimageBeacon is an implementation of the contractcourt.WitnessBeacon |
|
// interface, and the lnwallet.PreimageCache interface. This implementation is |
|
// concerned with a single witness type: sha256 hahsh preimages. |
|
type preimageBeacon struct { |
|
sync.RWMutex |
|
|
|
wCache *channeldb.WitnessCache |
|
|
|
clientCounter uint64 |
|
subscribers map[uint64]*preimageSubscriber |
|
} |
|
|
|
// SubscribeUpdates returns a channel that will be sent upon *each* time a new |
|
// preimage is discovered. |
|
func (p *preimageBeacon) SubscribeUpdates() *contractcourt.WitnessSubscription { |
|
p.Lock() |
|
defer p.Unlock() |
|
|
|
clientID := p.clientCounter |
|
client := &preimageSubscriber{ |
|
updateChan: make(chan lntypes.Preimage, 10), |
|
quit: make(chan struct{}), |
|
} |
|
|
|
p.subscribers[p.clientCounter] = client |
|
|
|
p.clientCounter++ |
|
|
|
srvrLog.Debugf("Creating new witness beacon subscriber, id=%v", |
|
p.clientCounter) |
|
|
|
return &contractcourt.WitnessSubscription{ |
|
WitnessUpdates: client.updateChan, |
|
CancelSubscription: func() { |
|
p.Lock() |
|
defer p.Unlock() |
|
|
|
delete(p.subscribers, clientID) |
|
|
|
close(client.quit) |
|
}, |
|
} |
|
} |
|
|
|
// LookupPreImage attempts to lookup a preimage in the global cache. True is |
|
// returned for the second argument if the preimage is found. |
|
func (p *preimageBeacon) LookupPreimage( |
|
payHash lntypes.Hash) (lntypes.Preimage, bool) { |
|
|
|
p.RLock() |
|
defer p.RUnlock() |
|
|
|
// Otherwise, we'll perform a final check using the witness cache. |
|
preimage, err := p.wCache.LookupSha256Witness(payHash) |
|
if err != nil { |
|
ltndLog.Errorf("Unable to lookup witness: %v", err) |
|
return lntypes.Preimage{}, false |
|
} |
|
|
|
return preimage, true |
|
} |
|
|
|
// AddPreimages adds a batch of newly discovered preimages to the global cache, |
|
// and also signals any subscribers of the newly discovered witness. |
|
func (p *preimageBeacon) AddPreimages(preimages ...lntypes.Preimage) error { |
|
// Exit early if no preimages are presented. |
|
if len(preimages) == 0 { |
|
return nil |
|
} |
|
|
|
// Copy the preimages to ensure the backing area can't be modified by |
|
// the caller when delivering notifications. |
|
preimageCopies := make([]lntypes.Preimage, 0, len(preimages)) |
|
for _, preimage := range preimages { |
|
srvrLog.Infof("Adding preimage=%v to witness cache", preimage) |
|
preimageCopies = append(preimageCopies, preimage) |
|
} |
|
|
|
// First, we'll add the witness to the decaying witness cache. |
|
err := p.wCache.AddSha256Witnesses(preimages...) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
p.Lock() |
|
defer p.Unlock() |
|
|
|
// With the preimage added to our state, we'll now send a new |
|
// notification to all subscribers. |
|
for _, client := range p.subscribers { |
|
go func(c *preimageSubscriber) { |
|
for _, preimage := range preimageCopies { |
|
select { |
|
case c.updateChan <- preimage: |
|
case <-c.quit: |
|
return |
|
} |
|
} |
|
}(client) |
|
} |
|
|
|
return nil |
|
} |
|
|
|
var _ contractcourt.WitnessBeacon = (*preimageBeacon)(nil)
|
|
|