diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index e69de29b..00000000 diff --git a/cmd/lnshell/commands.go b/cmd/lnshell/commands.go index cec85ea5..70a63598 100644 --- a/cmd/lnshell/commands.go +++ b/cmd/lnshell/commands.go @@ -1,6 +1,7 @@ package main import ( + "encoding/hex" "fmt" "time" @@ -70,18 +71,29 @@ func LnListen(args []string) error { // For testing. Syntax: lnhi hello world func LnChat(args []string) error { + var err error + if len(args) < 2 { + return fmt.Errorf("too short, need: lnhi 32hexcharLNID message.\n") + } + req := new(lnrpc.LnChatRequest) + req.DestID, err = hex.DecodeString(args[0]) + if err != nil { + return err + } + if len(req.DestID) != 16 { + return fmt.Errorf("requested destination %x is %d bytes, expenct 16\n", + req.DestID, len(req.DestID)) + } var chat string - for _, s := range args { + for _, s := range args[1:] { chat += s + " " } - // msg := append([]byte{lnwire.MSGID_TEXTCHAT}, []byte(chat)...) - fmt.Printf("will send text message: %s\n", chat) - req := new(lnrpc.LnChatRequest) - req.DestID = []byte("testID") + fmt.Printf("will send to %x text message: %s\n", req.DestID, chat) + req.Msg = chat - _, err := z.LNChat(stub, req) + _, err = z.LNChat(stub, req) if err != nil { return err } diff --git a/omnihandler.go b/omnihandler.go index cc22802d..a314eb4e 100644 --- a/omnihandler.go +++ b/omnihandler.go @@ -49,6 +49,7 @@ func OmniHandler(r *rpcServer) { fmt.Printf("msg from %x: %s\n", from, msg[1:]) continue } + // Based on MSGID, hand it off to functions fmt.Printf("Unknown message id byte %x", msgid) continue } diff --git a/peer.go b/peer.go index 2815a966..e112eda5 100644 --- a/peer.go +++ b/peer.go @@ -69,7 +69,7 @@ type peer struct { //} // TODO(roasbeef): akward import, just rename to Wallet? - wallet *lnwallet.LightningWallet + wallet *lnwallet.LightningWallet // (tadge: what is this for?) // Only will be set if the channel is in the 'pending' state. reservation *lnwallet.ChannelReservation diff --git a/rpcserver.go b/rpcserver.go index 82f8d444..c3a6b95b 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -13,6 +13,8 @@ import ( "li.lan/labs/plasma/lndc" "li.lan/labs/plasma/lnrpc" "li.lan/labs/plasma/lnwallet" + "li.lan/labs/plasma/lnwire" + "li.lan/labs/strux" ) var ( @@ -36,6 +38,25 @@ func newRpcServer(wallet *lnwallet.LightningWallet) *rpcServer { make(chan []byte)} // init OmniChan (size 1 ok...?) } +// getPriv gets the identity private key out of the wallet DB +func getPriv(l *lnwallet.LightningWallet) (*btcec.PrivateKey, error) { + adr, err := l.ChannelDB.GetIdAdr() + if err != nil { + return nil, err + } + fmt.Printf("got ID address: %s\n", adr.String()) + adr2, err := l.Manager.Address(adr) + if err != nil { + return nil, err + } + priv, err := adr2.(waddrmgr.ManagedPubKeyAddress).PrivKey() + if err != nil { + return nil, err + } + fmt.Printf("got privkey %x\n", priv.Serialize()) // may want to remove this :) + return priv, nil +} + // SendMany... func (r *rpcServer) SendMany(ctx context.Context, in *lnrpc.SendManyRequest) (*lnrpc.SendManyResponse, error) { @@ -70,30 +91,60 @@ func (r *rpcServer) NewAddress(ctx context.Context, in *lnrpc.NewAddressRequest) func (r *rpcServer) LNConnect(ctx context.Context, in *lnrpc.LNConnectRequest) (*lnrpc.LnConnectResponse, error) { + var err error + + if len(in.IdAtHost) == 0 { + return nil, fmt.Errorf("need: lnc pubkeyhash@hostname") + } + var newNode strux.LNAdr + + err = newNode.ParseFromString(in.IdAtHost) + if err != nil { + return nil, err + } + if _, ok := r.CnMap[newNode.LNId]; ok { + return nil, fmt.Errorf("Already connected to %x", newNode.LNId) + } + if newNode.Host == "" { // do PBX connect; leave for now + return nil, fmt.Errorf("no hostname") + } + priv, err := getPriv(r.lnwallet) + if err != nil { + return nil, err + } + + // dial TCP + newConn := new(lndc.LNDConn) + newConn.Cn, err = net.Dial("tcp", newNode.Host+":"+"2448") + if err != nil { + return nil, err + } + // TODO differentiate; right now only uses PKH + if newNode.PubKey != nil { // have pubkey, use that + err = newConn.Open(priv, newNode.Adr.ScriptAddress()) + if err != nil { + return nil, err + } + } else { // only have address (pubkey hash), use that + err = newConn.Open(priv, newNode.Adr.ScriptAddress()) + if err != nil { + return nil, err + } + } + + idslice := lndc.H160(newConn.RemotePub.SerializeCompressed()) + var newId [16]byte + copy(newId[:], idslice[:16]) + r.CnMap[newId] = newConn + log.Printf("added %x to map\n", newId) + + go LNDCReceiver(newConn, newId, r) + resp := new(lnrpc.LnConnectResponse) - resp.LnID = []byte("ya") - + resp.LnID = newId[:] return resp, nil } -func getPriv(l *lnwallet.LightningWallet) (*btcec.PrivateKey, error) { - adr, err := l.ChannelDB.GetIdAdr() - if err != nil { - return nil, err - } - fmt.Printf("got ID address: %s\n", adr.String()) - adr2, err := l.Manager.Address(adr) - if err != nil { - return nil, err - } - priv, err := adr2.(waddrmgr.ManagedPubKeyAddress).PrivKey() - if err != nil { - return nil, err - } - fmt.Printf("got privkey %x\n", priv.Serialize()) - return priv, nil -} - // TCPListen func (r *rpcServer) TCPListen(ctx context.Context, in *lnrpc.TCPListenRequest) (*lnrpc.TCPListenResponse, error) { @@ -114,6 +165,30 @@ func (r *rpcServer) TCPListen(ctx context.Context, func (r *rpcServer) LNChat(ctx context.Context, in *lnrpc.LnChatRequest) (*lnrpc.LnChatResponse, error) { log.Printf("requested to chat, message: %s\n", in.Msg) + + var dest [16]byte + if len(in.DestID) != 16 { + return nil, fmt.Errorf("Expect 16 byte destination Id, got %d byte", + len(in.DestID)) + } + copy(dest[:], in.DestID) + if len(in.Msg) == 0 { + return nil, fmt.Errorf("you have to say something") + } + if len(r.CnMap) == 0 { // This check is redundant. May still help though. + return nil, fmt.Errorf("Not connected to anyone") + } + if _, ok := r.CnMap[dest]; !ok { + return nil, fmt.Errorf("dest %x not connected", dest) + } + + msg := append([]byte{lnwire.MSGID_TEXTCHAT}, []byte(in.Msg)...) + + _, err := r.CnMap[dest].Write(msg) + if err != nil { + return nil, err + } + resp := new(lnrpc.LnChatResponse) return resp, nil }