trying to store private identity key. Doesn't work.
This commit is contained in:
parent
8bd8293c8c
commit
e70c6aa367
@ -21,6 +21,8 @@ var (
|
||||
closedChannelBucket = []byte("c")
|
||||
activeChanKey = []byte("a")
|
||||
|
||||
identityKey = []byte("idkey")
|
||||
|
||||
// TODO(roasbeef): replace w/ tesnet-L also revisit dependancy...
|
||||
ActiveNetParams = &chaincfg.TestNet3Params
|
||||
)
|
||||
@ -95,6 +97,35 @@ type OpenChannel struct {
|
||||
CreationTime time.Time
|
||||
}
|
||||
|
||||
// These don't really belong here but not sure which other file to put them yet.
|
||||
// PutIdKey saves the private key used for
|
||||
func (c *DB) PutIdKey(priv *btcec.PrivateKey) error {
|
||||
return c.namespace.Update(func(tx walletdb.Tx) error {
|
||||
// Get the bucket dedicated to storing the meta-data for open
|
||||
// channels.
|
||||
rootBucket := tx.RootBucket()
|
||||
return rootBucket.Put(identityKey, priv.Serialize())
|
||||
})
|
||||
}
|
||||
|
||||
// GetIdKey returns the IdKey
|
||||
func (c *DB) GetIdKey() (*btcec.PrivateKey, error) {
|
||||
var privbytes []byte
|
||||
err := c.namespace.View(func(tx walletdb.Tx) error {
|
||||
// Get the bucket dedicated to storing the meta-data for open
|
||||
// channels.
|
||||
rootBucket := tx.RootBucket()
|
||||
privbytes = rootBucket.Get(identityKey)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
priv, _ := btcec.PrivKeyFromBytes(btcec.S256(), privbytes)
|
||||
return priv, nil
|
||||
}
|
||||
|
||||
// PutOpenChannel...
|
||||
func (c *DB) PutOpenChannel(channel *OpenChannel) error {
|
||||
return c.namespace.Update(func(tx walletdb.Tx) error {
|
||||
|
@ -57,7 +57,14 @@ func LnConnect(args []string) error {
|
||||
// LnListen listens on the default port for incoming connections
|
||||
func LnListen(args []string) error {
|
||||
|
||||
fmt.Printf("will start TCP port listener\n")
|
||||
req := new(lnrpc.TCPListenRequest)
|
||||
req.Hostport = "0.0.0.0:2448"
|
||||
_, err := z.TCPListen(stub, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("started TCP port listener\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
633
lndc/netio.go
Normal file
633
lndc/netio.go
Normal file
@ -0,0 +1,633 @@
|
||||
package lndc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/cipher"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/fastsha256"
|
||||
"github.com/codahale/chacha20poly1305"
|
||||
"golang.org/x/crypto/ripemd160"
|
||||
"li.lan/labs/strux/lnwire"
|
||||
)
|
||||
|
||||
/* good ol' OP_HASH160, which is just ripemd160(sha256(input)) */
|
||||
func H160(input []byte) []byte {
|
||||
rp := ripemd160.New()
|
||||
shaout := fastsha256.Sum256(input)
|
||||
_, _ = rp.Write(shaout[:])
|
||||
return rp.Sum(nil)
|
||||
}
|
||||
|
||||
// Lightning Network Data Conection. Encrypted.
|
||||
type LNDConn struct {
|
||||
Version uint8
|
||||
Cn net.Conn
|
||||
RemotePub *btcec.PublicKey
|
||||
RemoteLNId [16]byte
|
||||
MyNonceInt uint64
|
||||
RemoteNonceInt uint64
|
||||
// if Authed == false, the RemotePub is the EPHEMERAL key.
|
||||
// once authed == true, RemotePub is who you're actually talking to.
|
||||
Authed bool
|
||||
// chachaStream saves some time as you don't have to init it with
|
||||
// the session key every time. Make SessionKey redundant; remove later
|
||||
chachaStream cipher.AEAD
|
||||
|
||||
// ViaPbx specifies whether this is a direct TCP connection or an
|
||||
// encapsulated PBX connection.
|
||||
// if going ViaPbx, Cn isn't used
|
||||
// channels are used for Read() and Write(),
|
||||
// which are filled by the PBXhandler.
|
||||
ViaPbx bool
|
||||
PbxIncoming chan []byte
|
||||
PbxOutgoing chan []byte
|
||||
}
|
||||
|
||||
/* new & improved tcp open session.
|
||||
There's connector A and listener B. Once the connection is set up there's no
|
||||
difference, but there can be during the setup.
|
||||
Setup:
|
||||
1 -> A sends B ephemeral secp256k1 pubkey (33 bytes)
|
||||
2 <- B sends A ephemeral secp256k1 pubkey (33 bytes)
|
||||
A and B do DH, get a shared secret.
|
||||
==========
|
||||
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.
|
||||
==========
|
||||
The DH proof is h160(remote eph pubkey, IDDH secret)
|
||||
A initiates auth.
|
||||
|
||||
If A does not know B's pubkey but only B's pubkey hash:
|
||||
|
||||
1 -> A sends [PubKeyA, PubKeyHashB] (53 bytes)
|
||||
B computes ID pubkey DH
|
||||
2 <- B sends [PubkeyB, DH proof] (53 bytes)
|
||||
3 -> A sends DH proof (20 bytes)
|
||||
done.
|
||||
|
||||
This exchange can be sped up if A already knows B's pubkey:
|
||||
|
||||
A already knows who they're talking to, or trying to talk to
|
||||
1 -> A sends [PubKeyA, PubkeyHashB, DH proof] (73 bytes)
|
||||
2 <- B sends DH proof (20 bytes)
|
||||
|
||||
A and B both verify those H160 hashes, and if matching consider their
|
||||
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
|
||||
*/
|
||||
|
||||
// Open creates and auths an lndc connections,
|
||||
// after the TCP or pbx connection is already assigned / dialed.
|
||||
func (lndc *LNDConn) Open(
|
||||
me *btcec.PrivateKey, remote []byte) error {
|
||||
// make TCP connection to listening host
|
||||
var err error
|
||||
|
||||
if len(remote) != 33 && len(remote) != 20 {
|
||||
return fmt.Errorf("must supply either remote pubkey or pubkey hash")
|
||||
}
|
||||
// calc remote LNId; need this for creating pbx connections
|
||||
// just because LNid is in the struct does not mean it's authed!
|
||||
if len(remote) == 20 {
|
||||
copy(lndc.RemoteLNId[:], remote[:16])
|
||||
} else {
|
||||
theirAdr := H160(remote)
|
||||
copy(lndc.RemoteLNId[:], theirAdr[:16])
|
||||
}
|
||||
|
||||
// make up an ephtemeral keypair. Doesn't exit this function.
|
||||
myEph, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sned 1. Send my ephemeral pubkey. Can add version bits.
|
||||
err = lndc.writeClear(myEph.PubKey().SerializeCompressed())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// read their ephemeral pubkey
|
||||
TheirEphPubBytes, err := lndc.readClear()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// deserialize their ephemeral pubkey
|
||||
TheirEphPub, err := btcec.ParsePubKey(TheirEphPubBytes, btcec.S256())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// do non-interactive diffie with ephemeral pubkeys
|
||||
// sha256 for good luck
|
||||
sessionKey :=
|
||||
fastsha256.Sum256(btcec.GenerateSharedSecret(myEph, TheirEphPub))
|
||||
|
||||
lndc.chachaStream, err = chacha20poly1305.New(sessionKey[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// display private key for debug only
|
||||
fmt.Printf("made session key %x\n", sessionKey)
|
||||
|
||||
lndc.MyNonceInt = 1 << 63
|
||||
lndc.RemoteNonceInt = 0
|
||||
|
||||
lndc.RemotePub = TheirEphPub
|
||||
lndc.Authed = false
|
||||
|
||||
// session is now open and confidential but not yet authenticated.
|
||||
// So auth!
|
||||
if len(remote) == 20 { // only know pubkey hash (20 bytes)
|
||||
return lndc.AuthPKH(me, remote, myEph.PubKey().SerializeCompressed())
|
||||
} else { // must be 33 byte pubkey
|
||||
return lndc.AuthPubKey(me, remote, myEph.PubKey().SerializeCompressed())
|
||||
}
|
||||
}
|
||||
|
||||
// TcpListen takes a lndc that's just connected, and sets it up.
|
||||
// Call this just after a connection comes in.
|
||||
// calls AuthListen, waiting for the auth step before returning.
|
||||
// in the case of a pbx connection, there is no lndc.Cn
|
||||
func (lndc *LNDConn) Setup(me *btcec.PrivateKey) error {
|
||||
var err error
|
||||
var TheirEphPubBytes []byte
|
||||
|
||||
TheirEphPubBytes, err = lndc.readClear()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(TheirEphPubBytes) != 33 {
|
||||
return fmt.Errorf("Got invalid %d byte eph pubkey %x\n",
|
||||
len(TheirEphPubBytes), TheirEphPubBytes)
|
||||
}
|
||||
// deserialize their ephemeral pubkey
|
||||
TheirEphPub, err := btcec.ParsePubKey(TheirEphPubBytes, btcec.S256())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// their key looks OK, make our own
|
||||
myEph, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// and send out our eph key
|
||||
err = lndc.writeClear(myEph.PubKey().SerializeCompressed())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// do non-interactive diffie with ephemeral pubkeys
|
||||
// sha256 for good luck
|
||||
sessionKey :=
|
||||
fastsha256.Sum256(btcec.GenerateSharedSecret(myEph, TheirEphPub))
|
||||
|
||||
lndc.chachaStream, err = chacha20poly1305.New(sessionKey[:])
|
||||
|
||||
// display private key for debug only
|
||||
fmt.Printf("made session key %x\n", sessionKey)
|
||||
|
||||
lndc.RemoteNonceInt = 1 << 63
|
||||
lndc.MyNonceInt = 0
|
||||
|
||||
lndc.RemotePub = TheirEphPub
|
||||
lndc.Authed = false
|
||||
|
||||
// session is open and confidential but not yet authenticated.
|
||||
// Listen for auth message
|
||||
return lndc.AuthListen(me, myEph.PubKey().SerializeCompressed())
|
||||
}
|
||||
|
||||
func (lndc *LNDConn) AuthListen(
|
||||
myId *btcec.PrivateKey, localEphPubBytes []byte) error {
|
||||
|
||||
var err error
|
||||
slice := make([]byte, 65535)
|
||||
n, err := lndc.Read(slice)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("read %d bytes\n", n)
|
||||
slice = slice[:n]
|
||||
if err != nil {
|
||||
fmt.Printf("Read error: %s\n", err.Error())
|
||||
err2 := lndc.Close()
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
authmsg := slice
|
||||
if len(authmsg) != 53 && len(authmsg) != 73 {
|
||||
err = lndc.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf(
|
||||
"Got auth message of %d bytes, expect 53 or 73", len(authmsg))
|
||||
}
|
||||
theirPub, err := btcec.ParsePubKey(authmsg[:33], btcec.S256())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
myPKH := H160(myId.PubKey().SerializeCompressed())
|
||||
if bytes.Equal(myPKH, authmsg[33:53]) == false {
|
||||
err = lndc.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf(
|
||||
"remote host asking for PKH %x, that's not me", authmsg[33:53])
|
||||
}
|
||||
|
||||
// do DH with id keys
|
||||
idDH := fastsha256.Sum256(btcec.GenerateSharedSecret(myId, theirPub))
|
||||
myDHproof := H160(append(lndc.RemotePub.SerializeCompressed(), idDH[:]...))
|
||||
theirDHproof := H160(append(localEphPubBytes, idDH[:]...))
|
||||
if len(authmsg) == 73 { // quick mode
|
||||
// verify their DH proof
|
||||
if bytes.Equal(authmsg[53:], theirDHproof) == false {
|
||||
err = lndc.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf(
|
||||
"Invalid DH proof from %s", lndc.Cn.RemoteAddr().String())
|
||||
}
|
||||
// looks good, send my own
|
||||
_, err = lndc.Write(myDHproof)
|
||||
if err != nil {
|
||||
err2 := lndc.Close()
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
return err
|
||||
}
|
||||
// and we're authed
|
||||
} else { // 53 byte, they don't know my pubkey
|
||||
msg := append(myId.PubKey().SerializeCompressed(), myDHproof...)
|
||||
_, err = lndc.Write(msg)
|
||||
if err != nil {
|
||||
err2 := lndc.Close()
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
return err
|
||||
}
|
||||
resp := make([]byte, 65535)
|
||||
n, err := lndc.Read(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp = resp[:n]
|
||||
|
||||
if n != 20 {
|
||||
err2 := lndc.Close()
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
fmt.Errorf("expected 20 byte DH proof, got %d", n)
|
||||
}
|
||||
|
||||
// verify their DH proof
|
||||
if bytes.Equal(resp, theirDHproof) == false {
|
||||
err = lndc.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("Invalid DH proof %x", theirDHproof)
|
||||
}
|
||||
//proof looks good, auth
|
||||
}
|
||||
lndc.RemotePub = theirPub
|
||||
theirAdr := H160(theirPub.SerializeCompressed())
|
||||
copy(lndc.RemoteLNId[:], theirAdr[:16])
|
||||
lndc.Authed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lndc *LNDConn) AuthPKH(
|
||||
myId *btcec.PrivateKey, theirPKH, localEphPubBytes []byte) error {
|
||||
var err error
|
||||
|
||||
if myId == nil {
|
||||
return fmt.Errorf("can't auth: supplied privkey is nil")
|
||||
}
|
||||
if lndc.Authed {
|
||||
return fmt.Errorf("%s already authed", lndc.RemotePub)
|
||||
}
|
||||
if len(theirPKH) != 20 {
|
||||
return fmt.Errorf("remote PKH must be 20 bytes, got %d", len(theirPKH))
|
||||
}
|
||||
|
||||
// send 53 bytes; my pubkey, and remote pubkey hash
|
||||
msg := myId.PubKey().SerializeCompressed()
|
||||
msg = append(msg, theirPKH...)
|
||||
|
||||
_, err = lndc.Write(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// wait for their response.
|
||||
// TODO add timeout here
|
||||
resp := make([]byte, 65535)
|
||||
n, err := lndc.Read(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp = resp[:n]
|
||||
// response should be 53 bytes, their pubkey and DH proof
|
||||
if n != 53 {
|
||||
return fmt.Errorf(
|
||||
"PKH auth response should be 53 bytes, got %d", len(resp))
|
||||
}
|
||||
theirPub, err := btcec.ParsePubKey(resp[:33], btcec.S256())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
idDH := fastsha256.Sum256(btcec.GenerateSharedSecret(myId, theirPub))
|
||||
fmt.Printf("made idDH %x\n", idDH)
|
||||
|
||||
theirDHproof := H160(append(localEphPubBytes, idDH[:]...))
|
||||
// verify their DH proof
|
||||
if bytes.Equal(resp[33:], theirDHproof) == false {
|
||||
return fmt.Errorf("Invalid DH proof %x", theirDHproof)
|
||||
}
|
||||
// their DH proof checks out, send our own
|
||||
myDHproof := H160(append(lndc.RemotePub.SerializeCompressed(), idDH[:]...))
|
||||
_, err = lndc.Write(myDHproof)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// proof sent, auth complete
|
||||
lndc.RemotePub = theirPub
|
||||
theirAdr := H160(theirPub.SerializeCompressed())
|
||||
copy(lndc.RemoteLNId[:], theirAdr[:16])
|
||||
lndc.Authed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lndc *LNDConn) AuthPubKey(
|
||||
myId *btcec.PrivateKey, remotePubBytes, localEphPubBytes []byte) error {
|
||||
|
||||
var err error
|
||||
if myId == nil {
|
||||
return fmt.Errorf("can't auth: supplied privkey is nil")
|
||||
}
|
||||
if lndc.Authed {
|
||||
return fmt.Errorf("%s already authed", lndc.RemotePub)
|
||||
}
|
||||
theirPub, err := btcec.ParsePubKey(remotePubBytes, btcec.S256())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
theirPKH := H160(remotePubBytes)
|
||||
// I know enough to generate DH, do so
|
||||
idDH := fastsha256.Sum256(btcec.GenerateSharedSecret(myId, theirPub))
|
||||
myDHproof := H160(append(lndc.RemotePub.SerializeCompressed(), idDH[:]...))
|
||||
// message is 73 bytes; my pubkey, their pubkey hash, DH proof
|
||||
msg := myId.PubKey().SerializeCompressed()
|
||||
msg = append(msg, theirPKH...)
|
||||
msg = append(msg, myDHproof...)
|
||||
|
||||
_, err = lndc.Write(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp := make([]byte, 65535)
|
||||
n, err := lndc.Read(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp = resp[:n]
|
||||
if n != 20 {
|
||||
fmt.Errorf("expected 20 byte DH proof, got %d", len(resp))
|
||||
}
|
||||
|
||||
theirDHproof := H160(append(localEphPubBytes, idDH[:]...))
|
||||
// verify their DH proof
|
||||
if bytes.Equal(resp, theirDHproof) == false {
|
||||
return fmt.Errorf("Invalid DH proof %x", theirDHproof)
|
||||
}
|
||||
// proof checks out, auth complete
|
||||
lndc.RemotePub = theirPub
|
||||
theirAdr := H160(theirPub.SerializeCompressed())
|
||||
copy(lndc.RemoteLNId[:], theirAdr[:16])
|
||||
lndc.Authed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lndc *LNDConn) WhoAreYou(host string) (*btcec.PublicKey, error) {
|
||||
var err error
|
||||
if lndc.Cn == nil {
|
||||
return nil, fmt.Errorf("no connection to ask on")
|
||||
}
|
||||
fmt.Printf("connecting to address %s\n", host)
|
||||
// make TCP connection to listening host
|
||||
lndc.Cn, err = net.Dial("tcp", host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = lndc.writeClear([]byte("WHOAREYOU"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var b bytes.Buffer
|
||||
lndc.Read(b.Bytes())
|
||||
|
||||
IamResp, err := lndc.readClear()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return btcec.ParsePubKey(IamResp[:33], btcec.S256())
|
||||
}
|
||||
|
||||
/*
|
||||
Make ETcpCons adhere to Conn interface.
|
||||
need:
|
||||
Read(b []byte) (n int, err error)
|
||||
Write(b []byte) (n int, err error)
|
||||
Close() error
|
||||
LocalAddr() Addr
|
||||
RemoteAddr() Addr
|
||||
SetDeadline(t time.Time) error
|
||||
SetReadDeadline(t time.Time) error
|
||||
SetWriteDeadline(t time.Time) error
|
||||
|
||||
ETcpCons can be either regular TCP connections, which is good, or PBX-routed
|
||||
connections, which is worse, but there are levels of connectivity we are
|
||||
prepared to accept.
|
||||
|
||||
When it's PBX, don't try to use Cn
|
||||
*/
|
||||
|
||||
func (lndc *LNDConn) Read(b []byte) (n int, err error) {
|
||||
// first get message length from first 2 bytes
|
||||
var ctext []byte
|
||||
ctext, err = lndc.readClear()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// now decrypt
|
||||
nonceBuf := new(bytes.Buffer)
|
||||
err = binary.Write(nonceBuf, binary.BigEndian, lndc.RemoteNonceInt)
|
||||
fmt.Printf("decrypt %d byte from %x nonce %d\n",
|
||||
len(ctext), lndc.RemoteLNId, lndc.RemoteNonceInt)
|
||||
lndc.RemoteNonceInt++ // increment remote nonce, no matter what...
|
||||
|
||||
msg, err := lndc.chachaStream.Open(nil, nonceBuf.Bytes(), ctext, nil)
|
||||
if err != nil {
|
||||
fmt.Printf("decrypt %d byte ciphertext failed\n", len(ctext))
|
||||
return 0, err
|
||||
}
|
||||
|
||||
n = copy(b, msg)
|
||||
if n < len(msg) {
|
||||
return 0, fmt.Errorf(
|
||||
"Can't read from %x: Slice provided too small. %d bytes, need %d",
|
||||
lndc.RemoteLNId, len(b), len(msg))
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (lndc *LNDConn) Write(b []byte) (n int, err error) {
|
||||
if b == nil {
|
||||
return 0, fmt.Errorf("Write to %x nil", lndc.RemoteLNId)
|
||||
}
|
||||
fmt.Printf("Encrypt %d byte plaintext to %x nonce %d\n",
|
||||
len(b), lndc.RemoteLNId, lndc.MyNonceInt)
|
||||
// first encrypt message with shared key
|
||||
nonceBuf := new(bytes.Buffer)
|
||||
err = binary.Write(nonceBuf, binary.BigEndian, lndc.MyNonceInt)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
lndc.MyNonceInt++ // increment mine
|
||||
|
||||
ctext := lndc.chachaStream.Seal(nil, nonceBuf.Bytes(), b, nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(ctext) > 65530 {
|
||||
return 0, fmt.Errorf("Write to %x too long, %d bytes",
|
||||
lndc.RemoteLNId, len(ctext))
|
||||
}
|
||||
|
||||
// use writeClear to prepend length / destination header
|
||||
err = lndc.writeClear(ctext)
|
||||
// returns len of how much you put in, not how much written on the wire
|
||||
return len(b), err
|
||||
}
|
||||
|
||||
func (lndc *LNDConn) Close() error {
|
||||
// return lndc.Cn.Close()
|
||||
// return nil
|
||||
lndc.MyNonceInt = 0
|
||||
lndc.RemoteNonceInt = 0
|
||||
lndc.RemotePub = nil
|
||||
|
||||
// if lndc.ViaPbx {
|
||||
// return nil // don't close pbx connection
|
||||
// }
|
||||
err := lndc.Cn.Close()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// network address; if PBX reports address of pbx host
|
||||
func (lndc *LNDConn) LocalAddr() net.Addr {
|
||||
return lndc.Cn.LocalAddr()
|
||||
}
|
||||
func (lndc *LNDConn) RemoteAddr() net.Addr {
|
||||
return lndc.Cn.RemoteAddr()
|
||||
}
|
||||
|
||||
// timing stuff for net.conn compatibility
|
||||
func (lndc *LNDConn) SetDeadline(t time.Time) error {
|
||||
return lndc.Cn.SetDeadline(t)
|
||||
}
|
||||
func (lndc *LNDConn) SetReadDeadline(t time.Time) error {
|
||||
|
||||
return lndc.Cn.SetReadDeadline(t)
|
||||
}
|
||||
func (lndc *LNDConn) SetWriteDeadline(t time.Time) error {
|
||||
return lndc.Cn.SetWriteDeadline(t)
|
||||
}
|
||||
|
||||
/* ReadClear and WriteClear don't encrypt but directly read and write to the
|
||||
underlying data link, only adding or subtracting a 2 byte length header.
|
||||
All Read() and Write() calls for lndc's use these functions internally
|
||||
(they aren't exported). They're also used in the key agreement phase.
|
||||
*/
|
||||
|
||||
// encapsulation for sending to Pbx host.
|
||||
// put FWDMSG, then 16 byte destination ID, then message (with msgtype)
|
||||
func (lndc *LNDConn) PbxEncapsulate(b *[]byte) {
|
||||
fmt.Printf("PbxEncapsulate %d byte message, dest ID %x\n",
|
||||
len(*b), lndc.RemoteLNId)
|
||||
*b = append(lndc.RemoteLNId[:], *b...)
|
||||
*b = append([]byte{lnwire.MSGID_FWDMSG}, *b...)
|
||||
}
|
||||
|
||||
func (lndc *LNDConn) readClear() ([]byte, error) {
|
||||
var msgLen uint16
|
||||
// needs to be pointer or will silently not do anything.
|
||||
var msg []byte
|
||||
|
||||
if lndc.ViaPbx { //pbx mode
|
||||
msg = <-lndc.PbxIncoming
|
||||
} else { // normal tcp mode
|
||||
err := binary.Read(lndc.Cn, binary.BigEndian, &msgLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// fmt.Printf("%d byte LMsg incoming\n", msgLen)
|
||||
msg = make([]byte, msgLen)
|
||||
_, err = io.ReadFull(lndc.Cn, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
func (lndc *LNDConn) writeClear(msg []byte) error {
|
||||
var err error
|
||||
if len(msg) > 65530 {
|
||||
return fmt.Errorf("LMsg too long, %d bytes", len(msg))
|
||||
}
|
||||
if msg == nil {
|
||||
return fmt.Errorf("LMsg nil")
|
||||
}
|
||||
if lndc.ViaPbx {
|
||||
lndc.PbxEncapsulate(&msg)
|
||||
lndc.PbxOutgoing <- msg
|
||||
} else {
|
||||
// add 2 byte length header (pbx doesn't need it) and send over TCP
|
||||
hdr := new(bytes.Buffer)
|
||||
err = binary.Write(hdr, binary.BigEndian, uint16(len(msg)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msg = append(hdr.Bytes(), msg...)
|
||||
_, err = lndc.Cn.Write(msg)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
@ -269,6 +269,36 @@ func NewLightningWallet(config *Config) (*LightningWallet, error) {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// open wallet to initialize and create id key
|
||||
wallet, db, err := openWallet(pubPass, netDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = wallet.Manager.Unlock(config.PrivatePass)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
adrs, err := wallet.Manager.NextInternalAddresses(0, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
priv, err := adrs[0].(waddrmgr.ManagedPubKeyAddress).PrivKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lnNamespace, err := db.Namespace(lightningNamespaceKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cdb := channeldb.New(wallet.Manager, lnNamespace)
|
||||
err = cdb.PutIdKey(priv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Printf("stored private identity key in channeldb\n")
|
||||
}
|
||||
|
||||
// Wallet has been created and been initialized at this point, open it
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
@ -36,7 +37,7 @@ func main() {
|
||||
fmt.Printf("unable to start wallet: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
lnwallet.Unlock(cf.PrivatePass, time.Duration(0))
|
||||
fmt.Println("wallet open")
|
||||
|
||||
// Initialize, and register our implementation of the gRPC server.
|
||||
|
55
rpcserver.go
55
rpcserver.go
@ -2,11 +2,14 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/btcsuite/btcwallet/waddrmgr"
|
||||
"golang.org/x/net/context"
|
||||
"li.lan/labs/plasma/lndc"
|
||||
"li.lan/labs/plasma/lnrpc"
|
||||
"li.lan/labs/plasma/lnwallet"
|
||||
)
|
||||
@ -70,6 +73,17 @@ func (r *rpcServer) LNConnect(ctx context.Context,
|
||||
// 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 := r.lnwallet.ChannelDB.GetIdKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Printf("got a private key. %x\n", priv.Serialize())
|
||||
|
||||
// go TCPListener()
|
||||
|
||||
resp := new(lnrpc.TCPListenResponse)
|
||||
return resp, nil
|
||||
@ -82,3 +96,44 @@ func (r *rpcServer) LNChat(ctx context.Context,
|
||||
resp := new(lnrpc.LnChatResponse)
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func TCPListener() {
|
||||
listener, err := net.Listen("tcp", ":"+"2448")
|
||||
if err != nil {
|
||||
fmt.Printf("TCP listen error: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Listening on %s\n", listener.Addr().String())
|
||||
for {
|
||||
con, err := listener.Accept() // this blocks
|
||||
if err != nil {
|
||||
log.Printf("Listener error: %s\n", err.Error())
|
||||
continue
|
||||
}
|
||||
newConn, err := InitIncomingConn(con)
|
||||
if err != nil {
|
||||
fmt.Printf("InitConn error: %s\n", err.Error())
|
||||
continue
|
||||
}
|
||||
idslice := lndc.H160(newConn.RemotePub.SerializeCompressed())
|
||||
var newId [16]byte
|
||||
copy(newId[:], idslice[:16])
|
||||
// CnMap[newId] = newConn
|
||||
fmt.Printf("added %x to map\n", newId)
|
||||
// go LNDCReceiver(newConn, newId)
|
||||
}
|
||||
}
|
||||
|
||||
func InitIncomingConn(con net.Conn) (*lndc.LNDConn, error) {
|
||||
LNcon := new(lndc.LNDConn)
|
||||
LNcon.Cn = con
|
||||
err := LNcon.Setup(nil)
|
||||
if err != nil {
|
||||
return LNcon, err
|
||||
}
|
||||
fmt.Printf("Got connection from %s authed with pubkey %x",
|
||||
LNcon.Cn.RemoteAddr().String(), LNcon.RemotePub.SerializeCompressed())
|
||||
return LNcon, nil
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user