multi: add labels to lnd native transactions
Follow up labelling of external transactions with labels for the transaction types we create within lnd. Since these labels will live a life of string matching, a version number and rigid format is added so that string matching is less painful. We start out with channel ID, where available, and a transaction "type". External labels, added in a previous PR, are not updated to this new versioned label because they are not lnd-initiated transactions. Label matching can check this case, then check for a version number.
This commit is contained in:
parent
a39c91fbcb
commit
2a614cc596
@ -20,6 +20,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/channeldb/kvdb"
|
"github.com/lightningnetwork/lnd/channeldb/kvdb"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
|
"github.com/lightningnetwork/lnd/labels"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||||
)
|
)
|
||||||
@ -566,7 +567,8 @@ justiceTxBroadcast:
|
|||||||
|
|
||||||
// We'll now attempt to broadcast the transaction which finalized the
|
// We'll now attempt to broadcast the transaction which finalized the
|
||||||
// channel's retribution against the cheating counter party.
|
// channel's retribution against the cheating counter party.
|
||||||
err = b.cfg.PublishTransaction(finalTx, "")
|
label := labels.MakeLabel(labels.LabelTypeJusticeTransaction, nil)
|
||||||
|
err = b.cfg.PublishTransaction(finalTx, label)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
brarLog.Errorf("Unable to broadcast justice tx: %v", err)
|
brarLog.Errorf("Unable to broadcast justice tx: %v", err)
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/channeldb/kvdb"
|
"github.com/lightningnetwork/lnd/channeldb/kvdb"
|
||||||
"github.com/lightningnetwork/lnd/clock"
|
"github.com/lightningnetwork/lnd/clock"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
|
"github.com/lightningnetwork/lnd/labels"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
@ -715,7 +716,10 @@ func (c *ChainArbitrator) rebroadcast(channel *channeldb.OpenChannel,
|
|||||||
log.Infof("Re-publishing %s close tx(%v) for channel %v",
|
log.Infof("Re-publishing %s close tx(%v) for channel %v",
|
||||||
kind, closeTx.TxHash(), chanPoint)
|
kind, closeTx.TxHash(), chanPoint)
|
||||||
|
|
||||||
err = c.cfg.PublishTx(closeTx, "")
|
label := labels.MakeLabel(
|
||||||
|
labels.LabelTypeChannelClose, &channel.ShortChannelID,
|
||||||
|
)
|
||||||
|
err = c.cfg.PublishTx(closeTx, label)
|
||||||
if err != nil && err != lnwallet.ErrDoubleSpend {
|
if err != nil && err != lnwallet.ErrDoubleSpend {
|
||||||
log.Warnf("Unable to broadcast %s close tx(%v): %v",
|
log.Warnf("Unable to broadcast %s close tx(%v): %v",
|
||||||
kind, closeTx.TxHash(), err)
|
kind, closeTx.TxHash(), err)
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/channeldb/kvdb"
|
"github.com/lightningnetwork/lnd/channeldb/kvdb"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
|
"github.com/lightningnetwork/lnd/labels"
|
||||||
"github.com/lightningnetwork/lnd/lntypes"
|
"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"
|
||||||
@ -874,7 +875,11 @@ func (c *ChannelArbitrator) stateStep(
|
|||||||
|
|
||||||
// At this point, we'll now broadcast the commitment
|
// At this point, we'll now broadcast the commitment
|
||||||
// transaction itself.
|
// transaction itself.
|
||||||
if err := c.cfg.PublishTx(closeTx, ""); err != nil {
|
label := labels.MakeLabel(
|
||||||
|
labels.LabelTypeChannelClose, &c.cfg.ShortChanID,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := c.cfg.PublishTx(closeTx, label); err != nil {
|
||||||
log.Errorf("ChannelArbitrator(%v): unable to broadcast "+
|
log.Errorf("ChannelArbitrator(%v): unable to broadcast "+
|
||||||
"close tx: %v", c.cfg.ChanPoint, err)
|
"close tx: %v", c.cfg.ChanPoint, err)
|
||||||
if err != lnwallet.ErrDoubleSpend {
|
if err != lnwallet.ErrDoubleSpend {
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
|
"github.com/lightningnetwork/lnd/labels"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/sweep"
|
"github.com/lightningnetwork/lnd/sweep"
|
||||||
)
|
)
|
||||||
@ -157,7 +158,10 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) {
|
|||||||
// Regardless of whether an existing transaction was found or newly
|
// Regardless of whether an existing transaction was found or newly
|
||||||
// constructed, we'll broadcast the sweep transaction to the
|
// constructed, we'll broadcast the sweep transaction to the
|
||||||
// network.
|
// network.
|
||||||
err := h.PublishTx(h.sweepTx, "")
|
label := labels.MakeLabel(
|
||||||
|
labels.LabelTypeChannelClose, &h.ShortChanID,
|
||||||
|
)
|
||||||
|
err := h.PublishTx(h.sweepTx, label)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Infof("%T(%x): unable to publish tx: %v",
|
log.Infof("%T(%x): unable to publish tx: %v",
|
||||||
h, h.htlc.RHash[:], err)
|
h, h.htlc.RHash[:], err)
|
||||||
@ -206,7 +210,10 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) {
|
|||||||
// the claiming process.
|
// the claiming process.
|
||||||
//
|
//
|
||||||
// TODO(roasbeef): after changing sighashes send to tx bundler
|
// TODO(roasbeef): after changing sighashes send to tx bundler
|
||||||
err := h.PublishTx(h.htlcResolution.SignedSuccessTx, "")
|
label := labels.MakeLabel(
|
||||||
|
labels.LabelTypeChannelClose, &h.ShortChanID,
|
||||||
|
)
|
||||||
|
err := h.PublishTx(h.htlcResolution.SignedSuccessTx, label)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
|
"github.com/lightningnetwork/lnd/labels"
|
||||||
"github.com/lightningnetwork/lnd/lnpeer"
|
"github.com/lightningnetwork/lnd/lnpeer"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
@ -243,6 +244,10 @@ type fundingConfig struct {
|
|||||||
// transaction to the network.
|
// transaction to the network.
|
||||||
PublishTransaction func(*wire.MsgTx, string) error
|
PublishTransaction func(*wire.MsgTx, string) error
|
||||||
|
|
||||||
|
// UpdateLabel updates the label that a transaction has in our wallet,
|
||||||
|
// overwriting any existing labels.
|
||||||
|
UpdateLabel func(chainhash.Hash, string) error
|
||||||
|
|
||||||
// FeeEstimator calculates appropriate fee rates based on historical
|
// FeeEstimator calculates appropriate fee rates based on historical
|
||||||
// transaction information.
|
// transaction information.
|
||||||
FeeEstimator chainfee.Estimator
|
FeeEstimator chainfee.Estimator
|
||||||
@ -576,8 +581,15 @@ func (f *fundingManager) start() error {
|
|||||||
channel.FundingOutpoint,
|
channel.FundingOutpoint,
|
||||||
fundingTxBuf.Bytes())
|
fundingTxBuf.Bytes())
|
||||||
|
|
||||||
|
// Set a nil short channel ID at this stage
|
||||||
|
// because we do not know it until our funding
|
||||||
|
// tx confirms.
|
||||||
|
label := labels.MakeLabel(
|
||||||
|
labels.LabelTypeChannelOpen, nil,
|
||||||
|
)
|
||||||
|
|
||||||
err = f.cfg.PublishTransaction(
|
err = f.cfg.PublishTransaction(
|
||||||
channel.FundingTxn, "",
|
channel.FundingTxn, label,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fndgLog.Errorf("Unable to rebroadcast "+
|
fndgLog.Errorf("Unable to rebroadcast "+
|
||||||
@ -2032,7 +2044,13 @@ func (f *fundingManager) handleFundingSigned(fmsg *fundingSignedMsg) {
|
|||||||
fndgLog.Infof("Broadcasting funding tx for ChannelPoint(%v): %x",
|
fndgLog.Infof("Broadcasting funding tx for ChannelPoint(%v): %x",
|
||||||
completeChan.FundingOutpoint, fundingTxBuf.Bytes())
|
completeChan.FundingOutpoint, fundingTxBuf.Bytes())
|
||||||
|
|
||||||
err = f.cfg.PublishTransaction(fundingTx, "")
|
// Set a nil short channel ID at this stage because we do not
|
||||||
|
// know it until our funding tx confirms.
|
||||||
|
label := labels.MakeLabel(
|
||||||
|
labels.LabelTypeChannelOpen, nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
err = f.cfg.PublishTransaction(fundingTx, label)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fndgLog.Errorf("Unable to broadcast funding tx %x for "+
|
fndgLog.Errorf("Unable to broadcast funding tx %x for "+
|
||||||
"ChannelPoint(%v): %v", fundingTxBuf.Bytes(),
|
"ChannelPoint(%v): %v", fundingTxBuf.Bytes(),
|
||||||
@ -2372,6 +2390,25 @@ func (f *fundingManager) handleFundingConfirmation(
|
|||||||
fndgLog.Errorf("unable to report short chan id: %v", err)
|
fndgLog.Errorf("unable to report short chan id: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we opened the channel, and lnd's wallet published our funding tx
|
||||||
|
// (which is not the case for some channels) then we update our
|
||||||
|
// transaction label with our short channel ID, which is known now that
|
||||||
|
// our funding transaction has confirmed. We do not label transactions
|
||||||
|
// we did not publish, because our wallet has no knowledge of them.
|
||||||
|
if completeChan.IsInitiator && completeChan.ChanType.HasFundingTx() {
|
||||||
|
shortChanID := completeChan.ShortChanID()
|
||||||
|
label := labels.MakeLabel(
|
||||||
|
labels.LabelTypeChannelOpen, &shortChanID,
|
||||||
|
)
|
||||||
|
|
||||||
|
err = f.cfg.UpdateLabel(
|
||||||
|
completeChan.FundingOutpoint.Hash, label,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
fndgLog.Errorf("unable to update label: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Close the discoverySignal channel, indicating to a separate
|
// Close the discoverySignal channel, indicating to a separate
|
||||||
// goroutine that the channel now is marked as open in the database
|
// goroutine that the channel now is marked as open in the database
|
||||||
// and that it is acceptable to process funding locked messages
|
// and that it is acceptable to process funding locked messages
|
||||||
|
@ -421,6 +421,9 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey,
|
|||||||
publTxChan <- txn
|
publTxChan <- txn
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
UpdateLabel: func(chainhash.Hash, string) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
ZombieSweeperInterval: 1 * time.Hour,
|
ZombieSweeperInterval: 1 * time.Hour,
|
||||||
ReservationTimeout: 1 * time.Nanosecond,
|
ReservationTimeout: 1 * time.Nanosecond,
|
||||||
MaxPendingChannels: lncfg.DefaultMaxPendingChannels,
|
MaxPendingChannels: lncfg.DefaultMaxPendingChannels,
|
||||||
@ -524,6 +527,9 @@ func recreateAliceFundingManager(t *testing.T, alice *testNode) {
|
|||||||
publishChan <- txn
|
publishChan <- txn
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
UpdateLabel: func(chainhash.Hash, string) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
ZombieSweeperInterval: oldCfg.ZombieSweeperInterval,
|
ZombieSweeperInterval: oldCfg.ZombieSweeperInterval,
|
||||||
ReservationTimeout: oldCfg.ReservationTimeout,
|
ReservationTimeout: oldCfg.ReservationTimeout,
|
||||||
OpenChannelPredicate: chainedAcceptor,
|
OpenChannelPredicate: chainedAcceptor,
|
||||||
|
@ -1,12 +1,24 @@
|
|||||||
// Package labels contains labels used to label transactions broadcast by lnd.
|
// Package labels contains labels used to label transactions broadcast by lnd.
|
||||||
// These labels are used across packages, so they are declared in a separate
|
// These labels are used across packages, so they are declared in a separate
|
||||||
// package to avoid dependency issues.
|
// package to avoid dependency issues.
|
||||||
|
//
|
||||||
|
// Labels for transactions broadcast by lnd have two set fields followed by an
|
||||||
|
// optional set labelled data values, all separated by colons.
|
||||||
|
// - Label version: an integer that indicates the version lnd used
|
||||||
|
// - Label type: the type of transaction we are labelling
|
||||||
|
// - {field name}-{value}: a named field followed by its value, these items are
|
||||||
|
// optional, and there may be more than field present.
|
||||||
|
//
|
||||||
|
// For version 0 we have the following optional data fields defined:
|
||||||
|
// - shortchanid: the short channel ID that a transaction is associated with,
|
||||||
|
// with its value set to the uint64 short channel id.
|
||||||
package labels
|
package labels
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/btcsuite/btcwallet/wtxmgr"
|
"github.com/btcsuite/btcwallet/wtxmgr"
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
|
|
||||||
// External labels a transaction as user initiated via the api. This
|
// External labels a transaction as user initiated via the api. This
|
||||||
@ -31,3 +43,50 @@ func ValidateAPI(label string) (string, error) {
|
|||||||
|
|
||||||
return label, nil
|
return label, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LabelVersion versions our labels so they can be easily update to contain
|
||||||
|
// new data while still easily string matched.
|
||||||
|
type LabelVersion uint8
|
||||||
|
|
||||||
|
// LabelVersionZero is the label version for labels that contain label type and
|
||||||
|
// channel ID (where available).
|
||||||
|
const LabelVersionZero LabelVersion = iota
|
||||||
|
|
||||||
|
// LabelType indicates the type of label we are creating. It is a string rather
|
||||||
|
// than an int for easy string matching and human-readability.
|
||||||
|
type LabelType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// LabelTypeChannelOpen is used to label channel opens.
|
||||||
|
LabelTypeChannelOpen LabelType = "openchannel"
|
||||||
|
|
||||||
|
// LabelTypeChannelClose is used to label channel closes.
|
||||||
|
LabelTypeChannelClose LabelType = "closechannel"
|
||||||
|
|
||||||
|
// LabelTypeJusticeTransaction is used to label justice transactions.
|
||||||
|
LabelTypeJusticeTransaction LabelType = "justicetx"
|
||||||
|
|
||||||
|
// LabelTypeSweepTransaction is used to label sweeps.
|
||||||
|
LabelTypeSweepTransaction LabelType = "sweep"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LabelField is used to tag a value within a label.
|
||||||
|
type LabelField string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ShortChanID is used to tag short channel id values in our labels.
|
||||||
|
ShortChanID LabelField = "shortchanid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MakeLabel creates a label with the provided type and short channel id. If
|
||||||
|
// our short channel ID is not known, we simply return version:label_type. If
|
||||||
|
// we do have a short channel ID set, the label will also contain its value:
|
||||||
|
// shortchanid-{int64 chan ID}.
|
||||||
|
func MakeLabel(labelType LabelType, channelID *lnwire.ShortChannelID) string {
|
||||||
|
if channelID == nil {
|
||||||
|
return fmt.Sprintf("%v:%v", LabelVersionZero, labelType)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%v:%v:%v-%v", LabelVersionZero, labelType,
|
||||||
|
ShortChanID, channelID.ToUint64())
|
||||||
|
}
|
||||||
|
@ -1204,9 +1204,14 @@ func (n *NetworkHarness) WaitForChannelClose(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AssertChannelExists asserts that an active channel identified by the
|
// AssertChannelExists asserts that an active channel identified by the
|
||||||
// specified channel point exists from the point-of-view of the node.
|
// specified channel point exists from the point-of-view of the node. It takes
|
||||||
|
// an optional set of check functions which can be used to make further
|
||||||
|
// assertions using channel's values. These functions are responsible for
|
||||||
|
// failing the test themselves if they do not pass.
|
||||||
|
// nolint: interfacer
|
||||||
func (n *NetworkHarness) AssertChannelExists(ctx context.Context,
|
func (n *NetworkHarness) AssertChannelExists(ctx context.Context,
|
||||||
node *HarnessNode, chanPoint *wire.OutPoint) error {
|
node *HarnessNode, chanPoint *wire.OutPoint,
|
||||||
|
checks ...func(*lnrpc.Channel)) error {
|
||||||
|
|
||||||
req := &lnrpc.ListChannelsRequest{}
|
req := &lnrpc.ListChannelsRequest{}
|
||||||
|
|
||||||
@ -1218,13 +1223,21 @@ func (n *NetworkHarness) AssertChannelExists(ctx context.Context,
|
|||||||
|
|
||||||
for _, channel := range resp.Channels {
|
for _, channel := range resp.Channels {
|
||||||
if channel.ChannelPoint == chanPoint.String() {
|
if channel.ChannelPoint == chanPoint.String() {
|
||||||
if channel.Active {
|
// First check whether our channel is active,
|
||||||
return nil
|
// failing early if it is not.
|
||||||
}
|
if !channel.Active {
|
||||||
|
|
||||||
return fmt.Errorf("channel %s inactive",
|
return fmt.Errorf("channel %s inactive",
|
||||||
chanPoint)
|
chanPoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply any additional checks that we would
|
||||||
|
// like to verify.
|
||||||
|
for _, check := range checks {
|
||||||
|
check(channel)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("channel %s not found", chanPoint)
|
return fmt.Errorf("channel %s not found", chanPoint)
|
||||||
|
@ -35,6 +35,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chanbackup"
|
"github.com/lightningnetwork/lnd/chanbackup"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
|
"github.com/lightningnetwork/lnd/labels"
|
||||||
"github.com/lightningnetwork/lnd/lncfg"
|
"github.com/lightningnetwork/lnd/lncfg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||||
@ -2905,6 +2906,7 @@ func testChannelFundingPersistence(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
t.Fatalf("unable to convert funding txid into chainhash.Hash:"+
|
t.Fatalf("unable to convert funding txid into chainhash.Hash:"+
|
||||||
" %v", err)
|
" %v", err)
|
||||||
}
|
}
|
||||||
|
fundingTxStr := fundingTxID.String()
|
||||||
|
|
||||||
// Mine a block, then wait for Alice's node to notify us that the
|
// Mine a block, then wait for Alice's node to notify us that the
|
||||||
// channel has been opened. The funding transaction should be found
|
// channel has been opened. The funding transaction should be found
|
||||||
@ -2912,6 +2914,10 @@ func testChannelFundingPersistence(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
block := mineBlocks(t, net, 1, 1)[0]
|
block := mineBlocks(t, net, 1, 1)[0]
|
||||||
assertTxInBlock(t, block, fundingTxID)
|
assertTxInBlock(t, block, fundingTxID)
|
||||||
|
|
||||||
|
// Get the height that our transaction confirmed at.
|
||||||
|
_, height, err := net.Miner.Node.GetBestBlock()
|
||||||
|
require.NoError(t.t, err, "could not get best block")
|
||||||
|
|
||||||
// Restart both nodes to test that the appropriate state has been
|
// Restart both nodes to test that the appropriate state has been
|
||||||
// persisted and that both nodes recover gracefully.
|
// persisted and that both nodes recover gracefully.
|
||||||
if err := net.RestartNode(net.Alice, nil); err != nil {
|
if err := net.RestartNode(net.Alice, nil); err != nil {
|
||||||
@ -2934,6 +2940,16 @@ func testChannelFundingPersistence(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
t.Fatalf("unable to mine blocks: %v", err)
|
t.Fatalf("unable to mine blocks: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assert that our wallet has our opening transaction with a label
|
||||||
|
// that does not have a channel ID set yet, because we have not
|
||||||
|
// reached our required confirmations.
|
||||||
|
tx := findTxAtHeight(ctxt, t, height, fundingTxStr, net, net.Alice)
|
||||||
|
|
||||||
|
// At this stage, we expect the transaction to be labelled, but not with
|
||||||
|
// our channel ID because our transaction has not yet confirmed.
|
||||||
|
label := labels.MakeLabel(labels.LabelTypeChannelOpen, nil)
|
||||||
|
require.Equal(t.t, label, tx.Label, "open channel label wrong")
|
||||||
|
|
||||||
// Both nodes should still show a single channel as pending.
|
// Both nodes should still show a single channel as pending.
|
||||||
time.Sleep(time.Second * 1)
|
time.Sleep(time.Second * 1)
|
||||||
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
||||||
@ -2957,9 +2973,27 @@ func testChannelFundingPersistence(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
Index: pendingUpdate.OutputIndex,
|
Index: pendingUpdate.OutputIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Re-lookup our transaction in the block that it confirmed in.
|
||||||
|
tx = findTxAtHeight(ctxt, t, height, fundingTxStr, net, net.Alice)
|
||||||
|
|
||||||
|
// Create an additional check for our channel assertion that will
|
||||||
|
// check that our label is as expected.
|
||||||
|
check := func(channel *lnrpc.Channel) {
|
||||||
|
shortChanID := lnwire.NewShortChanIDFromInt(
|
||||||
|
channel.ChanId,
|
||||||
|
)
|
||||||
|
|
||||||
|
label := labels.MakeLabel(
|
||||||
|
labels.LabelTypeChannelOpen, &shortChanID,
|
||||||
|
)
|
||||||
|
require.Equal(t.t, label, tx.Label,
|
||||||
|
"open channel label not updated")
|
||||||
|
}
|
||||||
|
|
||||||
// Check both nodes to ensure that the channel is ready for operation.
|
// Check both nodes to ensure that the channel is ready for operation.
|
||||||
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
||||||
if err := net.AssertChannelExists(ctxt, net.Alice, &outPoint); err != nil {
|
err = net.AssertChannelExists(ctxt, net.Alice, &outPoint, check)
|
||||||
|
if err != nil {
|
||||||
t.Fatalf("unable to assert channel existence: %v", err)
|
t.Fatalf("unable to assert channel existence: %v", err)
|
||||||
}
|
}
|
||||||
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
||||||
@ -2980,6 +3014,30 @@ func testChannelFundingPersistence(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
closeChannelAndAssert(ctxt, t, net, net.Alice, chanPoint, false)
|
closeChannelAndAssert(ctxt, t, net, net.Alice, chanPoint, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// findTxAtHeight gets all of the transactions that a node's wallet has a record
|
||||||
|
// of at the target height, and finds and returns the tx with the target txid,
|
||||||
|
// failing if it is not found.
|
||||||
|
func findTxAtHeight(ctx context.Context, t *harnessTest, height int32,
|
||||||
|
target string, net *lntest.NetworkHarness,
|
||||||
|
node *lntest.HarnessNode) *lnrpc.Transaction {
|
||||||
|
|
||||||
|
txns, err := node.LightningClient.GetTransactions(
|
||||||
|
ctx, &lnrpc.GetTransactionsRequest{
|
||||||
|
StartHeight: height,
|
||||||
|
EndHeight: height,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
require.NoError(t.t, err, "could not get transactions")
|
||||||
|
|
||||||
|
for _, tx := range txns.Transactions {
|
||||||
|
if tx.TxHash == target {
|
||||||
|
return tx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// testChannelBalance creates a new channel between Alice and Bob, then
|
// testChannelBalance creates a new channel between Alice and Bob, then
|
||||||
// checks channel balance to be equal amount specified while creation of channel.
|
// checks channel balance to be equal amount specified while creation of channel.
|
||||||
func testChannelBalance(net *lntest.NetworkHarness, t *harnessTest) {
|
func testChannelBalance(net *lntest.NetworkHarness, t *harnessTest) {
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||||
|
"github.com/lightningnetwork/lnd/labels"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
@ -551,7 +552,14 @@ func (c *ChanCloser) ProcessCloseMsg(msg lnwire.Message) ([]lnwire.Message,
|
|||||||
return spew.Sdump(closeTx)
|
return spew.Sdump(closeTx)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
if err := c.cfg.BroadcastTx(closeTx, ""); err != nil {
|
|
||||||
|
// Create a close channel label.
|
||||||
|
chanID := c.cfg.Channel.ShortChanID()
|
||||||
|
closeLabel := labels.MakeLabel(
|
||||||
|
labels.LabelTypeChannelClose, &chanID,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := c.cfg.BroadcastTx(closeTx, closeLabel); err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -971,6 +971,9 @@ func newServer(cfg *Config, listenAddrs []net.Addr, chanDB *channeldb.DB,
|
|||||||
IDKey: nodeKeyECDH.PubKey(),
|
IDKey: nodeKeyECDH.PubKey(),
|
||||||
Wallet: cc.wallet,
|
Wallet: cc.wallet,
|
||||||
PublishTransaction: cc.wallet.PublishTransaction,
|
PublishTransaction: cc.wallet.PublishTransaction,
|
||||||
|
UpdateLabel: func(hash chainhash.Hash, label string) error {
|
||||||
|
return cc.wallet.LabelTransaction(hash, label, true)
|
||||||
|
},
|
||||||
Notifier: cc.chainNotifier,
|
Notifier: cc.chainNotifier,
|
||||||
FeeEstimator: cc.feeEstimator,
|
FeeEstimator: cc.feeEstimator,
|
||||||
SignMessage: func(pubKey *btcec.PublicKey,
|
SignMessage: func(pubKey *btcec.PublicKey,
|
||||||
|
@ -11,10 +11,10 @@ import (
|
|||||||
"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/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
|
"github.com/lightningnetwork/lnd/labels"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/sweep"
|
"github.com/lightningnetwork/lnd/sweep"
|
||||||
)
|
)
|
||||||
@ -867,7 +867,8 @@ func (u *utxoNursery) sweepCribOutput(classHeight uint32, baby *babyOutput) erro
|
|||||||
|
|
||||||
// We'll now broadcast the HTLC transaction, then wait for it to be
|
// We'll now broadcast the HTLC transaction, then wait for it to be
|
||||||
// confirmed before transitioning it to kindergarten.
|
// confirmed before transitioning it to kindergarten.
|
||||||
err := u.cfg.PublishTransaction(baby.timeoutTx, "")
|
label := labels.MakeLabel(labels.LabelTypeSweepTransaction, nil)
|
||||||
|
err := u.cfg.PublishTransaction(baby.timeoutTx, label)
|
||||||
if err != nil && err != lnwallet.ErrDoubleSpend {
|
if err != nil && err != lnwallet.ErrDoubleSpend {
|
||||||
utxnLog.Errorf("Unable to broadcast baby tx: "+
|
utxnLog.Errorf("Unable to broadcast baby tx: "+
|
||||||
"%v, %v", err, spew.Sdump(baby.timeoutTx))
|
"%v, %v", err, spew.Sdump(baby.timeoutTx))
|
||||||
|
@ -2,6 +2,7 @@ package lookout
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
"github.com/lightningnetwork/lnd/labels"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PunisherConfig houses the resources required by the Punisher.
|
// PunisherConfig houses the resources required by the Punisher.
|
||||||
@ -42,7 +43,8 @@ func (p *BreachPunisher) Punish(desc *JusticeDescriptor, quit <-chan struct{}) e
|
|||||||
log.Infof("Publishing justice transaction for client=%s with txid=%s",
|
log.Infof("Publishing justice transaction for client=%s with txid=%s",
|
||||||
desc.SessionInfo.ID, justiceTxn.TxHash())
|
desc.SessionInfo.ID, justiceTxn.TxHash())
|
||||||
|
|
||||||
err = p.cfg.PublishTx(justiceTxn, "")
|
label := labels.MakeLabel(labels.LabelTypeJusticeTransaction, nil)
|
||||||
|
err = p.cfg.PublishTx(justiceTxn, label)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Unable to publish justice txn for client=%s"+
|
log.Errorf("Unable to publish justice txn for client=%s"+
|
||||||
"with breach-txid=%s: %v",
|
"with breach-txid=%s: %v",
|
||||||
|
Loading…
Reference in New Issue
Block a user