From d3eafab04f130fd8b942b23ef42cd2481ec5fb3e Mon Sep 17 00:00:00 2001 From: wuxiaofei Date: Fri, 22 Apr 2022 12:03:23 +0800 Subject: [PATCH] funding with asset: funding.TestFundingManagerNormalWorkflow --- autopilot/graph.go | 37 +++-- autopilot/interface.go | 5 +- autopilot/prefattach.go | 4 +- chanacceptor/rpcacceptor.go | 9 +- channeldb/graph.go | 70 +++++++-- channeldb/graph_cache.go | 40 +++-- discovery/gossiper.go | 54 +++++-- funding/batch.go | 6 +- funding/batch_test.go | 8 +- funding/manager.go | 189 ++++++++++++++++------- funding/manager_test.go | 98 +++++++----- htlcswitch/circuit.go | 16 +- htlcswitch/htlcnotifier.go | 13 +- htlcswitch/link.go | 21 ++- htlcswitch/mailbox.go | 8 +- htlcswitch/packet.go | 9 +- htlcswitch/switch.go | 28 ++-- htlcswitch/test_utils.go | 38 +++-- lnwallet/chanfunding/canned_assembler.go | 15 ++ lnwallet/commitment.go | 5 +- lnwallet/reservation.go | 96 +++++++----- lnwallet/wallet.go | 32 ++-- lnwire/channel_announcement.go | 4 + lnwire/channel_update.go | 49 ++++-- lnwire/open_channel.go | 34 +++- netann/channel_update.go | 6 +- routing/ann_validation.go | 4 +- routing/notifications.go | 35 ++++- routing/pathfind.go | 4 +- routing/payment_lifecycle.go | 3 +- routing/route/route.go | 2 + routing/router.go | 13 +- routing/unified_policies.go | 15 +- 33 files changed, 692 insertions(+), 278 deletions(-) diff --git a/autopilot/graph.go b/autopilot/graph.go index e630f8d35d..c183fd3f60 100644 --- a/autopilot/graph.go +++ b/autopilot/graph.go @@ -2,6 +2,7 @@ package autopilot import ( "bytes" + "github.com/lightningnetwork/lnd/lnwallet/omnicore" "math/big" "net" "sort" @@ -100,7 +101,9 @@ func (d dbNode) ForEachChannel(cb func(ChannelEdge) error) error { edge := ChannelEdge{ ChanID: lnwire.NewShortChanIDFromInt(ep.ChannelID), - Capacity: ei.Capacity, + BtcCapacity: ei.BtcCapacity, + AssetCapacity: ei.AssetCapacity, + AsserId: ei.AssetId, Peer: dbNode{ tx: tx, node: ep.Node, @@ -137,7 +140,7 @@ func (d *databaseChannelGraph) ForEachNode(cb func(Node) error) error { // meant to aide in the generation of random graphs for use within test cases // the exercise the autopilot package. func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey, - capacity btcutil.Amount) (*ChannelEdge, *ChannelEdge, error) { + capacity btcutil.Amount,assetCapacity omnicore.Amount,assetId uint32) (*ChannelEdge, *ChannelEdge, error) { fetchNode := func(pub *btcec.PublicKey) (*channeldb.LightningNode, error) { if pub != nil { @@ -222,7 +225,9 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey, chanID := randChanID() edge := &channeldb.ChannelEdgeInfo{ ChannelID: chanID.ToUint64(), - Capacity: capacity, + BtcCapacity: capacity, + AssetCapacity: assetCapacity, + AssetId: assetId, } edge.AddNodeKeys(lnNode1, lnNode2, lnNode1, lnNode2) if err := d.db.AddChannelEdge(edge); err != nil { @@ -233,8 +238,8 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey, ChannelID: chanID.ToUint64(), LastUpdate: time.Now(), TimeLockDelta: 10, - MinHTLC: 1, - MaxHTLC: lnwire.NewMSatFromSatoshis(capacity), + MinBtcHTLC: 1, + MaxBtcHTLC: lnwire.NewMSatFromSatoshis(capacity), FeeBaseMSat: 10, FeeProportionalMillionths: 10000, MessageFlags: 1, @@ -249,8 +254,8 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey, ChannelID: chanID.ToUint64(), LastUpdate: time.Now(), TimeLockDelta: 10, - MinHTLC: 1, - MaxHTLC: lnwire.NewMSatFromSatoshis(capacity), + MinBtcHTLC: 1, + MaxBtcHTLC: lnwire.NewMSatFromSatoshis(capacity), FeeBaseMSat: 10, FeeProportionalMillionths: 10000, MessageFlags: 1, @@ -262,14 +267,18 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey, return &ChannelEdge{ ChanID: chanID, - Capacity: capacity, + BtcCapacity: capacity, + AssetCapacity: assetCapacity, + AsserId: assetId, Peer: dbNode{ node: vertex1, }, }, &ChannelEdge{ ChanID: chanID, - Capacity: capacity, + BtcCapacity: capacity, + AssetCapacity: assetCapacity, + AsserId: assetId, Peer: dbNode{ node: vertex2, }, @@ -356,7 +365,7 @@ func randKey() (*btcec.PublicKey, error) { // meant to aide in the generation of random graphs for use within test cases // the exercise the autopilot package. func (m *memChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey, - capacity btcutil.Amount) (*ChannelEdge, *ChannelEdge, error) { + capacity btcutil.Amount, assetCapacity omnicore.Amount,assetId uint32 ) (*ChannelEdge, *ChannelEdge, error) { var ( vertex1, vertex2 *memNode @@ -419,14 +428,18 @@ func (m *memChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey, edge1 := ChannelEdge{ ChanID: randChanID(), - Capacity: capacity, + BtcCapacity: capacity, + AssetCapacity: assetCapacity, + AsserId: assetId, Peer: vertex2, } vertex1.chans = append(vertex1.chans, edge1) edge2 := ChannelEdge{ ChanID: randChanID(), - Capacity: capacity, + BtcCapacity: capacity, + AssetCapacity: assetCapacity, + AsserId: assetId, Peer: vertex1, } vertex2.chans = append(vertex2.chans, edge2) diff --git a/autopilot/interface.go b/autopilot/interface.go index 7858be436d..f7dc59b463 100644 --- a/autopilot/interface.go +++ b/autopilot/interface.go @@ -1,6 +1,7 @@ package autopilot import ( + "github.com/lightningnetwork/lnd/lnwallet/omnicore" "net" "github.com/btcsuite/btcd/btcec" @@ -64,7 +65,9 @@ type ChannelEdge struct { ChanID lnwire.ShortChannelID // Capacity is the capacity of the channel expressed in satoshis. - Capacity btcutil.Amount + BtcCapacity btcutil.Amount + AssetCapacity omnicore.Amount + AsserId uint32 // Peer is the peer that this channel creates an edge to in the channel // graph. diff --git a/autopilot/prefattach.go b/autopilot/prefattach.go index c25009d12e..e59335f533 100644 --- a/autopilot/prefattach.go +++ b/autopilot/prefattach.go @@ -94,7 +94,7 @@ func (p *PrefAttachment) NodeScores(g ChannelGraph, chans []LocalChannel, return nil } seenChans[e.ChanID.ToUint64()] = struct{}{} - allChans = append(allChans, e.Capacity) + allChans = append(allChans, e.BtcCapacity) return nil }) if err != nil { @@ -122,7 +122,7 @@ func (p *PrefAttachment) NodeScores(g ChannelGraph, chans []LocalChannel, // graph (we will potentially waste time trying to use // these useless channels in path finding), we decrease // the counter for such channels. - if e.Capacity < medianChanSize/minMedianChanSizeFraction { + if e.BtcCapacity < medianChanSize/minMedianChanSizeFraction { nodeChans-- return nil } diff --git a/chanacceptor/rpcacceptor.go b/chanacceptor/rpcacceptor.go index bec9143559..5bbcb232a3 100644 --- a/chanacceptor/rpcacceptor.go +++ b/chanacceptor/rpcacceptor.go @@ -299,8 +299,13 @@ func (r *RPCAcceptor) sendAcceptRequests(errChan chan error, NodePubkey: req.Node.SerializeCompressed(), ChainHash: req.OpenChanMsg.ChainHash[:], PendingChanId: req.OpenChanMsg.PendingChannelID[:], - FundingAmt: uint64(req.OpenChanMsg.FundingAmount), - PushAmt: uint64(req.OpenChanMsg.PushAmount), + FundingAmt: uint64(req.OpenChanMsg.FundingBtcAmount), + PushAmt: uint64(req.OpenChanMsg.PushBtcAmount), + /*obd update wxf + todo add asset + */ + //FundingAmt: uint64(req.OpenChanMsg.FundingAssetAmount), + //PushAmt: uint64(req.OpenChanMsg.PushAssetAmount), DustLimit: uint64(req.OpenChanMsg.DustLimit), MaxValueInFlight: uint64(req.OpenChanMsg.MaxValueInFlight), ChannelReserve: uint64(req.OpenChanMsg.ChannelReserve), diff --git a/channeldb/graph.go b/channeldb/graph.go index b5440418a3..9fdd4b22d8 100644 --- a/channeldb/graph.go +++ b/channeldb/graph.go @@ -6,6 +6,7 @@ import ( "encoding/binary" "errors" "fmt" + "github.com/lightningnetwork/lnd/lnwallet/omnicore" "image/color" "io" "math" @@ -492,7 +493,10 @@ func (c *ChannelGraph) ForEachNodeChannel(tx kvdb.RTx, node route.Vertex, ChannelID: e.ChannelID, IsNode1: node == e.NodeKey1Bytes, OtherNode: e.NodeKey2Bytes, - Capacity: e.Capacity, + /*obd add wxf*/ + BtcCapacity: e.BtcCapacity, + AssetCapacity: e.AssetCapacity, + AssetId: e.AssetId, OutPolicySet: p1 != nil, InPolicy: cachedInPolicy, } @@ -578,7 +582,9 @@ func (c *ChannelGraph) ForEachNodeCached(cb func(node route.Vertex, ChannelID: e.ChannelID, IsNode1: node.PubKeyBytes == e.NodeKey1Bytes, OtherNode: e.NodeKey2Bytes, - Capacity: e.Capacity, + BtcCapacity: e.BtcCapacity, + AssetCapacity: e.AssetCapacity, + AssetId: e.AssetId, OutPolicySet: p1 != nil, InPolicy: cachedInPolicy, } @@ -3061,9 +3067,14 @@ type ChannelEdgeInfo struct { // used to uniquely identify the channel within the channel graph. ChannelPoint wire.OutPoint + /* + obd update wxf + */ // Capacity is the total capacity of the channel, this is determined by // the value output in the outpoint that created this channel. - Capacity btcutil.Amount + BtcCapacity btcutil.Amount + AssetCapacity omnicore.Amount + AssetId uint32 // ExtraOpaqueData is the set of data that was appended to this // message, some of which we may not actually know how to iterate or @@ -3408,11 +3419,16 @@ type ChannelEdgePolicy struct { // MinHTLC is the smallest value HTLC this node will forward, expressed // in millisatoshi. - MinHTLC lnwire.MilliSatoshi + MinBtcHTLC lnwire.MilliSatoshi // MaxHTLC is the largest value HTLC this node will forward, expressed // in millisatoshi. - MaxHTLC lnwire.MilliSatoshi + MaxBtcHTLC lnwire.MilliSatoshi + /*obd add wxf + */ + MinAssetHTLC omnicore.Amount + MaxAssetHTLC omnicore.Amount + AssetId uint32 // FeeBaseMSat is the base HTLC fee that will be charged for forwarding // ANY HTLC, expressed in mSAT's. @@ -4358,7 +4374,13 @@ func putChanEdgeInfo(edgeIndex kvdb.RwBucket, edgeInfo *ChannelEdgeInfo, chanID if err := writeOutpoint(&b, &edgeInfo.ChannelPoint); err != nil { return err } - if err := binary.Write(&b, byteOrder, uint64(edgeInfo.Capacity)); err != nil { + if err := binary.Write(&b, byteOrder, uint64(edgeInfo.BtcCapacity)); err != nil { + return err + } + if err := binary.Write(&b, byteOrder, uint64(edgeInfo.AssetCapacity)); err != nil { + return err + } + if err := binary.Write(&b, byteOrder, uint32(edgeInfo.AssetId)); err != nil { return err } if _, err := b.Write(chanID[:]); err != nil { @@ -4442,7 +4464,13 @@ func deserializeChanEdgeInfo(r io.Reader) (ChannelEdgeInfo, error) { if err := readOutpoint(r, &edgeInfo.ChannelPoint); err != nil { return ChannelEdgeInfo{}, err } - if err := binary.Read(r, byteOrder, &edgeInfo.Capacity); err != nil { + if err := binary.Read(r, byteOrder, &edgeInfo.BtcCapacity); err != nil { + return ChannelEdgeInfo{}, err + } + if err := binary.Read(r, byteOrder, &edgeInfo.AssetCapacity); err != nil { + return ChannelEdgeInfo{}, err + } + if err := binary.Read(r, byteOrder, &edgeInfo.AssetId); err != nil { return ChannelEdgeInfo{}, err } if err := binary.Read(r, byteOrder, &edgeInfo.ChannelID); err != nil { @@ -4690,7 +4718,10 @@ func serializeChanEdgePolicy(w io.Writer, edge *ChannelEdgePolicy, if err := binary.Write(w, byteOrder, edge.TimeLockDelta); err != nil { return err } - if err := binary.Write(w, byteOrder, uint64(edge.MinHTLC)); err != nil { + if err := binary.Write(w, byteOrder, uint64(edge.MinBtcHTLC)); err != nil { + return err + } + if err := binary.Write(w, byteOrder, uint64(edge.MinAssetHTLC)); err != nil { return err } if err := binary.Write(w, byteOrder, uint64(edge.FeeBaseMSat)); err != nil { @@ -4710,7 +4741,12 @@ func serializeChanEdgePolicy(w io.Writer, edge *ChannelEdgePolicy, // TODO(halseth): clean up when moving to TLV. var opaqueBuf bytes.Buffer if edge.MessageFlags.HasMaxHtlc() { - err := binary.Write(&opaqueBuf, byteOrder, uint64(edge.MaxHTLC)) + err := binary.Write(&opaqueBuf, byteOrder, uint64(edge.MaxBtcHTLC)) + if err != nil { + return err + } + /*obd add wxf*/ + err = binary.Write(&opaqueBuf, byteOrder, uint64(edge.MaxAssetHTLC)) if err != nil { return err } @@ -4786,7 +4822,14 @@ func deserializeChanEdgePolicyRaw(r io.Reader) (*ChannelEdgePolicy, error) { if err := binary.Read(r, byteOrder, &n); err != nil { return nil, err } - edge.MinHTLC = lnwire.MilliSatoshi(n) + edge.MinBtcHTLC = lnwire.MilliSatoshi(n) + + /*obd add wxf*/ + var minAssetHtlc uint64 + if err := binary.Read(r, byteOrder, &minAssetHtlc); err != nil { + return nil, err + } + edge.MinAssetHTLC = omnicore.Amount(minAssetHtlc) if err := binary.Read(r, byteOrder, &n); err != nil { return nil, err @@ -4831,8 +4874,11 @@ func deserializeChanEdgePolicyRaw(r io.Reader) (*ChannelEdgePolicy, error) { return edge, ErrEdgePolicyOptionalFieldNotFound } - maxHtlc := byteOrder.Uint64(opq[:8]) - edge.MaxHTLC = lnwire.MilliSatoshi(maxHtlc) + /*obd update wxf*/ + maxBtcHtlc := byteOrder.Uint64(opq[:8]) + edge.MaxBtcHTLC = lnwire.MilliSatoshi(maxBtcHtlc) + maxAssetHtlc := byteOrder.Uint64(opq[8:16]) + edge.MaxAssetHTLC = omnicore.Amount(maxAssetHtlc) // Exclude the parsed field from the rest of the opaque data. edge.ExtraOpaqueData = opq[8:] diff --git a/channeldb/graph_cache.go b/channeldb/graph_cache.go index 2c3bc9024f..20dec2dd65 100644 --- a/channeldb/graph_cache.go +++ b/channeldb/graph_cache.go @@ -2,6 +2,7 @@ package channeldb import ( "fmt" + "github.com/lightningnetwork/lnd/lnwallet/omnicore" "sync" "github.com/btcsuite/btcutil" @@ -56,11 +57,16 @@ type CachedEdgePolicy struct { // MinHTLC is the smallest value HTLC this node will forward, expressed // in millisatoshi. - MinHTLC lnwire.MilliSatoshi + MinBtcHTLC lnwire.MilliSatoshi // MaxHTLC is the largest value HTLC this node will forward, expressed // in millisatoshi. - MaxHTLC lnwire.MilliSatoshi + MaxBtcHTLC lnwire.MilliSatoshi + /*obd add wxf + */ + MinAssetHTLC omnicore.Amount + MaxAssetHTLC omnicore.Amount + AssetId uint32 // FeeBaseMSat is the base HTLC fee that will be charged for forwarding // ANY HTLC, expressed in mSAT's. @@ -111,8 +117,11 @@ func NewCachedPolicy(policy *ChannelEdgePolicy) *CachedEdgePolicy { MessageFlags: policy.MessageFlags, ChannelFlags: policy.ChannelFlags, TimeLockDelta: policy.TimeLockDelta, - MinHTLC: policy.MinHTLC, - MaxHTLC: policy.MaxHTLC, + MinBtcHTLC: policy.MinBtcHTLC, + MaxBtcHTLC: policy.MaxBtcHTLC, + MinAssetHTLC:policy.MinAssetHTLC, + MaxAssetHTLC: policy.MaxAssetHTLC, + AssetId :policy.AssetId, FeeBaseMSat: policy.FeeBaseMSat, FeeProportionalMillionths: policy.FeeProportionalMillionths, } @@ -132,7 +141,10 @@ type DirectedChannel struct { OtherNode route.Vertex // Capacity is the announced capacity of this channel in satoshis. - Capacity btcutil.Amount + BtcCapacity btcutil.Amount + /*obd update wxf*/ + AssetCapacity omnicore.Amount + AssetId uint32 // OutPolicySet is a boolean that indicates whether the node has an // outgoing policy set. For pathfinding only the existence of the policy @@ -258,13 +270,19 @@ func (c *GraphCache) AddChannel(info *ChannelEdgeInfo, ChannelID: info.ChannelID, IsNode1: true, OtherNode: info.NodeKey2Bytes, - Capacity: info.Capacity, + /*obd update wxf*/ + BtcCapacity: info.BtcCapacity, + AssetCapacity: info.AssetCapacity, + AssetId: info.AssetId, }) c.updateOrAddEdge(info.NodeKey2Bytes, &DirectedChannel{ ChannelID: info.ChannelID, IsNode1: false, OtherNode: info.NodeKey1Bytes, - Capacity: info.Capacity, + /*obd update wxf*/ + BtcCapacity: info.BtcCapacity, + AssetCapacity: info.AssetCapacity, + AssetId: info.AssetId, }) c.mtx.Unlock() @@ -395,13 +413,17 @@ func (c *GraphCache) UpdateChannel(info *ChannelEdgeInfo) { if ok { // We only expect to be called when the channel is already // known. - channel.Capacity = info.Capacity + channel.BtcCapacity = info.BtcCapacity + channel.AssetCapacity = info.AssetCapacity + channel.AssetId = info.AssetId channel.OtherNode = info.NodeKey2Bytes } channel, ok = c.nodeChannels[info.NodeKey2Bytes][info.ChannelID] if ok { - channel.Capacity = info.Capacity + channel.BtcCapacity = info.BtcCapacity + channel.AssetCapacity = info.AssetCapacity + channel.AssetId = info.AssetId channel.OtherNode = info.NodeKey1Bytes } } diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 7ec7166f93..b0f6a7f21e 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -4,6 +4,7 @@ import ( "bytes" "errors" "fmt" + "github.com/lightningnetwork/lnd/lnwallet/omnicore" "sync" "time" @@ -70,7 +71,8 @@ var ( // can provide that serve useful when processing a specific network // announcement. type optionalMsgFields struct { - capacity *btcutil.Amount + btcCapacity *btcutil.Amount + AssetCapacity *omnicore.Amount channelPoint *wire.OutPoint } @@ -88,9 +90,17 @@ type OptionalMsgField func(*optionalMsgFields) // ChannelCapacity is an optional field that lets the gossiper know of the // capacity of a channel. -func ChannelCapacity(capacity btcutil.Amount) OptionalMsgField { +func ChannelBtcCapacity(capacity btcutil.Amount) OptionalMsgField { return func(f *optionalMsgFields) { - f.capacity = &capacity + f.btcCapacity = &capacity + } +} +/* +obd add wxf +*/ +func ChannelAssetCapacity(capacity omnicore.Amount) OptionalMsgField { + return func(f *optionalMsgFields) { + f.AssetCapacity = &capacity } } @@ -1394,12 +1404,13 @@ func (d *AuthenticatedGossiper) retransmitStaleAnns(now time.Time) error { // If this edge has a ChannelUpdate that was created before the // introduction of the MaxHTLC field, then we'll update this // edge to propagate this information in the network. + edge.AssetId = info.AssetId if !edge.MessageFlags.HasMaxHtlc() { // We'll make sure we support the new max_htlc field if // not already present. edge.MessageFlags |= lnwire.ChanUpdateOptionMaxHtlc - edge.MaxHTLC = lnwire.NewMSatFromSatoshis(info.Capacity) - + edge.MaxBtcHTLC = lnwire.NewMSatFromSatoshis(info.BtcCapacity) + edge.MaxAssetHTLC = info.AssetCapacity edgesToUpdate = append(edgesToUpdate, updateTuple{ info: info, edge: edge, @@ -1919,13 +1930,19 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement( AuthProof: proof, Features: featureBuf.Bytes(), ExtraOpaqueData: msg.ExtraOpaqueData, + /*obd add wxf*/ + AssetId: msg.AssetID, } // If there were any optional message fields provided, we'll // include them in its serialized disk representation now. if nMsg.optionalMsgFields != nil { - if nMsg.optionalMsgFields.capacity != nil { - edge.Capacity = *nMsg.optionalMsgFields.capacity + if nMsg.optionalMsgFields.btcCapacity != nil { + edge.BtcCapacity = *nMsg.optionalMsgFields.btcCapacity + } + /*obd add wxf*/ + if nMsg.optionalMsgFields.AssetCapacity != nil { + edge.AssetCapacity = *nMsg.optionalMsgFields.AssetCapacity } if nMsg.optionalMsgFields.channelPoint != nil { edge.ChannelPoint = *nMsg.optionalMsgFields.channelPoint @@ -2283,7 +2300,7 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement( // Validate the channel announcement with the expected public key and // channel capacity. In the case of an invalid channel update, we'll // return an error to the caller and exit early. - err = routing.ValidateChannelUpdateAnn(pubKey, chanInfo.Capacity, msg) + err = routing.ValidateChannelUpdateAnn(pubKey, chanInfo.BtcCapacity, msg) if err != nil { rErr := fmt.Errorf("unable to validate channel "+ "update announcement for short_chan_id=%v: %v", @@ -2301,8 +2318,12 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement( MessageFlags: msg.MessageFlags, ChannelFlags: msg.ChannelFlags, TimeLockDelta: msg.TimeLockDelta, - MinHTLC: msg.HtlcMinimumMsat, - MaxHTLC: msg.HtlcMaximumMsat, + MinBtcHTLC: msg.HtlcBtcMinimumMsat, + MaxBtcHTLC: msg.HtlcBtcMinimumMsat, + /*ob update wxf*/ + MinAssetHTLC: msg.HtlcAssetMinimum, + MaxAssetHTLC: msg.HtlcAssetMaximum, + AssetId: msg.AssetId, FeeBaseMSat: lnwire.MilliSatoshi(msg.BaseFee), FeeProportionalMillionths: lnwire.MilliSatoshi(msg.FeeRate), ExtraOpaqueData: msg.ExtraOpaqueData, @@ -2859,7 +2880,7 @@ func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo, // To ensure that our signature is valid, we'll verify it ourself // before committing it to the slice returned. - err = routing.ValidateChannelUpdateAnn(d.selfKey, info.Capacity, chanUpdate) + err = routing.ValidateChannelUpdateAnn(d.selfKey, info.BtcCapacity, chanUpdate) if err != nil { return nil, nil, fmt.Errorf("generated invalid channel "+ "update sig: %v", err) @@ -2951,13 +2972,20 @@ func IsKeepAliveUpdate(update *lnwire.ChannelUpdate, if update.TimeLockDelta != prev.TimeLockDelta { return false } - if update.HtlcMinimumMsat != prev.MinHTLC { + /*obd update wxf*/ + if update.HtlcBtcMinimumMsat != prev.MinBtcHTLC { + return false + } + if update.HtlcAssetMinimum != prev.MinAssetHTLC { return false } if update.MessageFlags.HasMaxHtlc() && !prev.MessageFlags.HasMaxHtlc() { return false } - if update.HtlcMaximumMsat != prev.MaxHTLC { + if update.HtlcBtcMaximumMsat != prev.MaxBtcHTLC { + return false + } + if update.HtlcAssetMaximum!= prev.MaxAssetHTLC { return false } if !bytes.Equal(update.ExtraOpaqueData, prev.ExtraOpaqueData) { diff --git a/funding/batch.go b/funding/batch.go index ec4eb744af..5f7012d3ad 100644 --- a/funding/batch.go +++ b/funding/batch.go @@ -51,10 +51,10 @@ func (c *batchChannel) processPsbtUpdate(u *lnrpc.OpenStatusUpdate) error { return fmt.Errorf("got unexpected channel update %v", u.Update) } - if psbtUpdate.FundingAmount != int64(c.fundingReq.LocalFundingAmt) { + if psbtUpdate.FundingAmount != int64(c.fundingReq.LocalFundingBtcAmt) { return fmt.Errorf("got unexpected funding amount %d, wanted "+ "%d", psbtUpdate.FundingAmount, - c.fundingReq.LocalFundingAmt) + c.fundingReq.LocalFundingBtcAmt) } c.fundingAddr = psbtUpdate.FundingAddress @@ -308,7 +308,7 @@ func (b *Batcher) BatchFund(ctx context.Context, } for _, channel := range b.channels { txTemplate.Outputs[channel.fundingAddr] = uint64( - channel.fundingReq.LocalFundingAmt, + channel.fundingReq.LocalFundingBtcAmt, ) } diff --git a/funding/batch_test.go b/funding/batch_test.go index 7b01ea95be..dd992eb764 100644 --- a/funding/batch_test.go +++ b/funding/batch_test.go @@ -108,8 +108,8 @@ func (h *testHarness) parseRequest( return &InitFundingMsg{ TargetPubkey: pubKey, - LocalFundingAmt: btcutil.Amount(in.LocalFundingAmount), - PushAmt: lnwire.NewMSatFromSatoshis( + LocalFundingBtcAmt: btcutil.Amount(in.LocalFundingAmount), + PushBtcAmt: lnwire.NewMSatFromSatoshis( btcutil.Amount(in.PushSat), ), FundingFeePerKw: chainfee.SatPerKVByte( @@ -138,7 +138,7 @@ func (h *testHarness) openChannel( } h.pendingTx.TxOut = append(h.pendingTx.TxOut, &wire.TxOut{ PkScript: []byte{1, 2, 3, byte(chanIndex)}, - Value: int64(req.LocalFundingAmt), + Value: int64(req.LocalFundingBtcAmt), }) if h.failUpdate1 { @@ -153,7 +153,7 @@ func (h *testHarness) openChannel( Update: &lnrpc.OpenStatusUpdate_PsbtFund{ PsbtFund: &lnrpc.ReadyForPsbtFunding{ FundingAmount: int64( - req.LocalFundingAmt, + req.LocalFundingBtcAmt, ), FundingAddress: fmt.Sprintf("foo%d", chanIndex), }, diff --git a/funding/manager.go b/funding/manager.go index a17b33e96d..ae3afeb75b 100644 --- a/funding/manager.go +++ b/funding/manager.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/binary" "fmt" + "github.com/lightningnetwork/lnd/lnwallet/omnicore" "io" "sync" "time" @@ -135,7 +136,9 @@ type reservationWithCtx struct { reservation *lnwallet.ChannelReservation peer lnpeer.Peer - chanAmt btcutil.Amount + chanBtcAmt btcutil.Amount + chanAssetAmt omnicore.Amount + assetId uint32 // Constraints we require for the remote. remoteCsvDelay uint16 @@ -194,10 +197,15 @@ type InitFundingMsg struct { SubtractFees bool // LocalFundingAmt is the size of the channel. - LocalFundingAmt btcutil.Amount + LocalFundingBtcAmt btcutil.Amount // PushAmt is the amount pushed to the counterparty. - PushAmt lnwire.MilliSatoshi + PushBtcAmt lnwire.MilliSatoshi + /*obd udpate wxf*/ + AssetId uint32 + PushAssetAmt omnicore.Amount + LocalFundingAssetAmt omnicore.Amount + // FundingFeePerKw is the fee for the funding transaction. FundingFeePerKw chainfee.SatPerKWeight @@ -795,7 +803,7 @@ func (f *Manager) failFundingFlow(peer lnpeer.Peer, tempChanID [32]byte, // For all other error types we just send a generic error. default: - msg = lnwire.ErrorData("funding failed due to internal error") + msg = lnwire.ErrorData("funding failed due to internal error:"+fundingErr.Error()) } errMsg := &lnwire.Error{ @@ -1063,13 +1071,22 @@ func (f *Manager) advancePendingChannelState( // maxWaitNumBlocksFundingConf and we are not the // channel initiator. ch := channel - localBalance := ch.LocalCommitment.LocalBalance.ToSatoshis() + /* + obd update wxf + */ + localBtcBalance := ch.LocalCommitment.LocalBtcBalance.ToSatoshis() + localAssetBalance := ch.LocalCommitment.LocalAssetBalance closeInfo := &channeldb.ChannelCloseSummary{ ChainHash: ch.ChainHash, ChanPoint: ch.FundingOutpoint, RemotePub: ch.IdentityPub, - Capacity: ch.Capacity, - SettledBalance: localBalance, + /* + obd update wxf + */ + BtcCapacity: ch.BtcCapacity, + AssetCapacity: ch.AssetCapacity, + SettledBtcBalance: localBtcBalance, + SettledAssetBalance: localAssetBalance, CloseType: channeldb.FundingCanceled, RemoteCurrentRevocation: ch.RemoteCurrentRevocation, RemoteNextRevocation: ch.RemoteNextRevocation, @@ -1159,7 +1176,9 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer, peerPubKey := peer.IdentityKey() peerIDKey := newSerializedKey(peerPubKey) - amt := msg.FundingAmount + btcAmt := msg.FundingBtcAmount + assetAmt := msg.FundingAssetAmount + assetId := msg.AssetId // We get all pending channels for this peer. This is the list of the // active reservations and the channels pending open in the database. @@ -1225,27 +1244,27 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer, } // Ensure that the remote party respects our maximum channel size. - if amt > f.cfg.MaxChanSize { + if btcAmt > f.cfg.MaxChanSize { f.failFundingFlow( peer, msg.PendingChannelID, - lnwallet.ErrChanTooLarge(amt, f.cfg.MaxChanSize), + lnwallet.ErrChanTooLarge(btcAmt, f.cfg.MaxChanSize), ) return } // We'll, also ensure that the remote party isn't attempting to propose // a channel that's below our current min channel size. - if amt < f.cfg.MinChanSize { + if btcAmt < f.cfg.MinChanSize { f.failFundingFlow( peer, msg.PendingChannelID, - lnwallet.ErrChanTooSmall(amt, btcutil.Amount(f.cfg.MinChanSize)), + lnwallet.ErrChanTooSmall(btcAmt, btcutil.Amount(f.cfg.MinChanSize)), ) return } // If request specifies non-zero push amount and 'rejectpush' is set, // signal an error. - if f.cfg.RejectPush && msg.PushAmount > 0 { + if f.cfg.RejectPush && msg.PushBtcAmount > 0 { f.failFundingFlow( peer, msg.PendingChannelID, lnwallet.ErrNonZeroPushAmount(), @@ -1272,9 +1291,13 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer, } log.Infof("Recv'd fundingRequest(amt=%v, push=%v, delay=%v, "+ - "pendingId=%x) from peer(%x)", amt, msg.PushAmount, + "pendingId=%x) from peer(%x)", btcAmt, msg.PushBtcAmount, msg.CsvDelay, msg.PendingChannelID, peer.IdentityKey().SerializeCompressed()) + if msg.AssetId>0{ + log.Infof("Recv'd fundingRequest(asset_id=%v asset_amt=%v, AssetPush=%v)", + msg.AssetId, assetAmt, msg.PushAssetAmount) + } // Attempt to initialize a reservation within the wallet. If the wallet // has insufficient resources to create the channel, then the @@ -1311,11 +1334,15 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer, PendingChanID: msg.PendingChannelID, NodeID: peer.IdentityKey(), NodeAddr: peer.Address(), - LocalFundingAmt: 0, - RemoteFundingAmt: amt, + LocalFundingBtcAmt: 0, + RemoteFundingBtcAmt: btcAmt, + LocalFundingAssetAmt :0, + RemoteFundingAssetAmt: assetAmt, + AssetId : assetId, CommitFeePerKw: chainfee.SatPerKWeight(msg.FeePerKiloWeight), FundingFeePerKw: 0, - PushMSat: msg.PushAmount, + PushMSat: msg.PushBtcAmount, + PushAsset: msg.PushAssetAmount, Flags: msg.ChannelFlags, MinConfs: 1, CommitType: commitType, @@ -1334,7 +1361,7 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer, // the amount of the channel, and also if any funds are being pushed to // us. If a depth value was set by our channel acceptor, we will use // that value instead. - numConfsReq := f.cfg.NumRequiredConfs(msg.FundingAmount, msg.PushAmount) + numConfsReq := f.cfg.NumRequiredConfs(msg.FundingBtcAmount, msg.PushBtcAmount) if acceptorResp.MinAcceptDepth != 0 { numConfsReq = acceptorResp.MinAcceptDepth } @@ -1409,12 +1436,16 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer, log.Infof("Requiring %v confirmations for pendingChan(%x): "+ "amt=%v, push_amt=%v, committype=%v, upfrontShutdown=%x", numConfsReq, - msg.PendingChannelID, amt, msg.PushAmount, + msg.PendingChannelID, btcAmt, msg.PushBtcAmount, commitType, msg.UpfrontShutdownScript) + if msg.AssetId>0{ + log.Infof("Requiring pendingChan(%x) Asset: "+ + "amt=%v, push_amt=%v", msg.PendingChannelID, assetAmt, msg.PushAssetAmount) + } // Generate our required constraints for the remote party, using the // values provided by the channel acceptor if they are non-zero. - remoteCsvDelay := f.cfg.RequiredRemoteDelay(amt) + remoteCsvDelay := f.cfg.RequiredRemoteDelay(btcAmt) if acceptorResp.CSVDelay != 0 { remoteCsvDelay = acceptorResp.CSVDelay } @@ -1431,17 +1462,17 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer, maxDustLimit = msg.DustLimit } - chanReserve := f.cfg.RequiredRemoteChanReserve(amt, maxDustLimit) + chanReserve := f.cfg.RequiredRemoteChanReserve(btcAmt, maxDustLimit) if acceptorResp.Reserve != 0 { chanReserve = acceptorResp.Reserve } - remoteMaxValue := f.cfg.RequiredRemoteMaxValue(amt) + remoteMaxValue := f.cfg.RequiredRemoteMaxValue(btcAmt) if acceptorResp.InFlightTotal != 0 { remoteMaxValue = acceptorResp.InFlightTotal } - maxHtlcs := f.cfg.RequiredRemoteMaxHTLCs(amt) + maxHtlcs := f.cfg.RequiredRemoteMaxHTLCs(btcAmt) if acceptorResp.HtlcLimit != 0 { maxHtlcs = acceptorResp.HtlcLimit } @@ -1462,7 +1493,9 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer, } resCtx := &reservationWithCtx{ reservation: reservation, - chanAmt: amt, + chanBtcAmt: btcAmt, + chanAssetAmt: assetAmt, + assetId: assetId, remoteCsvDelay: remoteCsvDelay, remoteMinHtlc: minHtlc, remoteMaxValue: remoteMaxValue, @@ -1481,7 +1514,9 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer, // With our parameters set, we'll now process their contribution so we // can move the funding workflow ahead. remoteContribution := &lnwallet.ChannelContribution{ - FundingAmount: amt, + FundingBtcAmount: btcAmt , + FundingAssetAmount: assetAmt, + AssetId: assetId, FirstCommitmentPoint: msg.FirstCommitmentPoint, ChannelConfig: &channeldb.ChannelConfig{ ChannelConstraints: channeldb.ChannelConstraints{ @@ -1678,7 +1713,7 @@ func (f *Manager) handleFundingAccept(peer lnpeer.Peer, // reservation. Also make sure that we re-generate the ChannelReserve // with our dust limit or we can get stuck channels. chanReserve := f.cfg.RequiredRemoteChanReserve( - resCtx.chanAmt, resCtx.reservation.OurContribution().DustLimit, + resCtx.chanBtcAmt, resCtx.reservation.OurContribution().DustLimit, ) // The remote node has responded with their portion of the channel @@ -1962,14 +1997,23 @@ func (f *Manager) handleFundingCreated(peer lnpeer.Peer, // we use this convenience method to delete the pending OpenChannel // from the database. deleteFromDatabase := func() { - localBalance := completeChan.LocalCommitment.LocalBalance.ToSatoshis() + /* + obd update wxf + */ + localBtcBalance := completeChan.LocalCommitment.LocalBtcBalance.ToSatoshis() + localAssetBalance := completeChan.LocalCommitment.LocalAssetBalance closeInfo := &channeldb.ChannelCloseSummary{ ChanPoint: completeChan.FundingOutpoint, ChainHash: completeChan.ChainHash, RemotePub: completeChan.IdentityPub, CloseType: channeldb.FundingCanceled, - Capacity: completeChan.Capacity, - SettledBalance: localBalance, + /* + obd update wxf + */ + BtcCapacity: completeChan.BtcCapacity, + SettledBtcBalance: localBtcBalance, + AssetCapacity: completeChan.AssetCapacity, + SettledAssetBalance: localAssetBalance, RemoteCurrentRevocation: completeChan.RemoteCurrentRevocation, RemoteNextRevocation: completeChan.RemoteNextRevocation, LocalChanConfig: completeChan.LocalChanCfg, @@ -2607,7 +2651,11 @@ func (f *Manager) addToRouterGraph(completeChan *channeldb.OpenChannel, // we'll use this value within our ChannelUpdate. This value must be <= // channel capacity and <= the maximum in-flight msats set by the peer. fwdMaxHTLC := completeChan.LocalChanCfg.MaxPendingAmount - capacityMSat := lnwire.NewMSatFromSatoshis(completeChan.Capacity) + /* + obd update wxf + */ + capacityMSat := lnwire.NewMSatFromSatoshis(completeChan.BtcCapacity) + capacityAsset := completeChan.AssetCapacity if fwdMaxHTLC > capacityMSat { fwdMaxHTLC = capacityMSat } @@ -2616,17 +2664,22 @@ func (f *Manager) addToRouterGraph(completeChan *channeldb.OpenChannel, f.cfg.IDKey, completeChan.IdentityPub, &completeChan.LocalChanCfg.MultiSigKey, completeChan.RemoteChanCfg.MultiSigKey.PubKey, *shortChanID, - chanID, fwdMinHTLC, fwdMaxHTLC, + chanID, fwdMinHTLC, fwdMaxHTLC,0, + capacityAsset,completeChan.AssetID, ) if err != nil { return fmt.Errorf("error generating channel "+ "announcement: %v", err) } + /* + obd update wxf + */ // Send ChannelAnnouncement and ChannelUpdate to the gossiper to add // to the Router's topology. errChan := f.cfg.SendAnnouncement( - ann.chanAnn, discovery.ChannelCapacity(completeChan.Capacity), + ann.chanAnn, discovery.ChannelBtcCapacity(completeChan.BtcCapacity), + discovery.ChannelAssetCapacity(completeChan.AssetCapacity), discovery.ChannelPoint(completeChan.FundingOutpoint), ) select { @@ -2779,7 +2832,7 @@ func (f *Manager) annAfterSixConfs(completeChan *channeldb.OpenChannel, f.cfg.IDKey, completeChan.IdentityPub, &completeChan.LocalChanCfg.MultiSigKey, completeChan.RemoteChanCfg.MultiSigKey.PubKey, - *shortChanID, chanID, + *shortChanID, chanID,completeChan.AssetID, ) if err != nil { return fmt.Errorf("channel announcement failed: %v", err) @@ -2920,8 +2973,9 @@ type chanAnnouncement struct { func (f *Manager) newChanAnnouncement(localPubKey, remotePubKey *btcec.PublicKey, localFundingKey *keychain.KeyDescriptor, remoteFundingKey *btcec.PublicKey, shortChanID lnwire.ShortChannelID, - chanID lnwire.ChannelID, fwdMinHTLC, - fwdMaxHTLC lnwire.MilliSatoshi) (*chanAnnouncement, error) { + chanID lnwire.ChannelID, fwdMinBtcHTLC, + fwdMaxBtcHTLC lnwire.MilliSatoshi, fwdMinAssetHTLC, + fwdMaxAssetHTLC omnicore.Amount,assetId uint32,) (*chanAnnouncement, error) { chainHash := *f.cfg.Wallet.Cfg.NetParams.GenesisHash @@ -2932,6 +2986,10 @@ func (f *Manager) newChanAnnouncement(localPubKey, ShortChannelID: shortChanID, Features: lnwire.NewRawFeatureVector(), ChainHash: chainHash, + /* + obd add wxf + */ + AssetID: assetId, } // The chanFlags field indicates which directed edge of the channel is @@ -2983,11 +3041,18 @@ func (f *Manager) newChanAnnouncement(localPubKey, // We use the HtlcMinimumMsat that the remote party required us // to use, as our ChannelUpdate will be used to carry HTLCs // towards them. - HtlcMinimumMsat: fwdMinHTLC, - HtlcMaximumMsat: fwdMaxHTLC, + /* + obd update wxf + */ + HtlcBtcMinimumMsat: fwdMinBtcHTLC, + HtlcBtcMaximumMsat: fwdMaxBtcHTLC, + HtlcAssetMinimum: fwdMinAssetHTLC, + HtlcAssetMaximum: fwdMaxAssetHTLC, + AssetId: assetId, BaseFee: uint32(f.cfg.DefaultRoutingPolicy.BaseFee), FeeRate: uint32(f.cfg.DefaultRoutingPolicy.FeeRate), + } // With the channel update announcement constructed, we'll generate a @@ -3066,7 +3131,7 @@ func (f *Manager) newChanAnnouncement(localPubKey, func (f *Manager) announceChannel(localIDKey, remoteIDKey *btcec.PublicKey, localFundingKey *keychain.KeyDescriptor, remoteFundingKey *btcec.PublicKey, shortChanID lnwire.ShortChannelID, - chanID lnwire.ChannelID) error { + chanID lnwire.ChannelID,assetId uint32) error { // First, we'll create the batch of announcements to be sent upon // initial channel creation. This includes the channel announcement @@ -3077,7 +3142,7 @@ func (f *Manager) announceChannel(localIDKey, remoteIDKey *btcec.PublicKey, // only use the channel announcement message from the returned struct. ann, err := f.newChanAnnouncement(localIDKey, remoteIDKey, localFundingKey, remoteFundingKey, shortChanID, chanID, - 0, 0, + 0, 0,0,0,assetId, ) if err != nil { log.Errorf("can't generate channel announcement: %v", err) @@ -3196,7 +3261,10 @@ func getUpfrontShutdownScript(enableUpfrontShutdown bool, peer lnpeer.Peer, func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) { var ( peerKey = msg.Peer.IdentityKey() - localAmt = msg.LocalFundingAmt + localBtcAmt = msg.LocalFundingBtcAmt + /*obd update wxf*/ + localAssetAmt = msg.LocalFundingAssetAmt + assetId = msg.AssetId minHtlcIn = msg.MinHtlcIn remoteCsvDelay = msg.RemoteCsvDelay maxValue = msg.MaxValueInFlight @@ -3210,11 +3278,15 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) { maxCSV = f.cfg.MaxLocalCSVDelay } + /*obd update wxf*/ log.Infof("Initiating fundingRequest(local_amt=%v "+ "(subtract_fees=%v), push_amt=%v, chain_hash=%v, peer=%x, "+ - "min_confs=%v)", localAmt, msg.SubtractFees, msg.PushAmt, + "min_confs=%v)", localBtcAmt, msg.SubtractFees, msg.PushBtcAmt, msg.ChainHash, peerKey.SerializeCompressed(), msg.MinConfs) - + if assetId>0 { + log.Infof("Initiating fundingRequest(asset_id=%v local_asset_amt=%v push_asset_amt=%v)", + assetId, localAssetAmt, msg.PushAssetAmt) + } // We set the channel flags to indicate whether we want this channel to // be announced to the network. var channelFlags lnwire.FundingFlag @@ -3304,11 +3376,14 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) { NodeID: peerKey, NodeAddr: msg.Peer.Address(), SubtractFees: msg.SubtractFees, - LocalFundingAmt: localAmt, - RemoteFundingAmt: 0, + LocalFundingBtcAmt: localBtcAmt, + RemoteFundingBtcAmt: 0, + LocalFundingAssetAmt: localAssetAmt, + RemoteFundingAssetAmt: 0, + AssetId: msg.AssetId, CommitFeePerKw: commitFeePerKw, FundingFeePerKw: msg.FundingFeePerKw, - PushMSat: msg.PushAmt, + PushMSat: msg.PushBtcAmt, Flags: channelFlags, MinConfs: msg.MinConfs, CommitType: commitType, @@ -3328,7 +3403,8 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) { // wallet, we can fetch the final channel capacity. This is done at // this point since the final capacity might change in case of // SubtractFees=true. - capacity := reservation.Capacity() + btcCapacity := reservation.BtcCapacity() + assetCapacity := reservation.AssetCapacity() log.Infof("Target commit tx sat/kw for pendingID(%x): %v", chanID, int64(commitFeePerKw)) @@ -3337,7 +3413,7 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) { // we'll use the RequiredRemoteDelay closure to compute the delay we // require given the total amount of funds within the channel. if remoteCsvDelay == 0 { - remoteCsvDelay = f.cfg.RequiredRemoteDelay(capacity) + remoteCsvDelay = f.cfg.RequiredRemoteDelay(btcCapacity) } // If no minimum HTLC value was specified, use the default one. @@ -3347,11 +3423,11 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) { // If no max value was specified, use the default one. if maxValue == 0 { - maxValue = f.cfg.RequiredRemoteMaxValue(capacity) + maxValue = f.cfg.RequiredRemoteMaxValue(btcCapacity) } if maxHtlcs == 0 { - maxHtlcs = f.cfg.RequiredRemoteMaxHTLCs(capacity) + maxHtlcs = f.cfg.RequiredRemoteMaxHTLCs(btcCapacity) } // If a pending channel map for this peer isn't already created, then @@ -3364,7 +3440,10 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) { } resCtx := &reservationWithCtx{ - chanAmt: capacity, + /*obd update wxf*/ + chanBtcAmt: btcCapacity, + chanAssetAmt: assetCapacity, + assetId: msg.AssetId, remoteCsvDelay: remoteCsvDelay, remoteMinHtlc: minHtlcIn, remoteMaxValue: maxValue, @@ -3395,7 +3474,7 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) { // Finally, we'll use the current value of the channels and our default // policy to determine of required commitment constraints for the // remote party. - chanReserve := f.cfg.RequiredRemoteChanReserve(capacity, ourDustLimit) + chanReserve := f.cfg.RequiredRemoteChanReserve(btcCapacity, ourDustLimit) // When opening a script enforced channel lease, include the required // expiry TLV record in our proposal. @@ -3411,8 +3490,12 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) { fundingOpen := lnwire.OpenChannel{ ChainHash: *f.cfg.Wallet.Cfg.NetParams.GenesisHash, PendingChannelID: chanID, - FundingAmount: capacity, - PushAmount: msg.PushAmt, + FundingBtcAmount: btcCapacity, + PushBtcAmount: msg.PushBtcAmt, + /*obd add wxf*/ + FundingAssetAmount: assetCapacity, + PushAssetAmount: msg.PushAssetAmt, + AssetId: msg.AssetId, DustLimit: ourDustLimit, MaxValueInFlight: maxValue, ChannelReserve: chanReserve, diff --git a/funding/manager_test.go b/funding/manager_test.go index bfd47329fc..e1a8852e79 100644 --- a/funding/manager_test.go +++ b/funding/manager_test.go @@ -7,6 +7,7 @@ import ( "bytes" "errors" "fmt" + "github.com/lightningnetwork/lnd/lnwallet/omnicore" "io/ioutil" "math/big" "net" @@ -646,12 +647,14 @@ func tearDownFundingManagers(t *testing.T, a, b *testNode) { // transaction is confirmed on-chain. Returns the funding out point. func openChannel(t *testing.T, alice, bob *testNode, localFundingAmt, pushAmt btcutil.Amount, numConfs uint32, - updateChan chan *lnrpc.OpenStatusUpdate, announceChan bool) ( + updateChan chan *lnrpc.OpenStatusUpdate, announceChan bool, + localFundingAssetAmt, + pushAssetAmt omnicore.Amount ,assetId uint32) ( *wire.OutPoint, *wire.MsgTx) { publ := fundChannel( t, alice, bob, localFundingAmt, pushAmt, false, numConfs, - updateChan, announceChan, + updateChan, announceChan,localFundingAssetAmt,pushAssetAmt,assetId, ) fundingOutPoint := &wire.OutPoint{ Hash: publ.TxHash(), @@ -664,7 +667,8 @@ func openChannel(t *testing.T, alice, bob *testNode, localFundingAmt, // transaction is confirmed on-chain. Returns the funding tx. func fundChannel(t *testing.T, alice, bob *testNode, localFundingAmt, pushAmt btcutil.Amount, subtractFees bool, numConfs uint32, - updateChan chan *lnrpc.OpenStatusUpdate, announceChan bool) *wire.MsgTx { + updateChan chan *lnrpc.OpenStatusUpdate, announceChan bool,localFundingAssetAmt, + pushAssetAmt omnicore.Amount ,assetId uint32) *wire.MsgTx { // Create a funding request and start the workflow. errChan := make(chan error, 1) @@ -673,8 +677,11 @@ func fundChannel(t *testing.T, alice, bob *testNode, localFundingAmt, TargetPubkey: bob.privKey.PubKey(), ChainHash: *fundingNetParams.GenesisHash, SubtractFees: subtractFees, - LocalFundingAmt: localFundingAmt, - PushAmt: lnwire.NewMSatFromSatoshis(pushAmt), + LocalFundingBtcAmt: localFundingAmt, + PushBtcAmt: lnwire.NewMSatFromSatoshis(pushAmt), + LocalFundingAssetAmt: localFundingAssetAmt, + PushAssetAmt: pushAssetAmt, + AssetId: assetId, FundingFeePerKw: 1000, Private: !announceChan, Updates: updateChan, @@ -814,7 +821,7 @@ func assertFundingMsgSent(t *testing.T, msgChan chan lnwire.Message, var msg lnwire.Message select { case msg = <-msgChan: - case <-time.After(time.Second * 5): + case <-time.After(time.Second * 15): t.Fatalf("peer did not send %s message", msgType) } @@ -1042,10 +1049,10 @@ func assertChannelAnnouncements(t *testing.T, alice, bob *testNode, minHtlc = customMinHtlc[j] } - if m.HtlcMinimumMsat != minHtlc { + if m.HtlcBtcMinimumMsat != minHtlc { t.Fatalf("expected ChannelUpdate to "+ "advertise min HTLC %v, had %v", - minHtlc, m.HtlcMinimumMsat) + minHtlc, m.HtlcBtcMinimumMsat) } maxHtlc := alice.fundingMgr.cfg.RequiredRemoteMaxValue( @@ -1066,11 +1073,11 @@ func assertChannelAnnouncements(t *testing.T, alice, bob *testNode, "be 1, was %v", m.MessageFlags) } - if maxHtlc != m.HtlcMaximumMsat { + if maxHtlc != m.HtlcBtcMaximumMsat { t.Fatalf("expected ChannelUpdate to "+ "advertise max HTLC %v, had %v", maxHtlc, - m.HtlcMaximumMsat) + m.HtlcBtcMaximumMsat) } gotChannelUpdate = true @@ -1217,9 +1224,13 @@ func TestFundingManagerNormalWorkflow(t *testing.T) { // transaction is broadcasted. localAmt := btcutil.Amount(500000) pushAmt := btcutil.Amount(0) + localAssetAmt := omnicore.Amount(500000) + pushAssetAmt := omnicore.Amount(0) + assetId:=uint32(31) capacity := localAmt + pushAmt fundingOutPoint, fundingTx := openChannel( t, alice, bob, localAmt, pushAmt, 1, updateChan, true, + localAssetAmt,pushAssetAmt,assetId, ) // Check that neither Alice nor Bob sent an error message. @@ -1333,7 +1344,7 @@ func testLocalCSVLimit(t *testing.T, aliceMaxCSV, bobRequiredCSV uint16) { Peer: bob, TargetPubkey: bob.privKey.PubKey(), ChainHash: *fundingNetParams.GenesisHash, - LocalFundingAmt: 200000, + LocalFundingBtcAmt: 200000, FundingFeePerKw: 1000, Updates: updateChan, Err: errChan, @@ -1399,7 +1410,7 @@ func testLocalCSVLimit(t *testing.T, aliceMaxCSV, bobRequiredCSV uint16) { Peer: alice, TargetPubkey: alice.privKey.PubKey(), ChainHash: *fundingNetParams.GenesisHash, - LocalFundingAmt: 200000, + LocalFundingBtcAmt: 200000, FundingFeePerKw: 1000, Updates: updateChan, Err: errChan, @@ -1453,10 +1464,13 @@ func TestFundingManagerRestartBehavior(t *testing.T) { // transaction is broadcasted. localAmt := btcutil.Amount(500000) pushAmt := btcutil.Amount(0) + localAssetAmt := omnicore.Amount(500000) + pushAssetAmt := omnicore.Amount(0) capacity := localAmt + pushAmt updateChan := make(chan *lnrpc.OpenStatusUpdate) fundingOutPoint, fundingTx := openChannel( t, alice, bob, localAmt, pushAmt, 1, updateChan, true, + localAssetAmt,pushAssetAmt, 31, ) // After the funding transaction gets mined, both nodes will send the @@ -1602,10 +1616,13 @@ func TestFundingManagerOfflinePeer(t *testing.T) { // transaction is broadcasted. localAmt := btcutil.Amount(500000) pushAmt := btcutil.Amount(0) + localAssetAmt := omnicore.Amount(500000) + pushAssetAmt := omnicore.Amount(0) capacity := localAmt + pushAmt updateChan := make(chan *lnrpc.OpenStatusUpdate) fundingOutPoint, fundingTx := openChannel( t, alice, bob, localAmt, pushAmt, 1, updateChan, true, + localAssetAmt,pushAssetAmt,31, ) // After the funding transaction gets mined, both nodes will send the @@ -1752,8 +1769,8 @@ func TestFundingManagerPeerTimeoutAfterInitFunding(t *testing.T) { Peer: bob, TargetPubkey: bob.privKey.PubKey(), ChainHash: *fundingNetParams.GenesisHash, - LocalFundingAmt: 500000, - PushAmt: lnwire.NewMSatFromSatoshis(0), + LocalFundingBtcAmt: 500000, + PushBtcAmt: lnwire.NewMSatFromSatoshis(0), Private: false, Updates: updateChan, Err: errChan, @@ -1815,8 +1832,8 @@ func TestFundingManagerPeerTimeoutAfterFundingOpen(t *testing.T) { Peer: bob, TargetPubkey: bob.privKey.PubKey(), ChainHash: *fundingNetParams.GenesisHash, - LocalFundingAmt: 500000, - PushAmt: lnwire.NewMSatFromSatoshis(0), + LocalFundingBtcAmt: 500000, + PushBtcAmt: lnwire.NewMSatFromSatoshis(0), Private: false, Updates: updateChan, Err: errChan, @@ -1887,8 +1904,8 @@ func TestFundingManagerPeerTimeoutAfterFundingAccept(t *testing.T) { Peer: bob, TargetPubkey: bob.privKey.PubKey(), ChainHash: *fundingNetParams.GenesisHash, - LocalFundingAmt: 500000, - PushAmt: lnwire.NewMSatFromSatoshis(0), + LocalFundingBtcAmt: 500000, + PushBtcAmt: lnwire.NewMSatFromSatoshis(0), Private: false, Updates: updateChan, Err: errChan, @@ -1960,7 +1977,8 @@ func TestFundingManagerFundingTimeout(t *testing.T) { // Run through the process of opening the channel, up until the funding // transaction is broadcasted. - _, _ = openChannel(t, alice, bob, 500000, 0, 1, updateChan, true) + _, _ = openChannel(t, alice, bob, 500000, 0, 1, updateChan, true, + 0,0,0,) // Bob will at this point be waiting for the funding transaction to be // confirmed, so the channel should be considered pending. @@ -2006,7 +2024,8 @@ func TestFundingManagerFundingNotTimeoutInitiator(t *testing.T) { // Run through the process of opening the channel, up until the funding // transaction is broadcasted. - _, _ = openChannel(t, alice, bob, 500000, 0, 1, updateChan, true) + _, _ = openChannel(t, alice, bob, 500000, 0, 1, updateChan, true, + 0,0,0) // Alice will at this point be waiting for the funding transaction to be // confirmed, so the channel should be considered pending. @@ -2080,6 +2099,7 @@ func TestFundingManagerReceiveFundingLockedTwice(t *testing.T) { capacity := localAmt + pushAmt fundingOutPoint, fundingTx := openChannel( t, alice, bob, localAmt, pushAmt, 1, updateChan, true, + 0,0,0, ) // Notify that transaction was mined @@ -2183,6 +2203,7 @@ func TestFundingManagerRestartAfterChanAnn(t *testing.T) { capacity := localAmt + pushAmt fundingOutPoint, fundingTx := openChannel( t, alice, bob, localAmt, pushAmt, 1, updateChan, true, + 0,0,0, ) // Notify that transaction was mined @@ -2271,6 +2292,7 @@ func TestFundingManagerRestartAfterReceivingFundingLocked(t *testing.T) { capacity := localAmt + pushAmt fundingOutPoint, fundingTx := openChannel( t, alice, bob, localAmt, pushAmt, 1, updateChan, true, + 0,0,0, ) // Notify that transaction was mined @@ -2355,6 +2377,7 @@ func TestFundingManagerPrivateChannel(t *testing.T) { capacity := localAmt + pushAmt fundingOutPoint, fundingTx := openChannel( t, alice, bob, localAmt, pushAmt, 1, updateChan, false, + 0,0,0, ) // Notify that transaction was mined @@ -2468,6 +2491,7 @@ func TestFundingManagerPrivateRestart(t *testing.T) { capacity := localAmt + pushAmt fundingOutPoint, fundingTx := openChannel( t, alice, bob, localAmt, pushAmt, 1, updateChan, false, + 0,0,0, ) // Notify that transaction was mined @@ -2612,8 +2636,8 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { Peer: bob, TargetPubkey: bob.privKey.PubKey(), ChainHash: *fundingNetParams.GenesisHash, - LocalFundingAmt: localAmt, - PushAmt: lnwire.NewMSatFromSatoshis(pushAmt), + LocalFundingBtcAmt: localAmt, + PushBtcAmt: lnwire.NewMSatFromSatoshis(pushAmt), Private: false, MaxValueInFlight: maxValueInFlight, MinHtlcIn: minHtlcIn, @@ -2898,8 +2922,8 @@ func TestFundingManagerMaxPendingChannels(t *testing.T) { Peer: bob, TargetPubkey: bob.privKey.PubKey(), ChainHash: *fundingNetParams.GenesisHash, - LocalFundingAmt: 5000000, - PushAmt: lnwire.NewMSatFromSatoshis(0), + LocalFundingBtcAmt: 5000000, + PushBtcAmt: lnwire.NewMSatFromSatoshis(0), Private: false, Updates: updateChan, Err: errChan, @@ -3069,8 +3093,8 @@ func TestFundingManagerRejectPush(t *testing.T) { Peer: bob, TargetPubkey: bob.privKey.PubKey(), ChainHash: *fundingNetParams.GenesisHash, - LocalFundingAmt: 500000, - PushAmt: lnwire.NewMSatFromSatoshis(10), + LocalFundingBtcAmt: 500000, + PushBtcAmt: lnwire.NewMSatFromSatoshis(10), Private: true, Updates: updateChan, Err: errChan, @@ -3127,8 +3151,8 @@ func TestFundingManagerMaxConfs(t *testing.T) { Peer: bob, TargetPubkey: bob.privKey.PubKey(), ChainHash: *fundingNetParams.GenesisHash, - LocalFundingAmt: 500000, - PushAmt: lnwire.NewMSatFromSatoshis(10), + LocalFundingBtcAmt: 500000, + PushBtcAmt: lnwire.NewMSatFromSatoshis(10), Private: false, Updates: updateChan, Err: errChan, @@ -3250,7 +3274,7 @@ func TestFundingManagerFundAll(t *testing.T) { pushAmt := btcutil.Amount(0) fundingTx := fundChannel( t, alice, bob, test.spendAmt, pushAmt, true, 1, - updateChan, true, + updateChan, true,0,0,0, ) // Check whether the expected change output is present. @@ -3410,8 +3434,8 @@ func TestMaxChannelSizeConfig(t *testing.T) { Peer: bob, TargetPubkey: bob.privKey.PubKey(), ChainHash: *fundingNetParams.GenesisHash, - LocalFundingAmt: MaxBtcFundingAmount, - PushAmt: lnwire.NewMSatFromSatoshis(0), + LocalFundingBtcAmt: MaxBtcFundingAmount, + PushBtcAmt: lnwire.NewMSatFromSatoshis(0), Private: false, Updates: updateChan, Err: errChan, @@ -3456,7 +3480,7 @@ func TestMaxChannelSizeConfig(t *testing.T) { // Attempt to create a channel above the limit // imposed by --maxchansize, which should be rejected. - initReq.LocalFundingAmt = btcutil.SatoshiPerBitcoin + 1 + initReq.LocalFundingBtcAmt = btcutil.SatoshiPerBitcoin + 1 // After processing the funding open message, bob should respond with // an error rejecting the channel that exceeds size limit. @@ -3486,8 +3510,8 @@ func TestWumboChannelConfig(t *testing.T) { Peer: bob, TargetPubkey: bob.privKey.PubKey(), ChainHash: *fundingNetParams.GenesisHash, - LocalFundingAmt: MaxBtcFundingAmount, - PushAmt: lnwire.NewMSatFromSatoshis(0), + LocalFundingBtcAmt: MaxBtcFundingAmount, + PushBtcAmt: lnwire.NewMSatFromSatoshis(0), Private: false, Updates: updateChan, Err: errChan, @@ -3501,7 +3525,7 @@ func TestWumboChannelConfig(t *testing.T) { // We'll now attempt to create a channel above the wumbo mark, which // should be rejected. - initReq.LocalFundingAmt = btcutil.SatoshiPerBitcoin + initReq.LocalFundingBtcAmt = btcutil.SatoshiPerBitcoin // After processing the funding open message, bob should respond with // an error rejecting the channel. @@ -3636,8 +3660,8 @@ func testUpfrontFailure(t *testing.T, pkscript []byte, expectErr bool) { TargetPubkey: alice.privKey.PubKey(), ChainHash: *fundingNetParams.GenesisHash, SubtractFees: false, - LocalFundingAmt: fundingAmt, - PushAmt: pushAmt, + LocalFundingBtcAmt: fundingAmt, + PushBtcAmt: pushAmt, FundingFeePerKw: 1000, Private: false, Updates: updateChan, diff --git a/htlcswitch/circuit.go b/htlcswitch/circuit.go index 16b48c2947..37fe2011cd 100644 --- a/htlcswitch/circuit.go +++ b/htlcswitch/circuit.go @@ -2,6 +2,7 @@ package htlcswitch import ( "encoding/binary" + "github.com/lightningnetwork/lnd/lnwallet/omnicore" "io" "github.com/lightningnetwork/lnd/channeldb" @@ -50,6 +51,11 @@ type PaymentCircuit struct { // either as a payment or forwarded amount. OutgoingAmount lnwire.MilliSatoshi + /*obd add wxf*/ + IncomingAssetAmount omnicore.Amount + OutgoingAssetAmount omnicore.Amount + AssetId uint32 + // ErrorEncrypter is used to re-encrypt the onion failure before // sending it back to the originator of the payment. ErrorEncrypter hop.ErrorEncrypter @@ -84,7 +90,10 @@ func newPaymentCircuit(hash *[32]byte, pkt *htlcPacket) *PaymentCircuit { }, PaymentHash: *hash, IncomingAmount: pkt.incomingAmount, - OutgoingAmount: pkt.amount, + IncomingAssetAmount: pkt.incomingAssetAmount, + OutgoingAmount: pkt.btcAmount, + OutgoingAssetAmount: pkt.assetAmount, + AssetId: pkt.assetId, ErrorEncrypter: pkt.obfuscator, } } @@ -105,7 +114,10 @@ func makePaymentCircuit(hash *[32]byte, pkt *htlcPacket) PaymentCircuit { }, PaymentHash: *hash, IncomingAmount: pkt.incomingAmount, - OutgoingAmount: pkt.amount, + OutgoingAmount: pkt.btcAmount, + IncomingAssetAmount: pkt.incomingAssetAmount, + OutgoingAssetAmount: pkt.assetAmount, + AssetId: pkt.assetId, ErrorEncrypter: pkt.obfuscator, } } diff --git a/htlcswitch/htlcnotifier.go b/htlcswitch/htlcnotifier.go index fd067e2b48..fa8e3e4952 100644 --- a/htlcswitch/htlcnotifier.go +++ b/htlcswitch/htlcnotifier.go @@ -2,6 +2,7 @@ package htlcswitch import ( "fmt" + "github.com/lightningnetwork/lnd/lnwallet/omnicore" "strings" "sync" "time" @@ -145,6 +146,13 @@ type HtlcInfo struct { // OutgoingAmt is the amount of the htlc on our outgoing channel. OutgoingAmt lnwire.MilliSatoshi + + /*obd add wxf*/ + IncomingAssetAmt omnicore.Amount + OutgoingAssetAmt omnicore.Amount + AssetId uint32 + + } // String returns a string representation of a htlc. @@ -417,7 +425,10 @@ func newHtlcInfo(pkt *htlcPacket) HtlcInfo { IncomingTimeLock: pkt.incomingTimeout, OutgoingTimeLock: pkt.outgoingTimeout, IncomingAmt: pkt.incomingAmount, - OutgoingAmt: pkt.amount, + OutgoingAmt: pkt.btcAmount, + IncomingAssetAmt: pkt.incomingAssetAmount, + OutgoingAssetAmt: pkt.assetAmount, + AssetId: pkt.assetId, } } diff --git a/htlcswitch/link.go b/htlcswitch/link.go index acbf277d12..d574008242 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -4,6 +4,7 @@ import ( "bytes" "crypto/sha256" "fmt" + "github.com/lightningnetwork/lnd/lnwallet/omnicore" prand "math/rand" "sync" "sync/atomic" @@ -2244,25 +2245,25 @@ func (l *channelLink) getDustClosure() dustClosure { // the HTLC is incoming (i.e. one that the remote sent), a boolean denoting // whether to evaluate on the local or remote commit, and finally an HTLC // amount to test. -type dustClosure func(chainfee.SatPerKWeight, bool, bool, btcutil.Amount) bool +type dustClosure func(chainfee.SatPerKWeight, bool, bool, btcutil.Amount,omnicore.Amount) bool // dustHelper is used to construct the dustClosure. func dustHelper(chantype channeldb.ChannelType, localDustLimit, remoteDustLimit btcutil.Amount) dustClosure { isDust := func(feerate chainfee.SatPerKWeight, incoming, - localCommit bool, amt btcutil.Amount) bool { + localCommit bool, amt btcutil.Amount, assetAmount omnicore.Amount) bool { if localCommit { return lnwallet.HtlcIsDust( chantype, incoming, true, feerate, amt, - localDustLimit, + localDustLimit,assetAmount, ) } return lnwallet.HtlcIsDust( chantype, incoming, false, feerate, amt, - remoteDustLimit, + remoteDustLimit,assetAmount, ) } @@ -2909,7 +2910,10 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg, outgoingChanID: fwdInfo.NextHop, sourceRef: pd.SourceRef, incomingAmount: pd.BtcAmount, - amount: addMsg.BtcAmount, + incomingAssetAmount: pd.AssetAmount, + btcAmount: addMsg.BtcAmount, + assetAmount: addMsg.AssetAmount, + assetId: addMsg.AssetID, htlc: addMsg, obfuscator: obfuscator, incomingTimeout: pd.Timeout, @@ -2973,7 +2977,9 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg, outgoingChanID: fwdInfo.NextHop, sourceRef: pd.SourceRef, incomingAmount: pd.BtcAmount, - amount: addMsg.BtcAmount, + btcAmount: addMsg.BtcAmount, + assetAmount: addMsg.AssetAmount, + assetId: addMsg.AssetID, htlc: addMsg, obfuscator: obfuscator, incomingTimeout: pd.Timeout, @@ -3205,7 +3211,8 @@ func (l *channelLink) sendHTLCError(pd *lnwallet.PaymentDescriptor, }, HtlcInfo{ IncomingTimeLock: pd.Timeout, - IncomingAmt: pd.Amount, + IncomingAmt: pd.BtcAmount, + IncomingAssetAmt: pd.AssetAmount, }, eventType, failure, diff --git a/htlcswitch/mailbox.go b/htlcswitch/mailbox.go index 6bec19f398..55f846e093 100644 --- a/htlcswitch/mailbox.go +++ b/htlcswitch/mailbox.go @@ -672,16 +672,16 @@ func (m *memoryMailBox) DustPackets() (lnwire.MilliSatoshi, // Evaluate whether this HTLC is dust on the local commitment. if m.isDust( - m.feeRate, false, true, addPkt.amount.ToSatoshis(), + m.feeRate, false, true, addPkt.btcAmount.ToSatoshis(),addPkt.assetAmount, ) { - localDustSum += addPkt.amount + localDustSum += addPkt.btcAmount } // Evaluate whether this HTLC is dust on the remote commitment. if m.isDust( - m.feeRate, false, false, addPkt.amount.ToSatoshis(), + m.feeRate, false, false, addPkt.btcAmount.ToSatoshis(),addPkt.assetAmount, ) { - remoteDustSum += addPkt.amount + remoteDustSum += addPkt.btcAmount } } diff --git a/htlcswitch/packet.go b/htlcswitch/packet.go index 78c3af8e23..a47b6eebb9 100644 --- a/htlcswitch/packet.go +++ b/htlcswitch/packet.go @@ -3,6 +3,7 @@ package htlcswitch import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/htlcswitch/hop" + "github.com/lightningnetwork/lnd/lnwallet/omnicore" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/record" ) @@ -40,8 +41,14 @@ type htlcPacket struct { // incoming link. incomingAmount lnwire.MilliSatoshi + /* + obd update wxf + */ // amount is the value of the HTLC that is being created or modified. - amount lnwire.MilliSatoshi + btcAmount lnwire.MilliSatoshi + assetAmount omnicore.Amount + assetId uint32 + incomingAssetAmount omnicore.Amount // htlc lnwire message type of which depends on switch request type. htlc lnwire.Message diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index 99c46737a7..ef3b61a941 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -4,6 +4,7 @@ import ( "bytes" "errors" "fmt" + "github.com/lightningnetwork/lnd/lnwallet/omnicore" "math/rand" "sync" "sync/atomic" @@ -491,7 +492,8 @@ func (s *Switch) SendHTLC(firstHop lnwire.ShortChannelID, attemptID uint64, newHtlcKey(packet), HtlcInfo{ OutgoingTimeLock: htlc.Expiry, - OutgoingAmt: htlc.Amount, + OutgoingAmt: htlc.BtcAmount, + OutgoingAssetAmt: htlc.AssetAmount, }, HtlcEventTypeSend, linkErr, @@ -503,7 +505,7 @@ func (s *Switch) SendHTLC(firstHop lnwire.ShortChannelID, attemptID uint64, // Evaluate whether this HTLC would increase our exposure to dust. If // it does, don't send it out and instead return an error. - if s.evaluateDustThreshold(link, htlc.Amount, false) { + if s.evaluateDustThreshold(link, htlc.BtcAmount,htlc.AssetAmount, false) { // Notify the htlc notifier of a link failure on our outgoing // link. We use the FailTemporaryChannelFailure in place of a // more descriptive error message. @@ -514,7 +516,8 @@ func (s *Switch) SendHTLC(firstHop lnwire.ShortChannelID, attemptID uint64, newHtlcKey(packet), HtlcInfo{ OutgoingTimeLock: htlc.Expiry, - OutgoingAmt: htlc.Amount, + OutgoingAmt: htlc.BtcAmount, + OutgoingAssetAmt: htlc.AssetAmount, }, HtlcEventTypeSend, linkErr, @@ -806,7 +809,7 @@ func (s *Switch) getLocalLink(pkt *htlcPacket, htlc *lnwire.UpdateAddHTLC) ( // Ensure that the htlc satisfies the outgoing channel policy. currentHeight := atomic.LoadUint32(&s.bestHeight) htlcErr := link.CheckHtlcTransit( - htlc.PaymentHash, htlc.Amount, htlc.Expiry, currentHeight, + htlc.PaymentHash, htlc.BtcAmount, htlc.Expiry, currentHeight, ) if htlcErr != nil { log.Errorf("Link %v policy for local forward not "+ @@ -1080,7 +1083,7 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { currentHeight := atomic.LoadUint32(&s.bestHeight) failure = link.CheckHtlcForward( htlc.PaymentHash, packet.incomingAmount, - packet.amount, packet.incomingTimeout, + packet.btcAmount, packet.incomingTimeout, packet.outgoingTimeout, currentHeight, ) } @@ -1151,7 +1154,7 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { // Evaluate whether this HTLC would increase our exposure to // dust on the incoming link. If it does, fail it backwards. if s.evaluateDustThreshold( - incomingLink, packet.incomingAmount, true, + incomingLink, packet.incomingAmount, packet.assetAmount, true, ) { // The incoming dust exceeds the threshold, so we fail // the add back. @@ -1165,7 +1168,7 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { // Also evaluate whether this HTLC would increase our exposure // to dust on the destination link. If it does, fail it back. if s.evaluateDustThreshold( - destination, packet.amount, false, + destination, packet.btcAmount,packet.assetAmount, false, ) { // The outgoing dust exceeds the threshold, so we fail // the add back. @@ -1342,7 +1345,10 @@ func (s *Switch) failAddPacket(packet *htlcPacket, failure *LinkError) error { outgoingChanID: packet.outgoingChanID, outgoingHTLCID: packet.outgoingHTLCID, incomingAmount: packet.incomingAmount, - amount: packet.amount, + incomingAssetAmount: packet.incomingAssetAmount, + btcAmount: packet.btcAmount, + assetAmount: packet.assetAmount, + assetId: packet.assetId, incomingTimeout: packet.incomingTimeout, outgoingTimeout: packet.outgoingTimeout, circuit: packet.circuit, @@ -2366,15 +2372,15 @@ func (s *Switch) BestHeight() uint32 { // in the sum as it was already included in the commitment's dust. A boolean is // returned telling the caller whether the HTLC should be failed back. func (s *Switch) evaluateDustThreshold(link ChannelLink, - amount lnwire.MilliSatoshi, incoming bool) bool { + amount lnwire.MilliSatoshi,assetAmount omnicore.Amount, incoming bool) bool { // Retrieve the link's current commitment feerate and dustClosure. feeRate := link.getFeeRate() isDust := link.getDustClosure() // Evaluate if the HTLC is dust on either sides' commitment. - isLocalDust := isDust(feeRate, incoming, true, amount.ToSatoshis()) - isRemoteDust := isDust(feeRate, incoming, false, amount.ToSatoshis()) + isLocalDust := isDust(feeRate, incoming, true, amount.ToSatoshis(),assetAmount) + isRemoteDust := isDust(feeRate, incoming, false, amount.ToSatoshis(),assetAmount) if !(isLocalDust || isRemoteDust) { // If the HTLC is not dust on either commitment, it's fine to diff --git a/htlcswitch/test_utils.go b/htlcswitch/test_utils.go index de29dca84f..0ea0b27127 100644 --- a/htlcswitch/test_utils.go +++ b/htlcswitch/test_utils.go @@ -232,7 +232,7 @@ func createTestChannel(alicePrivKey, bobPrivKey []byte, aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns( aliceAmount, bobAmount,aliceAssetAmount, bobAssetAmount, &aliceCfg, &bobCfg, aliceCommitPoint, - bobCommitPoint, *fundingTxIn, channeldb.SingleFunderTweaklessBit, + bobCommitPoint, *fundingTxIn, channeldb.SingleFunderTweaklessBit,31, isAliceInitiator, 0, ) if err != nil { @@ -522,6 +522,7 @@ func getChanID(msg lnwire.Message) (lnwire.ChannelID, error) { // generateHoldPayment generates the htlc add request by given path blob and // invoice which should be added by destination peer. func generatePaymentWithPreimage(invoiceAmt, htlcAmt lnwire.MilliSatoshi, + htlcAssetAmount omnicore.Amount,assetId uint32, timelock uint32, blob [lnwire.OnionPacketSize]byte, preimage *lntypes.Preimage, rhash, payAddr [32]byte) ( *channeldb.Invoice, *lnwire.UpdateAddHTLC, uint64, error) { @@ -549,7 +550,9 @@ func generatePaymentWithPreimage(invoiceAmt, htlcAmt lnwire.MilliSatoshi, htlc := &lnwire.UpdateAddHTLC{ PaymentHash: rhash, - Amount: htlcAmt, + BtcAmount: htlcAmt, + AssetAmount: htlcAssetAmount, + AssetID: assetId, Expiry: timelock, OnionBlob: blob, } @@ -565,7 +568,9 @@ func generatePaymentWithPreimage(invoiceAmt, htlcAmt lnwire.MilliSatoshi, // generatePayment generates the htlc add request by given path blob and // invoice which should be added by destination peer. -func generatePayment(invoiceAmt, htlcAmt lnwire.MilliSatoshi, timelock uint32, +func generatePayment(invoiceAmt, htlcAmt lnwire.MilliSatoshi, + htlcAssetAmount omnicore.Amount,assetId uint32, + timelock uint32, blob [lnwire.OnionPacketSize]byte) (*channeldb.Invoice, *lnwire.UpdateAddHTLC, uint64, error) { @@ -586,7 +591,7 @@ func generatePayment(invoiceAmt, htlcAmt lnwire.MilliSatoshi, timelock uint32, copy(payAddr[:], r) return generatePaymentWithPreimage( - invoiceAmt, htlcAmt, timelock, blob, &preimage, rhash, payAddr, + invoiceAmt, htlcAmt,htlcAssetAmount,assetId, timelock, blob, &preimage, rhash, payAddr, ) } @@ -733,13 +738,14 @@ func waitForPayFuncResult(payFunc func() error, d time.Duration) error { func makePayment(sendingPeer, receivingPeer lnpeer.Peer, firstHop lnwire.ShortChannelID, hops []*hop.Payload, invoiceAmt, htlcAmt lnwire.MilliSatoshi, + htlcAssetAmt omnicore.Amount,assetId uint32, timelock uint32) *paymentResponse { paymentErr := make(chan error, 1) var rhash lntypes.Hash invoice, payFunc, err := preparePayment(sendingPeer, receivingPeer, - firstHop, hops, invoiceAmt, htlcAmt, timelock, + firstHop, hops, invoiceAmt, htlcAmt,htlcAssetAmt,assetId, timelock, ) if err != nil { paymentErr <- err @@ -766,7 +772,7 @@ func makePayment(sendingPeer, receivingPeer lnpeer.Peer, // that, when called, launches the payment from the sendingPeer. func preparePayment(sendingPeer, receivingPeer lnpeer.Peer, firstHop lnwire.ShortChannelID, hops []*hop.Payload, - invoiceAmt, htlcAmt lnwire.MilliSatoshi, + invoiceAmt, htlcAmt lnwire.MilliSatoshi,htlcAssetAmt omnicore.Amount,assetId uint32, timelock uint32) (*channeldb.Invoice, func() error, error) { sender := sendingPeer.(*mockServer) @@ -781,7 +787,7 @@ func preparePayment(sendingPeer, receivingPeer lnpeer.Peer, // Generate payment: invoice and htlc. invoice, htlc, pid, err := generatePayment( - invoiceAmt, htlcAmt, timelock, blob, + invoiceAmt, htlcAmt, htlcAssetAmt, assetId,timelock, blob, ) if err != nil { return nil, nil, err @@ -881,7 +887,9 @@ func createClusterChannels(aliceToBob, bobToCarol btcutil.Amount) ( // Create lightning channels between Alice<->Bob and Bob<->Carol aliceChannel, firstBobChannel, cleanAliceBob, err := createTestChannel(alicePrivKey, bobPrivKey, aliceToBob, - aliceToBob, 0, 0, firstChanID) + aliceToBob, 0, 0, + 0,0,0,0, + firstChanID) if err != nil { return nil, nil, nil, errors.Errorf("unable to create "+ "alice<->bob channel: %v", err) @@ -889,7 +897,9 @@ func createClusterChannels(aliceToBob, bobToCarol btcutil.Amount) ( secondBobChannel, carolChannel, cleanBobCarol, err := createTestChannel(bobPrivKey, carolPrivKey, bobToCarol, - bobToCarol, 0, 0, secondChanID) + bobToCarol, 0, 0, + 0,0,0,0, + secondChanID) if err != nil { cleanAliceBob() return nil, nil, nil, errors.Errorf("unable to create "+ @@ -1078,7 +1088,9 @@ func createTwoClusterChannels(aliceToBob, bobToCarol btcutil.Amount) ( // Create lightning channels between Alice<->Bob and Bob<->Carol alice, bob, cleanAliceBob, err := createTestChannel(alicePrivKey, bobPrivKey, aliceToBob, - aliceToBob, 0, 0, firstChanID) + aliceToBob, 0, 0, + 0,0,0,0, + firstChanID) if err != nil { return nil, nil, nil, errors.Errorf("unable to create "+ "alice<->bob channel: %v", err) @@ -1295,6 +1307,7 @@ func (n *twoHopNetwork) stop() { func (n *twoHopNetwork) makeHoldPayment(sendingPeer, receivingPeer lnpeer.Peer, firstHop lnwire.ShortChannelID, hops []*hop.Payload, invoiceAmt, htlcAmt lnwire.MilliSatoshi, + htlcAssetAmount omnicore.Amount,assetId uint32, timelock uint32, preimage lntypes.Preimage) chan error { paymentErr := make(chan error, 1) @@ -1319,8 +1332,9 @@ func (n *twoHopNetwork) makeHoldPayment(sendingPeer, receivingPeer lnpeer.Peer, // Generate payment: invoice and htlc. invoice, htlc, pid, err := generatePaymentWithPreimage( - invoiceAmt, htlcAmt, timelock, blob, - nil, rhash, payAddr, + invoiceAmt, htlcAmt, + htlcAssetAmount,assetId, + timelock, blob,nil, rhash, payAddr, ) if err != nil { paymentErr <- err diff --git a/lnwallet/chanfunding/canned_assembler.go b/lnwallet/chanfunding/canned_assembler.go index 81b426bae0..4422278dae 100644 --- a/lnwallet/chanfunding/canned_assembler.go +++ b/lnwallet/chanfunding/canned_assembler.go @@ -2,6 +2,7 @@ package chanfunding import ( "fmt" + "github.com/lightningnetwork/lnd/lnwallet/omnicore" "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/wire" @@ -21,6 +22,12 @@ type ShimIntent struct { // remoteFundingAmt is the final amount the remote party put into the // funding output. remoteFundingAmt btcutil.Amount + /* + obd add wxf + */ + localFundingAssetAmt omnicore.Amount + remoteFundingAssetAmt omnicore.Amount + // localKey is our multi-sig key. localKey *keychain.KeyDescriptor @@ -79,6 +86,14 @@ func (s *ShimIntent) RemoteFundingAmt() btcutil.Amount { return s.remoteFundingAmt } +/*obd add wxf*/ +func (s *ShimIntent) LocalFundingAssetAmt() omnicore.Amount { + return s.remoteFundingAssetAmt +} +func (s *ShimIntent) RemoteFundingAssetAmt() omnicore.Amount { + return s.remoteFundingAssetAmt +} + // ChanPoint returns the final outpoint that will create the funding output // described above. // diff --git a/lnwallet/commitment.go b/lnwallet/commitment.go index 027288feb2..49ade7a2e6 100644 --- a/lnwallet/commitment.go +++ b/lnwallet/commitment.go @@ -808,7 +808,8 @@ func CreateCommitTx(chanType channeldb.ChannelType, obd add wxf */ if !remoteOutput && assetAmountToRemote>0{ - return nil,fmt.Errorf("CreateCommitTx err: remoteOutput less than DustLimit, it will ignore asset") + return nil,fmt.Errorf("CreateCommitTx err: remoteBtcOutput less than DustLimit, it will ignore asset: btcAmt %v dust: %v assetAmt %v ", + btcAmountToRemote,localChanCfg.DustLimit,assetAmountToRemote) } if remoteOutput { commitTx.AddTxOut(&wire.TxOut{ @@ -818,7 +819,7 @@ func CreateCommitTx(chanType channeldb.ChannelType, /* obd add wxf */ - opAmounts.Add(toLocalScript.PkScript,assetAmountToRemote) + opAmounts.Add(toRemoteScript.PkScript,assetAmountToRemote) } // If this channel type has anchors, we'll also add those. diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index 408de59a32..32b8f29173 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -95,7 +95,9 @@ func (c CommitmentType) String() string { type ChannelContribution struct { // FundingOutpoint is the amount of funds contributed to the funding // transaction. - FundingAmount btcutil.Amount + FundingBtcAmount btcutil.Amount + FundingAssetAmount omnicore.Amount + AssetId uint32 // Inputs to the funding transaction. Inputs []*wire.TxIn @@ -217,8 +219,10 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, assetCapacity, localAssetFundingAmt ,pushAsset omnicore.Amount,assetID uint32) (*ChannelReservation, error) { var ( - ourBalance lnwire.MilliSatoshi - theirBalance lnwire.MilliSatoshi + ourBtcBalance lnwire.MilliSatoshi + theirBtcBalance lnwire.MilliSatoshi + ourAssetBalance omnicore.Amount + theirAssetBalance omnicore.Amount initiator bool ) @@ -230,7 +234,7 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, } commitFee := commitFeePerKw.FeeForWeight(commitWeight) - localFundingMSat := lnwire.NewMSatFromSatoshis(localFundingAmt) + //localFundingMSat := lnwire.NewMSatFromSatoshis(localFundingAmt) // TODO(halseth): make method take remote funding amount directly // instead of inferring it from capacity and local amt. capacityMSat := lnwire.NewMSatFromSatoshis(capacity) @@ -249,15 +253,17 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, // no initial balance in the channel unless the remote party is pushing // some funds to us within the first commitment state. if localFundingAmt == 0 { - ourBalance = pushMSat - theirBalance = capacityMSat - feeMSat - pushMSat + ourBtcBalance = pushMSat + theirBtcBalance = capacityMSat - feeMSat - pushMSat initiator = false + ourAssetBalance=pushAsset + theirAssetBalance=assetCapacity - pushAsset // If the responder doesn't have enough funds to actually pay // the fees, then we'll bail our early. - if int64(theirBalance) < 0 { + if int64(theirBtcBalance) < 0 { return nil, ErrFunderBalanceDust( - int64(commitFee), int64(theirBalance.ToSatoshis()), + int64(commitFee), int64(theirBtcBalance.ToSatoshis()), int64(2*defaultDust), ) } @@ -270,23 +276,28 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, // we pay all the initial fees within the commitment // transaction. We also deduct our balance by the // amount pushed as part of the initial state. - ourBalance = capacityMSat - feeMSat - pushMSat - theirBalance = pushMSat + ourBtcBalance = capacityMSat - feeMSat - pushMSat + theirBtcBalance = pushMSat + + ourAssetBalance=assetCapacity -pushAsset + theirAssetBalance=pushAsset } else { - // Otherwise, this is a dual funder workflow where both - // slides split the amount funded and the commitment - // fee. - ourBalance = localFundingMSat - (feeMSat / 2) - theirBalance = capacityMSat - localFundingMSat - (feeMSat / 2) + pushMSat + /*obd update wxf*/ + //// Otherwise, this is a dual funder workflow where both + //// slides split the amount funded and the commitment + //// fee. + //ourBalance = localFundingMSat - (feeMSat / 2) + //theirBalance = capacityMSat - localFundingMSat - (feeMSat / 2) + pushMSat + return nil,errors.New("disable dual funder workflow") } initiator = true // If we, the initiator don't have enough funds to actually pay // the fees, then we'll exit with an error. - if int64(ourBalance) < 0 { + if int64(ourBtcBalance) < 0 { return nil, ErrFunderBalanceDust( - int64(commitFee), int64(ourBalance), + int64(commitFee), int64(ourBtcBalance), int64(2*defaultDust), ) } @@ -297,20 +308,20 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, // reject this channel creation request. // // TODO(roasbeef): reject if 30% goes to fees? dust channel - if initiator && ourBalance.ToSatoshis() <= 2*defaultDust { + if initiator && ourBtcBalance.ToSatoshis() <= 2*defaultDust { return nil, ErrFunderBalanceDust( int64(commitFee), - int64(ourBalance.ToSatoshis()), + int64(ourBtcBalance.ToSatoshis()), int64(2*defaultDust), ) } // Similarly we ensure their balance is reasonable if we are not the // initiator. - if !initiator && theirBalance.ToSatoshis() <= 2*defaultDust { + if !initiator && theirBtcBalance.ToSatoshis() <= 2*defaultDust { return nil, ErrFunderBalanceDust( int64(commitFee), - int64(theirBalance.ToSatoshis()), + int64(theirBtcBalance.ToSatoshis()), int64(2*defaultDust), ) } @@ -322,7 +333,7 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, // If either of the balances are zero at this point, or we have a // non-zero push amt (there's no pushing for dual funder), then this is // a single-funder channel. - if ourBalance == 0 || theirBalance == 0 || pushMSat != 0 { + if ourBtcBalance == 0 || theirBtcBalance == 0 || pushMSat != 0 { // Both the tweakless type and the anchor type is tweakless, // hence set the bit. if commitType.HasStaticRemoteKey() { @@ -353,6 +364,8 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, } } else { + /*obd add wxf*/ + return nil,errors.New("disable dual funder workflow") // Otherwise, this is a dual funder channel, and no side is // technically the "initiator" initiator = false @@ -380,11 +393,15 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, return &ChannelReservation{ ourContribution: &ChannelContribution{ - FundingAmount: ourBalance.ToSatoshis(), + FundingBtcAmount: ourBtcBalance.ToSatoshis(), + FundingAssetAmount: ourAssetBalance, + AssetId: assetID, ChannelConfig: &channeldb.ChannelConfig{}, }, theirContribution: &ChannelContribution{ - FundingAmount: theirBalance.ToSatoshis(), + FundingBtcAmount: theirBtcBalance.ToSatoshis(), + FundingAssetAmount: theirAssetBalance, + AssetId: assetID, ChannelConfig: &channeldb.ChannelConfig{}, }, partialState: &channeldb.OpenChannel{ @@ -397,24 +414,20 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, AssetCapacity: assetCapacity, AssetID: assetID, LocalCommitment: channeldb.ChannelCommitment{ - LocalBtcBalance: ourBalance, - RemoteBtcBalance: theirBalance, - /*obd update wxf - todo add ourBalance - */ - //LocalAssetBalance: ourBalance, - //RemoteAssetBalance: theirBalance, + LocalBtcBalance: ourBtcBalance, + RemoteBtcBalance: theirBtcBalance, + /*obd update wxf*/ + LocalAssetBalance: ourAssetBalance, + RemoteAssetBalance: theirAssetBalance, FeePerKw: btcutil.Amount(commitFeePerKw), CommitFee: commitFee, }, RemoteCommitment: channeldb.ChannelCommitment{ - LocalBtcBalance: ourBalance, - RemoteBtcBalance: theirBalance, - /*obd update wxf - todo add ourBalance - */ - //LocalAssetBalance: ourBalance, - //RemoteAssetBalance: theirBalance, + LocalBtcBalance: ourBtcBalance, + RemoteBtcBalance: theirBtcBalance, + /*obd update wxf*/ + LocalAssetBalance: ourAssetBalance, + RemoteAssetBalance: theirAssetBalance, FeePerKw: btcutil.Amount(commitFeePerKw), CommitFee: commitFee, }, @@ -773,6 +786,13 @@ func (r *ChannelReservation) BtcCapacity() btcutil.Amount { return r.partialState.BtcCapacity } +/*obd add wxf*/ +func (r *ChannelReservation) AssetCapacity() omnicore.Amount { + r.RLock() + defer r.RUnlock() + return r.partialState.AssetCapacity +} + // LeaseExpiry returns the absolute expiration height for a leased channel using // the script enforced commitment type. A zero value is returned when the // channel is not using a script enforced lease commitment type. diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index 69826ea432..877bcf957c 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -117,11 +117,18 @@ type InitFundingReserveMsg struct { // LocalFundingAmt is the amount of funds requested from us for this // channel. - LocalFundingAmt btcutil.Amount + LocalFundingBtcAmt btcutil.Amount // RemoteFundingAmnt is the amount of funds the remote will contribute // to this channel. - RemoteFundingAmt btcutil.Amount + RemoteFundingBtcAmt btcutil.Amount + /* + obd add wxf + */ + LocalFundingAssetAmt omnicore.Amount + RemoteFundingAssetAmt omnicore.Amount + AssetId uint32 + PushAsset omnicore.Amount // CommitFeePerKw is the starting accepted satoshis/Kw fee for the set // of initial commitment transactions. In order to ensure timely @@ -690,7 +697,7 @@ func (l *LightningWallet) CancelFundingIntent(pid [32]byte) error { // validate a funding reservation request. func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg) { // It isn't possible to create a channel with zero funds committed. - if req.LocalFundingAmt+req.RemoteFundingAmt == 0 { + if req.LocalFundingBtcAmt+req.RemoteFundingBtcAmt == 0 { err := ErrZeroCapacity() req.err <- err req.resp <- nil @@ -733,8 +740,10 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg enforceNewReservedValue = !isPsbtFunder } - localFundingAmt := req.LocalFundingAmt - remoteFundingAmt := req.RemoteFundingAmt + localFundingAmt := req.LocalFundingBtcAmt + remoteFundingAmt := req.RemoteFundingBtcAmt + localFundingAssetAmt := req.LocalFundingAssetAmt + remoteFundingAssetAmt := req.RemoteFundingAssetAmt var ( fundingIntent chanfunding.Intent @@ -758,8 +767,8 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg // the fee rate passed in to perform coin selection. var err error fundingReq := &chanfunding.Request{ - RemoteAmt: req.RemoteFundingAmt, - LocalAmt: req.LocalFundingAmt, + RemoteAmt: req.RemoteFundingBtcAmt, + LocalAmt: req.LocalFundingBtcAmt, MinConfs: req.MinConfs, SubtractFees: req.SubtractFees, FeeRate: req.FundingFeePerKw, @@ -844,6 +853,7 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg // The total channel capacity will be the size of the funding output we // created plus the remote contribution. capacity := localFundingAmt + remoteFundingAmt + assetCapacity := localFundingAssetAmt + remoteFundingAssetAmt id := atomic.AddUint64(&l.nextFundingID, 1) /* @@ -854,7 +864,7 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg capacity, localFundingAmt, req.CommitFeePerKw, l, id, req.PushMSat, l.Cfg.NetParams.GenesisHash, req.Flags, req.CommitType, req.ChanFunder, req.PendingChanID, - thawHeight,0,0,0,0, + thawHeight,assetCapacity,localFundingAssetAmt,req.PushAsset,req.AssetId, ) if err != nil { fundingIntent.Cancel() @@ -1293,7 +1303,7 @@ func CreateCommitmentTxns(localBalance, remoteBalance btcutil.Amount, theirCommitTx, err := CreateCommitTx( chanType, fundingTxIn, remoteCommitmentKeys, theirChanCfg, - ourChanCfg, remoteBalance, localBalance, localAssetBalance, remoteAssetBalance, 0, !initiator, leaseExpiry, theirOpAmounts, + ourChanCfg, remoteBalance, localBalance, remoteAssetBalance, localAssetBalance, 0, !initiator, leaseExpiry, theirOpAmounts, ) if err != nil { return nil, nil, err @@ -1556,12 +1566,12 @@ func (l *LightningWallet) handleChanPointReady(req *continueContributionMsg) { // With the funding tx complete, create both commitment transactions. localBalance := pendingReservation.partialState.LocalCommitment.LocalBtcBalance.ToSatoshis() - remoteBalance := pendingReservation.partialState.LocalCommitment.LocalBtcBalance.ToSatoshis() + remoteBalance := pendingReservation.partialState.LocalCommitment.RemoteBtcBalance.ToSatoshis() /* obd add wxf */ localAssetBalance := pendingReservation.partialState.LocalCommitment.LocalAssetBalance - remoteAssetBalance := pendingReservation.partialState.LocalCommitment.LocalAssetBalance + remoteAssetBalance := pendingReservation.partialState.LocalCommitment.RemoteAssetBalance var leaseExpiry uint32 if pendingReservation.partialState.ChanType.HasLeaseExpiration() { leaseExpiry = pendingReservation.partialState.ThawHeight diff --git a/lnwire/channel_announcement.go b/lnwire/channel_announcement.go index 2b34c0f990..bf1e200151 100644 --- a/lnwire/channel_announcement.go +++ b/lnwire/channel_announcement.go @@ -37,6 +37,10 @@ type ChannelAnnouncement struct { // ShortChannelID is the unique description of the funding transaction, // or where exactly it's located within the target blockchain. ShortChannelID ShortChannelID + /* + obd add wxf + */ + AssetID uint32 // The public keys of the two nodes who are operating the channel, such // that is NodeID1 the numerically-lesser than NodeID2 (ascending diff --git a/lnwire/channel_update.go b/lnwire/channel_update.go index 7881f972fb..1773275d9d 100644 --- a/lnwire/channel_update.go +++ b/lnwire/channel_update.go @@ -3,6 +3,7 @@ package lnwire import ( "bytes" "fmt" + "github.com/lightningnetwork/lnd/lnwallet/omnicore" "io" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -100,7 +101,7 @@ type ChannelUpdate struct { TimeLockDelta uint16 // HtlcMinimumMsat is the minimum HTLC value which will be accepted. - HtlcMinimumMsat MilliSatoshi + HtlcBtcMinimumMsat MilliSatoshi // BaseFee is the base fee that must be used for incoming HTLC's to // this particular channel. This value will be tacked onto the required @@ -112,7 +113,13 @@ type ChannelUpdate struct { FeeRate uint32 // HtlcMaximumMsat is the maximum HTLC value which will be accepted. - HtlcMaximumMsat MilliSatoshi + HtlcBtcMaximumMsat MilliSatoshi + /* + obd add wxf + */ + HtlcAssetMaximum omnicore.Amount + HtlcAssetMinimum omnicore.Amount + AssetId uint32 // ExtraData is the set of data that was appended to this message to // fill out the full maximum transport message size. These fields can @@ -137,7 +144,9 @@ func (a *ChannelUpdate) Decode(r io.Reader, pver uint32) error { &a.MessageFlags, &a.ChannelFlags, &a.TimeLockDelta, - &a.HtlcMinimumMsat, + &a.HtlcBtcMinimumMsat, + &a.HtlcAssetMinimum, + &a.AssetId, &a.BaseFee, &a.FeeRate, ) @@ -147,7 +156,10 @@ func (a *ChannelUpdate) Decode(r io.Reader, pver uint32) error { // Now check whether the max HTLC field is present and read it if so. if a.MessageFlags.HasMaxHtlc() { - if err := ReadElements(r, &a.HtlcMaximumMsat); err != nil { + if err := ReadElements(r, &a.HtlcBtcMaximumMsat); err != nil { + return err + } + if err := ReadElements(r, &a.HtlcAssetMaximum); err != nil { return err } } @@ -188,7 +200,13 @@ func (a *ChannelUpdate) Encode(w *bytes.Buffer, pver uint32) error { return err } - if err := WriteMilliSatoshi(w, a.HtlcMinimumMsat); err != nil { + if err := WriteMilliSatoshi(w, a.HtlcBtcMinimumMsat); err != nil { + return err + } + if err := WriteAssetMinUnit(w, a.HtlcAssetMinimum); err != nil { + return err + } + if err := WriteUint32(w, a.AssetId); err != nil { return err } @@ -203,7 +221,11 @@ func (a *ChannelUpdate) Encode(w *bytes.Buffer, pver uint32) error { // Now append optional fields if they are set. Currently, the only // optional field is max HTLC. if a.MessageFlags.HasMaxHtlc() { - err := WriteMilliSatoshi(w, a.HtlcMaximumMsat) + err := WriteMilliSatoshi(w, a.HtlcBtcMaximumMsat) + if err != nil { + return err + } + err = WriteAssetMinUnit(w, a.HtlcAssetMaximum) if err != nil { return err } @@ -212,7 +234,6 @@ func (a *ChannelUpdate) Encode(w *bytes.Buffer, pver uint32) error { // Finally, append any extra opaque data. return WriteBytes(w, a.ExtraOpaqueData) } - // MsgType returns the integer uniquely identifying this message type on the // wire. // @@ -251,7 +272,13 @@ func (a *ChannelUpdate) DataToSign() ([]byte, error) { return nil, err } - if err := WriteMilliSatoshi(buf, a.HtlcMinimumMsat); err != nil { + if err := WriteMilliSatoshi(buf, a.HtlcBtcMinimumMsat); err != nil { + return nil, err + } + if err := WriteAssetMinUnit(buf, a.HtlcAssetMinimum); err != nil { + return nil, err + } + if err := WriteUint32(buf, a.AssetId); err != nil { return nil, err } @@ -266,7 +293,11 @@ func (a *ChannelUpdate) DataToSign() ([]byte, error) { // Now append optional fields if they are set. Currently, the only // optional field is max HTLC. if a.MessageFlags.HasMaxHtlc() { - err := WriteMilliSatoshi(buf, a.HtlcMaximumMsat) + err := WriteMilliSatoshi(buf, a.HtlcBtcMaximumMsat) + if err != nil { + return nil, err + } + err = WriteAssetMinUnit(buf, a.HtlcAssetMaximum) if err != nil { return nil, err } diff --git a/lnwire/open_channel.go b/lnwire/open_channel.go index 273129ad2a..211c328c46 100644 --- a/lnwire/open_channel.go +++ b/lnwire/open_channel.go @@ -2,6 +2,7 @@ package lnwire import ( "bytes" + "github.com/lightningnetwork/lnd/lnwallet/omnicore" "io" "github.com/btcsuite/btcd/btcec" @@ -39,12 +40,20 @@ type OpenChannel struct { // channel wishes to use as the total capacity of the channel. The // initial balance of the funding will be this value minus the push // amount (if set). - FundingAmount btcutil.Amount + FundingBtcAmount btcutil.Amount // PushAmount is the value that the initiating party wishes to "push" // to the responding as part of the first commitment state. If the // responder accepts, then this will be their initial balance. - PushAmount MilliSatoshi + PushBtcAmount MilliSatoshi + + /* + obd add wxf + */ + FundingAssetAmount omnicore.Amount + PushAssetAmount omnicore.Amount + AssetId uint32 + // DustLimit is the specific dust limit the sender of this message // would like enforced on their version of the commitment transaction. @@ -182,11 +191,20 @@ func (o *OpenChannel) Encode(w *bytes.Buffer, pver uint32) error { return err } - if err := WriteSatoshi(w, o.FundingAmount); err != nil { + if err := WriteSatoshi(w, o.FundingBtcAmount); err != nil { return err } - if err := WriteMilliSatoshi(w, o.PushAmount); err != nil { + if err := WriteMilliSatoshi(w, o.PushBtcAmount); err != nil { + return err + } + if err := WriteAssetMinUnit(w, o.FundingAssetAmount); err != nil { + return err + } + if err := WriteAssetMinUnit(w, o.PushAssetAmount); err != nil { + return err + } + if err := WriteUint32(w, o.AssetId); err != nil { return err } @@ -260,8 +278,12 @@ func (o *OpenChannel) Decode(r io.Reader, pver uint32) error { err := ReadElements(r, o.ChainHash[:], o.PendingChannelID[:], - &o.FundingAmount, - &o.PushAmount, + /*obd update wxf*/ + &o.FundingBtcAmount, + &o.PushBtcAmount, + &o.FundingAssetAmount, + &o.PushAssetAmount, + &o.AssetId, &o.DustLimit, &o.MaxValueInFlight, &o.ChannelReserve, diff --git a/netann/channel_update.go b/netann/channel_update.go index 0fec750f9d..2236cc5b2d 100644 --- a/netann/channel_update.go +++ b/netann/channel_update.go @@ -127,8 +127,10 @@ func UnsignedChannelUpdateFromEdge(info *channeldb.ChannelEdgeInfo, ChannelFlags: policy.ChannelFlags, MessageFlags: policy.MessageFlags, TimeLockDelta: policy.TimeLockDelta, - HtlcMinimumMsat: policy.MinHTLC, - HtlcMaximumMsat: policy.MaxHTLC, + HtlcBtcMinimumMsat: policy.MinBtcHTLC, + HtlcBtcMaximumMsat: policy.MaxBtcHTLC, + HtlcAssetMinimum: policy.MinAssetHTLC, + HtlcAssetMaximum: policy.MaxAssetHTLC, BaseFee: uint32(policy.FeeBaseMSat), FeeRate: uint32(policy.FeeProportionalMillionths), ExtraOpaqueData: policy.ExtraOpaqueData, diff --git a/routing/ann_validation.go b/routing/ann_validation.go index cc8530bb16..34990a1b0b 100644 --- a/routing/ann_validation.go +++ b/routing/ann_validation.go @@ -166,8 +166,8 @@ func validateOptionalFields(capacity btcutil.Amount, msg *lnwire.ChannelUpdate) error { if msg.MessageFlags.HasMaxHtlc() { - maxHtlc := msg.HtlcMaximumMsat - if maxHtlc == 0 || maxHtlc < msg.HtlcMinimumMsat { + maxHtlc := msg.HtlcBtcMaximumMsat + if maxHtlc == 0 || maxHtlc < msg.HtlcBtcMinimumMsat { return errors.Errorf("invalid max htlc for channel "+ "update %v", spew.Sdump(msg)) } diff --git a/routing/notifications.go b/routing/notifications.go index a04f3be51e..5778f3ea29 100644 --- a/routing/notifications.go +++ b/routing/notifications.go @@ -2,6 +2,7 @@ package routing import ( "fmt" + "github.com/lightningnetwork/lnd/lnwallet/omnicore" "image/color" "net" "sync" @@ -194,8 +195,12 @@ type ClosedChanSummary struct { // channel. ChanID uint64 + /*obd update wxf*/ // Capacity was the total capacity of the channel before it was closed. - Capacity btcutil.Amount + //Capacity btcutil.Amount + BtcCapacity btcutil.Amount + AssetCapacity omnicore.Amount + AssetId uint32 // ClosedHeight is the height in the chain that the channel was closed // at. @@ -215,7 +220,9 @@ func createCloseSummaries(blockHeight uint32, for i, closedChan := range closedChans { closeSummaries[i] = &ClosedChanSummary{ ChanID: closedChan.ChannelID, - Capacity: closedChan.Capacity, + BtcCapacity: closedChan.BtcCapacity, + AssetCapacity: closedChan.AssetCapacity, + AssetId: closedChan.AssetId, ClosedHeight: blockHeight, ChanPoint: closedChan.ChannelPoint, } @@ -265,14 +272,21 @@ type ChannelEdgeUpdate struct { // output for the channel. ChanPoint wire.OutPoint + /*obd update wxf*/ // Capacity is the capacity of the newly created channel. - Capacity btcutil.Amount + //Capacity btcutil.Amount + BtcCapacity btcutil.Amount + AssetCapacity omnicore.Amount + AssetId uint32 + MinAssetHTLC omnicore.Amount + MaxAssetHTLC omnicore.Amount // MinHTLC is the minimum HTLC amount that this channel will forward. - MinHTLC lnwire.MilliSatoshi + MinBtcHTLC lnwire.MilliSatoshi // MaxHTLC is the maximum HTLC amount that this channel will forward. - MaxHTLC lnwire.MilliSatoshi + MaxBtcHTLC lnwire.MilliSatoshi + // BaseFee is the base fee that will charged for all HTLC's forwarded // across the this channel direction. @@ -368,9 +382,14 @@ func addToTopologyChange(graph *channeldb.ChannelGraph, update *TopologyChange, ChanID: m.ChannelID, ChanPoint: edgeInfo.ChannelPoint, TimeLockDelta: m.TimeLockDelta, - Capacity: edgeInfo.Capacity, - MinHTLC: m.MinHTLC, - MaxHTLC: m.MaxHTLC, + /*obd update wxf*/ + BtcCapacity: edgeInfo.BtcCapacity, + AssetCapacity: edgeInfo.AssetCapacity, + AssetId: edgeInfo.AssetId, + MinBtcHTLC: m.MinBtcHTLC, + MaxBtcHTLC: m.MaxBtcHTLC, + MinAssetHTLC: m.MinAssetHTLC, + MaxAssetHTLC: m.MaxAssetHTLC, BaseFee: m.FeeBaseMSat, FeeRate: m.FeeProportionalMillionths, AdvertisingNode: aNode, diff --git a/routing/pathfind.go b/routing/pathfind.go index c07271550f..e5492290b5 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -381,7 +381,7 @@ func getOutgoingBalance(node route.Vertex, outgoingChans map[uint64]struct{}, // This can happen when a channel is added to the graph after // we've already queried the bandwidth hints. if !ok { - bandwidth = lnwire.NewMSatFromSatoshis(channel.Capacity) + bandwidth = lnwire.NewMSatFromSatoshis(channel.BtcCapacity) } if bandwidth > max { @@ -815,7 +815,7 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, } for _, reverseEdge := range additionalEdgesWithSrc[pivot] { - u.addPolicy(reverseEdge.sourceNode, reverseEdge.edge, 0) + u.addPolicy(reverseEdge.sourceNode, reverseEdge.edge, 0,0) } amtToSend := partialPath.amountToReceive diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index 945a534666..eaa401a0ce 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -703,7 +703,8 @@ func (p *shardHandler) createNewPaymentAttempt(rt *route.Route, lastShard bool) // metadata within this packet will be used to route the // payment through the network, starting with the first-hop. htlcAdd := &lnwire.UpdateAddHTLC{ - Amount: rt.TotalAmount, + BtcAmount: rt.TotalAmount, + AssetAmount: rt.TotalAssetAmount, Expiry: rt.TotalTimeLock, PaymentHash: hash, } diff --git a/routing/route/route.go b/routing/route/route.go index 63944af18a..4a0c765adf 100644 --- a/routing/route/route.go +++ b/routing/route/route.go @@ -6,6 +6,7 @@ import ( "encoding/hex" "errors" "fmt" + "github.com/lightningnetwork/lnd/lnwallet/omnicore" "io" "strconv" "strings" @@ -294,6 +295,7 @@ type Route struct { // route will fail at an intermediate node due to an insufficient // amount of fees. TotalAmount lnwire.MilliSatoshi + TotalAssetAmount omnicore.Amount // SourcePubKey is the pubkey of the node where this route originates // from. diff --git a/routing/router.go b/routing/router.go index c0578c5643..cb07f57c25 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1570,7 +1570,7 @@ func (r *ChannelRouter) processUpdate(msg interface{}, // TODO(roasbeef): this is a hack, needs to be removed // after commitment fees are dynamic. - msg.Capacity = btcutil.Amount(chanUtxo.Value) + msg.BtcCapacity = btcutil.Amount(chanUtxo.Value) msg.ChannelPoint = *fundingPoint if err := r.cfg.Graph.AddChannelEdge(msg, op...); err != nil { return errors.Errorf("unable to add edge: %v", err) @@ -1580,7 +1580,7 @@ func (r *ChannelRouter) processUpdate(msg interface{}, "connects %x and %x with ChannelPoint(%v): "+ "chan_id=%v, capacity=%v", msg.NodeKey1Bytes, msg.NodeKey2Bytes, - fundingPoint, msg.ChannelID, msg.Capacity) + fundingPoint, msg.ChannelID, msg.BtcCapacity) r.stats.incNumEdgesDiscovered() // As a new edge has been added to the channel graph, we'll @@ -2366,7 +2366,7 @@ func (r *ChannelRouter) applyChannelUpdate(msg *lnwire.ChannelUpdate, return false } - if err := ValidateChannelUpdateAnn(pubKey, ch.Capacity, msg); err != nil { + if err := ValidateChannelUpdateAnn(pubKey, ch.BtcCapacity, msg); err != nil { log.Errorf("Unable to validate channel update: %v", err) return false } @@ -2378,8 +2378,11 @@ func (r *ChannelRouter) applyChannelUpdate(msg *lnwire.ChannelUpdate, MessageFlags: msg.MessageFlags, ChannelFlags: msg.ChannelFlags, TimeLockDelta: msg.TimeLockDelta, - MinHTLC: msg.HtlcMinimumMsat, - MaxHTLC: msg.HtlcMaximumMsat, + MinBtcHTLC: msg.HtlcBtcMinimumMsat, + MaxBtcHTLC: msg.HtlcBtcMaximumMsat, + MinAssetHTLC: msg.HtlcAssetMinimum, + MaxAssetHTLC: msg.HtlcAssetMaximum, + AssetId: msg.AssetId, FeeBaseMSat: lnwire.MilliSatoshi(msg.BaseFee), FeeProportionalMillionths: lnwire.MilliSatoshi(msg.FeeRate), }) diff --git a/routing/unified_policies.go b/routing/unified_policies.go index b54689e134..314d29f1fd 100644 --- a/routing/unified_policies.go +++ b/routing/unified_policies.go @@ -3,6 +3,7 @@ package routing import ( "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/lnwallet/omnicore" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" ) @@ -40,7 +41,7 @@ func newUnifiedPolicies(sourceNode, toNode route.Vertex, // addPolicy adds a single channel policy. Capacity may be zero if unknown // (light clients). func (u *unifiedPolicies) addPolicy(fromNode route.Vertex, - edge *channeldb.CachedEdgePolicy, capacity btcutil.Amount) { + edge *channeldb.CachedEdgePolicy, capacity btcutil.Amount,Assetcapacity omnicore.Amount) { localChan := fromNode == u.sourceNode @@ -63,6 +64,7 @@ func (u *unifiedPolicies) addPolicy(fromNode route.Vertex, policy.edges = append(policy.edges, &unifiedPolicyEdge{ policy: edge, capacity: capacity, + assetCapacity: Assetcapacity, }) } @@ -79,7 +81,7 @@ func (u *unifiedPolicies) addGraphPolicies(g routingGraph) error { // Add this policy to the unified policies map. u.addPolicy( - channel.OtherNode, channel.InPolicy, channel.Capacity, + channel.OtherNode, channel.InPolicy, channel.BtcCapacity,channel.AssetCapacity, ) return nil @@ -94,6 +96,7 @@ func (u *unifiedPolicies) addGraphPolicies(g routingGraph) error { type unifiedPolicyEdge struct { policy *channeldb.CachedEdgePolicy capacity btcutil.Amount + assetCapacity omnicore.Amount } // amtInRange checks whether an amount falls within the valid range for a @@ -109,13 +112,13 @@ func (u *unifiedPolicyEdge) amtInRange(amt lnwire.MilliSatoshi) bool { // Skip channels for which this htlc is too large. if u.policy.MessageFlags.HasMaxHtlc() && - amt > u.policy.MaxHTLC { + amt > u.policy.MaxBtcHTLC { return false } // Skip channels for which this htlc is too small. - if amt < u.policy.MinHTLC { + if amt < u.policy.MinBtcHTLC { return false } @@ -265,8 +268,8 @@ func (u *unifiedPolicy) getPolicyNetwork( func (u *unifiedPolicy) minAmt() lnwire.MilliSatoshi { min := lnwire.MaxMilliSatoshi for _, edge := range u.edges { - if edge.policy.MinHTLC < min { - min = edge.policy.MinHTLC + if edge.policy.MinBtcHTLC < min { + min = edge.policy.MinBtcHTLC } }