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 }