2024-03-26 17:05:24 +00:00
|
|
|
// Server implement of lnprototest
|
|
|
|
//
|
|
|
|
// This server is implementing all the lightning rules
|
|
|
|
// for communicate between two nodes.
|
|
|
|
//
|
|
|
|
// For terminology used in this program, please visit
|
|
|
|
// <https://www.ibm.com/docs/en/aix/7.2?topic=protocol-tcpip-terminology>
|
|
|
|
//
|
|
|
|
// Author: Vincenzo Palazzo <vincenzopalazzo@member.fsf.org>
|
|
|
|
package lnprototest
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"net"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/btcsuite/btcd/btcec/v2"
|
|
|
|
"github.com/btcsuite/btcd/wire"
|
|
|
|
"github.com/lightningnetwork/lnd/brontide"
|
|
|
|
"github.com/lightningnetwork/lnd/keychain"
|
|
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
|
|
)
|
|
|
|
|
|
|
|
type ProtoTestServer struct {
|
|
|
|
Conn *brontide.Conn
|
|
|
|
PrivKeyECDH keychain.PrivKeyECDH
|
|
|
|
}
|
|
|
|
|
|
|
|
func MakeKeys() (*keychain.PrivKeyECDH, error) {
|
|
|
|
remotePriv, err := btcec.NewPrivateKey()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &keychain.PrivKeyECDH{PrivKey: remotePriv}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// / Make - Make a new ProtoTestServer with a random private key
|
|
|
|
func Make() (*ProtoTestServer, error) {
|
|
|
|
xpriv, err := MakeKeys()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &ProtoTestServer{
|
|
|
|
Conn: nil,
|
|
|
|
PrivKeyECDH: *xpriv,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// / Connect - Perform the connection with the peer with
|
|
|
|
// / the provided public key (aka nodeId) that it is listening
|
|
|
|
// / on the specified port.
|
2024-03-26 19:40:04 +00:00
|
|
|
func (self *ProtoTestServer) Connect(nodeId string, port uint32, network wire.BitcoinNet) (*bytes.Buffer, error) {
|
2024-03-26 17:05:24 +00:00
|
|
|
pubkey, err := StringToPubKey(nodeId)
|
|
|
|
if err != nil {
|
2024-03-26 19:40:04 +00:00
|
|
|
return nil, err
|
2024-03-26 17:05:24 +00:00
|
|
|
}
|
2024-03-26 19:26:20 +00:00
|
|
|
hostname := fmt.Sprintf("127.0.0.1:%d", port)
|
2024-03-26 17:05:24 +00:00
|
|
|
addr, err := net.ResolveTCPAddr("tcp", hostname)
|
|
|
|
if err != nil {
|
2024-03-26 19:40:04 +00:00
|
|
|
return nil, err
|
2024-03-26 17:05:24 +00:00
|
|
|
}
|
|
|
|
wireaddr := lnwire.NetAddress{
|
|
|
|
Address: addr,
|
|
|
|
IdentityKey: pubkey,
|
|
|
|
ChainNet: network,
|
|
|
|
}
|
|
|
|
conn, err := brontide.Dial(&self.PrivKeyECDH, &wireaddr, time.Second*3, net.DialTimeout)
|
|
|
|
if err != nil {
|
2024-03-26 19:40:04 +00:00
|
|
|
return nil, err
|
2024-03-26 17:05:24 +00:00
|
|
|
}
|
|
|
|
self.Conn = conn
|
2024-03-26 19:40:04 +00:00
|
|
|
if err := self.Conn.SetDeadline(time.Now().Add(time.Second)); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return self.Receive()
|
2024-03-26 17:05:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// / Send - Send an message to the connection
|
|
|
|
func (self *ProtoTestServer) Send(buff *bytes.Buffer) error {
|
2024-03-26 19:40:04 +00:00
|
|
|
size, err := self.Conn.Write(buff.Bytes())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if size == 0 {
|
|
|
|
return fmt.Errorf("No message to flush")
|
|
|
|
}
|
2024-03-26 17:05:24 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// / Send - Wait a message from the connection, usually this is
|
|
|
|
// / an answer from a previous send message
|
|
|
|
func (self *ProtoTestServer) Receive() (*bytes.Buffer, error) {
|
2024-03-26 19:40:04 +00:00
|
|
|
buff, err := self.Conn.ReadNextMessage()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return bytes.NewBuffer(buff), nil
|
2024-03-26 17:05:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// / Destroy - Stop the connecto for lnprototest
|
|
|
|
func (self *ProtoTestServer) Destroy() {
|
|
|
|
if self.Conn == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
(*self.Conn).Close()
|
|
|
|
}
|