cnct+lnwl+hswc: use lntypes.Preimage for witness beacon

This commit is contained in:
Conner Fromknecht 2019-02-19 17:06:00 -08:00
parent 2d8bc99d9e
commit 29f07a58cb
No known key found for this signature in database
GPG Key ID: E7D737B67FA592C7
16 changed files with 126 additions and 114 deletions

@ -1548,10 +1548,7 @@ func createInitChannels(revocationWindow int) (*lnwallet.LightningChannel, *lnwa
Packager: channeldb.NewChannelPackager(shortChanID), Packager: channeldb.NewChannelPackager(shortChanID),
} }
pCache := &mockPreimageCache{ pCache := newMockPreimageCache()
// hash -> preimage
preimageMap: make(map[[32]byte][]byte),
}
aliceSigner := &mockSigner{aliceKeyPriv} aliceSigner := &mockSigner{aliceKeyPriv}
bobSigner := &mockSigner{bobKeyPriv} bobSigner := &mockSigner{bobKeyPriv}

@ -11,6 +11,7 @@ import (
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
) )
@ -40,7 +41,7 @@ type WitnessSubscription struct {
// sent over. // sent over.
// //
// TODO(roasbeef): couple with WitnessType? // TODO(roasbeef): couple with WitnessType?
WitnessUpdates <-chan []byte WitnessUpdates <-chan lntypes.Preimage
// CancelSubscription is a function closure that should be used by a // CancelSubscription is a function closure that should be used by a
// client to cancel the subscription once they are no longer interested // client to cancel the subscription once they are no longer interested
@ -62,12 +63,12 @@ type WitnessBeacon interface {
// LookupPreImage attempts to lookup a preimage in the global cache. // LookupPreImage attempts to lookup a preimage in the global cache.
// True is returned for the second argument if the preimage is found. // True is returned for the second argument if the preimage is found.
LookupPreimage(payhash []byte) ([]byte, bool) LookupPreimage(payhash lntypes.Hash) (lntypes.Preimage, bool)
// AddPreimages adds a batch of newly discovered preimages to the global // AddPreimages adds a batch of newly discovered preimages to the global
// cache, and also signals any subscribers of the newly discovered // cache, and also signals any subscribers of the newly discovered
// witness. // witness.
AddPreimages(preimages ...[]byte) error AddPreimages(preimages ...lntypes.Preimage) error
} }
// ChannelArbitratorConfig contains all the functionality that the // ChannelArbitratorConfig contains all the functionality that the
@ -1129,7 +1130,7 @@ func (c *ChannelArbitrator) checkChainActions(height uint32,
// know the pre-image and it's close to timing out. We need to // know the pre-image and it's close to timing out. We need to
// ensure that we claim the funds that our rightfully ours // ensure that we claim the funds that our rightfully ours
// on-chain. // on-chain.
if _, ok := c.cfg.PreimageDB.LookupPreimage(htlc.RHash[:]); !ok { if _, ok := c.cfg.PreimageDB.LookupPreimage(htlc.RHash); !ok {
continue continue
} }
haveChainActions = haveChainActions || c.shouldGoOnChain( haveChainActions = haveChainActions || c.shouldGoOnChain(
@ -1206,13 +1207,12 @@ func (c *ChannelArbitrator) checkChainActions(height uint32,
// either learn of it eventually from the outgoing HTLC, or the sender // either learn of it eventually from the outgoing HTLC, or the sender
// will timeout the HTLC. // will timeout the HTLC.
for _, htlc := range c.activeHTLCs.incomingHTLCs { for _, htlc := range c.activeHTLCs.incomingHTLCs {
payHash := htlc.RHash
// If we have the pre-image, then we should go on-chain to // If we have the pre-image, then we should go on-chain to
// redeem the HTLC immediately. // redeem the HTLC immediately.
if _, ok := c.cfg.PreimageDB.LookupPreimage(payHash[:]); ok { if _, ok := c.cfg.PreimageDB.LookupPreimage(htlc.RHash); ok {
log.Tracef("ChannelArbitrator(%v): preimage for "+ log.Tracef("ChannelArbitrator(%v): preimage for "+
"htlc=%x is known!", c.cfg.ChanPoint, payHash[:]) "htlc=%x is known!", c.cfg.ChanPoint,
htlc.RHash[:])
actionMap[HtlcClaimAction] = append( actionMap[HtlcClaimAction] = append(
actionMap[HtlcClaimAction], htlc, actionMap[HtlcClaimAction], htlc,
@ -1222,7 +1222,7 @@ func (c *ChannelArbitrator) checkChainActions(height uint32,
log.Tracef("ChannelArbitrator(%v): watching chain to decide "+ log.Tracef("ChannelArbitrator(%v): watching chain to decide "+
"action for incoming htlc=%x", c.cfg.ChanPoint, "action for incoming htlc=%x", c.cfg.ChanPoint,
payHash[:]) htlc.RHash[:])
// Otherwise, we don't yet have the pre-image, but should watch // Otherwise, we don't yet have the pre-image, but should watch
// on-chain to see if either: the remote party times out the // on-chain to see if either: the remote party times out the

@ -2,12 +2,12 @@ package contractcourt
import ( import (
"bytes" "bytes"
"crypto/sha256"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/lntypes"
) )
// htlcIncomingContestResolver is a ContractResolver that's able to resolve an // htlcIncomingContestResolver is a ContractResolver that's able to resolve an
@ -74,11 +74,11 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
// resolver with the preimage we learn of. This should be called once // resolver with the preimage we learn of. This should be called once
// the preimage is revealed so the inner resolver can properly complete // the preimage is revealed so the inner resolver can properly complete
// its duties. // its duties.
applyPreimage := func(preimage []byte) { applyPreimage := func(preimage lntypes.Preimage) {
copy(h.htlcResolution.Preimage[:], preimage) h.htlcResolution.Preimage = preimage
log.Infof("%T(%v): extracted preimage=%x from beacon!", h, log.Infof("%T(%v): extracted preimage=%v from beacon!", h,
h.htlcResolution.ClaimOutpoint, preimage[:]) h.htlcResolution.ClaimOutpoint, preimage)
// If this our commitment transaction, then we'll need to // If this our commitment transaction, then we'll need to
// populate the witness for the second-level HTLC transaction. // populate the witness for the second-level HTLC transaction.
@ -93,8 +93,6 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
// preimage. // preimage.
h.htlcResolution.SignedSuccessTx.TxIn[0].Witness[3] = preimage[:] h.htlcResolution.SignedSuccessTx.TxIn[0].Witness[3] = preimage[:]
} }
copy(h.htlcResolution.Preimage[:], preimage[:])
} }
// If the HTLC hasn't expired yet, then we may still be able to claim // If the HTLC hasn't expired yet, then we may still be able to claim
@ -116,12 +114,12 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
// With the epochs and preimage subscriptions initialized, we'll query // With the epochs and preimage subscriptions initialized, we'll query
// to see if we already know the preimage. // to see if we already know the preimage.
preimage, ok := h.PreimageDB.LookupPreimage(h.payHash[:]) preimage, ok := h.PreimageDB.LookupPreimage(h.payHash)
if ok { if ok {
// If we do, then this means we can claim the HTLC! However, // If we do, then this means we can claim the HTLC! However,
// we don't know how to ourselves, so we'll return our inner // we don't know how to ourselves, so we'll return our inner
// resolver which has the knowledge to do so. // resolver which has the knowledge to do so.
applyPreimage(preimage[:]) applyPreimage(preimage)
return &h.htlcSuccessResolver, nil return &h.htlcSuccessResolver, nil
} }
@ -131,8 +129,8 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
case preimage := <-preimageSubscription.WitnessUpdates: case preimage := <-preimageSubscription.WitnessUpdates:
// If this isn't our preimage, then we'll continue // If this isn't our preimage, then we'll continue
// onwards. // onwards.
newHash := sha256.Sum256(preimage) hash := preimage.Hash()
preimageMatches := bytes.Equal(newHash[:], h.payHash[:]) preimageMatches := bytes.Equal(hash[:], h.payHash[:])
if !preimageMatches { if !preimageMatches {
continue continue
} }

@ -2,13 +2,15 @@ package contractcourt
import ( import (
"fmt" "fmt"
"github.com/lightningnetwork/lnd/input"
"io" "io"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lntypes"
) )
// htlcOutgoingContestResolver is a ContractResolver that's able to resolve an // htlcOutgoingContestResolver is a ContractResolver that's able to resolve an
@ -58,38 +60,47 @@ func (h *htlcOutgoingContestResolver) Resolve() (ContractResolver, error) {
// If this is the remote party's commitment, then we'll be // If this is the remote party's commitment, then we'll be
// looking for them to spend using the second-level success // looking for them to spend using the second-level success
// transaction. // transaction.
var preimage [32]byte var preimageBytes []byte
if h.htlcResolution.SignedTimeoutTx == nil { if h.htlcResolution.SignedTimeoutTx == nil {
// The witness stack when the remote party sweeps the // The witness stack when the remote party sweeps the
// output to them looks like: // output to them looks like:
// //
// * <sender sig> <recvr sig> <preimage> <witness script> // * <sender sig> <recvr sig> <preimage> <witness script>
copy(preimage[:], spendingInput.Witness[3]) preimageBytes = spendingInput.Witness[3]
} else { } else {
// Otherwise, they'll be spending directly from our // Otherwise, they'll be spending directly from our
// commitment output. In which case the witness stack // commitment output. In which case the witness stack
// looks like: // looks like:
// //
// * <sig> <preimage> <witness script> // * <sig> <preimage> <witness script>
copy(preimage[:], spendingInput.Witness[1]) preimageBytes = spendingInput.Witness[1]
} }
log.Infof("%T(%v): extracting preimage=%x from on-chain "+ preimage, err := lntypes.MakePreimage(preimageBytes)
"spend!", h, h.htlcResolution.ClaimOutpoint, preimage[:]) if err != nil {
return nil, err
}
log.Infof("%T(%v): extracting preimage=%v from on-chain "+
"spend!", h, h.htlcResolution.ClaimOutpoint,
preimage)
// With the preimage obtained, we can now add it to the global // With the preimage obtained, we can now add it to the global
// cache. // cache.
if err := h.PreimageDB.AddPreimages(preimage[:]); err != nil { if err := h.PreimageDB.AddPreimages(preimage); err != nil {
log.Errorf("%T(%v): unable to add witness to cache", log.Errorf("%T(%v): unable to add witness to cache",
h, h.htlcResolution.ClaimOutpoint) h, h.htlcResolution.ClaimOutpoint)
} }
var pre [32]byte
copy(pre[:], preimage[:])
// Finally, we'll send the clean up message, mark ourselves as // Finally, we'll send the clean up message, mark ourselves as
// resolved, then exit. // resolved, then exit.
if err := h.DeliverResolutionMsg(ResolutionMsg{ if err := h.DeliverResolutionMsg(ResolutionMsg{
SourceChan: h.ShortChanID, SourceChan: h.ShortChanID,
HtlcIndex: h.htlcIndex, HtlcIndex: h.htlcIndex,
PreImage: &preimage, PreImage: &pre,
}); err != nil { }); err != nil {
return nil, err return nil, err
} }

@ -3,15 +3,16 @@ package contractcourt
import ( import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"github.com/lightningnetwork/lnd/input"
"io" "io"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/sweep" "github.com/lightningnetwork/lnd/sweep"
) )
@ -41,7 +42,7 @@ type htlcSuccessResolver struct {
broadcastHeight uint32 broadcastHeight uint32
// payHash is the payment hash of the original HTLC extended to us. // payHash is the payment hash of the original HTLC extended to us.
payHash [32]byte payHash lntypes.Hash
// sweepTx will be non-nil if we've already crafted a transaction to // sweepTx will be non-nil if we've already crafted a transaction to
// sweep a direct HTLC output. This is only a concern if we're sweeping // sweep a direct HTLC output. This is only a concern if we're sweeping

@ -1417,7 +1417,7 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
// any contested contracts watched by any on-chain arbitrators // any contested contracts watched by any on-chain arbitrators
// can now sweep this HTLC on-chain. // can now sweep this HTLC on-chain.
go func() { go func() {
err := l.cfg.PreimageCache.AddPreimages(pre[:]) err := l.cfg.PreimageCache.AddPreimages(pre)
if err != nil { if err != nil {
l.errorf("unable to add preimage=%x to "+ l.errorf("unable to add preimage=%x to "+
"cache", pre[:]) "cache", pre[:])

@ -1532,10 +1532,7 @@ func newSingleLinkTestHarness(chanAmt, chanReserve btcutil.Amount) (
invoiceRegistry = newMockRegistry(globalPolicy.TimeLockDelta) invoiceRegistry = newMockRegistry(globalPolicy.TimeLockDelta)
) )
pCache := &mockPreimageCache{ pCache := newMockPreimageCache()
// hash -> preimage
preimageMap: make(map[[32]byte][]byte),
}
aliceDb := aliceChannel.State().Db aliceDb := aliceChannel.State().Db
aliceSwitch, err := initSwitchWithDB(testStartingHeight, aliceDb) aliceSwitch, err := initSwitchWithDB(testStartingHeight, aliceDb)
@ -4042,10 +4039,7 @@ func restartLink(aliceChannel *lnwallet.LightningChannel, aliceSwitch *Switch,
invoiceRegistry = newMockRegistry(globalPolicy.TimeLockDelta) invoiceRegistry = newMockRegistry(globalPolicy.TimeLockDelta)
pCache = &mockPreimageCache{ pCache = newMockPreimageCache()
// hash -> preimage
preimageMap: make(map[[32]byte][]byte),
}
) )
aliceDb := aliceChannel.State().Db aliceDb := aliceChannel.State().Db

@ -32,26 +32,31 @@ import (
type mockPreimageCache struct { type mockPreimageCache struct {
sync.Mutex sync.Mutex
preimageMap map[[32]byte][]byte preimageMap map[lntypes.Hash]lntypes.Preimage
} }
func (m *mockPreimageCache) LookupPreimage(hash []byte) ([]byte, bool) { func newMockPreimageCache() *mockPreimageCache {
return &mockPreimageCache{
preimageMap: make(map[lntypes.Hash]lntypes.Preimage),
}
}
func (m *mockPreimageCache) LookupPreimage(
hash lntypes.Hash) (lntypes.Preimage, bool) {
m.Lock() m.Lock()
defer m.Unlock() defer m.Unlock()
var h [32]byte p, ok := m.preimageMap[hash]
copy(h[:], hash)
p, ok := m.preimageMap[h]
return p, ok return p, ok
} }
func (m *mockPreimageCache) AddPreimages(preimages ...[]byte) error { func (m *mockPreimageCache) AddPreimages(preimages ...lntypes.Preimage) error {
m.Lock() m.Lock()
defer m.Unlock() defer m.Unlock()
for _, preimage := range preimages { for _, preimage := range preimages {
m.preimageMap[sha256.Sum256(preimage)] = preimage m.preimageMap[preimage.Hash()] = preimage
} }
return nil return nil

@ -367,10 +367,7 @@ func createTestChannel(alicePrivKey, bobPrivKey []byte,
aliceSigner := &mockSigner{aliceKeyPriv} aliceSigner := &mockSigner{aliceKeyPriv}
bobSigner := &mockSigner{bobKeyPriv} bobSigner := &mockSigner{bobKeyPriv}
pCache := &mockPreimageCache{ pCache := newMockPreimageCache()
// hash -> preimage
preimageMap: make(map[[32]byte][]byte),
}
alicePool := lnwallet.NewSigPool(runtime.NumCPU(), aliceSigner) alicePool := lnwallet.NewSigPool(runtime.NumCPU(), aliceSigner)
channelAlice, err := lnwallet.NewLightningChannel( channelAlice, err := lnwallet.NewLightningChannel(
@ -982,10 +979,7 @@ type hopNetwork struct {
func newHopNetwork() *hopNetwork { func newHopNetwork() *hopNetwork {
defaultDelta := uint32(6) defaultDelta := uint32(6)
pCache := &mockPreimageCache{ pCache := newMockPreimageCache()
// hash -> preimage
preimageMap: make(map[[32]byte][]byte),
}
globalPolicy := ForwardingPolicy{ globalPolicy := ForwardingPolicy{
MinHTLC: lnwire.NewMSatFromSatoshis(5), MinHTLC: lnwire.NewMSatFromSatoshis(5),

@ -5577,12 +5577,12 @@ func extractHtlcResolutions(feePerKw SatPerKWeight, ourCommit bool,
// We'll now query the preimage cache for the preimage // We'll now query the preimage cache for the preimage
// for this HTLC. If it's present then we can fully // for this HTLC. If it's present then we can fully
// populate this resolution. // populate this resolution.
preimage, _ := pCache.LookupPreimage(htlc.RHash[:]) preimage, _ := pCache.LookupPreimage(htlc.RHash)
// Otherwise, we'll create an incoming HTLC resolution // Otherwise, we'll create an incoming HTLC resolution
// as we can satisfy the contract. // as we can satisfy the contract.
var pre [32]byte var pre [32]byte
copy(pre[:], preimage) copy(pre[:], preimage[:])
ihr, err := newIncomingHtlcResolution( ihr, err := newIncomingHtlcResolution(
signer, localChanCfg, commitHash, &htlc, keyRing, signer, localChanCfg, commitHash, &htlc, keyRing,
feePerKw, dustLimit, uint32(csvDelay), ourCommit, feePerKw, dustLimit, uint32(csvDelay), ourCommit,

@ -19,6 +19,7 @@ import (
"github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
) )
@ -584,7 +585,7 @@ func TestForceClose(t *testing.T) {
// Before we force close Alice's channel, we'll add the pre-image of // Before we force close Alice's channel, we'll add the pre-image of
// Bob's HTLC to her preimage cache. // Bob's HTLC to her preimage cache.
aliceChannel.pCache.AddPreimages(preimageBob[:]) aliceChannel.pCache.AddPreimages(lntypes.Preimage(preimageBob))
// With the cache populated, we'll now attempt the force close // With the cache populated, we'll now attempt the force close
// initiated by Alice. // initiated by Alice.
@ -4953,7 +4954,7 @@ func TestChannelUnilateralCloseHtlcResolution(t *testing.T) {
// Now that Bob has force closed, we'll modify Alice's pre image cache // Now that Bob has force closed, we'll modify Alice's pre image cache
// such that she now gains the ability to also settle the incoming HTLC // such that she now gains the ability to also settle the incoming HTLC
// from Bob. // from Bob.
aliceChannel.pCache.AddPreimages(preimageBob[:]) aliceChannel.pCache.AddPreimages(lntypes.Preimage(preimageBob))
// We'll then use Bob's transaction to trigger a spend notification for // We'll then use Bob's transaction to trigger a spend notification for
// Alice. // Alice.

@ -9,6 +9,7 @@ import (
"github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/lntypes"
) )
// AddressType is an enum-like type which denotes the possible address types // AddressType is an enum-like type which denotes the possible address types
@ -272,15 +273,12 @@ type PreimageCache interface {
// LookupPreimage attempts to look up a preimage according to its hash. // LookupPreimage attempts to look up a preimage according to its hash.
// If found, the preimage is returned along with true for the second // If found, the preimage is returned along with true for the second
// argument. Otherwise, it'll return false. // argument. Otherwise, it'll return false.
LookupPreimage(hash []byte) ([]byte, bool) LookupPreimage(hash lntypes.Hash) (lntypes.Preimage, bool)
// AddPreimages adds a batch of newly discovered preimages to the global // AddPreimages adds a batch of newly discovered preimages to the global
// cache, and also signals any subscribers of the newly discovered // cache, and also signals any subscribers of the newly discovered
// witness. // witness.
// AddPreimages(preimages ...lntypes.Preimage) error
// NOTE: The backing slice of MUST NOT be modified, otherwise the
// subscribers may be notified of the incorrect preimages.
AddPreimages(preimages ...[]byte) error
} }
// WalletDriver represents a "driver" for a particular concrete // WalletDriver represents a "driver" for a particular concrete

@ -3,7 +3,6 @@ package lnwallet
import ( import (
"bytes" "bytes"
"crypto/rand" "crypto/rand"
"crypto/sha256"
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"io" "io"
@ -18,6 +17,7 @@ import (
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/shachain" "github.com/lightningnetwork/lnd/shachain"
) )
@ -301,10 +301,7 @@ func CreateTestChannels() (*LightningChannel, *LightningChannel, func(), error)
aliceSigner := &input.MockSigner{Privkeys: aliceKeys} aliceSigner := &input.MockSigner{Privkeys: aliceKeys}
bobSigner := &input.MockSigner{Privkeys: bobKeys} bobSigner := &input.MockSigner{Privkeys: bobKeys}
pCache := &mockPreimageCache{ pCache := newMockPreimageCache()
// hash -> preimage
preimageMap: make(map[[32]byte][]byte),
}
// TODO(roasbeef): make mock version of pre-image store // TODO(roasbeef): make mock version of pre-image store
@ -389,26 +386,36 @@ func initRevocationWindows(chanA, chanB *LightningChannel) error {
type mockPreimageCache struct { type mockPreimageCache struct {
sync.Mutex sync.Mutex
preimageMap map[[32]byte][]byte preimageMap map[lntypes.Hash]lntypes.Preimage
} }
func (m *mockPreimageCache) LookupPreimage(hash []byte) ([]byte, bool) { func newMockPreimageCache() *mockPreimageCache {
return &mockPreimageCache{
preimageMap: make(map[lntypes.Hash]lntypes.Preimage),
}
}
func (m *mockPreimageCache) LookupPreimage(
hash lntypes.Hash) (lntypes.Preimage, bool) {
m.Lock() m.Lock()
defer m.Unlock() defer m.Unlock()
var h [32]byte p, ok := m.preimageMap[hash]
copy(h[:], hash)
p, ok := m.preimageMap[h]
return p, ok return p, ok
} }
func (m *mockPreimageCache) AddPreimages(preimages ...[]byte) error { func (m *mockPreimageCache) AddPreimages(preimages ...lntypes.Preimage) error {
preimageCopies := make([]lntypes.Preimage, 0, len(preimages))
for _, preimage := range preimages {
preimageCopies = append(preimageCopies, preimage)
}
m.Lock() m.Lock()
defer m.Unlock() defer m.Unlock()
for _, preimage := range preimages { for _, preimage := range preimageCopies {
m.preimageMap[sha256.Sum256(preimage)] = preimage m.preimageMap[preimage.Hash()] = preimage
} }
return nil return nil

@ -780,10 +780,7 @@ func TestCommitmentAndHTLCTransactions(t *testing.T) {
}, },
} }
pCache := &mockPreimageCache{ pCache := newMockPreimageCache()
// hash -> preimage
preimageMap: make(map[[32]byte][]byte),
}
for i, test := range testCases { for i, test := range testCases {
expectedCommitmentTx, err := txFromHex(test.expectedCommitmentTxHex) expectedCommitmentTx, err := txFromHex(test.expectedCommitmentTxHex)

21
mock.go

@ -1,7 +1,6 @@
package main package main
import ( import (
"crypto/sha256"
"fmt" "fmt"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -16,6 +15,7 @@ import (
"github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet"
) )
@ -303,26 +303,29 @@ func (m *mockSecretKeyRing) ScalarMult(keyDesc keychain.KeyDescriptor,
type mockPreimageCache struct { type mockPreimageCache struct {
sync.Mutex sync.Mutex
preimageMap map[[32]byte][]byte preimageMap map[lntypes.Hash]lntypes.Preimage
} }
func (m *mockPreimageCache) LookupPreimage(hash []byte) ([]byte, bool) { func newMockPreimageCache() *mockPreimageCache {
return &mockPreimageCache{
preimageMap: make(map[lntypes.Hash]lntypes.Preimage),
}
}
func (m *mockPreimageCache) LookupPreimage(hash lntypes.Hash) (lntypes.Preimage, bool) {
m.Lock() m.Lock()
defer m.Unlock() defer m.Unlock()
var h [32]byte p, ok := m.preimageMap[hash]
copy(h[:], hash)
p, ok := m.preimageMap[h]
return p, ok return p, ok
} }
func (m *mockPreimageCache) AddPreimages(preimages ...[]byte) error { func (m *mockPreimageCache) AddPreimages(preimages ...lntypes.Preimage) error {
m.Lock() m.Lock()
defer m.Unlock() defer m.Unlock()
for _, preimage := range preimages { for _, preimage := range preimages {
m.preimageMap[sha256.Sum256(preimage)] = preimage m.preimageMap[preimage.Hash()] = preimage
} }
return nil return nil

@ -13,7 +13,7 @@ import (
// preimageSubscriber reprints an active subscription to be notified once the // preimageSubscriber reprints an active subscription to be notified once the
// daemon discovers new preimages, either on chain or off-chain. // daemon discovers new preimages, either on chain or off-chain.
type preimageSubscriber struct { type preimageSubscriber struct {
updateChan chan []byte updateChan chan lntypes.Preimage
quit chan struct{} quit chan struct{}
} }
@ -40,7 +40,7 @@ func (p *preimageBeacon) SubscribeUpdates() *contractcourt.WitnessSubscription {
clientID := p.clientCounter clientID := p.clientCounter
client := &preimageSubscriber{ client := &preimageSubscriber{
updateChan: make(chan []byte, 10), updateChan: make(chan lntypes.Preimage, 10),
quit: make(chan struct{}), quit: make(chan struct{}),
} }
@ -66,36 +66,42 @@ func (p *preimageBeacon) SubscribeUpdates() *contractcourt.WitnessSubscription {
// LookupPreImage attempts to lookup a preimage in the global cache. True is // LookupPreImage attempts to lookup a preimage in the global cache. True is
// returned for the second argument if the preimage is found. // returned for the second argument if the preimage is found.
func (p *preimageBeacon) LookupPreimage(payHash []byte) ([]byte, bool) { func (p *preimageBeacon) LookupPreimage(
payHash lntypes.Hash) (lntypes.Preimage, bool) {
p.RLock() p.RLock()
defer p.RUnlock() defer p.RUnlock()
// First, we'll check the invoice registry to see if we already know of // First, we'll check the invoice registry to see if we already know of
// the preimage as it's on that we created ourselves. // the preimage as it's on that we created ourselves.
var invoiceKey lntypes.Hash invoice, _, err := p.invoices.LookupInvoice(payHash)
copy(invoiceKey[:], payHash)
invoice, _, err := p.invoices.LookupInvoice(invoiceKey)
switch { switch {
case err == channeldb.ErrInvoiceNotFound: case err == channeldb.ErrInvoiceNotFound:
// If we get this error, then it simply means that this invoice // If we get this error, then it simply means that this invoice
// wasn't found, so we don't treat it as a critical error. // wasn't found, so we don't treat it as a critical error.
case err != nil: case err != nil:
return nil, false return lntypes.Preimage{}, false
} }
// If we've found the invoice, then we can return the preimage // If we've found the invoice, then we can return the preimage
// directly. // directly.
if err != channeldb.ErrInvoiceNotFound { if err != channeldb.ErrInvoiceNotFound {
return invoice.Terms.PaymentPreimage[:], true return invoice.Terms.PaymentPreimage, true
} }
// Otherwise, we'll perform a final check using the witness cache. // Otherwise, we'll perform a final check using the witness cache.
preimage, err := p.wCache.LookupWitness( preimageBytes, err := p.wCache.LookupWitness(
channeldb.Sha256HashWitness, payHash, channeldb.Sha256HashWitness, payHash[:],
) )
if err != nil { if err != nil {
ltndLog.Errorf("unable to lookup witness: %v", err) ltndLog.Errorf("Unable to lookup witness: %v", err)
return nil, false return lntypes.Preimage{}, false
}
preimage, err := lntypes.MakePreimage(preimageBytes)
if err != nil {
ltndLog.Errorf("Unable to build witness: %v", err)
return lntypes.Preimage{}, false
} }
return preimage, true return preimage, true
@ -103,7 +109,7 @@ func (p *preimageBeacon) LookupPreimage(payHash []byte) ([]byte, bool) {
// AddPreimages adds a batch of newly discovered preimages to the global cache, // AddPreimages adds a batch of newly discovered preimages to the global cache,
// and also signals any subscribers of the newly discovered witness. // and also signals any subscribers of the newly discovered witness.
func (p *preimageBeacon) AddPreimages(preimages ...[]byte) error { func (p *preimageBeacon) AddPreimages(preimages ...lntypes.Preimage) error {
// Exit early if no preimages are presented. // Exit early if no preimages are presented.
if len(preimages) == 0 { if len(preimages) == 0 {
return nil return nil
@ -111,14 +117,14 @@ func (p *preimageBeacon) AddPreimages(preimages ...[]byte) error {
// Copy the preimages to ensure the backing area can't be modified by // Copy the preimages to ensure the backing area can't be modified by
// the caller when delivering notifications. // the caller when delivering notifications.
preimageCopies := make([][]byte, 0, len(preimages)) preimageCopies := make([]lntypes.Preimage, 0, len(preimages))
for _, preimage := range preimages { for _, preimage := range preimages {
srvrLog.Infof("Adding preimage=%x to witness cache", preimage) srvrLog.Infof("Adding preimage=%v to witness cache", preimage)
preimageCopies = append(preimageCopies, preimage) preimageCopies = append(preimageCopies, preimage)
} }
// First, we'll add the witness to the decaying witness cache. // First, we'll add the witness to the decaying witness cache.
err := p.wCache.AddWitnesses(channeldb.Sha256HashWitness, preimages...) err := p.wCache.AddSha256Witnesses(preimages...)
if err != nil { if err != nil {
return err return err
} }