github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/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  }