github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/service/debugging_devel.go (about) 1 // Copyright 2018 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 // 4 //go:build !production 5 // +build !production 6 7 package service 8 9 import ( 10 "encoding/json" 11 "fmt" 12 "sort" 13 "strings" 14 "sync" 15 "time" 16 17 "github.com/davecgh/go-spew/spew" 18 chatwallet "github.com/keybase/client/go/chat/wallet" 19 "github.com/keybase/client/go/engine" 20 "github.com/keybase/client/go/libkb" 21 "github.com/keybase/client/go/protocol/keybase1" 22 "github.com/keybase/client/go/protocol/stellar1" 23 "github.com/keybase/client/go/teams" 24 "github.com/keybase/stellarnet" 25 "github.com/stellar/go/build" 26 27 // nolint 28 "github.com/stellar/go/clients/horizon" 29 "golang.org/x/net/context" 30 ) 31 32 func (t *DebuggingHandler) scriptExtras(ctx context.Context, arg keybase1.ScriptArg) (res string, err error) { 33 ctx = libkb.WithLogTag(ctx, "DG") 34 m := libkb.NewMetaContext(ctx, t.G()) 35 args := arg.Args 36 log := func(format string, args ...interface{}) { 37 t.G().Log.CInfof(ctx, format, args...) 38 } 39 defer time.Sleep(100 * time.Millisecond) // Without this CInfof often doesn't reach the CLI 40 switch arg.Script { 41 case "rid2": 42 if len(args) != 2 { 43 return "", fmt.Errorf("require 2 args: <mode:gui/kbfs> <assertion>") 44 } 45 idBehavior := keybase1.TLFIdentifyBehavior_CHAT_GUI 46 var iui libkb.IdentifyUI 47 switch args[0] { 48 case "gui": 49 case "kbfs": 50 idBehavior = keybase1.TLFIdentifyBehavior_CHAT_GUI 51 iui = t.NewRemoteIdentifyUI(0) 52 default: 53 return "", fmt.Errorf("unrecognized mode %v: use 'gui' or 'kbfs'", args[0]) 54 } 55 eng := engine.NewResolveThenIdentify2(t.G(), &keybase1.Identify2Arg{ 56 UserAssertion: args[1], 57 UseDelegateUI: false, 58 Reason: keybase1.IdentifyReason{Reason: "debugging script"}, 59 CanSuppressUI: true, 60 IdentifyBehavior: idBehavior, 61 }) 62 m = m.WithUIs(libkb.UIs{IdentifyUI: iui}) 63 err := engine.RunEngine2(m, eng) 64 log("GetProofSet: %v", spew.Sdump(eng.GetProofSet())) 65 log("ConfirmResult: %v", spew.Sdump(eng.ConfirmResult())) 66 eres, eerr := eng.Result(m) 67 if eres != nil { 68 log("Result.Upk.Username: %v", spew.Sdump(eres.Upk.GetName())) 69 log("Result.IdentifiedAt: %v", spew.Sdump(eres.IdentifiedAt)) 70 log("Result.TrackBreaks: %v", spew.Sdump(eres.TrackBreaks)) 71 } else { 72 log("Result: %v", spew.Sdump(eres)) 73 } 74 if eerr != nil { 75 log("Result.error: %v", spew.Sdump(eerr)) 76 } 77 return "", err 78 case "loadkey": 79 if len(args) != 2 { 80 return "", fmt.Errorf("require 2 args: <uid> <kid>") 81 } 82 uid, err := keybase1.UIDFromString(args[0]) 83 if err != nil { 84 return "", err 85 } 86 kid := keybase1.KIDFromString(args[1]) 87 _, _, _, err = t.G().GetUPAKLoader().LoadKeyV2(ctx, uid, kid) 88 return "", err 89 case "eldest": 90 if len(args) != 1 { 91 return "", fmt.Errorf("require 1 arg: username") 92 } 93 94 // UPAK 95 upak, _, err := t.G().GetUPAKLoader().LoadV2(libkb.NewLoadUserArgWithMetaContext(m).WithName(args[0]).WithPublicKeyOptional()) 96 if err != nil { 97 return "", err 98 } 99 var upakEldestSeqnos []keybase1.Seqno 100 for _, upak := range upak.AllIncarnations() { 101 upakEldestSeqnos = append(upakEldestSeqnos, upak.EldestSeqno) 102 } 103 sort.Slice(upakEldestSeqnos, func(i, j int) bool { 104 return upakEldestSeqnos[i] < upakEldestSeqnos[j] 105 }) 106 107 // Full user 108 them, err := libkb.LoadUser(libkb.NewLoadUserArgWithMetaContext(m).WithName(args[0]).WithPublicKeyOptional()) 109 if err != nil { 110 return "", err 111 } 112 113 obj := struct { 114 UPAKEldestSeqno keybase1.Seqno `json:"upak_current_eldest"` 115 UPAKEldestSeqnos []keybase1.Seqno `json:"upak_eldest_seqnos"` 116 FullUserEldestSeqno keybase1.Seqno `json:"fu_eldest_seqno"` 117 }{upak.ToUserVersion().EldestSeqno, upakEldestSeqnos, them.GetCurrentEldestSeqno()} 118 bs, err := json.Marshal(obj) 119 if err != nil { 120 return "", err 121 } 122 return fmt.Sprintf("%v\n", string(bs)), nil 123 case "userhigh": 124 // List user high links 125 if len(args) != 1 { 126 return "", fmt.Errorf("require 1 arg: username") 127 } 128 user, err := libkb.LoadUser(libkb.NewLoadUserArgWithMetaContext(m).WithName(args[0]).WithPublicKeyOptional()) 129 if err != nil { 130 return "", err 131 } 132 hls, err := user.GetHighLinkSeqnos(m) 133 if err != nil { 134 return "", err 135 } 136 obj := struct { 137 Seqnos []keybase1.Seqno `json:"seqnos"` 138 }{hls} 139 bs, err := json.Marshal(obj) 140 if err != nil { 141 return "", err 142 } 143 return fmt.Sprintf("%v\n", string(bs)), nil 144 case "buildpayment": 145 // Run build a bunch of times with a tight spread. 146 if len(args) != 1 { 147 return "", fmt.Errorf("require 1 args: <recipient>") 148 } 149 recipient := args[0] 150 count := 30 151 var wg sync.WaitGroup 152 for i := 0; i < count; i++ { 153 i := i 154 wg.Add(1) 155 if i%5 == 0 { 156 time.Sleep(100 * time.Millisecond) 157 } 158 if i == 10 { 159 time.Sleep(2 * time.Second) 160 } 161 start := time.Now() 162 log("build[%v] starting", i) 163 go func() { 164 defer wg.Done() 165 ctx := libkb.WithLogTagWithValue(ctx, "DGI", fmt.Sprintf("%vx", i)) 166 res, err := t.walletHandler.BuildPaymentLocal(ctx, stellar1.BuildPaymentLocalArg{ 167 SessionID: 500 + i, 168 FromPrimaryAccount: true, 169 To: recipient, 170 Amount: "0.01", 171 SecretNote: "xx", 172 PublicMemo: "yy", 173 }) 174 took := time.Since(start) 175 if err != nil { 176 log("build[%v] [%v] error: %v", i, took, err) 177 return 178 } 179 log("build[%v] [%v] ok", i, took) 180 log("build[%v] res: %v", i, spew.Sdump(res)) 181 }() 182 } 183 wg.Wait() 184 return "", nil 185 case "reviewpayment": 186 // Send a payment including the review stage. 187 if len(args) != 1 { 188 return "", fmt.Errorf("require 1 args: <recipient>") 189 } 190 recipient := args[0] 191 sessionIDNext := 500 192 sessionID := func() int { 193 sessionIDNext++ 194 return sessionIDNext - 1 195 } 196 bid, err := t.walletHandler.StartBuildPaymentLocal(ctx, sessionID()) 197 if err != nil { 198 return "", err 199 } 200 log("%v", bid) 201 202 buildRes, err := t.walletHandler.BuildPaymentLocal(ctx, stellar1.BuildPaymentLocalArg{ 203 SessionID: sessionID(), 204 Bid: bid, 205 FromPrimaryAccount: true, 206 To: recipient, 207 Amount: "3.004", 208 SecretNote: "xx", 209 PublicMemo: "yy", 210 }) 211 if err != nil { 212 return "", err 213 } 214 log("%v", spew.Sdump(buildRes)) 215 216 err = t.walletHandler.ReviewPaymentLocal(ctx, stellar1.ReviewPaymentLocalArg{ 217 SessionID: sessionID(), 218 Bid: bid, 219 }) 220 if err != nil { 221 return "", err 222 } 223 // Assume that the review closed because it succeeded. 224 // This is not necessarily true. Better would be to use stellar UI. 225 // Grep for "sending UIPaymentReview". 226 227 sendRes, err := t.walletHandler.SendPaymentLocal(ctx, stellar1.SendPaymentLocalArg{ 228 SessionID: sessionID(), 229 Bid: bid, 230 From: buildRes.From, 231 To: recipient, 232 Amount: "3.004", 233 Asset: stellar1.AssetNative(), 234 SecretNote: "xx", 235 PublicMemo: "yy", 236 }) 237 if err != nil { 238 return "", err 239 } 240 log("%v", spew.Sdump(sendRes)) 241 return "done\n", nil 242 case "minichatpayment": 243 parsed := chatwallet.FindChatTxCandidates(strings.Join(args, " ")) 244 minis := make([]libkb.MiniChatPayment, len(parsed)) 245 for i, p := range parsed { 246 if p.Username == nil { 247 return "", fmt.Errorf("missing username") 248 } 249 mini := libkb.MiniChatPayment{ 250 Username: libkb.NewNormalizedUsername(*p.Username), 251 Amount: p.Amount, 252 Currency: p.CurrencyCode, 253 } 254 minis[i] = mini 255 } 256 stellarnet.SetClientAndNetwork(horizon.DefaultTestNetClient, build.TestNetwork) 257 258 results, err := t.G().GetStellar().SendMiniChatPayments(m, nil, minis) 259 if err != nil { 260 return "", err 261 } 262 log("send mini results: %+v", results) 263 return "success", nil 264 case "proof-suggestions": 265 if len(args) > 0 { 266 return "", fmt.Errorf("require 0 args") 267 } 268 ret, err := t.userHandler.ProofSuggestions(ctx, 0) 269 if err != nil { 270 return "", err 271 } 272 log("%v", spew.Sdump(ret)) 273 return "", nil 274 case "execute-invite": 275 teamID, err := keybase1.TeamIDFromString("978d0d88131e85123a142f87e8769d24") 276 if err != nil { 277 return "", err 278 } 279 err = teams.HandleSBSRequest(ctx, m.G(), keybase1.TeamSBSMsg{ 280 TeamID: teamID, 281 Invitees: []keybase1.TeamInvitee{{ 282 InviteID: "828cb94d4c2b07b694ce578b2944ae27", 283 Uid: "7080d7d007b46805c33e66b267e1e819", 284 EldestSeqno: 30, 285 Role: keybase1.TeamRole_OWNER, 286 }}, 287 }) 288 return "", err 289 case "re-add": 290 teamID, err := keybase1.TeamIDFromString("fa6da9bceb6df00c5c6afd724a889d24") 291 if err != nil { 292 return "", err 293 } 294 err = teams.ReAddMemberAfterReset(ctx, m.G(), teamID, "ireset1") 295 return "", err 296 case "": 297 return "", fmt.Errorf("empty script name") 298 default: 299 return "", fmt.Errorf("unknown script: %v", arg.Script) 300 } 301 } 302 303 func (t *DebuggingHandler) NewRemoteIdentifyUI(sessionID int) *RemoteIdentifyUI { 304 c := t.rpcClient() 305 return &RemoteIdentifyUI{ 306 sessionID: sessionID, 307 uicli: keybase1.IdentifyUiClient{Cli: c}, 308 logUI: t.getLogUI(sessionID), 309 Contextified: libkb.NewContextified(t.G()), 310 } 311 }