diff --git a/chancloser.go b/chancloser.go index bd518555..15f8e9b4 100644 --- a/chancloser.go +++ b/chancloser.go @@ -10,7 +10,6 @@ import ( "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" - "github.com/roasbeef/btcd/btcec" "github.com/roasbeef/btcd/txscript" "github.com/roasbeef/btcd/wire" "github.com/roasbeef/btcutil" @@ -410,12 +409,12 @@ func (c *channelCloser) ProcessCloseMsg(msg lnwire.Message) ([]lnwire.Message, b // transaction! We'll craft the final closing transaction so // we can broadcast it to the network. matchingSig := c.priorFeeOffers[remoteProposedFee].Signature - localSig := append( - matchingSig.Serialize(), byte(txscript.SigHashAll), - ) - remoteSig := append( - closeSignedMsg.Signature.Serialize(), byte(txscript.SigHashAll), - ) + localSigBytes := matchingSig.ToSignatureBytes() + localSig := append(localSigBytes, byte(txscript.SigHashAll)) + + remoteSigBytes := closeSignedMsg.Signature.ToSignatureBytes() + remoteSig := append(remoteSigBytes, byte(txscript.SigHashAll)) + closeTx, finalLocalBalance, err := c.cfg.channel.CompleteCooperativeClose( localSig, remoteSig, c.localDeliveryScript, c.remoteDeliveryScript, remoteProposedFee, @@ -512,7 +511,7 @@ func (c *channelCloser) proposeCloseSigned(fee btcutil.Amount) (*lnwire.ClosingS // party responds we'll be able to decide if we've agreed on fees or // not. c.lastFeeProposal = fee - parsedSig, err := btcec.ParseSignature(rawSig, btcec.S256()) + parsedSig, err := lnwire.NewSigFromRawSignature(rawSig) if err != nil { return nil, err } diff --git a/fundingmanager.go b/fundingmanager.go index 6b8c6c4d..434e7711 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -1062,14 +1062,6 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) { // the commitment transaction to the remote peer. outPoint := resCtx.reservation.FundingOutpoint() _, sig := resCtx.reservation.OurSignatures() - commitSig, err := btcec.ParseSignature(sig, btcec.S256()) - if err != nil { - fndgLog.Errorf("Unable to parse signature: %v", err) - f.failFundingFlow(fmsg.peerAddress.IdentityKey, - msg.PendingChannelID, []byte(err.Error())) - resCtx.err <- err - return - } // A new channel has almost finished the funding process. In order to // properly synchronize with the writeHandler goroutine, we add a new @@ -1095,7 +1087,14 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) { fundingCreated := &lnwire.FundingCreated{ PendingChannelID: pendingChanID, FundingPoint: *outPoint, - CommitSig: commitSig, + } + fundingCreated.CommitSig, err = lnwire.NewSigFromRawSignature(sig) + if err != nil { + fndgLog.Errorf("Unable to parse signature: %v", err) + f.failFundingFlow(fmsg.peerAddress.IdentityKey, + msg.PendingChannelID, []byte(err.Error())) + resCtx.err <- err + return } err = f.cfg.SendToPeer(fmsg.peerAddress.IdentityKey, fundingCreated) if err != nil { @@ -1148,7 +1147,7 @@ func (f *fundingManager) handleFundingCreated(fmsg *fundingCreatedMsg) { // funding transaction will broadcast after our next message. // CompleteReservationSingle will also mark the channel as 'IsPending' // in the database. - commitSig := fmsg.msg.CommitSig.Serialize() + commitSig := fmsg.msg.CommitSig.ToSignatureBytes() completeChan, err := resCtx.reservation.CompleteReservationSingle( &fundingOut, commitSig) if err != nil { @@ -1191,11 +1190,8 @@ func (f *fundingManager) handleFundingCreated(fmsg *fundingCreatedMsg) { // With their signature for our version of the commitment transaction // verified, we can now send over our signature to the remote peer. - // - // TODO(roasbeef): just have raw bytes in wire msg? avoids decoding - // then decoding shortly afterwards. _, sig := resCtx.reservation.OurSignatures() - ourCommitSig, err := btcec.ParseSignature(sig, btcec.S256()) + ourCommitSig, err := lnwire.NewSigFromRawSignature(sig) if err != nil { fndgLog.Errorf("unable to parse signature: %v", err) f.failFundingFlow(fmsg.peerAddress.IdentityKey, @@ -1344,7 +1340,7 @@ func (f *fundingManager) handleFundingSigned(fmsg *fundingSignedMsg) { // The remote peer has responded with a signature for our commitment // transaction. We'll verify the signature for validity, then commit // the state to disk as we can now open the channel. - commitSig := fmsg.msg.CommitSig.Serialize() + commitSig := fmsg.msg.CommitSig.ToSignatureBytes() completeChan, err := resCtx.reservation.CompleteReservation(nil, commitSig) if err != nil { fndgLog.Errorf("Unable to complete reservation sign complete: %v", err) @@ -2127,19 +2123,19 @@ func (f *fundingManager) newChanAnnouncement(localPubKey, remotePubKey *btcec.Pu selfBytes := localPubKey.SerializeCompressed() remoteBytes := remotePubKey.SerializeCompressed() if bytes.Compare(selfBytes, remoteBytes) == -1 { - chanAnn.NodeID1 = localPubKey - chanAnn.NodeID2 = remotePubKey - chanAnn.BitcoinKey1 = localFundingKey - chanAnn.BitcoinKey2 = remoteFundingKey + copy(chanAnn.NodeID1[:], localPubKey.SerializeCompressed()) + copy(chanAnn.NodeID2[:], remotePubKey.SerializeCompressed()) + copy(chanAnn.BitcoinKey1[:], localFundingKey.SerializeCompressed()) + copy(chanAnn.BitcoinKey2[:], remoteFundingKey.SerializeCompressed()) // If we're the first node then update the chanFlags to // indicate the "direction" of the update. chanFlags = 0 } else { - chanAnn.NodeID1 = remotePubKey - chanAnn.NodeID2 = localPubKey - chanAnn.BitcoinKey1 = remoteFundingKey - chanAnn.BitcoinKey2 = localFundingKey + copy(chanAnn.NodeID1[:], remotePubKey.SerializeCompressed()) + copy(chanAnn.NodeID2[:], localPubKey.SerializeCompressed()) + copy(chanAnn.BitcoinKey1[:], remoteFundingKey.SerializeCompressed()) + copy(chanAnn.BitcoinKey2[:], localFundingKey.SerializeCompressed()) // If we're the second node then update the chanFlags to // indicate the "direction" of the update. @@ -2171,7 +2167,12 @@ func (f *fundingManager) newChanAnnouncement(localPubKey, remotePubKey *btcec.Pu if err != nil { return nil, err } - chanUpdateAnn.Signature, err = f.cfg.SignMessage(f.cfg.IDKey, chanUpdateMsg) + sig, err := f.cfg.SignMessage(f.cfg.IDKey, chanUpdateMsg) + if err != nil { + return nil, errors.Errorf("unable to generate channel "+ + "update announcement signature: %v", err) + } + chanUpdateAnn.Signature, err = lnwire.NewSigFromSignature(sig) if err != nil { return nil, errors.Errorf("unable to generate channel "+ "update announcement signature: %v", err) @@ -2203,10 +2204,16 @@ func (f *fundingManager) newChanAnnouncement(localPubKey, remotePubKey *btcec.Pu // provide the other side with the necessary signatures required to // allow them to reconstruct the full channel announcement. proof := &lnwire.AnnounceSignatures{ - ChannelID: chanID, - ShortChannelID: shortChanID, - NodeSignature: nodeSig, - BitcoinSignature: bitcoinSig, + ChannelID: chanID, + ShortChannelID: shortChanID, + } + proof.NodeSignature, err = lnwire.NewSigFromSignature(nodeSig) + if err != nil { + return nil, err + } + proof.BitcoinSignature, err = lnwire.NewSigFromSignature(bitcoinSig) + if err != nil { + return nil, err } return &chanAnnouncement{ diff --git a/fundingmanager_test.go b/fundingmanager_test.go index ffa48b44..e00dd72f 100644 --- a/fundingmanager_test.go +++ b/fundingmanager_test.go @@ -5,6 +5,7 @@ package main import ( "fmt" "io/ioutil" + "math/big" "net" "os" "path/filepath" @@ -79,6 +80,13 @@ var ( IdentityKey: bobPubKey, Address: bobTCPAddr, } + + testSig = &btcec.Signature{ + R: new(big.Int), + S: new(big.Int), + } + _, _ = testSig.R.SetString("63724406601629180062774974542967536251589935445068131219452686511677818569431", 10) + _, _ = testSig.S.SetString("18801056069249825825291287104931333862866033135609736119018462340006816851118", 10) ) type mockNotifier struct { @@ -217,7 +225,7 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey, Notifier: chainNotifier, FeeEstimator: estimator, SignMessage: func(pubKey *btcec.PublicKey, msg []byte) (*btcec.Signature, error) { - return nil, nil + return testSig, nil }, SendAnnouncement: func(msg lnwire.Message) error { select { @@ -319,7 +327,7 @@ func recreateAliceFundingManager(t *testing.T, alice *testNode) { FeeEstimator: oldCfg.FeeEstimator, SignMessage: func(pubKey *btcec.PublicKey, msg []byte) (*btcec.Signature, error) { - return nil, nil + return testSig, nil }, SendAnnouncement: func(msg lnwire.Message) error { select { diff --git a/peer.go b/peer.go index 041198c4..b950a536 100644 --- a/peer.go +++ b/peer.go @@ -344,7 +344,9 @@ func (p *peer) loadActiveChannels(chans []*channeldb.OpenChannel) error { // TODO(roasbeef): can add helper method to get policy for // particular channel. var selfPolicy *channeldb.ChannelEdgePolicy - if info != nil && info.NodeKey1.IsEqual(p.server.identityPriv.PubKey()) { + if info != nil && bytes.Equal(info.NodeKey1Bytes[:], + p.server.identityPriv.PubKey().SerializeCompressed()) { + selfPolicy = p1 } else { selfPolicy = p2 @@ -900,8 +902,7 @@ func messageSummary(msg lnwire.Message) string { case *lnwire.NodeAnnouncement: return fmt.Sprintf("node=%x, update_time=%v", - msg.NodeID.SerializeCompressed(), - time.Unix(int64(msg.Timestamp), 0)) + msg.NodeID, time.Unix(int64(msg.Timestamp), 0)) case *lnwire.Ping: // No summary. @@ -957,13 +958,6 @@ func (p *peer) logWireMessage(msg lnwire.Message, read bool) { } case *lnwire.RevokeAndAck: m.NextRevocationKey.Curve = nil - case *lnwire.NodeAnnouncement: - m.NodeID.Curve = nil - case *lnwire.ChannelAnnouncement: - m.NodeID1.Curve = nil - m.NodeID2.Curve = nil - m.BitcoinKey1.Curve = nil - m.BitcoinKey2.Curve = nil case *lnwire.AcceptChannel: m.FundingKey.Curve = nil m.RevocationPoint.Curve = nil @@ -1774,16 +1768,17 @@ func createGetLastUpdate(router *routing.ChannelRouter, "channel by ShortChannelID(%v)", chanID) } + // If we're the outgoing node on the first edge, then that + // means the second edge is our policy. Otherwise, the first + // edge is our policy. var local *channeldb.ChannelEdgePolicy - if bytes.Compare(edge1.Node.PubKey.SerializeCompressed(), - pubKey[:]) == 0 { + if bytes.Equal(edge1.Node.PubKeyBytes[:], pubKey[:]) { local = edge2 } else { local = edge1 } update := &lnwire.ChannelUpdate{ - Signature: local.Signature, ChainHash: info.ChainHash, ShortChannelID: lnwire.NewShortChanIDFromInt(local.ChannelID), Timestamp: uint32(local.LastUpdate.Unix()), @@ -1793,6 +1788,10 @@ func createGetLastUpdate(router *routing.ChannelRouter, BaseFee: uint32(local.FeeBaseMSat), FeeRate: uint32(local.FeeProportionalMillionths), } + update.Signature, err = lnwire.NewSigFromRawSignature(local.SigBytes) + if err != nil { + return nil, err + } hswcLog.Debugf("Sending latest channel_update: %v", spew.Sdump(update)) diff --git a/peer_test.go b/peer_test.go index 90d7d694..4e9f93f0 100644 --- a/peer_test.go +++ b/peer_test.go @@ -14,8 +14,6 @@ import ( "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" - "github.com/roasbeef/btcd/btcec" - "github.com/roasbeef/btcd/txscript" "github.com/roasbeef/btcd/wire" "github.com/roasbeef/btcutil" ) @@ -95,8 +93,7 @@ func TestPeerChannelClosureAcceptFeeResponder(t *testing.T) { t.Fatalf("error creating close proposal: %v", err) } - initSig := append(initiatorSig, byte(txscript.SigHashAll)) - parsedSig, err := btcec.ParseSignature(initSig, btcec.S256()) + parsedSig, err := lnwire.NewSigFromRawSignature(initiatorSig) if err != nil { t.Fatalf("error parsing signature: %v", err) } @@ -183,7 +180,7 @@ func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) { if err != nil { t.Fatalf("unable to create close proposal: %v", err) } - parsedSig, err := btcec.ParseSignature(closeSig, btcec.S256()) + parsedSig, err := lnwire.NewSigFromRawSignature(closeSig) if err != nil { t.Fatalf("unable to parse signature: %v", err) } @@ -295,7 +292,7 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) { t.Fatalf("error creating close proposal: %v", err) } - parsedSig, err := btcec.ParseSignature(initiatorSig, btcec.S256()) + parsedSig, err := lnwire.NewSigFromRawSignature(initiatorSig) if err != nil { t.Fatalf("error parsing signature: %v", err) } @@ -339,7 +336,7 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) { t.Fatalf("error creating close proposal: %v", err) } - parsedSig, err = btcec.ParseSignature(initiatorSig, btcec.S256()) + parsedSig, err = lnwire.NewSigFromRawSignature(initiatorSig) if err != nil { t.Fatalf("error parsing signature: %v", err) } @@ -384,8 +381,7 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) { t.Fatalf("error creating close proposal: %v", err) } - initSig := append(initiatorSig, byte(txscript.SigHashAll)) - parsedSig, err = btcec.ParseSignature(initSig, btcec.S256()) + parsedSig, err = lnwire.NewSigFromRawSignature(initiatorSig) if err != nil { t.Fatalf("error parsing signature: %v", err) } @@ -478,7 +474,7 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) { if err != nil { t.Fatalf("unable to create close proposal: %v", err) } - parsedSig, err := btcec.ParseSignature(closeSig, btcec.S256()) + parsedSig, err := lnwire.NewSigFromRawSignature(closeSig) if err != nil { t.Fatalf("unable to parse signature: %v", err) } @@ -544,7 +540,7 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) { t.Fatalf("error creating close proposal: %v", err) } - parsedSig, err = btcec.ParseSignature(responderSig, btcec.S256()) + parsedSig, err = lnwire.NewSigFromRawSignature(responderSig) if err != nil { t.Fatalf("error parsing signature: %v", err) } @@ -590,8 +586,7 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) { t.Fatalf("error creating close proposal: %v", err) } - respSig := append(responderSig, byte(txscript.SigHashAll)) - parsedSig, err = btcec.ParseSignature(respSig, btcec.S256()) + parsedSig, err = lnwire.NewSigFromRawSignature(responderSig) if err != nil { t.Fatalf("error parsing signature: %v", err) } diff --git a/rpcserver.go b/rpcserver.go index 414c6d3d..c709e998 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -535,11 +535,14 @@ func (r *rpcServer) VerifyMessage(ctx context.Context, } pubKeyHex := hex.EncodeToString(pubKey.SerializeCompressed()) + var pub [33]byte + copy(pub[:], pubKey.SerializeCompressed()) + // Query the channel graph to ensure a node in the network with active // channels signed the message. // TODO(phlip9): Require valid nodes to have capital in active channels. graph := r.server.chanDB.ChannelGraph() - _, active, err := graph.HasLightningNode(pubKey) + _, active, err := graph.HasLightningNode(pub) if err != nil { return nil, fmt.Errorf("failed to query graph: %v", err) } @@ -1576,8 +1579,8 @@ func (r *rpcServer) savePayment(route *routing.Route, amount lnwire.MilliSatoshi paymentPath := make([][33]byte, len(route.Hops)) for i, hop := range route.Hops { - hopPub := hop.Channel.Node.PubKey.SerializeCompressed() - copy(paymentPath[i][:], hopPub) + hopPub := hop.Channel.Node.PubKeyBytes + copy(paymentPath[i][:], hopPub[:]) } payment := &channeldb.OutgoingPayment{ @@ -2407,7 +2410,7 @@ func (r *rpcServer) DescribeGraph(ctx context.Context, nodeColor := fmt.Sprintf("#%02x%02x%02x", node.Color.R, node.Color.G, node.Color.B) resp.Nodes = append(resp.Nodes, &lnrpc.LightningNode{ LastUpdate: uint32(node.LastUpdate.Unix()), - PubKey: hex.EncodeToString(node.PubKey.SerializeCompressed()), + PubKey: hex.EncodeToString(node.PubKeyBytes[:]), Addresses: nodeAddrs, Alias: node.Alias, Color: nodeColor, @@ -2455,8 +2458,8 @@ func marshalDbEdge(edgeInfo *channeldb.ChannelEdgeInfo, ChanPoint: edgeInfo.ChannelPoint.String(), // TODO(roasbeef): update should be on edge info itself LastUpdate: uint32(lastUpdate), - Node1Pub: hex.EncodeToString(edgeInfo.NodeKey1.SerializeCompressed()), - Node2Pub: hex.EncodeToString(edgeInfo.NodeKey2.SerializeCompressed()), + Node1Pub: hex.EncodeToString(edgeInfo.NodeKey1Bytes[:]), + Node2Pub: hex.EncodeToString(edgeInfo.NodeKey2Bytes[:]), Capacity: int64(edgeInfo.Capacity), } diff --git a/server.go b/server.go index 44470974..86a9f06d 100644 --- a/server.go +++ b/server.go @@ -258,11 +258,11 @@ func newServer(listenAddrs []string, chanDB *channeldb.DB, cc *chainControl, HaveNodeAnnouncement: true, LastUpdate: time.Now(), Addresses: selfAddrs, - PubKey: privKey.PubKey(), Alias: nodeAlias.String(), Features: s.globalFeatures, Color: color, } + copy(selfNode.PubKeyBytes[:], privKey.PubKey().SerializeCompressed()) // If our information has changed since our last boot, then we'll // re-sign our node announcement so a fresh authenticated version of it @@ -272,31 +272,35 @@ func newServer(listenAddrs []string, chanDB *channeldb.DB, cc *chainControl, nodeAnn := &lnwire.NodeAnnouncement{ Timestamp: uint32(selfNode.LastUpdate.Unix()), Addresses: selfNode.Addresses, - NodeID: selfNode.PubKey, + NodeID: selfNode.PubKeyBytes, Alias: nodeAlias, Features: selfNode.Features.RawFeatureVector, RGBColor: color, } - selfNode.AuthSig, err = discovery.SignAnnouncement(s.nodeSigner, - s.identityPriv.PubKey(), nodeAnn, + authSig, err := discovery.SignAnnouncement( + s.nodeSigner, s.identityPriv.PubKey(), nodeAnn, ) if err != nil { return nil, fmt.Errorf("unable to generate signature for "+ "self node announcement: %v", err) } + selfNode.AuthSigBytes = authSig.Serialize() + s.currentNodeAnn = nodeAnn + if err := chanGraph.SetSourceNode(selfNode); err != nil { return nil, fmt.Errorf("can't set self node: %v", err) } - nodeAnn.Signature = selfNode.AuthSig - s.currentNodeAnn = nodeAnn - + nodeAnn.Signature, err = lnwire.NewSigFromRawSignature(selfNode.AuthSigBytes) + if err != nil { + return nil, err + } s.chanRouter, err = routing.New(routing.Config{ Graph: chanGraph, Chain: cc.chainIO, ChainView: cc.chainView, - SendToSwitch: func(firstHop *btcec.PublicKey, + SendToSwitch: func(firstHopPub [33]byte, htlcAdd *lnwire.UpdateAddHTLC, circuit *sphinx.Circuit) ([32]byte, error) { @@ -307,9 +311,6 @@ func newServer(listenAddrs []string, chanDB *channeldb.DB, cc *chainControl, OnionErrorDecrypter: sphinx.NewOnionErrorDecrypter(circuit), } - var firstHopPub [33]byte - copy(firstHopPub[:], firstHop.SerializeCompressed()) - return s.htlcSwitch.SendHTLC(firstHopPub, htlcAdd, errorDecryptor) }, ChannelPruneExpiry: time.Duration(time.Hour * 24 * 14), @@ -806,11 +807,19 @@ func (s *server) genNodeAnnouncement( } s.currentNodeAnn.Timestamp = newStamp - s.currentNodeAnn.Signature, err = discovery.SignAnnouncement( + sig, err := discovery.SignAnnouncement( s.nodeSigner, s.identityPriv.PubKey(), s.currentNodeAnn, ) + if err != nil { + return lnwire.NodeAnnouncement{}, err + } - return *s.currentNodeAnn, err + s.currentNodeAnn.Signature, err = lnwire.NewSigFromSignature(sig) + if err != nil { + return lnwire.NodeAnnouncement{}, err + } + + return *s.currentNodeAnn, nil } type nodeAddresses struct { @@ -870,7 +879,7 @@ func (s *server) establishPersistentConnections() error { _ *channeldb.ChannelEdgeInfo, policy, _ *channeldb.ChannelEdgePolicy) error { - pubStr := string(policy.Node.PubKey.SerializeCompressed()) + pubStr := string(policy.Node.PubKeyBytes[:]) // Add addresses from channel graph/NodeAnnouncements to the // list of addresses we'll connect to. If there are duplicates @@ -906,11 +915,15 @@ func (s *server) establishPersistentConnections() error { } } - nodeAddrsMap[pubStr] = &nodeAddresses{ - pubKey: policy.Node.PubKey, + n := &nodeAddresses{ addresses: addrs, } + n.pubKey, err = policy.Node.PubKey() + if err != nil { + return err + } + nodeAddrsMap[pubStr] = n return nil }) if err != nil && err != channeldb.ErrGraphNoEdgesFound {