github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/litrpc/netcmds.go (about)

     1  package litrpc
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/mit-dci/lit/bech32"
     9  	"github.com/mit-dci/lit/crypto/koblitz"
    10  	"github.com/mit-dci/lit/lncore"
    11  	"github.com/mit-dci/lit/lnutil"
    12  	"github.com/mit-dci/lit/logging"
    13  	"github.com/mit-dci/lit/qln"
    14  )
    15  
    16  // ------------------------- testlog
    17  
    18  func (r *LitRPC) TestLog(arg string, reply *string) error {
    19  	logging.Info(arg)
    20  	*reply = arg
    21  	return nil
    22  }
    23  
    24  // ------------------------- listen
    25  
    26  type ListenArgs struct {
    27  	Port int
    28  }
    29  
    30  type ListeningPortsReply struct {
    31  	LisIpPorts []string
    32  	Adr        string
    33  }
    34  
    35  func (r *LitRPC) Listen(args ListenArgs, reply *ListeningPortsReply) error {
    36  	// this case is covered in lit-af, but in case other clients want to call this
    37  	// RPC with an empty argument, ints default to 0 but there might be people who
    38  	// want the computer to do the port assignment. To do it the proper way, they
    39  	// can call the RPC with port set to -1
    40  	if args.Port == -1 {
    41  		args.Port = 2448
    42  	}
    43  	_, err := r.Node.TCPListener(args.Port)
    44  	if err != nil {
    45  		return err
    46  	}
    47  
    48  	reply.Adr, reply.LisIpPorts = r.Node.GetLisAddressAndPorts()
    49  
    50  	return nil
    51  }
    52  
    53  // ------------------------- connect
    54  type ConnectArgs struct {
    55  	LNAddr string
    56  }
    57  
    58  type ConnectReply struct {
    59  	Status  string
    60  	PeerIdx uint32
    61  }
    62  
    63  func (r *LitRPC) Connect(args ConnectArgs, reply *ConnectReply) error {
    64  
    65  	// first, see if the peer to connect to is referenced by peer index.
    66  	var connectAdr string
    67  	// check if a peer number was supplied instead of a pubkeyhash
    68  	peerIdxint, err := strconv.Atoi(args.LNAddr)
    69  	// number will mean no error
    70  	if err == nil {
    71  		// get peer from address book
    72  		pubArr, host := r.Node.GetPubHostFromPeerIdx(uint32(peerIdxint))
    73  
    74  		connectAdr = lnutil.LitAdrFromPubkey(pubArr)
    75  		if host != "" {
    76  			connectAdr += "@" + host
    77  		}
    78  		logging.Infof("try string %s\n", connectAdr)
    79  
    80  	} else {
    81  		// use string as is, try to convert to ln address
    82  		connectAdr = args.LNAddr
    83  	}
    84  
    85  	err = r.Node.DialPeer(connectAdr)
    86  	if err != nil {
    87  		return err
    88  	}
    89  
    90  	// Extract the plain lit addr since we don't always have it.
    91  	// TODO Make this more "correct" since it's using the old system a lot.
    92  	paddr := connectAdr
    93  	if strings.Contains(paddr, "@") {
    94  		paddr = strings.SplitN(paddr, "@", 2)[0]
    95  	}
    96  
    97  	pm := r.Node.PeerMan
    98  	lnaddr, err := lncore.ParseLnAddr(paddr)
    99  	if err != nil {
   100  		return err
   101  	}
   102  
   103  	p := pm.GetPeer(lnaddr)
   104  	if p == nil {
   105  		return fmt.Errorf("couldn't find peer in manager after connecting")
   106  	}
   107  
   108  	reply.Status = fmt.Sprintf("connected to peer %s", connectAdr)
   109  	reply.PeerIdx = p.GetIdx()
   110  	return nil
   111  }
   112  
   113  // ------------------------- name a connection
   114  type AssignNicknameArgs struct {
   115  	Peer     uint32
   116  	Nickname string
   117  }
   118  
   119  func (r *LitRPC) AssignNickname(args AssignNicknameArgs, reply *StatusReply) error {
   120  	// attempt to save nickname to the database, this process also checks if the peer exists
   121  	err := r.Node.SaveNicknameForPeerIdx(args.Nickname, args.Peer)
   122  	if err != nil {
   123  		return err
   124  	}
   125  
   126  	// it's okay if we aren't connected to this peer right now, but if we are
   127  	// then their nickname needs to be updated in the remote connections list
   128  	// otherwise this doesn't get updated til after a restart
   129  	if peer, ok := r.Node.RemoteCons[args.Peer]; ok {
   130  		peer.Nickname = args.Nickname
   131  	}
   132  
   133  	reply.Status = fmt.Sprintf("changed nickname of peer %d to %s",
   134  		args.Peer, args.Nickname)
   135  	return nil
   136  }
   137  
   138  // ------------------------- ShowConnections
   139  
   140  type ListConnectionsReply struct {
   141  	Connections []qln.SimplePeerInfo
   142  	MyPKH       string
   143  }
   144  type ConInfo struct {
   145  	PeerNumber uint32
   146  	RemoteHost string
   147  }
   148  
   149  func (r *LitRPC) ListConnections(args NoArgs, reply *ListConnectionsReply) error {
   150  	reply.Connections = r.Node.GetConnectedPeerList()
   151  	reply.MyPKH = r.Node.GetLnAddr()
   152  	return nil
   153  }
   154  
   155  func (r *LitRPC) GetListeningPorts(args NoArgs, reply *ListeningPortsReply) error {
   156  	reply.Adr, reply.LisIpPorts = r.Node.GetLisAddressAndPorts()
   157  	return nil
   158  }
   159  
   160  // ------- receive chat
   161  func (r *LitRPC) GetMessages(args NoArgs, reply *StatusReply) error {
   162  	reply.Status = <-r.Node.UserMessageBox
   163  	return nil
   164  }
   165  
   166  type SayArgs struct {
   167  	Peer    uint32
   168  	Message string
   169  }
   170  
   171  func (r *LitRPC) Say(args SayArgs, reply *StatusReply) error {
   172  	return r.Node.SendChat(args.Peer, args.Message)
   173  }
   174  
   175  func (r *LitRPC) Stop(args NoArgs, reply *StatusReply) error {
   176  	reply.Status = "Stopping lit node"
   177  	r.OffButton <- true
   178  	return nil
   179  }
   180  
   181  // ------------ Dump channel map
   182  type ChannelGraphReply struct {
   183  	Graph string
   184  }
   185  
   186  func (r *LitRPC) GetChannelMap(args NoArgs, reply *ChannelGraphReply) error {
   187  	reply.Graph = r.Node.VisualiseGraph()
   188  	return nil
   189  }
   190  
   191  // ------------ Show multihop payments
   192  type MultihopPaymentInfo struct {
   193  	RHash     [32]byte
   194  	R         [16]byte
   195  	Amt       int64
   196  	Path      []string
   197  	Succeeded bool
   198  }
   199  
   200  type MultihopPaymentsReply struct {
   201  	Payments []MultihopPaymentInfo
   202  }
   203  
   204  func (r *LitRPC) ListMultihopPayments(args NoArgs, reply *MultihopPaymentsReply) error {
   205  	r.Node.MultihopMutex.Lock()
   206  	defer r.Node.MultihopMutex.Unlock()
   207  	for _, p := range r.Node.InProgMultihop {
   208  		var path []string
   209  		for _, hop := range p.Path {
   210  			path = append(path, fmt.Sprintf("%s:%d", bech32.Encode("ln", hop.Node[:]), hop.CoinType))
   211  		}
   212  
   213  		i := MultihopPaymentInfo{
   214  			p.HHash,
   215  			p.PreImage,
   216  			p.Amt,
   217  			path,
   218  			p.Succeeded,
   219  		}
   220  
   221  		reply.Payments = append(reply.Payments, i)
   222  	}
   223  
   224  	return nil
   225  }
   226  
   227  type RCAuthArgs struct {
   228  	PubKey        []byte
   229  	Authorization *qln.RemoteControlAuthorization
   230  }
   231  
   232  func (r *LitRPC) RemoteControlAuth(args RCAuthArgs, reply *StatusReply) error {
   233  
   234  	pub, err := koblitz.ParsePubKey(args.PubKey, koblitz.S256())
   235  	if err != nil {
   236  		reply.Status = fmt.Sprintf("Error deserializing pubkey: %s", err.Error())
   237  		return err
   238  	}
   239  	compressedPubKey := pub.SerializeCompressed()
   240  	var pubKey [33]byte
   241  	copy(pubKey[:], compressedPubKey[:])
   242  
   243  	args.Authorization.UnansweredRequest = false
   244  
   245  	err = r.Node.SaveRemoteControlAuthorization(pubKey, args.Authorization)
   246  	if err != nil {
   247  		logging.Errorf("Error saving auth: %s", err.Error())
   248  		return err
   249  	}
   250  
   251  	action := "Granted"
   252  	if !args.Authorization.Allowed {
   253  		action = "Denied / revoked"
   254  	}
   255  	reply.Status = fmt.Sprintf("%s remote control access for pubkey [%x]", action, pubKey)
   256  	return nil
   257  }
   258  
   259  type RCRequestAuthArgs struct {
   260  	PubKey [33]byte
   261  }
   262  
   263  func (r *LitRPC) RequestRemoteControlAuthorization(args RCRequestAuthArgs, reply *StatusReply) error {
   264  	auth := new(qln.RemoteControlAuthorization)
   265  	auth.Allowed = false
   266  	auth.UnansweredRequest = true
   267  
   268  	err := r.Node.SaveRemoteControlAuthorization(args.PubKey, auth)
   269  	if err != nil {
   270  		logging.Errorf("Error saving auth request: %s", err.Error())
   271  		return err
   272  	}
   273  
   274  	reply.Status = fmt.Sprintf("Access requested for pubkey [%x]", args.PubKey)
   275  	return nil
   276  }
   277  
   278  type RCPendingAuthRequestsReply struct {
   279  	PubKeys [][33]byte
   280  }
   281  
   282  func (r *LitRPC) ListPendingRemoteControlAuthRequests(args NoArgs, reply *RCPendingAuthRequestsReply) error {
   283  	auth := new(qln.RemoteControlAuthorization)
   284  	auth.Allowed = false
   285  	auth.UnansweredRequest = true
   286  
   287  	requests, err := r.Node.GetPendingRemoteControlRequests()
   288  	if err != nil {
   289  		logging.Errorf("Error saving auth request: %s", err.Error())
   290  		return err
   291  	}
   292  
   293  	reply.PubKeys = make([][33]byte, len(requests))
   294  	for i, r := range requests {
   295  		reply.PubKeys[i] = r.PubKey
   296  	}
   297  
   298  	return nil
   299  
   300  }