From 5bafdc4bc687d71f9c1f0c76c30f713bfcbfa2c1 Mon Sep 17 00:00:00 2001 From: Tadge Dryja Date: Fri, 1 Jan 2016 22:44:52 -0400 Subject: [PATCH] rpc client can tell plasma to listen, it can listen & auth --- lndc/netio.go | 7 +++++-- omnihandler.go | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ plasma.go | 2 ++ rpcserver.go | 52 ++++++++++++++++++++++++++++++----------------- 4 files changed, 95 insertions(+), 21 deletions(-) create mode 100644 omnihandler.go diff --git a/lndc/netio.go b/lndc/netio.go index bb8649fd..fbb7c32f 100644 --- a/lndc/netio.go +++ b/lndc/netio.go @@ -13,7 +13,7 @@ import ( "github.com/btcsuite/fastsha256" "github.com/codahale/chacha20poly1305" "golang.org/x/crypto/ripemd160" - "li.lan/labs/strux/lnwire" + "li.lan/labs/plasma/lnwire" ) /* good ol' OP_HASH160, which is just ripemd160(sha256(input)) */ @@ -61,6 +61,9 @@ Seesion is open! Done! Well not quite. Session is confidential but not yet authenticated. From here on, can use the Send() and Recv() functions with chacha20poly1305. ========== + +Nodes authenticate by doing a DH with their persistent identity keys, and then +exchanging hash based proofs that they got the same shared IDDH secret. The DH proof is h160(remote eph pubkey, IDDH secret) A initiates auth. @@ -83,7 +86,7 @@ session counterparty authenticated. A possible weakness of the DH proof is if B re-uses eph keys. That potentially makes *A*'s proof weaker though. A gets to choose the proof B creates. As -long as your software makes new eph keys each time, you should be +long as your software makes new eph keys each time, you should be OK. */ // Open creates and auths an lndc connections, diff --git a/omnihandler.go b/omnihandler.go new file mode 100644 index 00000000..cc22802d --- /dev/null +++ b/omnihandler.go @@ -0,0 +1,55 @@ +package main + +import ( + "fmt" + "net" + + "li.lan/labs/plasma/lnwire" +) + +// it listens for incoming messages on the lndc and hands it over +// to the OmniHandler via omnichan +func LNDCReceiver(l net.Conn, id [16]byte, r *rpcServer) error { + for { + msg := make([]byte, 65535) + // fmt.Printf("read message from %x\n", l.RemoteLNId) + n, err := l.Read(msg) + if err != nil { + fmt.Printf("read error with %x: %s\n", + id, err.Error()) + delete(r.CnMap, id) + return l.Close() + } + msg = msg[:n] + msg = append(id[:], msg...) + r.OmniChan <- msg + } +} + +// handles stuff that comes in over the wire. Not user-initiated. +func OmniHandler(r *rpcServer) { + // var err error + var from [16]byte + for { + newdata := <-r.OmniChan // blocks here + if len(newdata) < 17 { + fmt.Printf("got too short message") + continue + } + copy(from[:], newdata[:16]) + msg := newdata[16:] + msgid := msg[0] + _, ok := r.CnMap[from] + if !ok { + fmt.Printf("not connected to %x\n", from) + continue + } + // TEXT MESSAGE. SIMPLE + if msgid == lnwire.MSGID_TEXTCHAT { //it's text + fmt.Printf("msg from %x: %s\n", from, msg[1:]) + continue + } + fmt.Printf("Unknown message id byte %x", msgid) + continue + } +} diff --git a/plasma.go b/plasma.go index 7d1a77a6..f4e2a5e4 100644 --- a/plasma.go +++ b/plasma.go @@ -43,6 +43,8 @@ func main() { // Initialize, and register our implementation of the gRPC server. var opts []grpc.ServerOption rpcServer := newRpcServer(lnwallet) + // start message handler for incoming LN messages + go OmniHandler(rpcServer) grpcServer := grpc.NewServer(opts...) lnrpc.RegisterLightningServer(grpcServer, rpcServer) diff --git a/rpcserver.go b/rpcserver.go index 88af5983..82f8d444 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -6,6 +6,7 @@ import ( "log" "net" + "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcwallet/waddrmgr" "golang.org/x/net/context" @@ -19,15 +20,20 @@ var ( ) // rpcServer... -type rpcServer struct { - lnwallet *lnwallet.LightningWallet +type rpcServer struct { // doesn't count as globals I think + lnwallet *lnwallet.LightningWallet // interface to the bitcoin network + CnMap map[[16]byte]net.Conn //interface to the lightning network + OmniChan chan []byte // channel for all incoming messages from LN nodes. + // can split the OmniChan up if that is helpful. So far 1 seems OK. } var _ lnrpc.LightningServer = (*rpcServer)(nil) // newRpcServer... func newRpcServer(wallet *lnwallet.LightningWallet) *rpcServer { - return &rpcServer{wallet} + return &rpcServer{wallet, + make(map[[16]byte]net.Conn), // initialize with empty CnMap + make(chan []byte)} // init OmniChan (size 1 ok...?) } // SendMany... @@ -70,19 +76,13 @@ func (r *rpcServer) LNConnect(ctx context.Context, return resp, nil } -// TCPListen -func (r *rpcServer) TCPListen(ctx context.Context, - in *lnrpc.TCPListenRequest) (*lnrpc.TCPListenResponse, error) { - // LnListen listens on the default port for incoming connections - //ignore args and launch listener goroutine - - adr, err := r.lnwallet.ChannelDB.GetIdAdr() +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 := r.lnwallet.Manager.Address(adr) + adr2, err := l.Manager.Address(adr) if err != nil { return nil, err } @@ -91,7 +91,20 @@ func (r *rpcServer) TCPListen(ctx context.Context, return nil, err } fmt.Printf("got privkey %x\n", priv.Serialize()) - // go TCPListener() + return priv, nil +} + +// TCPListen +func (r *rpcServer) TCPListen(ctx context.Context, + in *lnrpc.TCPListenRequest) (*lnrpc.TCPListenResponse, error) { + // LnListen listens on the default port for incoming connections + //ignore args and launch listener goroutine + priv, err := getPriv(r.lnwallet) + if err != nil { + return nil, err + } + + go TCPListener(priv, r) resp := new(lnrpc.TCPListenResponse) return resp, nil @@ -105,7 +118,7 @@ func (r *rpcServer) LNChat(ctx context.Context, return resp, nil } -func TCPListener() { +func TCPListener(priv *btcec.PrivateKey, r *rpcServer) { listener, err := net.Listen("tcp", ":"+"2448") if err != nil { fmt.Printf("TCP listen error: %s\n", err.Error()) @@ -119,7 +132,7 @@ func TCPListener() { log.Printf("Listener error: %s\n", err.Error()) continue } - newConn, err := InitIncomingConn(con) + newConn, err := InitIncomingConn(priv, con) if err != nil { fmt.Printf("InitConn error: %s\n", err.Error()) continue @@ -127,16 +140,17 @@ func TCPListener() { idslice := lndc.H160(newConn.RemotePub.SerializeCompressed()) var newId [16]byte copy(newId[:], idslice[:16]) - // CnMap[newId] = newConn + r.CnMap[newId] = newConn fmt.Printf("added %x to map\n", newId) - // go LNDCReceiver(newConn, newId) + + go LNDCReceiver(newConn, newId, r) } } -func InitIncomingConn(con net.Conn) (*lndc.LNDConn, error) { +func InitIncomingConn(priv *btcec.PrivateKey, con net.Conn) (*lndc.LNDConn, error) { LNcon := new(lndc.LNDConn) LNcon.Cn = con - err := LNcon.Setup(nil) + err := LNcon.Setup(priv) if err != nil { return LNcon, err }