lnwallet: extract fetchparent for individual testing
This commit is contained in:
parent
2c979fc179
commit
54a06cb96a
@ -2494,10 +2494,106 @@ func (lc *LightningChannel) evaluateHTLCView(view *htlcView, ourBalance,
|
|||||||
skipUs := make(map[uint64]struct{})
|
skipUs := make(map[uint64]struct{})
|
||||||
skipThem := make(map[uint64]struct{})
|
skipThem := make(map[uint64]struct{})
|
||||||
|
|
||||||
// fetchParentEntry is a helper method that will fetch the parent of
|
// First we run through non-add entries in both logs, populating the
|
||||||
// entry from the corresponding update log.
|
// skip sets and mutating the current chain state (crediting balances,
|
||||||
fetchParentEntry := func(entry *PaymentDescriptor,
|
// etc) to reflect the settle/timeout entry encountered.
|
||||||
remoteLog bool) (*PaymentDescriptor, error) {
|
for _, entry := range view.ourUpdates {
|
||||||
|
switch entry.EntryType {
|
||||||
|
// Skip adds for now. They will be processed below.
|
||||||
|
case Add:
|
||||||
|
continue
|
||||||
|
|
||||||
|
// Process fee updates, updating the current feePerKw.
|
||||||
|
case FeeUpdate:
|
||||||
|
processFeeUpdate(
|
||||||
|
entry, nextHeight, remoteChain, mutateState,
|
||||||
|
newView,
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're settling an inbound HTLC, and it hasn't been
|
||||||
|
// processed yet, then increment our state tracking the total
|
||||||
|
// number of satoshis we've received within the channel.
|
||||||
|
if mutateState && entry.EntryType == Settle && !remoteChain &&
|
||||||
|
entry.removeCommitHeightLocal == 0 {
|
||||||
|
lc.channelState.TotalMSatReceived += entry.Amount
|
||||||
|
}
|
||||||
|
|
||||||
|
addEntry, err := lc.fetchParent(entry, remoteChain, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
skipThem[addEntry.HtlcIndex] = struct{}{}
|
||||||
|
processRemoveEntry(entry, ourBalance, theirBalance,
|
||||||
|
nextHeight, remoteChain, true, mutateState)
|
||||||
|
}
|
||||||
|
for _, entry := range view.theirUpdates {
|
||||||
|
switch entry.EntryType {
|
||||||
|
// Skip adds for now. They will be processed below.
|
||||||
|
case Add:
|
||||||
|
continue
|
||||||
|
|
||||||
|
// Process fee updates, updating the current feePerKw.
|
||||||
|
case FeeUpdate:
|
||||||
|
processFeeUpdate(
|
||||||
|
entry, nextHeight, remoteChain, mutateState,
|
||||||
|
newView,
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the remote party is settling one of our outbound HTLC's,
|
||||||
|
// and it hasn't been processed, yet, the increment our state
|
||||||
|
// tracking the total number of satoshis we've sent within the
|
||||||
|
// channel.
|
||||||
|
if mutateState && entry.EntryType == Settle && !remoteChain &&
|
||||||
|
entry.removeCommitHeightLocal == 0 {
|
||||||
|
lc.channelState.TotalMSatSent += entry.Amount
|
||||||
|
}
|
||||||
|
|
||||||
|
addEntry, err := lc.fetchParent(entry, remoteChain, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
skipUs[addEntry.HtlcIndex] = struct{}{}
|
||||||
|
processRemoveEntry(entry, ourBalance, theirBalance,
|
||||||
|
nextHeight, remoteChain, false, mutateState)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next we take a second pass through all the log entries, skipping any
|
||||||
|
// settled HTLCs, and debiting the chain state balance due to any newly
|
||||||
|
// added HTLCs.
|
||||||
|
for _, entry := range view.ourUpdates {
|
||||||
|
isAdd := entry.EntryType == Add
|
||||||
|
if _, ok := skipUs[entry.HtlcIndex]; !isAdd || ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
processAddEntry(entry, ourBalance, theirBalance, nextHeight,
|
||||||
|
remoteChain, false, mutateState)
|
||||||
|
newView.ourUpdates = append(newView.ourUpdates, entry)
|
||||||
|
}
|
||||||
|
for _, entry := range view.theirUpdates {
|
||||||
|
isAdd := entry.EntryType == Add
|
||||||
|
if _, ok := skipThem[entry.HtlcIndex]; !isAdd || ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
processAddEntry(entry, ourBalance, theirBalance, nextHeight,
|
||||||
|
remoteChain, true, mutateState)
|
||||||
|
newView.theirUpdates = append(newView.theirUpdates, entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
return newView, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getFetchParent is a helper that looks up update log parent entries in the
|
||||||
|
// appropriate log.
|
||||||
|
func (lc *LightningChannel) fetchParent(entry *PaymentDescriptor,
|
||||||
|
remoteChain, remoteLog bool) (*PaymentDescriptor, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
updateLog *updateLog
|
updateLog *updateLog
|
||||||
@ -2545,102 +2641,6 @@ func (lc *LightningChannel) evaluateHTLCView(view *htlcView, ourBalance,
|
|||||||
return addEntry, nil
|
return addEntry, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// First we run through non-add entries in both logs, populating the
|
|
||||||
// skip sets and mutating the current chain state (crediting balances,
|
|
||||||
// etc) to reflect the settle/timeout entry encountered.
|
|
||||||
for _, entry := range view.ourUpdates {
|
|
||||||
switch entry.EntryType {
|
|
||||||
// Skip adds for now. They will be processed below.
|
|
||||||
case Add:
|
|
||||||
continue
|
|
||||||
|
|
||||||
// Process fee updates, updating the current feePerKw.
|
|
||||||
case FeeUpdate:
|
|
||||||
processFeeUpdate(
|
|
||||||
entry, nextHeight, remoteChain, mutateState,
|
|
||||||
newView,
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're settling an inbound HTLC, and it hasn't been
|
|
||||||
// processed yet, then increment our state tracking the total
|
|
||||||
// number of satoshis we've received within the channel.
|
|
||||||
if mutateState && entry.EntryType == Settle && !remoteChain &&
|
|
||||||
entry.removeCommitHeightLocal == 0 {
|
|
||||||
lc.channelState.TotalMSatReceived += entry.Amount
|
|
||||||
}
|
|
||||||
|
|
||||||
addEntry, err := fetchParentEntry(entry, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
skipThem[addEntry.HtlcIndex] = struct{}{}
|
|
||||||
processRemoveEntry(entry, ourBalance, theirBalance,
|
|
||||||
nextHeight, remoteChain, true, mutateState)
|
|
||||||
}
|
|
||||||
for _, entry := range view.theirUpdates {
|
|
||||||
switch entry.EntryType {
|
|
||||||
// Skip adds for now. They will be processed below.
|
|
||||||
case Add:
|
|
||||||
continue
|
|
||||||
|
|
||||||
// Process fee updates, updating the current feePerKw.
|
|
||||||
case FeeUpdate:
|
|
||||||
processFeeUpdate(
|
|
||||||
entry, nextHeight, remoteChain, mutateState,
|
|
||||||
newView,
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the remote party is settling one of our outbound HTLC's,
|
|
||||||
// and it hasn't been processed, yet, the increment our state
|
|
||||||
// tracking the total number of satoshis we've sent within the
|
|
||||||
// channel.
|
|
||||||
if mutateState && entry.EntryType == Settle && !remoteChain &&
|
|
||||||
entry.removeCommitHeightLocal == 0 {
|
|
||||||
lc.channelState.TotalMSatSent += entry.Amount
|
|
||||||
}
|
|
||||||
|
|
||||||
addEntry, err := fetchParentEntry(entry, false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
skipUs[addEntry.HtlcIndex] = struct{}{}
|
|
||||||
processRemoveEntry(entry, ourBalance, theirBalance,
|
|
||||||
nextHeight, remoteChain, false, mutateState)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next we take a second pass through all the log entries, skipping any
|
|
||||||
// settled HTLCs, and debiting the chain state balance due to any newly
|
|
||||||
// added HTLCs.
|
|
||||||
for _, entry := range view.ourUpdates {
|
|
||||||
isAdd := entry.EntryType == Add
|
|
||||||
if _, ok := skipUs[entry.HtlcIndex]; !isAdd || ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
processAddEntry(entry, ourBalance, theirBalance, nextHeight,
|
|
||||||
remoteChain, false, mutateState)
|
|
||||||
newView.ourUpdates = append(newView.ourUpdates, entry)
|
|
||||||
}
|
|
||||||
for _, entry := range view.theirUpdates {
|
|
||||||
isAdd := entry.EntryType == Add
|
|
||||||
if _, ok := skipThem[entry.HtlcIndex]; !isAdd || ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
processAddEntry(entry, ourBalance, theirBalance, nextHeight,
|
|
||||||
remoteChain, true, mutateState)
|
|
||||||
newView.theirUpdates = append(newView.theirUpdates, entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
return newView, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// processAddEntry evaluates the effect of an add entry within the HTLC log.
|
// processAddEntry evaluates the effect of an add entry within the HTLC log.
|
||||||
// If the HTLC hasn't yet been committed in either chain, then the height it
|
// If the HTLC hasn't yet been committed in either chain, then the height it
|
||||||
// was committed is updated. Keeping track of this inclusion height allows us to
|
// was committed is updated. Keeping track of this inclusion height allows us to
|
||||||
|
@ -7676,3 +7676,231 @@ func TestChannelFeeRateFloor(t *testing.T) {
|
|||||||
err)
|
err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestFetchParent tests lookup of an entry's parent in the appropriate log.
|
||||||
|
func TestFetchParent(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
remoteChain bool
|
||||||
|
remoteLog bool
|
||||||
|
localEntries []*PaymentDescriptor
|
||||||
|
remoteEntries []*PaymentDescriptor
|
||||||
|
|
||||||
|
// parentIndex is the parent index of the entry that we will
|
||||||
|
// lookup with fetch parent.
|
||||||
|
parentIndex uint64
|
||||||
|
|
||||||
|
// expectErr indicates that we expect fetch parent to fail.
|
||||||
|
expectErr bool
|
||||||
|
|
||||||
|
// expectedIndex is the htlc index that we expect the parent
|
||||||
|
// to have.
|
||||||
|
expectedIndex uint64
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "not found in remote log",
|
||||||
|
localEntries: nil,
|
||||||
|
remoteEntries: nil,
|
||||||
|
remoteChain: true,
|
||||||
|
remoteLog: true,
|
||||||
|
parentIndex: 0,
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "not found in local log",
|
||||||
|
localEntries: nil,
|
||||||
|
remoteEntries: nil,
|
||||||
|
remoteChain: false,
|
||||||
|
remoteLog: false,
|
||||||
|
parentIndex: 0,
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "remote log + chain, remote add height 0",
|
||||||
|
localEntries: nil,
|
||||||
|
remoteEntries: []*PaymentDescriptor{
|
||||||
|
// This entry will be added at log index =0.
|
||||||
|
{
|
||||||
|
HtlcIndex: 1,
|
||||||
|
addCommitHeightLocal: 100,
|
||||||
|
addCommitHeightRemote: 100,
|
||||||
|
},
|
||||||
|
// This entry will be added at log index =1, it
|
||||||
|
// is the parent entry we are looking for.
|
||||||
|
{
|
||||||
|
HtlcIndex: 2,
|
||||||
|
addCommitHeightLocal: 100,
|
||||||
|
addCommitHeightRemote: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
remoteChain: true,
|
||||||
|
remoteLog: true,
|
||||||
|
parentIndex: 1,
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "remote log, local chain, local add height 0",
|
||||||
|
remoteEntries: []*PaymentDescriptor{
|
||||||
|
// This entry will be added at log index =0.
|
||||||
|
{
|
||||||
|
HtlcIndex: 1,
|
||||||
|
addCommitHeightLocal: 100,
|
||||||
|
addCommitHeightRemote: 100,
|
||||||
|
},
|
||||||
|
// This entry will be added at log index =1, it
|
||||||
|
// is the parent entry we are looking for.
|
||||||
|
{
|
||||||
|
HtlcIndex: 2,
|
||||||
|
addCommitHeightLocal: 0,
|
||||||
|
addCommitHeightRemote: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
localEntries: nil,
|
||||||
|
remoteChain: false,
|
||||||
|
remoteLog: true,
|
||||||
|
parentIndex: 1,
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "local log + chain, local add height 0",
|
||||||
|
localEntries: []*PaymentDescriptor{
|
||||||
|
// This entry will be added at log index =0.
|
||||||
|
{
|
||||||
|
HtlcIndex: 1,
|
||||||
|
addCommitHeightLocal: 100,
|
||||||
|
addCommitHeightRemote: 100,
|
||||||
|
},
|
||||||
|
// This entry will be added at log index =1, it
|
||||||
|
// is the parent entry we are looking for.
|
||||||
|
{
|
||||||
|
HtlcIndex: 2,
|
||||||
|
addCommitHeightLocal: 0,
|
||||||
|
addCommitHeightRemote: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
remoteEntries: nil,
|
||||||
|
remoteChain: false,
|
||||||
|
remoteLog: false,
|
||||||
|
parentIndex: 1,
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "local log + remote chain, remote add height 0",
|
||||||
|
localEntries: []*PaymentDescriptor{
|
||||||
|
// This entry will be added at log index =0.
|
||||||
|
{
|
||||||
|
HtlcIndex: 1,
|
||||||
|
addCommitHeightLocal: 100,
|
||||||
|
addCommitHeightRemote: 100,
|
||||||
|
},
|
||||||
|
// This entry will be added at log index =1, it
|
||||||
|
// is the parent entry we are looking for.
|
||||||
|
{
|
||||||
|
HtlcIndex: 2,
|
||||||
|
addCommitHeightLocal: 100,
|
||||||
|
addCommitHeightRemote: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
remoteEntries: nil,
|
||||||
|
remoteChain: true,
|
||||||
|
remoteLog: false,
|
||||||
|
parentIndex: 1,
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "remote log found",
|
||||||
|
localEntries: nil,
|
||||||
|
remoteEntries: []*PaymentDescriptor{
|
||||||
|
// This entry will be added at log index =0.
|
||||||
|
{
|
||||||
|
HtlcIndex: 1,
|
||||||
|
addCommitHeightLocal: 100,
|
||||||
|
addCommitHeightRemote: 0,
|
||||||
|
},
|
||||||
|
// This entry will be added at log index =1, it
|
||||||
|
// is the parent entry we are looking for.
|
||||||
|
{
|
||||||
|
HtlcIndex: 2,
|
||||||
|
addCommitHeightLocal: 100,
|
||||||
|
addCommitHeightRemote: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
remoteChain: true,
|
||||||
|
remoteLog: true,
|
||||||
|
parentIndex: 1,
|
||||||
|
expectErr: false,
|
||||||
|
expectedIndex: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "local log found",
|
||||||
|
localEntries: []*PaymentDescriptor{
|
||||||
|
// This entry will be added at log index =0.
|
||||||
|
{
|
||||||
|
HtlcIndex: 1,
|
||||||
|
addCommitHeightLocal: 0,
|
||||||
|
addCommitHeightRemote: 100,
|
||||||
|
},
|
||||||
|
// This entry will be added at log index =1, it
|
||||||
|
// is the parent entry we are looking for.
|
||||||
|
{
|
||||||
|
HtlcIndex: 2,
|
||||||
|
addCommitHeightLocal: 100,
|
||||||
|
addCommitHeightRemote: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
remoteEntries: nil,
|
||||||
|
remoteChain: false,
|
||||||
|
remoteLog: false,
|
||||||
|
parentIndex: 1,
|
||||||
|
expectErr: false,
|
||||||
|
expectedIndex: 2,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
test := test
|
||||||
|
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
// Create a lightning channel with newly initialized
|
||||||
|
// local and remote logs.
|
||||||
|
lc := LightningChannel{
|
||||||
|
localUpdateLog: newUpdateLog(0, 0),
|
||||||
|
remoteUpdateLog: newUpdateLog(0, 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the local and remote entries to update logs.
|
||||||
|
for _, entry := range test.localEntries {
|
||||||
|
lc.localUpdateLog.appendHtlc(entry)
|
||||||
|
}
|
||||||
|
for _, entry := range test.remoteEntries {
|
||||||
|
lc.remoteUpdateLog.appendHtlc(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
parent, err := lc.fetchParent(
|
||||||
|
&PaymentDescriptor{
|
||||||
|
ParentIndex: test.parentIndex,
|
||||||
|
},
|
||||||
|
test.remoteChain,
|
||||||
|
test.remoteLog,
|
||||||
|
)
|
||||||
|
gotErr := err != nil
|
||||||
|
if test.expectErr != gotErr {
|
||||||
|
t.Fatalf("expected error: %v, got: %v, "+
|
||||||
|
"error:%v", test.expectErr, gotErr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If our lookup failed, we do not need to check parent
|
||||||
|
// index.
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if parent.HtlcIndex != test.expectedIndex {
|
||||||
|
t.Fatalf("expected parent index: %v, got: %v",
|
||||||
|
test.parentIndex, parent.HtlcIndex)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user