github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/libkb/rpc_exim.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  // Export-Import for RPC stubs
     5  
     6  package libkb
     7  
     8  import (
     9  	"encoding/hex"
    10  	"encoding/json"
    11  	"errors"
    12  	"fmt"
    13  	"io"
    14  	"sort"
    15  	"strconv"
    16  	"strings"
    17  	"time"
    18  
    19  	"github.com/keybase/client/go/protocol/chat1"
    20  	"github.com/keybase/client/go/protocol/gregor1"
    21  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    22  	"github.com/keybase/go-crypto/openpgp"
    23  	pgpErrors "github.com/keybase/go-crypto/openpgp/errors"
    24  	"github.com/keybase/go-framed-msgpack-rpc/rpc"
    25  	"golang.org/x/net/context"
    26  )
    27  
    28  func (sh SigHint) Export() *keybase1.SigHint {
    29  	return &keybase1.SigHint{
    30  		RemoteId:  sh.remoteID,
    31  		ApiUrl:    sh.apiURL,
    32  		HumanUrl:  sh.humanURL,
    33  		CheckText: sh.checkText,
    34  	}
    35  }
    36  
    37  func (l LinkCheckResult) ExportToIdentifyRow(i int) keybase1.IdentifyRow {
    38  	return keybase1.IdentifyRow{
    39  		RowId:     i,
    40  		Proof:     ExportRemoteProof(l.link),
    41  		TrackDiff: ExportTrackDiff(l.diff),
    42  	}
    43  }
    44  
    45  func (l LinkCheckResult) Export() keybase1.LinkCheckResult {
    46  	ret := keybase1.LinkCheckResult{
    47  		ProofId:       l.position,
    48  		ProofResult:   ExportProofError(l.err),
    49  		SnoozedResult: ExportProofError(l.snoozedErr),
    50  		TorWarning:    l.torWarning,
    51  	}
    52  	if l.cached != nil {
    53  		ret.Cached = l.cached.Export()
    54  	}
    55  	bt := false
    56  	if l.diff != nil {
    57  		ret.Diff = ExportTrackDiff(l.diff)
    58  		if l.diff.BreaksTracking() {
    59  			bt = true
    60  		}
    61  	}
    62  	if l.remoteDiff != nil {
    63  		ret.RemoteDiff = ExportTrackDiff(l.remoteDiff)
    64  		if l.remoteDiff.BreaksTracking() {
    65  			bt = true
    66  		}
    67  	}
    68  	if l.hint != nil {
    69  		ret.Hint = l.GetHint().Export()
    70  	}
    71  	ret.TmpTrackExpireTime = keybase1.ToTime(l.tmpTrackExpireTime)
    72  	ret.BreaksTracking = bt
    73  	return ret
    74  }
    75  
    76  func (cr CheckResult) Export() *keybase1.CheckResult {
    77  	return &keybase1.CheckResult{
    78  		ProofResult: ExportProofError(cr.Status),
    79  		Time:        keybase1.ToTime(cr.Time),
    80  		Freshness:   cr.Freshness(),
    81  	}
    82  }
    83  
    84  func ExportRemoteProof(p RemoteProofChainLink) keybase1.RemoteProof {
    85  	k, v := p.ToKeyValuePair()
    86  	return keybase1.RemoteProof{
    87  		ProofType:     p.GetProofType(),
    88  		Key:           k,
    89  		Value:         strings.ToLower(v),
    90  		DisplayMarkup: v,
    91  		SigID:         p.GetSigID(),
    92  		MTime:         keybase1.ToTime(p.GetCTime()),
    93  	}
    94  }
    95  
    96  func (is IdentifyState) ExportToUncheckedIdentity(mctx MetaContext) *keybase1.Identity {
    97  	return is.res.ExportToUncheckedIdentity(mctx)
    98  }
    99  
   100  func (ir IdentifyOutcome) ExportToUncheckedIdentity(mctx MetaContext) *keybase1.Identity {
   101  	tmp := keybase1.Identity{
   102  		Status: ExportErrorAsStatus(mctx.G(), ir.Error),
   103  	}
   104  	if ir.TrackUsed != nil {
   105  		tmp.WhenLastTracked = keybase1.ToTime(ir.TrackUsed.GetCTime())
   106  	}
   107  
   108  	pc := ir.ProofChecksSorted(mctx)
   109  	tmp.Proofs = make([]keybase1.IdentifyRow, len(pc))
   110  	for j, p := range pc {
   111  		tmp.Proofs[j] = p.ExportToIdentifyRow(j)
   112  	}
   113  
   114  	tmp.Revoked = make([]keybase1.TrackDiff, len(ir.Revoked))
   115  	for j, d := range ir.Revoked {
   116  		// Should have all non-nil elements...
   117  		tmp.Revoked[j] = *ExportTrackDiff(d)
   118  		if d.BreaksTracking() {
   119  			tmp.BreaksTracking = true
   120  		}
   121  	}
   122  	tmp.RevokedDetails = ir.RevokedDetails
   123  	return &tmp
   124  }
   125  
   126  type ExportableError interface {
   127  	error
   128  	ToStatus() keybase1.Status
   129  }
   130  
   131  func ExportProofError(pe ProofError) (ret keybase1.ProofResult) {
   132  	if pe == nil {
   133  		ret.State = keybase1.ProofState_OK
   134  		ret.Status = keybase1.ProofStatus_OK
   135  	} else {
   136  		ret.Status = pe.GetProofStatus()
   137  		ret.State = ProofErrorToState(pe)
   138  		ret.Desc = pe.GetDesc()
   139  	}
   140  	return
   141  }
   142  
   143  func ImportProofError(e keybase1.ProofResult) ProofError {
   144  	ps := e.Status
   145  	if ps == keybase1.ProofStatus_OK {
   146  		return nil
   147  	}
   148  	return NewProofError(ps, e.Desc)
   149  }
   150  
   151  func ExportErrorAsStatus(g *GlobalContext, e error) (ret *keybase1.Status) {
   152  	switch e {
   153  	case nil:
   154  		return nil
   155  	case io.EOF:
   156  		return &keybase1.Status{
   157  			Code: SCStreamEOF,
   158  			Name: "STREAM_EOF",
   159  		}
   160  	case pgpErrors.ErrKeyIncorrect:
   161  		return &keybase1.Status{
   162  			Code: SCKeyNoActive,
   163  			Name: "SC_KEY_NO_ACTIVE",
   164  			Desc: "No PGP key found",
   165  		}
   166  	case context.Canceled:
   167  		return &keybase1.Status{
   168  			Code: SCCanceled,
   169  			Name: "SC_CANCELED",
   170  			Desc: "Canceled",
   171  		}
   172  	}
   173  
   174  	// Before checking to see if an error implements ExportableError, peel off
   175  	// any wrappers from the `errors` package (KBFS uses these). This is a
   176  	// no-op for other types.
   177  	e = HumanError(e)
   178  	if ee, ok := e.(ExportableError); ok {
   179  		tmp := ee.ToStatus()
   180  		return &tmp
   181  	}
   182  
   183  	if g != nil && g.Env.GetRunMode() != ProductionRunMode {
   184  		g.Log.Warning("not exportable error: %v (%T)", e, e)
   185  	}
   186  
   187  	return &keybase1.Status{
   188  		Name: "GENERIC",
   189  		Code: SCGeneric,
   190  		Desc: e.Error(),
   191  	}
   192  }
   193  
   194  // =============================================================================
   195  
   196  func MakeWrapError(g *GlobalContext) func(e error) interface{} {
   197  	return func(e error) interface{} {
   198  		return ExportErrorAsStatus(g, e)
   199  	}
   200  }
   201  
   202  func WrapError(e error) interface{} {
   203  	return ExportErrorAsStatus(nil, e)
   204  }
   205  
   206  var _ rpc.WrapErrorFunc = MakeWrapError(nil)
   207  
   208  type ErrorUnwrapper struct {
   209  	Contextified
   210  }
   211  
   212  func NewContextifiedErrorUnwrapper(g *GlobalContext) ErrorUnwrapper {
   213  	return ErrorUnwrapper{NewContextified(g)}
   214  
   215  }
   216  
   217  func (c ErrorUnwrapper) MakeArg() interface{} {
   218  	return &keybase1.Status{}
   219  }
   220  
   221  func (c ErrorUnwrapper) UnwrapError(arg interface{}) (appError error, dispatchError error) {
   222  	targ, ok := arg.(*keybase1.Status)
   223  	if !ok {
   224  		dispatchError = errors.New("Error converting status to keybase1.Status object")
   225  		return
   226  	}
   227  	appError = ImportStatusAsError(c.G(), targ)
   228  	return
   229  }
   230  
   231  var _ rpc.ErrorUnwrapper = NewContextifiedErrorUnwrapper(nil)
   232  var _ rpc.ErrorUnwrapper = ErrorUnwrapper{}
   233  
   234  // =============================================================================
   235  
   236  func ImportStatusAsError(g *GlobalContext, s *keybase1.Status) error {
   237  	if s == nil {
   238  		return nil
   239  	}
   240  	switch s.Code {
   241  	case SCOk:
   242  		return nil
   243  	case SCGeneric:
   244  		return errors.New(s.Desc)
   245  	case SCBadSession:
   246  		return BadSessionError{s.Desc}
   247  	case SCBadLoginPassword:
   248  		return PassphraseError{s.Desc}
   249  	case SCKeyBadGen:
   250  		return KeyGenError{s.Desc}
   251  	case SCAlreadyLoggedIn:
   252  		return LoggedInError{}
   253  	case SCCanceled:
   254  		return CanceledError{s.Desc}
   255  	case SCInputCanceled:
   256  		return InputCanceledError{}
   257  	case SCKeyNoSecret:
   258  		return NoSecretKeyError{}
   259  	case SCLoginRequired:
   260  		return LoginRequiredError{s.Desc}
   261  	case SCNoSession:
   262  		return NoSessionError{}
   263  	case SCKeyCorrupted:
   264  		return KeyCorruptedError{s.Desc}
   265  	case SCOffline:
   266  		return OfflineError{}
   267  	case SCKeyInUse:
   268  		var fp *PGPFingerprint
   269  		if len(s.Desc) > 0 {
   270  			fp, _ = PGPFingerprintFromHex(s.Desc)
   271  		}
   272  		return KeyExistsError{fp}
   273  	case SCKeyNotFound:
   274  		return NoKeyError{s.Desc}
   275  	case SCKeyNoEldest:
   276  		return NoSigChainError{}
   277  	case SCStreamExists:
   278  		return StreamExistsError{}
   279  	case SCBadInvitationCode:
   280  		return BadInvitationCodeError{}
   281  	case SCStreamNotFound:
   282  		return StreamNotFoundError{}
   283  	case SCStreamWrongKind:
   284  		return StreamWrongKindError{}
   285  	case SCStreamEOF:
   286  		return io.EOF
   287  	case SCSelfNotFound:
   288  		return SelfNotFoundError{msg: s.Desc}
   289  	case SCDeviceNotFound:
   290  		return NoDeviceError{Reason: s.Desc}
   291  	case SCDecryptionKeyNotFound:
   292  		return NoDecryptionKeyError{Msg: s.Desc}
   293  	case SCTimeout:
   294  		return TimeoutError{}
   295  	case SCDeviceMismatch:
   296  		return ReceiverDeviceError{Msg: s.Desc}
   297  	case SCBadKexPhrase:
   298  		return InvalidKexPhraseError{}
   299  	case SCReloginRequired:
   300  		return ReloginRequiredError{}
   301  	case SCDeviceRequired:
   302  		return DeviceRequiredError{}
   303  	case SCMissingResult:
   304  		return IdentifyDidNotCompleteError{}
   305  	case SCSibkeyAlreadyExists:
   306  		return SibkeyAlreadyExistsError{}
   307  	case SCSigCreationDisallowed:
   308  		service := ""
   309  		if len(s.Fields) > 0 && s.Fields[0].Key == "remote_service" {
   310  			service = s.Fields[0].Value
   311  		}
   312  		return ServiceDoesNotSupportNewProofsError{Service: service}
   313  	case SCNoUI:
   314  		return NoUIError{Which: s.Desc}
   315  	case SCNoUIDelegation:
   316  		return UIDelegationUnavailableError{}
   317  	case SCProfileNotPublic:
   318  		return ProfileNotPublicError{msg: s.Desc}
   319  	case SCIdentifyFailed:
   320  		var assertion string
   321  		if len(s.Fields) > 0 && s.Fields[0].Key == "assertion" {
   322  			assertion = s.Fields[0].Value
   323  		}
   324  		return IdentifyFailedError{Assertion: assertion, Reason: s.Desc}
   325  	case SCIdentifiesFailed:
   326  		return IdentifiesFailedError{}
   327  	case SCIdentifySummaryError:
   328  		ret := IdentifySummaryError{}
   329  		for _, pair := range s.Fields {
   330  			if pair.Key == "username" {
   331  				ret.username = NewNormalizedUsername(pair.Value)
   332  			} else {
   333  				// The other keys are expected to be "problem_%d".
   334  				ret.problems = append(ret.problems, pair.Value)
   335  			}
   336  		}
   337  		return ret
   338  	case SCTrackingBroke:
   339  		return TrackingBrokeError{}
   340  	case SCResolutionFailed:
   341  		var input string
   342  		if len(s.Fields) > 0 && s.Fields[0].Key == "input" {
   343  			input = s.Fields[0].Value
   344  		}
   345  		return ResolutionError{Msg: s.Desc, Input: input}
   346  	case SCAccountReset:
   347  		var e keybase1.UserVersion
   348  		var r keybase1.Seqno
   349  		seqnoFromString := func(s string) keybase1.Seqno {
   350  			i, _ := strconv.Atoi(s)
   351  			return keybase1.Seqno(i)
   352  		}
   353  		for _, field := range s.Fields {
   354  			switch field.Key {
   355  			case "e_uid":
   356  				e.Uid, _ = keybase1.UIDFromString(field.Value)
   357  			case "e_version":
   358  				e.EldestSeqno = seqnoFromString(field.Value)
   359  			case "r_version":
   360  				r = seqnoFromString(field.Value)
   361  			}
   362  		}
   363  		return NewAccountResetError(e, r)
   364  	case SCKeyNoPGPEncryption:
   365  		ret := NoPGPEncryptionKeyError{User: s.Desc}
   366  		for _, field := range s.Fields {
   367  			if field.Key == "HasKeybaseEncryptionKey" {
   368  				ret.HasKeybaseEncryptionKey = true
   369  			}
   370  		}
   371  		return ret
   372  	case SCKeyNoNaClEncryption:
   373  		ret := NoNaClEncryptionKeyError{}
   374  		for _, field := range s.Fields {
   375  			switch field.Key {
   376  			case "Username":
   377  				ret.Username = field.Value
   378  			case "HasPGPKey":
   379  				ret.HasPGPKey = true
   380  			case "HasPUK":
   381  				ret.HasPUK = true
   382  			case "HasPaperKey":
   383  				ret.HasPaperKey = true
   384  			case "HasDeviceKey":
   385  				ret.HasDeviceKey = true
   386  			}
   387  		}
   388  		return ret
   389  	case SCWrongCryptoFormat:
   390  		ret := WrongCryptoFormatError{Operation: s.Desc}
   391  		for _, field := range s.Fields {
   392  			switch field.Key {
   393  			case "wanted":
   394  				ret.Wanted = CryptoMessageFormat(field.Value)
   395  			case "received":
   396  				ret.Received = CryptoMessageFormat(field.Value)
   397  			}
   398  		}
   399  		return ret
   400  	case SCKeySyncedPGPNotFound:
   401  		return NoSyncedPGPKeyError{}
   402  	case SCKeyNoMatchingGPG:
   403  		ret := NoMatchingGPGKeysError{}
   404  		for _, field := range s.Fields {
   405  			switch field.Key {
   406  			case "fingerprints":
   407  				ret.Fingerprints = strings.Split(field.Value, ",")
   408  			case "has_active_device":
   409  				ret.HasActiveDevice = true
   410  			}
   411  		}
   412  		return ret
   413  	case SCDevicePrevProvisioned:
   414  		return DeviceAlreadyProvisionedError{}
   415  	case SCDeviceProvisionViaDevice:
   416  		return ProvisionViaDeviceRequiredError{}
   417  	case SCDeviceNoProvision:
   418  		return ProvisionUnavailableError{}
   419  	case SCGPGUnavailable:
   420  		return GPGUnavailableError{}
   421  	case SCNotFound:
   422  		return NotFoundError{Msg: s.Desc}
   423  	case SCDeleted:
   424  		return UserDeletedError{Msg: s.Desc}
   425  	case SCDecryptionError:
   426  		ret := DecryptionError{}
   427  		for _, field := range s.Fields {
   428  			switch field.Key {
   429  			case "Cause":
   430  				ret.Cause.Err = fmt.Errorf(field.Value)
   431  			case "Code":
   432  				if code, err := strconv.Atoi(field.Value); err == nil {
   433  					ret.Cause.StatusCode = code
   434  				}
   435  			}
   436  		}
   437  		return ret
   438  	case SCSigCannotVerify:
   439  		ret := VerificationError{}
   440  		for _, field := range s.Fields {
   441  			switch field.Key {
   442  			case "Cause":
   443  				ret.Cause.Err = fmt.Errorf(field.Value)
   444  			case "Code":
   445  				if code, err := strconv.Atoi(field.Value); err == nil {
   446  					ret.Cause.StatusCode = code
   447  				}
   448  			}
   449  		}
   450  		return ret
   451  	case SCKeyRevoked:
   452  		return KeyRevokedError{msg: s.Desc}
   453  	case SCDeviceNameInUse:
   454  		return DeviceNameInUseError{}
   455  	case SCDeviceBadName:
   456  		return DeviceBadNameError{}
   457  	case SCGenericAPIError:
   458  		var code int
   459  		for _, field := range s.Fields {
   460  			if field.Key == "code" {
   461  				var err error
   462  				code, err = strconv.Atoi(field.Value)
   463  				if err != nil && g != nil {
   464  					g.Log.Warning("error parsing generic API error code: %s", err)
   465  				}
   466  			}
   467  		}
   468  		return &APIError{
   469  			Msg:  s.Desc,
   470  			Code: code,
   471  		}
   472  	case SCChatInternal:
   473  		return ChatInternalError{}
   474  	case SCChatStalePreviousState:
   475  		return ChatStalePreviousStateError{}
   476  	case SCChatEphemeralRetentionPolicyViolatedError:
   477  		var maxAge gregor1.DurationSec
   478  		for _, field := range s.Fields {
   479  			if field.Key == "MaxAge" {
   480  				dur, err := time.ParseDuration(field.Value)
   481  				if err == nil {
   482  					maxAge = gregor1.ToDurationSec(dur)
   483  				}
   484  			}
   485  		}
   486  		return ChatEphemeralRetentionPolicyViolatedError{maxAge}
   487  	case SCChatConvExists:
   488  		var convID chat1.ConversationID
   489  		for _, field := range s.Fields {
   490  			if field.Key == "ConvID" {
   491  				bs, err := chat1.MakeConvID(field.Value)
   492  				if err != nil && g != nil {
   493  					g.Log.Warning("error parsing ChatConvExistsError")
   494  				}
   495  				convID = bs
   496  			}
   497  		}
   498  		return ChatConvExistsError{
   499  			ConvID: convID,
   500  		}
   501  	case SCChatUnknownTLFID:
   502  		var tlfID chat1.TLFID
   503  		for _, field := range s.Fields {
   504  			if field.Key == "TlfID" {
   505  				var err error
   506  				tlfID, err = chat1.MakeTLFID(field.Value)
   507  				if err != nil && g != nil {
   508  					g.Log.Warning("error parsing chat unknown TLF ID error")
   509  				}
   510  			}
   511  		}
   512  		return ChatUnknownTLFIDError{
   513  			TlfID: tlfID,
   514  		}
   515  	case SCChatNotInConv:
   516  		var uid gregor1.UID
   517  		for _, field := range s.Fields {
   518  			if field.Key == "UID" {
   519  				val, err := hex.DecodeString(field.Value)
   520  				if err != nil && g != nil {
   521  					g.Log.Warning("error parsing chat not in conv UID")
   522  				}
   523  				uid = gregor1.UID(val)
   524  			}
   525  		}
   526  		return ChatNotInConvError{
   527  			UID: uid,
   528  		}
   529  	case SCChatNotInTeam:
   530  		var uid gregor1.UID
   531  		for _, field := range s.Fields {
   532  			if field.Key == "UID" {
   533  				val, err := hex.DecodeString(field.Value)
   534  				if err != nil && g != nil {
   535  					g.Log.Warning("error parsing chat not in conv UID")
   536  				}
   537  				uid = gregor1.UID(val)
   538  			}
   539  		}
   540  		return ChatNotInTeamError{
   541  			UID: uid,
   542  		}
   543  	case SCChatTLFFinalized:
   544  		var tlfID chat1.TLFID
   545  		for _, field := range s.Fields {
   546  			if field.Key == "TlfID" {
   547  				var err error
   548  				tlfID, err = chat1.MakeTLFID(field.Value)
   549  				if err != nil && g != nil {
   550  					g.Log.Warning("error parsing chat tlf finalized TLFID: %s", err.Error())
   551  				}
   552  			}
   553  		}
   554  		return ChatTLFFinalizedError{
   555  			TlfID: tlfID,
   556  		}
   557  	case SCChatBadMsg:
   558  		return ChatBadMsgError{Msg: s.Desc}
   559  	case SCChatBroadcast:
   560  		return ChatBroadcastError{Msg: s.Desc}
   561  	case SCChatRateLimit:
   562  		var rlimit chat1.RateLimit
   563  		for _, field := range s.Fields {
   564  			if field.Key == "RateLimit" {
   565  				err := json.Unmarshal([]byte(field.Value), &rlimit)
   566  				if err != nil && g != nil {
   567  					g.Log.Warning("error parsing chat rate limit: %s", err.Error())
   568  				}
   569  			}
   570  		}
   571  		if rlimit.Name == "" && g != nil {
   572  			g.Log.Warning("error rate limit information not found")
   573  		}
   574  		return ChatRateLimitError{
   575  			RateLimit: rlimit,
   576  			Msg:       s.Desc,
   577  		}
   578  	case SCChatAlreadySuperseded:
   579  		return ChatAlreadySupersededError{Msg: s.Desc}
   580  	case SCChatAlreadyDeleted:
   581  		return ChatAlreadyDeletedError{Msg: s.Desc}
   582  	case SCBadEmail:
   583  		return BadEmailError{Msg: s.Desc}
   584  	case SCExists:
   585  		return ExistsError{Msg: s.Desc}
   586  	case SCInvalidAddress:
   587  		return InvalidAddressError{Msg: s.Desc}
   588  	case SCChatCollision:
   589  		return ChatCollisionError{}
   590  	case SCChatMessageCollision:
   591  		var headerHash string
   592  		for _, field := range s.Fields {
   593  			if field.Key == "HeaderHash" {
   594  				headerHash = field.Value
   595  			}
   596  		}
   597  		return ChatMessageCollisionError{
   598  			HeaderHash: headerHash,
   599  		}
   600  	case SCChatDuplicateMessage:
   601  		var soutboxID string
   602  		for _, field := range s.Fields {
   603  			if field.Key == "OutboxID" {
   604  				soutboxID = field.Value
   605  			}
   606  		}
   607  		boutboxID, _ := hex.DecodeString(soutboxID)
   608  		return ChatDuplicateMessageError{
   609  			OutboxID: chat1.OutboxID(boutboxID),
   610  		}
   611  	case SCChatClientError:
   612  		return ChatClientError{Msg: s.Desc}
   613  	case SCChatUsersAlreadyInConversationError:
   614  		var uids []keybase1.UID
   615  		for _, field := range s.Fields {
   616  			if field.Key == "uid" {
   617  				uids = append(uids, keybase1.UID(field.Value))
   618  			}
   619  		}
   620  		return ChatUsersAlreadyInConversationError{Uids: uids}
   621  	case SCChatBadConversationError:
   622  		var msg string
   623  		for _, field := range s.Fields {
   624  			if field.Key == "Msg" {
   625  				msg = field.Value
   626  			}
   627  		}
   628  		return ChatBadConversationError{
   629  			Msg: msg,
   630  		}
   631  	case SCNeedSelfRekey:
   632  		ret := NeedSelfRekeyError{Msg: s.Desc}
   633  		for _, field := range s.Fields {
   634  			if field.Key == "Tlf" {
   635  				ret.Tlf = field.Value
   636  			}
   637  		}
   638  		return ret
   639  	case SCNeedOtherRekey:
   640  		ret := NeedOtherRekeyError{Msg: s.Desc}
   641  		for _, field := range s.Fields {
   642  			if field.Key == "Tlf" {
   643  				ret.Tlf = field.Value
   644  			}
   645  		}
   646  		return ret
   647  	case SCLoginStateTimeout:
   648  		var e LoginStateTimeoutError
   649  		for _, field := range s.Fields {
   650  			switch field.Key {
   651  			case "ActiveRequest":
   652  				e.ActiveRequest = field.Value
   653  			case "AttemptedRequest":
   654  				e.AttemptedRequest = field.Value
   655  			case "Duration":
   656  				dur, err := time.ParseDuration(field.Value)
   657  				if err == nil {
   658  					e.Duration = dur
   659  				}
   660  			}
   661  		}
   662  		return e
   663  	case SCRevokeCurrentDevice:
   664  		return RevokeCurrentDeviceError{}
   665  	case SCRevokeLastDevice:
   666  		e := RevokeLastDeviceError{}
   667  		for _, field := range s.Fields {
   668  			if field.Key == "NoPassphrase" {
   669  				e.NoPassphrase = field.BoolValue()
   670  			}
   671  		}
   672  		return e
   673  	case SCRevokeLastDevicePGP:
   674  		return RevokeLastDevicePGPError{}
   675  	case SCTeamKeyMaskNotFound:
   676  		e := KeyMaskNotFoundError{}
   677  		for _, field := range s.Fields {
   678  			switch field.Key {
   679  			case "App":
   680  				e.App = keybase1.TeamApplication(field.IntValue())
   681  			case "Gen":
   682  				e.Gen = keybase1.PerTeamKeyGeneration(field.IntValue())
   683  			}
   684  		}
   685  		return e
   686  	case SCDeviceProvisionOffline:
   687  		return ProvisionFailedOfflineError{}
   688  	case SCGitInvalidRepoName:
   689  		e := InvalidRepoNameError{}
   690  		for _, field := range s.Fields {
   691  			if field.Key == "Name" {
   692  				e.Name = field.Value
   693  			}
   694  		}
   695  		return e
   696  	case SCGitRepoAlreadyExists:
   697  		e := RepoAlreadyExistsError{}
   698  		for _, field := range s.Fields {
   699  			switch field.Key {
   700  			case "DesiredName":
   701  				e.DesiredName = field.Value
   702  			case "ExistingName":
   703  				e.ExistingName = field.Value
   704  			case "ExistingID":
   705  				e.ExistingID = field.Value
   706  			}
   707  		}
   708  		return e
   709  	case SCGitRepoDoesntExist:
   710  		e := RepoDoesntExistError{}
   711  		for _, field := range s.Fields {
   712  			if field.Key == "Name" {
   713  				e.Name = field.Value
   714  			}
   715  		}
   716  		return e
   717  	case SCNoOp:
   718  		return NoOpError{Desc: s.Desc}
   719  	case SCNoSpaceOnDevice:
   720  		return NoSpaceOnDeviceError{Desc: s.Desc}
   721  	case SCTeamInviteBadToken:
   722  		return TeamInviteBadTokenError{}
   723  	case SCTeamInviteTokenReused:
   724  		return TeamInviteTokenReusedError{}
   725  	case SCTeamBadMembership:
   726  		return TeamBadMembershipError{}
   727  	case SCTeamProvisionalCanKey, SCTeamProvisionalCannotKey:
   728  		e := TeamProvisionalError{}
   729  		for _, field := range s.Fields {
   730  			switch field.Key {
   731  			case "IsPublic":
   732  				if field.Value == "1" {
   733  					e.IsPublic = true
   734  				}
   735  			case "PreResolveDisplayName":
   736  				e.PreResolveDisplayName = field.Value
   737  			}
   738  		}
   739  		if s.Code == SCTeamProvisionalCanKey {
   740  			e.CanKey = true
   741  		}
   742  		return e
   743  	case SCEphemeralPairwiseMACsMissingUIDs:
   744  		uids := []keybase1.UID{}
   745  		for _, field := range s.Fields {
   746  			uids = append(uids, keybase1.UID(field.Value))
   747  		}
   748  		return NewEphemeralPairwiseMACsMissingUIDsError(uids)
   749  	case SCMerkleClientError:
   750  		e := MerkleClientError{m: s.Desc}
   751  		for _, field := range s.Fields {
   752  			if field.Key == "type" {
   753  				i, err := strconv.Atoi(field.Value)
   754  				if err != nil {
   755  					g.Log.Warning("error parsing merkle error type: %s", err)
   756  				} else {
   757  					e.t = merkleClientErrorType(i)
   758  				}
   759  			}
   760  		}
   761  		return e
   762  	case SCFeatureFlag:
   763  		var feature Feature
   764  		for _, field := range s.Fields {
   765  			if field.Key == "feature" {
   766  				feature = Feature(field.Value)
   767  			}
   768  		}
   769  		return NewFeatureFlagError(s.Desc, feature)
   770  	case SCNoPaperKeys:
   771  		return NoPaperKeysError{}
   772  	case SCTeamContactSettingsBlock:
   773  		e := TeamContactSettingsBlockError{}
   774  		for _, field := range s.Fields {
   775  			switch field.Key {
   776  			case "uids":
   777  				e.blockedUIDs = parseUIDsFromString(field.Value)
   778  			case "usernames":
   779  				e.blockedUsernames = parseUsernamesFromString(field.Value)
   780  			}
   781  		}
   782  		return e
   783  	case SCAssertionParseError:
   784  		e := AssertionParseError{}
   785  		for _, field := range s.Fields {
   786  			switch field.Key {
   787  			case "err":
   788  				e.err = field.Value
   789  			case "reason":
   790  				s, err := strconv.Atoi(field.Value)
   791  				if err == nil {
   792  					reason := AssertionParseErrorReason(s)
   793  					e.reason = reason
   794  				}
   795  			}
   796  		}
   797  		return e
   798  
   799  	default:
   800  		ase := AppStatusError{
   801  			Code:   s.Code,
   802  			Name:   s.Name,
   803  			Desc:   s.Desc,
   804  			Fields: make(map[string]string),
   805  		}
   806  		for _, f := range s.Fields {
   807  			ase.Fields[f.Key] = f.Value
   808  		}
   809  		return ase
   810  	}
   811  }
   812  
   813  // =============================================================================
   814  
   815  func (a AppStatusError) ToStatus() keybase1.Status {
   816  	var fields []keybase1.StringKVPair
   817  	for k, v := range a.Fields {
   818  		fields = append(fields, keybase1.StringKVPair{Key: k, Value: v})
   819  	}
   820  
   821  	return keybase1.Status{
   822  		Code:   a.Code,
   823  		Name:   a.Name,
   824  		Desc:   a.Desc,
   825  		Fields: fields,
   826  	}
   827  }
   828  
   829  // =============================================================================
   830  
   831  func ExportTrackDiff(d TrackDiff) (res *keybase1.TrackDiff) {
   832  	if d != nil {
   833  		res = &keybase1.TrackDiff{
   834  			Type:          d.GetTrackDiffType(),
   835  			DisplayMarkup: d.ToDisplayString(),
   836  		}
   837  	}
   838  	return
   839  }
   840  
   841  // =============================================================================
   842  
   843  func ImportPGPFingerprintSlice(fp []byte) (ret *PGPFingerprint) {
   844  	if fp == nil {
   845  		return nil
   846  	}
   847  	if len(fp) != PGPFingerprintLen {
   848  		return nil
   849  	}
   850  
   851  	var tmp PGPFingerprint
   852  	copy(tmp[:], fp)
   853  	return &tmp
   854  }
   855  
   856  // =============================================================================
   857  
   858  func (s TrackSummary) Export(username string) (ret keybase1.TrackSummary) {
   859  	ret.Time = keybase1.ToTime(s.time)
   860  	ret.IsRemote = s.isRemote
   861  	ret.Username = username
   862  	return
   863  }
   864  
   865  func ImportTrackSummary(s *keybase1.TrackSummary) *TrackSummary {
   866  	if s == nil {
   867  		return nil
   868  	}
   869  
   870  	ret := &TrackSummary{
   871  		time:     keybase1.FromTime(s.Time),
   872  		isRemote: s.IsRemote,
   873  		username: s.Username,
   874  	}
   875  	return ret
   876  }
   877  
   878  func ExportTrackSummary(l *TrackLookup, username string) *keybase1.TrackSummary {
   879  	if l == nil {
   880  		return nil
   881  	}
   882  
   883  	tmp := l.ToSummary().Export(username)
   884  	return &tmp
   885  }
   886  
   887  // =============================================================================
   888  
   889  func (ir *IdentifyOutcome) Export(g *GlobalContext) *keybase1.IdentifyOutcome {
   890  	v := make([]string, len(ir.Warnings))
   891  	for i, w := range ir.Warnings {
   892  		v[i] = w.Warning()
   893  	}
   894  	del := make([]keybase1.TrackDiff, len(ir.Revoked))
   895  	for i, d := range ir.Revoked {
   896  		del[i] = *ExportTrackDiff(d)
   897  	}
   898  	ret := &keybase1.IdentifyOutcome{
   899  		Username:          ir.Username.String(),
   900  		Status:            ExportErrorAsStatus(g, ir.Error),
   901  		Warnings:          v,
   902  		TrackUsed:         ExportTrackSummary(ir.TrackUsed, ir.Username.String()),
   903  		TrackStatus:       ir.TrackStatus(),
   904  		NumTrackFailures:  ir.NumTrackFailures(),
   905  		NumTrackChanges:   ir.NumTrackChanges(),
   906  		NumProofFailures:  ir.NumProofFailures(),
   907  		NumRevoked:        ir.NumRevoked(),
   908  		NumProofSuccesses: ir.NumProofSuccesses(),
   909  		Revoked:           del,
   910  		TrackOptions:      ir.TrackOptions,
   911  		Reason:            ir.Reason,
   912  	}
   913  	return ret
   914  }
   915  
   916  // =============================================================================
   917  
   918  func DisplayTrackArg(sessionID int, stmt string) *keybase1.DisplayTrackStatementArg {
   919  	return &keybase1.DisplayTrackStatementArg{
   920  		SessionID: sessionID,
   921  		Stmt:      stmt,
   922  	}
   923  }
   924  
   925  // =============================================================================
   926  
   927  func ImportWarnings(v []string) Warnings {
   928  	w := make([]Warning, len(v))
   929  	for i, s := range v {
   930  		w[i] = StringWarning(s)
   931  	}
   932  	return Warnings{w: w}
   933  }
   934  
   935  // =============================================================================
   936  
   937  func (c CryptocurrencyChainLink) Export() (ret keybase1.Cryptocurrency) {
   938  	ret.Pkhash = c.pkhash
   939  	ret.Address = c.address
   940  	ret.SigID = c.GetSigID()
   941  	ret.Type = c.typ.String()
   942  	ret.Family = string(c.typ.ToCryptocurrencyFamily())
   943  	return ret
   944  }
   945  
   946  // =============================================================================
   947  
   948  func (p PassphraseError) ToStatus() (s keybase1.Status) {
   949  	s.Code = SCBadLoginPassword
   950  	s.Name = "BAD_LOGIN_PASSWORD"
   951  	s.Desc = p.Msg
   952  	return
   953  }
   954  
   955  func (m Markup) Export() (ret keybase1.Text) {
   956  	ret.Data = m.data
   957  	ret.Markup = true
   958  	return
   959  }
   960  
   961  // =============================================================================
   962  
   963  func (e LoggedInError) ToStatus() (s keybase1.Status) {
   964  	s.Code = SCAlreadyLoggedIn
   965  	s.Name = "ALREADY_LOGGED_IN"
   966  	s.Desc = "Already logged in as a different user"
   967  	return
   968  }
   969  
   970  // =============================================================================
   971  
   972  func (e LoggedInWrongUserError) ToStatus() (s keybase1.Status) {
   973  	s.Code = SCAlreadyLoggedIn
   974  	s.Name = "ALREADY_LOGGED_IN"
   975  	s.Desc = e.Error()
   976  	return
   977  }
   978  
   979  // =============================================================================
   980  
   981  func (e KeyGenError) ToStatus() (s keybase1.Status) {
   982  	s.Code = SCKeyBadGen
   983  	s.Name = "KEY_BAD_GEN"
   984  	s.Desc = e.Msg
   985  	return
   986  }
   987  
   988  // =============================================================================
   989  
   990  func (c CanceledError) ToStatus() (s keybase1.Status) {
   991  	s.Code = SCCanceled
   992  	s.Name = "CANCELED"
   993  	s.Desc = c.M
   994  	return
   995  }
   996  
   997  // =============================================================================
   998  
   999  func (e BadSessionError) ToStatus() (s keybase1.Status) {
  1000  	s.Code = SCBadSession
  1001  	s.Name = "BAD_SESSION"
  1002  	s.Desc = e.Desc
  1003  	return s
  1004  }
  1005  
  1006  // =============================================================================
  1007  
  1008  func (e InputCanceledError) ToStatus() (s keybase1.Status) {
  1009  	s.Code = SCInputCanceled
  1010  	s.Name = "CANCELED"
  1011  	s.Desc = "Input canceled"
  1012  	return
  1013  }
  1014  
  1015  // =============================================================================
  1016  
  1017  func (e SkipSecretPromptError) ToStatus() (s keybase1.Status) {
  1018  	s.Code = SCInputCanceled
  1019  	s.Name = "CANCELED"
  1020  	s.Desc = "Input canceled due to skip secret prompt"
  1021  	return
  1022  }
  1023  
  1024  // =============================================================================
  1025  
  1026  func (c KeyCorruptedError) ToStatus() (s keybase1.Status) {
  1027  	s.Code = SCKeyCorrupted
  1028  	s.Name = "KEY_CORRUPTED"
  1029  	if c.Msg != "" {
  1030  		s.Desc = c.Msg
  1031  	}
  1032  	return
  1033  }
  1034  
  1035  // =============================================================================
  1036  
  1037  func (e OfflineError) ToStatus() (s keybase1.Status) {
  1038  	s.Code = SCOffline
  1039  	s.Name = "OFFLINE"
  1040  	return s
  1041  }
  1042  
  1043  // =============================================================================
  1044  
  1045  func (c KeyExistsError) ToStatus() (s keybase1.Status) {
  1046  	s.Code = SCKeyInUse
  1047  	s.Name = "KEY_IN_USE"
  1048  	if c.Key != nil {
  1049  		s.Desc = c.Key.String()
  1050  	}
  1051  	return
  1052  }
  1053  
  1054  // =============================================================================
  1055  
  1056  func (ids Identities) Export() (res []keybase1.PGPIdentity) {
  1057  	var n int
  1058  	if ids == nil {
  1059  		n = 0
  1060  	} else {
  1061  		n = len(ids)
  1062  	}
  1063  	res = make([]keybase1.PGPIdentity, n)
  1064  	for i, id := range ids {
  1065  		res[i] = id.Export()
  1066  	}
  1067  	return
  1068  }
  1069  
  1070  func ImportPGPIdentities(ids []keybase1.PGPIdentity) (ret Identities) {
  1071  	ret = Identities(make([]Identity, len(ids)))
  1072  	for i, id := range ids {
  1073  		ret[i] = ImportPGPIdentity(id)
  1074  	}
  1075  	return
  1076  }
  1077  
  1078  // =============================================================================
  1079  
  1080  func (id Identity) Export() (ret keybase1.PGPIdentity) {
  1081  	ret.Username = id.Username
  1082  	ret.Email = id.Email
  1083  	ret.Comment = id.Comment
  1084  	return
  1085  }
  1086  
  1087  func ImportPGPIdentity(arg keybase1.PGPIdentity) (ret Identity) {
  1088  	ret.Username = arg.Username
  1089  	ret.Email = arg.Email
  1090  	ret.Comment = arg.Comment
  1091  	return
  1092  }
  1093  
  1094  // =============================================================================
  1095  
  1096  // Interface for sorting a list of PublicKeys
  1097  
  1098  type PublicKeyList []keybase1.PublicKey
  1099  
  1100  func (l PublicKeyList) Len() int { return len(l) }
  1101  func (l PublicKeyList) Less(i, j int) bool {
  1102  	// Keys created first come first.
  1103  	if l[i].CTime != l[j].CTime {
  1104  		return l[i].CTime < l[j].CTime
  1105  	}
  1106  	// For keys created at the same time, if one of them's the eldest key, it comes first.
  1107  	if l[i].IsEldest != l[j].IsEldest {
  1108  		return l[i].IsEldest
  1109  	}
  1110  	// Otherwise just sort by KID.
  1111  	return l[i].KID < l[j].KID
  1112  }
  1113  func (l PublicKeyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
  1114  
  1115  func ExportPGPIdentity(identity *openpgp.Identity) keybase1.PGPIdentity {
  1116  	if identity == nil || identity.UserId == nil {
  1117  		return keybase1.PGPIdentity{}
  1118  	}
  1119  	return keybase1.PGPIdentity{
  1120  		Username: identity.UserId.Name,
  1121  		Email:    identity.UserId.Email,
  1122  		Comment:  identity.UserId.Comment,
  1123  	}
  1124  }
  1125  
  1126  func (kf KeyFamily) Export() []keybase1.PublicKey {
  1127  	var res []keybase1.PublicKey
  1128  	for kid := range kf.AllKIDs {
  1129  		if pgpKeySet, isPGP := kf.PGPKeySets[kid]; isPGP {
  1130  			res = append(res, pgpKeySet.PermissivelyMergedKey.Export())
  1131  		} else {
  1132  			res = append(res, keybase1.PublicKey{KID: kid})
  1133  		}
  1134  	}
  1135  	return res
  1136  }
  1137  
  1138  func (bundle *PGPKeyBundle) Export() keybase1.PublicKey {
  1139  	kid := bundle.GetKID()
  1140  	fingerprintStr := ""
  1141  	identities := []keybase1.PGPIdentity{}
  1142  	fingerprintStr = bundle.GetFingerprint().String()
  1143  	for _, identity := range bundle.Identities {
  1144  		identities = append(identities, ExportPGPIdentity(identity))
  1145  	}
  1146  	return keybase1.PublicKey{
  1147  		KID:            kid,
  1148  		PGPFingerprint: fingerprintStr,
  1149  		PGPIdentities:  identities,
  1150  	}
  1151  }
  1152  
  1153  func (ckf ComputedKeyFamily) exportPublicKey(key GenericKey) (pk keybase1.PublicKey) {
  1154  	pk.KID = key.GetKID()
  1155  	if pgpBundle, isPGP := key.(*PGPKeyBundle); isPGP {
  1156  		pk.PGPFingerprint = pgpBundle.GetFingerprint().String()
  1157  		ids := make([]keybase1.PGPIdentity, len(pgpBundle.Identities))
  1158  		i := 0
  1159  		for _, identity := range pgpBundle.Identities {
  1160  			ids[i] = ExportPGPIdentity(identity)
  1161  			i++
  1162  		}
  1163  		pk.PGPIdentities = ids
  1164  		pk.IsRevoked = len(pgpBundle.Revocations)+len(pgpBundle.UnverifiedRevocations) > 0
  1165  	}
  1166  	pk.DeviceID = ckf.cki.KIDToDeviceID[pk.KID]
  1167  	device := ckf.cki.Devices[pk.DeviceID]
  1168  	if device != nil {
  1169  		if device.Description != nil {
  1170  			pk.DeviceDescription = *device.Description
  1171  		}
  1172  		pk.DeviceType = device.Type
  1173  	}
  1174  	cki, ok := ckf.cki.Infos[pk.KID]
  1175  	if ok && cki != nil {
  1176  		if cki.Parent.IsValid() {
  1177  			pk.ParentID = cki.Parent.String()
  1178  		}
  1179  		pk.IsSibkey = cki.Sibkey
  1180  		pk.IsEldest = cki.Eldest
  1181  		pk.CTime = keybase1.TimeFromSeconds(cki.CTime)
  1182  		pk.ETime = keybase1.TimeFromSeconds(cki.ETime)
  1183  	}
  1184  	return pk
  1185  }
  1186  
  1187  func publicKeyV2BaseFromComputedKeyInfo(kid keybase1.KID, info ComputedKeyInfo) (base keybase1.PublicKeyV2Base) {
  1188  	base = keybase1.PublicKeyV2Base{
  1189  		Kid:      kid,
  1190  		IsSibkey: info.Sibkey,
  1191  		IsEldest: info.Eldest,
  1192  		CTime:    keybase1.TimeFromSeconds(info.CTime),
  1193  		ETime:    keybase1.TimeFromSeconds(info.ETime),
  1194  	}
  1195  	if info.DelegatedAt != nil {
  1196  		base.Provisioning = keybase1.SignatureMetadata{
  1197  			Time: keybase1.TimeFromSeconds(info.DelegatedAt.Unix),
  1198  			PrevMerkleRootSigned: keybase1.MerkleRootV2{
  1199  				HashMeta: info.DelegatedAtHashMeta,
  1200  				Seqno:    info.DelegatedAt.Chain,
  1201  			},
  1202  			FirstAppearedUnverified: info.FirstAppearedUnverified,
  1203  		}
  1204  		dLen := len(info.DelegationsList)
  1205  		if dLen > 0 {
  1206  			base.Provisioning.SigningKID = info.DelegationsList[dLen-1].KID
  1207  		}
  1208  	}
  1209  	base.Provisioning.SigChainLocation = info.DelegatedAtSigChainLocation
  1210  	if info.RevokedAt != nil {
  1211  		base.Revocation = &keybase1.SignatureMetadata{
  1212  			Time: keybase1.TimeFromSeconds(info.RevokedAt.Unix),
  1213  			PrevMerkleRootSigned: keybase1.MerkleRootV2{
  1214  				HashMeta: info.RevokedAtHashMeta,
  1215  				Seqno:    info.RevokedAt.Chain,
  1216  			},
  1217  			FirstAppearedUnverified: info.RevokeFirstAppearedUnverified,
  1218  			SigningKID:              info.RevokedBy,
  1219  		}
  1220  		if info.RevokedAtSigChainLocation != nil {
  1221  			base.Revocation.SigChainLocation = *info.RevokedAtSigChainLocation
  1222  		}
  1223  	}
  1224  	return
  1225  }
  1226  
  1227  func (cki ComputedKeyInfos) exportDeviceKeyV2(kid keybase1.KID) (key keybase1.PublicKeyV2NaCl) {
  1228  	info := cki.Infos[kid]
  1229  	if info == nil {
  1230  		cki.G().Log.Errorf("Tried to export nonexistent KID: %s", kid.String())
  1231  		return
  1232  	}
  1233  	key = keybase1.PublicKeyV2NaCl{
  1234  		Base:     publicKeyV2BaseFromComputedKeyInfo(kid, *info),
  1235  		DeviceID: cki.KIDToDeviceID[kid],
  1236  	}
  1237  	if !info.Parent.IsNil() {
  1238  		key.Parent = &info.Parent
  1239  	}
  1240  	if device := cki.Devices[key.DeviceID]; device != nil {
  1241  		key.DeviceType = device.Type
  1242  		if device.Description != nil {
  1243  			key.DeviceDescription = *device.Description
  1244  		}
  1245  	}
  1246  	return
  1247  }
  1248  
  1249  func (cki ComputedKeyInfos) exportPGPKeyV2(kid keybase1.KID, kf *KeyFamily) (key keybase1.PublicKeyV2PGPSummary) {
  1250  	info := cki.Infos[kid]
  1251  	if info == nil {
  1252  		cki.G().Log.Errorf("Tried to export nonexistent KID: %s", kid.String())
  1253  		return
  1254  	}
  1255  	keySet := kf.PGPKeySets[kid]
  1256  	if keySet == nil {
  1257  		cki.G().Log.Errorf("Tried to export PGP key with no key set, KID: %s", kid.String())
  1258  		return
  1259  	}
  1260  	var bundle *PGPKeyBundle
  1261  	if info.ActivePGPHash != "" {
  1262  		bundle = keySet.KeysByHash[info.ActivePGPHash]
  1263  	} else {
  1264  		bundle = keySet.PermissivelyMergedKey
  1265  	}
  1266  	if bundle == nil {
  1267  		cki.G().Log.Errorf("Tried to export PGP key with no bundle, KID: %s", kid.String())
  1268  		return
  1269  	}
  1270  	key = keybase1.PublicKeyV2PGPSummary{
  1271  		Base:        publicKeyV2BaseFromComputedKeyInfo(kid, *info),
  1272  		Fingerprint: keybase1.PGPFingerprint(bundle.GetFingerprint()),
  1273  		Identities:  bundle.Export().PGPIdentities,
  1274  	}
  1275  	return
  1276  }
  1277  
  1278  // Export is used by IDRes.  It includes PGP keys.
  1279  func (ckf ComputedKeyFamily) Export() []keybase1.PublicKey {
  1280  	var exportedKeys []keybase1.PublicKey
  1281  	for _, key := range ckf.GetAllActiveSibkeys() {
  1282  		exportedKeys = append(exportedKeys, ckf.exportPublicKey(key))
  1283  	}
  1284  	for _, key := range ckf.GetAllActiveSubkeys() {
  1285  		exportedKeys = append(exportedKeys, ckf.exportPublicKey(key))
  1286  	}
  1287  	sort.Sort(PublicKeyList(exportedKeys))
  1288  	return exportedKeys
  1289  }
  1290  
  1291  // ExportDeviceKeys is used by ExportToUserPlusKeys.  The key list
  1292  // only contains device keys.  It also returns the number of PGP
  1293  // keys in the key family.
  1294  func (ckf ComputedKeyFamily) ExportDeviceKeys() (exportedKeys []keybase1.PublicKey, pgpKeyCount int) {
  1295  	for _, key := range ckf.GetAllActiveSibkeys() {
  1296  		if _, isPGP := key.(*PGPKeyBundle); isPGP {
  1297  			pgpKeyCount++
  1298  			continue
  1299  		}
  1300  		exportedKeys = append(exportedKeys, ckf.exportPublicKey(key))
  1301  	}
  1302  	for _, key := range ckf.GetAllActiveSubkeys() {
  1303  		if _, isPGP := key.(*PGPKeyBundle); isPGP {
  1304  			pgpKeyCount++
  1305  			continue
  1306  		}
  1307  		exportedKeys = append(exportedKeys, ckf.exportPublicKey(key))
  1308  	}
  1309  	sort.Sort(PublicKeyList(exportedKeys))
  1310  	return exportedKeys, pgpKeyCount
  1311  }
  1312  
  1313  type perUserKeyList []keybase1.PerUserKey
  1314  
  1315  func (l perUserKeyList) Len() int { return len(l) }
  1316  func (l perUserKeyList) Less(i, j int) bool {
  1317  	return l[i].Gen < l[j].Gen
  1318  }
  1319  func (l perUserKeyList) Swap(i, j int) {
  1320  	l[i], l[j] = l[j], l[i]
  1321  }
  1322  
  1323  // ExportPerUserKeys exports the per-user public KIDs.
  1324  func (ckf ComputedKeyFamily) ExportPerUserKeys() (ret []keybase1.PerUserKey) {
  1325  
  1326  	for _, k := range ckf.cki.PerUserKeys {
  1327  		ret = append(ret, k)
  1328  	}
  1329  	sort.Sort(perUserKeyList(ret))
  1330  	return ret
  1331  }
  1332  
  1333  // ExportDeletedDeviceKeys is used by ExportToUserPlusKeys.  The key list
  1334  // only contains deleted device keys.
  1335  func (ckf ComputedKeyFamily) ExportDeletedDeviceKeys() []keybase1.PublicKey {
  1336  	var keys []keybase1.PublicKey
  1337  	for _, key := range ckf.GetDeletedKeys() {
  1338  		if _, isPGP := key.(*PGPKeyBundle); isPGP {
  1339  			continue
  1340  		}
  1341  		keys = append(keys, ckf.exportPublicKey(key))
  1342  	}
  1343  	sort.Sort(PublicKeyList(keys))
  1344  	return keys
  1345  }
  1346  
  1347  // ExportAllPGPKeys exports all pgp keys.
  1348  func (ckf ComputedKeyFamily) ExportAllPGPKeys() (keys []keybase1.PublicKey) {
  1349  	for _, key := range ckf.GetAllActiveSibkeys() {
  1350  		if _, isPGP := key.(*PGPKeyBundle); isPGP {
  1351  			keys = append(keys, ckf.exportPublicKey(key))
  1352  		}
  1353  	}
  1354  	for _, key := range ckf.GetAllActiveSubkeys() {
  1355  		if _, isPGP := key.(*PGPKeyBundle); isPGP {
  1356  			keys = append(keys, ckf.exportPublicKey(key))
  1357  		}
  1358  	}
  1359  	sort.Sort(PublicKeyList(keys))
  1360  	return keys
  1361  }
  1362  
  1363  func (ckf ComputedKeyFamily) ExportRevokedDeviceKeys() []keybase1.RevokedKey {
  1364  	var ex []keybase1.RevokedKey
  1365  	for _, key := range ckf.GetRevokedKeys() {
  1366  		if _, isPGP := key.Key.(*PGPKeyBundle); isPGP {
  1367  			continue
  1368  		}
  1369  		rkey := keybase1.RevokedKey{
  1370  			Key: ckf.exportPublicKey(key.Key),
  1371  			Time: keybase1.KeybaseTime{
  1372  				Unix:  keybase1.TimeFromSeconds(key.RevokedAt.Unix),
  1373  				Chain: key.RevokedAt.Chain,
  1374  			},
  1375  			By: key.RevokedBy,
  1376  		}
  1377  		ex = append(ex, rkey)
  1378  	}
  1379  
  1380  	return ex
  1381  }
  1382  
  1383  func (u *User) Export() *keybase1.User {
  1384  	return &keybase1.User{
  1385  		Uid:      u.GetUID(),
  1386  		Username: u.GetName(),
  1387  	}
  1388  }
  1389  
  1390  func (u *User) ExportToVersionVector() keybase1.UserVersionVector {
  1391  	idv, _ := u.GetIDVersion()
  1392  	return keybase1.UserVersionVector{
  1393  		Id:       idv,
  1394  		SigHints: u.GetSigHintsVersion(),
  1395  		SigChain: int64(u.GetSigChainLastKnownSeqno()),
  1396  		// CachedAt is set by the upak loader right before we write to disk.
  1397  	}
  1398  }
  1399  
  1400  func (u *User) ExportToUserPlusKeys() keybase1.UserPlusKeys {
  1401  	ret := keybase1.UserPlusKeys{
  1402  		Uid:         u.GetUID(),
  1403  		Username:    u.GetName(),
  1404  		EldestSeqno: u.GetCurrentEldestSeqno(),
  1405  	}
  1406  	ckf := u.GetComputedKeyFamily()
  1407  	if ckf != nil {
  1408  		ret.DeviceKeys, ret.PGPKeyCount = ckf.ExportDeviceKeys()
  1409  		ret.RevokedDeviceKeys = ckf.ExportRevokedDeviceKeys()
  1410  		ret.DeletedDeviceKeys = ckf.ExportDeletedDeviceKeys()
  1411  		ret.PerUserKeys = ckf.ExportPerUserKeys()
  1412  	}
  1413  
  1414  	ret.Uvv = u.ExportToVersionVector()
  1415  	return ret
  1416  }
  1417  
  1418  func (u *User) ExportToUserPlusAllKeys() keybase1.UserPlusAllKeys {
  1419  	return keybase1.UserPlusAllKeys{
  1420  		Base:         u.ExportToUserPlusKeys(),
  1421  		PGPKeys:      u.GetComputedKeyFamily().ExportAllPGPKeys(),
  1422  		RemoteTracks: u.ExportRemoteTracks(),
  1423  	}
  1424  }
  1425  
  1426  type PerUserKeysList []keybase1.PerUserKey
  1427  
  1428  func (p PerUserKeysList) Len() int           { return len(p) }
  1429  func (p PerUserKeysList) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
  1430  func (p PerUserKeysList) Less(i, j int) bool { return p[i].Gen < p[j].Gen }
  1431  
  1432  func (cki *ComputedKeyInfos) exportUPKV2Incarnation(uid keybase1.UID, username string, eldestSeqno keybase1.Seqno, kf *KeyFamily, status keybase1.StatusCode, reset *keybase1.ResetSummary) keybase1.UserPlusKeysV2 {
  1433  
  1434  	var perUserKeysList PerUserKeysList
  1435  	if cki != nil {
  1436  		for _, puk := range cki.PerUserKeys {
  1437  			perUserKeysList = append(perUserKeysList, puk)
  1438  		}
  1439  		sort.Sort(perUserKeysList)
  1440  	}
  1441  
  1442  	deviceKeys := make(map[keybase1.KID]keybase1.PublicKeyV2NaCl)
  1443  	pgpSummaries := make(map[keybase1.KID]keybase1.PublicKeyV2PGPSummary)
  1444  	if cki != nil {
  1445  		for kid := range cki.Infos {
  1446  			if KIDIsPGP(kid) {
  1447  				pgpSummaries[kid] = cki.exportPGPKeyV2(kid, kf)
  1448  			} else {
  1449  				deviceKeys[kid] = cki.exportDeviceKeyV2(kid)
  1450  			}
  1451  		}
  1452  	}
  1453  
  1454  	return keybase1.UserPlusKeysV2{
  1455  		Uid:         uid,
  1456  		Username:    username,
  1457  		EldestSeqno: eldestSeqno,
  1458  		PerUserKeys: perUserKeysList,
  1459  		DeviceKeys:  deviceKeys,
  1460  		PGPKeys:     pgpSummaries,
  1461  		Status:      status,
  1462  		Reset:       reset,
  1463  		// Uvv and RemoteTracks are set later, and only for the current incarnation
  1464  	}
  1465  }
  1466  
  1467  func (u *User) ExportToUPKV2AllIncarnations() (*keybase1.UserPlusKeysV2AllIncarnations, error) {
  1468  	// The KeyFamily holds all the PGP key bundles, and it applies to all
  1469  	// generations of this user.
  1470  	kf := u.GetKeyFamily()
  1471  
  1472  	uid := u.GetUID()
  1473  	name := u.GetName()
  1474  	status := u.GetStatus()
  1475  
  1476  	// Make a map of EldestKID -> ResetSummary for all resets
  1477  
  1478  	resetMap := make(map[keybase1.Seqno](*keybase1.ResetSummary))
  1479  	if resets := u.leaf.resets; resets != nil {
  1480  		for _, l := range resets.chain {
  1481  			tmp := l.Summarize()
  1482  			resetMap[l.Prev.LastSeqno] = &tmp
  1483  		}
  1484  	}
  1485  
  1486  	// First assemble all the past versions of this user.
  1487  	pastIncarnations := []keybase1.UserPlusKeysV2{}
  1488  	if u.sigChain() != nil {
  1489  		for _, subchain := range u.sigChain().prevSubchains {
  1490  			if len(subchain) == 0 {
  1491  				return nil, fmt.Errorf("Tried to export empty subchain for uid %s username %s", u.GetUID(), u.GetName())
  1492  			}
  1493  			lastLink := subchain[len(subchain)-1]
  1494  			cki := lastLink.cki
  1495  			eldestSeqno := subchain[0].GetSeqno()
  1496  			lastSeqno := lastLink.GetSeqno()
  1497  			reset := resetMap[lastSeqno]
  1498  			if reset != nil {
  1499  				reset.EldestSeqno = eldestSeqno
  1500  			}
  1501  			pastIncarnations = append(pastIncarnations, cki.exportUPKV2Incarnation(uid, name, eldestSeqno, kf, status, reset))
  1502  		}
  1503  	}
  1504  
  1505  	// Then assemble the current version. This one gets a couple extra fields, Uvv and RemoteTracks.
  1506  	current := u.GetComputedKeyInfos().exportUPKV2Incarnation(uid, name, u.GetCurrentEldestSeqno(), kf, status, nil)
  1507  	current.RemoteTracks = make(map[keybase1.UID]keybase1.RemoteTrack)
  1508  	if tab := u.IDTable(); tab != nil {
  1509  		for _, track := range tab.GetTrackList() {
  1510  			current.RemoteTracks[track.whomUID] = track.Export()
  1511  		}
  1512  		current.Unstubbed = !tab.HasStubs()
  1513  	}
  1514  	if accountID := u.StellarAccountID(); accountID != nil {
  1515  		tmp := accountID.String()
  1516  		current.StellarAccountID = &tmp
  1517  	}
  1518  
  1519  	// Collect the link IDs (that is, the hashes of the signature inputs) from all subchains.
  1520  	linkIDs := map[keybase1.Seqno]keybase1.LinkID{}
  1521  	if u.sigChain() != nil {
  1522  		for _, link := range u.sigChain().chainLinks {
  1523  			// Assert that all the links are in order as they go in. We should
  1524  			// never fail this check, but we *really* want to know about it if
  1525  			// we do.
  1526  			if int(link.GetSeqno()) != len(linkIDs)+1 {
  1527  				return nil, fmt.Errorf("Encountered out-of-sequence chain link %d while exporting uid %s username %s", link.GetSeqno(), u.GetUID(), u.GetName())
  1528  			}
  1529  			linkIDs[link.GetSeqno()] = link.LinkID().Export()
  1530  		}
  1531  	}
  1532  
  1533  	return &keybase1.UserPlusKeysV2AllIncarnations{
  1534  		Current:          current,
  1535  		PastIncarnations: pastIncarnations,
  1536  		Uvv:              u.ExportToVersionVector(),
  1537  		SeqnoLinkIDs:     linkIDs,
  1538  		MinorVersion:     UPK2MinorVersionCurrent,
  1539  	}, nil
  1540  }
  1541  
  1542  // NOTE: This list *must* be in sorted order. If we ever write V3, be careful to keep it sorted!
  1543  func (u *User) ExportRemoteTracks() []keybase1.RemoteTrack {
  1544  	var ret []keybase1.RemoteTrack
  1545  	if u.IDTable() == nil {
  1546  		return ret
  1547  	}
  1548  	trackList := u.IDTable().GetTrackList()
  1549  	for _, track := range trackList {
  1550  		ret = append(ret, track.Export())
  1551  	}
  1552  	sort.Slice(ret, func(i, j int) bool { return ret[i].Username < ret[j].Username })
  1553  	return ret
  1554  }
  1555  
  1556  func (i LinkID) Export() keybase1.LinkID {
  1557  	return keybase1.LinkID(i.String())
  1558  }
  1559  
  1560  func (t TrackChainLink) Export() keybase1.RemoteTrack {
  1561  	return keybase1.RemoteTrack{
  1562  		Uid:      t.whomUID,
  1563  		Username: t.whomUsername.String(),
  1564  		LinkID:   t.id.Export(),
  1565  	}
  1566  }
  1567  
  1568  // =============================================================================
  1569  
  1570  func (a PGPGenArg) ExportTo(ret *keybase1.PGPKeyGenArg) {
  1571  	ret.PrimaryBits = a.PrimaryBits
  1572  	ret.SubkeyBits = a.SubkeyBits
  1573  	ret.CreateUids = keybase1.PGPCreateUids{Ids: a.Ids.Export()}
  1574  }
  1575  
  1576  // =============================================================================
  1577  
  1578  func ImportKeyGenArg(a keybase1.PGPKeyGenArg) (ret PGPGenArg) {
  1579  	ret.PrimaryBits = a.PrimaryBits
  1580  	ret.SubkeyBits = a.SubkeyBits
  1581  	ret.Ids = ImportPGPIdentities(a.CreateUids.Ids)
  1582  	return ret
  1583  }
  1584  
  1585  // =============================================================================
  1586  
  1587  func (e BadInvitationCodeError) ToStatus() (s keybase1.Status) {
  1588  	s.Code = SCBadInvitationCode
  1589  	s.Name = "BAD_INVITATION_CODE"
  1590  	return s
  1591  }
  1592  
  1593  // =============================================================================
  1594  
  1595  func (e StreamExistsError) ToStatus() (s keybase1.Status) {
  1596  	s.Code = SCStreamExists
  1597  	s.Name = "STREAM_EXISTS"
  1598  	return s
  1599  }
  1600  
  1601  func (e StreamNotFoundError) ToStatus() (s keybase1.Status) {
  1602  	s.Code = SCStreamNotFound
  1603  	s.Name = "SC_STREAM_NOT_FOUND"
  1604  	return s
  1605  }
  1606  
  1607  func (e StreamWrongKindError) ToStatus() (s keybase1.Status) {
  1608  	s.Code = SCStreamWrongKind
  1609  	s.Name = "STREAM_WRONG_KIND"
  1610  	return s
  1611  }
  1612  
  1613  func (e UnknownStreamError) ToStatus() (s keybase1.Status) {
  1614  	s.Code = SCStreamUnknown
  1615  	s.Name = "STREAM_UNKNOWN"
  1616  	return s
  1617  }
  1618  
  1619  // =============================================================================
  1620  
  1621  func (u NoSecretKeyError) ToStatus() (s keybase1.Status) {
  1622  	s.Code = SCKeyNoSecret
  1623  	s.Name = "KEY_NO_SECRET"
  1624  	return s
  1625  }
  1626  
  1627  // =============================================================================
  1628  
  1629  func (u LoginRequiredError) ToStatus() (s keybase1.Status) {
  1630  	s.Code = SCLoginRequired
  1631  	s.Name = "LOGIN_REQUIRED"
  1632  	s.Desc = u.Context
  1633  	return s
  1634  }
  1635  
  1636  // =============================================================================
  1637  
  1638  func (u NoSessionError) ToStatus() (s keybase1.Status) {
  1639  	s.Code = SCNoSession
  1640  	s.Name = "NO_SESSION"
  1641  	return s
  1642  }
  1643  
  1644  // =============================================================================
  1645  
  1646  func (e APINetError) ToStatus() (s keybase1.Status) {
  1647  	s.Code = SCAPINetworkError
  1648  	s.Name = "API_NETWORK_ERROR"
  1649  	s.Desc = e.Error()
  1650  	return s
  1651  }
  1652  
  1653  func (e ProofNotFoundForServiceError) ToStatus() (s keybase1.Status) {
  1654  	s.Code = SCProofError
  1655  	s.Name = "PROOF_ERROR"
  1656  	s.Desc = e.Error()
  1657  	return s
  1658  }
  1659  
  1660  func (e ProofNotFoundForUsernameError) ToStatus() (s keybase1.Status) {
  1661  	s.Code = SCProofError
  1662  	s.Name = "PROOF_ERROR"
  1663  	s.Desc = e.Error()
  1664  	return s
  1665  }
  1666  
  1667  func (e NoDecryptionKeyError) ToStatus() (s keybase1.Status) {
  1668  	s.Code = SCDecryptionKeyNotFound
  1669  	s.Name = "KEY_NOT_FOUND_DECRYPTION"
  1670  	s.Desc = e.Msg
  1671  	return s
  1672  }
  1673  
  1674  func (e NoKeyError) ToStatus() (s keybase1.Status) {
  1675  	s.Code = SCKeyNotFound
  1676  	s.Name = "KEY_NOT_FOUND"
  1677  	s.Desc = e.Msg
  1678  	return s
  1679  }
  1680  
  1681  func (e NoSyncedPGPKeyError) ToStatus() keybase1.Status {
  1682  	return keybase1.Status{
  1683  		Code: SCKeySyncedPGPNotFound,
  1684  		Name: "KEY_NOT_FOUND_SYNCED_PGP",
  1685  		Desc: e.Error(),
  1686  	}
  1687  }
  1688  
  1689  func (e IdentifyTimeoutError) ToStatus() keybase1.Status {
  1690  	return keybase1.Status{
  1691  		Code: SCIdentificationExpired,
  1692  		Name: "IDENTIFICATION_EXPIRED",
  1693  		Desc: e.Error(),
  1694  	}
  1695  }
  1696  
  1697  func (e SelfNotFoundError) ToStatus() keybase1.Status {
  1698  	return keybase1.Status{
  1699  		Code: SCSelfNotFound,
  1700  		Name: "SELF_NOT_FOUND",
  1701  		Desc: e.Error(),
  1702  	}
  1703  }
  1704  
  1705  func (e NoDeviceError) ToStatus() keybase1.Status {
  1706  	return keybase1.Status{
  1707  		Code: SCDeviceNotFound,
  1708  		Name: "DEVICE_NOT_FOUND",
  1709  		Desc: e.Reason,
  1710  	}
  1711  }
  1712  
  1713  func (e TimeoutError) ToStatus() keybase1.Status {
  1714  	return keybase1.Status{
  1715  		Code: SCTimeout,
  1716  		Name: "SC_TIMEOUT",
  1717  		Desc: e.Error(),
  1718  	}
  1719  }
  1720  
  1721  func (e ReceiverDeviceError) ToStatus() keybase1.Status {
  1722  	return keybase1.Status{
  1723  		Code: SCDeviceMismatch,
  1724  		Name: "SC_DEVICE_MISMATCH",
  1725  		Desc: e.Error(),
  1726  	}
  1727  }
  1728  
  1729  func (e InvalidKexPhraseError) ToStatus() keybase1.Status {
  1730  	return keybase1.Status{
  1731  		Code: SCBadKexPhrase,
  1732  		Name: "SC_BAD_KEX_PHRASE",
  1733  		Desc: e.Error(),
  1734  	}
  1735  }
  1736  
  1737  func (e ReloginRequiredError) ToStatus() keybase1.Status {
  1738  	return keybase1.Status{
  1739  		Code: SCReloginRequired,
  1740  		Name: "SC_RELOGIN_REQUIRED",
  1741  		Desc: e.Error(),
  1742  	}
  1743  }
  1744  
  1745  func (e DeviceRequiredError) ToStatus() keybase1.Status {
  1746  	return keybase1.Status{
  1747  		Code: SCDeviceRequired,
  1748  		Name: "SC_DEVICE_REQUIRED",
  1749  		Desc: e.Error(),
  1750  	}
  1751  }
  1752  
  1753  func (e IdentifyDidNotCompleteError) ToStatus() keybase1.Status {
  1754  	return keybase1.Status{
  1755  		Code: SCMissingResult,
  1756  		Name: "SC_MISSING_RESULT",
  1757  		Desc: e.Error(),
  1758  	}
  1759  }
  1760  
  1761  func (e SibkeyAlreadyExistsError) ToStatus() keybase1.Status {
  1762  	return keybase1.Status{
  1763  		Code: SCSibkeyAlreadyExists,
  1764  		Name: "SC_SIBKEY_ALREADY_EXISTS",
  1765  		Desc: e.Error(),
  1766  	}
  1767  }
  1768  
  1769  func (e ServiceDoesNotSupportNewProofsError) ToStatus() keybase1.Status {
  1770  	return keybase1.Status{
  1771  		Code: SCSigCreationDisallowed,
  1772  		Name: "SC_SIG_CREATION_DISALLOWED",
  1773  		Desc: e.Error(),
  1774  	}
  1775  }
  1776  
  1777  func (e UIDelegationUnavailableError) ToStatus() keybase1.Status {
  1778  	return keybase1.Status{
  1779  		Code: SCNoUIDelegation,
  1780  		Name: "SC_UI_DELEGATION_UNAVAILABLE",
  1781  		Desc: e.Error(),
  1782  	}
  1783  }
  1784  
  1785  func (e NoUIError) ToStatus() keybase1.Status {
  1786  	return keybase1.Status{
  1787  		Code: SCNoUI,
  1788  		Name: "SC_NO_UI",
  1789  		Desc: e.Which,
  1790  	}
  1791  }
  1792  
  1793  func (e ResolutionError) ToStatus() keybase1.Status {
  1794  	return keybase1.Status{
  1795  		Code: SCResolutionFailed,
  1796  		Name: "SC_RESOLUTION_FAILED",
  1797  		Desc: e.Msg,
  1798  		Fields: []keybase1.StringKVPair{
  1799  			{Key: "input", Value: e.Input},
  1800  		},
  1801  	}
  1802  }
  1803  
  1804  func (e IdentifyFailedError) ToStatus() keybase1.Status {
  1805  	return keybase1.Status{
  1806  		Code: SCIdentifyFailed,
  1807  		Name: "SC_IDENTIFY_FAILED",
  1808  		Desc: e.Reason,
  1809  		Fields: []keybase1.StringKVPair{
  1810  			{Key: "assertion", Value: e.Assertion},
  1811  		},
  1812  	}
  1813  }
  1814  
  1815  func (e IdentifiesFailedError) ToStatus() keybase1.Status {
  1816  	return keybase1.Status{
  1817  		Code: SCIdentifiesFailed,
  1818  		Name: "SC_IDENTIFIES_FAILED",
  1819  		Desc: e.Error(),
  1820  	}
  1821  }
  1822  
  1823  func (e IdentifySummaryError) ToStatus() keybase1.Status {
  1824  	kvpairs := []keybase1.StringKVPair{
  1825  		{Key: "username", Value: e.username.String()},
  1826  	}
  1827  	for index, problem := range e.problems {
  1828  		kvpairs = append(kvpairs, keybase1.StringKVPair{
  1829  			Key:   fmt.Sprintf("problem_%d", index),
  1830  			Value: problem,
  1831  		})
  1832  	}
  1833  	return keybase1.Status{
  1834  		Code:   SCIdentifySummaryError,
  1835  		Name:   "SC_IDENTIFY_SUMMARY_ERROR",
  1836  		Desc:   e.Error(),
  1837  		Fields: kvpairs,
  1838  	}
  1839  }
  1840  
  1841  func (e ProfileNotPublicError) ToStatus() keybase1.Status {
  1842  	return keybase1.Status{
  1843  		Code: SCProfileNotPublic,
  1844  		Name: "SC_PROFILE_NOT_PUBLIC",
  1845  		Desc: e.msg,
  1846  	}
  1847  }
  1848  
  1849  func (e TrackingBrokeError) ToStatus() keybase1.Status {
  1850  	return keybase1.Status{
  1851  		Code: SCTrackingBroke,
  1852  		Name: "SC_TRACKING_BROKE",
  1853  	}
  1854  }
  1855  
  1856  func (e NoPGPEncryptionKeyError) ToStatus() keybase1.Status {
  1857  	ret := keybase1.Status{
  1858  		Code: SCKeyNoPGPEncryption,
  1859  		Name: "SC_KEY_NO_PGP_ENCRYPTION",
  1860  		Desc: e.User,
  1861  	}
  1862  	if e.HasKeybaseEncryptionKey {
  1863  		ret.Fields = []keybase1.StringKVPair{
  1864  			{Key: "HasKeybaseEncryptionKey", Value: "1"},
  1865  		}
  1866  	}
  1867  	return ret
  1868  }
  1869  
  1870  func (e NoNaClEncryptionKeyError) ToStatus() keybase1.Status {
  1871  	ret := keybase1.Status{
  1872  		Code: SCKeyNoNaClEncryption,
  1873  		Name: "SC_KEY_NO_NACL_ENCRYPTION",
  1874  		Desc: e.Error(),
  1875  	}
  1876  
  1877  	ret.Fields = []keybase1.StringKVPair{{Key: "Username", Value: e.Username}}
  1878  
  1879  	if e.HasPGPKey {
  1880  		ret.Fields = append(ret.Fields, keybase1.StringKVPair{Key: "HasPGPKey", Value: "1"})
  1881  	}
  1882  	if e.HasPUK {
  1883  		ret.Fields = append(ret.Fields, keybase1.StringKVPair{Key: "HasPUK", Value: "1"})
  1884  	}
  1885  	if e.HasDeviceKey {
  1886  		ret.Fields = append(ret.Fields, keybase1.StringKVPair{Key: "HasDeviceKey", Value: "1"})
  1887  	}
  1888  	if e.HasPaperKey {
  1889  		ret.Fields = append(ret.Fields, keybase1.StringKVPair{Key: "HasPaperKey", Value: "1"})
  1890  	}
  1891  	return ret
  1892  }
  1893  
  1894  func (e WrongCryptoFormatError) ToStatus() keybase1.Status {
  1895  	ret := keybase1.Status{
  1896  		Code: SCWrongCryptoFormat,
  1897  		Name: "SC_WRONG_CRYPTO_FORMAT",
  1898  		Desc: e.Operation,
  1899  		Fields: []keybase1.StringKVPair{
  1900  			{Key: "wanted", Value: string(e.Wanted)},
  1901  			{Key: "received", Value: string(e.Received)},
  1902  		},
  1903  	}
  1904  	return ret
  1905  }
  1906  
  1907  func (e NoMatchingGPGKeysError) ToStatus() keybase1.Status {
  1908  	s := keybase1.Status{
  1909  		Code: SCKeyNoMatchingGPG,
  1910  		Name: "SC_KEY_NO_MATCHING_GPG",
  1911  		Fields: []keybase1.StringKVPair{
  1912  			{Key: "fingerprints", Value: strings.Join(e.Fingerprints, ",")},
  1913  		},
  1914  	}
  1915  	if e.HasActiveDevice {
  1916  		s.Fields = append(s.Fields, keybase1.StringKVPair{Key: "has_active_device", Value: "1"})
  1917  	}
  1918  	return s
  1919  }
  1920  
  1921  func (e DeviceAlreadyProvisionedError) ToStatus() keybase1.Status {
  1922  	return keybase1.Status{
  1923  		Code: SCDevicePrevProvisioned,
  1924  		Name: "SC_DEVICE_PREV_PROVISIONED",
  1925  		Desc: e.Error(),
  1926  	}
  1927  }
  1928  
  1929  func (e ProvisionUnavailableError) ToStatus() keybase1.Status {
  1930  	return keybase1.Status{
  1931  		Code: SCDeviceNoProvision,
  1932  		Name: "SC_DEVICE_NO_PROVISION",
  1933  		Desc: e.Error(),
  1934  	}
  1935  }
  1936  
  1937  func (e ProvisionViaDeviceRequiredError) ToStatus() keybase1.Status {
  1938  	return keybase1.Status{
  1939  		Code: SCDeviceProvisionViaDevice,
  1940  		Name: "SC_DEVICE_PROVISION_VIA_DEVICE",
  1941  		Desc: e.Error(),
  1942  	}
  1943  }
  1944  
  1945  func ExportTrackIDComponentToRevokedProof(tidc TrackIDComponent) keybase1.RevokedProof {
  1946  	key, value := tidc.ToKeyValuePair()
  1947  	ret := keybase1.RevokedProof{
  1948  		Diff: *ExportTrackDiff(TrackDiffRevoked{tidc}),
  1949  		Proof: keybase1.RemoteProof{
  1950  			Key:           key,
  1951  			Value:         value,
  1952  			DisplayMarkup: value,
  1953  			ProofType:     tidc.GetProofType(),
  1954  		},
  1955  	}
  1956  	return ret
  1957  }
  1958  
  1959  func (e GPGUnavailableError) ToStatus() keybase1.Status {
  1960  	return keybase1.Status{
  1961  		Code: SCGPGUnavailable,
  1962  		Name: "SC_GPG_UNAVAILABLE",
  1963  		Desc: e.Error(),
  1964  	}
  1965  }
  1966  
  1967  func (e NotFoundError) ToStatus() keybase1.Status {
  1968  	return keybase1.Status{
  1969  		Code: SCNotFound,
  1970  		Name: "SC_NOT_FOUND",
  1971  		Desc: e.Error(),
  1972  	}
  1973  }
  1974  
  1975  func (e UserDeletedError) ToStatus() keybase1.Status {
  1976  	return keybase1.Status{
  1977  		Code: SCDeleted,
  1978  		Name: "SC_DELETED",
  1979  		Desc: e.Error(),
  1980  	}
  1981  }
  1982  
  1983  func (e DecryptionError) ToStatus() keybase1.Status {
  1984  	cause := e.Cause.Err.Error()
  1985  	return keybase1.Status{
  1986  		Code: SCDecryptionError,
  1987  		Name: "SC_DECRYPTION_ERROR",
  1988  		Fields: []keybase1.StringKVPair{
  1989  			{Key: "Cause", Value: cause}, // raw developer-friendly string
  1990  			{Key: "Code", Value: strconv.Itoa(e.Cause.StatusCode)},
  1991  		},
  1992  	}
  1993  }
  1994  
  1995  func (e VerificationError) ToStatus() keybase1.Status {
  1996  	cause := e.Cause.Err.Error()
  1997  	return keybase1.Status{
  1998  		Code: SCSigCannotVerify,
  1999  		Name: "SC_SIG_CANNOT_VERIFY",
  2000  		Fields: []keybase1.StringKVPair{
  2001  			{Key: "Cause", Value: cause}, // raw developer-friendly string
  2002  			{Key: "Code", Value: strconv.Itoa(e.Cause.StatusCode)},
  2003  		},
  2004  	}
  2005  }
  2006  
  2007  func (e NoSigChainError) ToStatus() keybase1.Status {
  2008  	return keybase1.Status{
  2009  		Code: SCKeyNoEldest,
  2010  		Name: "SC_KEY_NO_ELDEST",
  2011  		Desc: e.Error(),
  2012  	}
  2013  }
  2014  
  2015  func (e KeyRevokedError) ToStatus() keybase1.Status {
  2016  	return keybase1.Status{
  2017  		Code: SCKeyRevoked,
  2018  		Name: "SC_KEY_REVOKED_ERROR",
  2019  		Desc: e.msg,
  2020  	}
  2021  }
  2022  
  2023  func (a *APIError) ToStatus() (s keybase1.Status) {
  2024  	s.Code = SCGenericAPIError
  2025  	s.Name = "GENERIC_API_ERROR"
  2026  	s.Desc = a.Msg
  2027  	s.Fields = []keybase1.StringKVPair{
  2028  		{Key: "code", Value: fmt.Sprintf("%d", a.Code)},
  2029  	}
  2030  	return
  2031  }
  2032  
  2033  func (e DeviceNameInUseError) ToStatus() (s keybase1.Status) {
  2034  	return keybase1.Status{
  2035  		Code: SCDeviceNameInUse,
  2036  		Name: "SC_DEVICE_NAME_IN_USE",
  2037  		Desc: e.Error(),
  2038  	}
  2039  }
  2040  
  2041  func (e ChatInternalError) ToStatus() keybase1.Status {
  2042  	return keybase1.Status{
  2043  		Code: SCChatInternal,
  2044  		Name: "SC_CHAT_INTERNAL",
  2045  		Desc: e.Error(),
  2046  	}
  2047  }
  2048  
  2049  func (e ChatStalePreviousStateError) ToStatus() keybase1.Status {
  2050  	return keybase1.Status{
  2051  		Code: SCChatStalePreviousState,
  2052  		Name: "SC_CHAT_STALE_PREVIOUS_STATE",
  2053  		Desc: e.Error(),
  2054  	}
  2055  }
  2056  
  2057  func (e ChatEphemeralRetentionPolicyViolatedError) ToStatus() keybase1.Status {
  2058  	kv := keybase1.StringKVPair{
  2059  		Key:   "MaxAge",
  2060  		Value: e.MaxAge.ToDuration().String(),
  2061  	}
  2062  	return keybase1.Status{
  2063  		Code:   SCChatEphemeralRetentionPolicyViolatedError,
  2064  		Name:   "SC_CHAT_EPHEMERAL_RETENTION_POLICY_VIOLATED",
  2065  		Desc:   e.Error(),
  2066  		Fields: []keybase1.StringKVPair{kv},
  2067  	}
  2068  }
  2069  
  2070  func (e ChatConvExistsError) ToStatus() keybase1.Status {
  2071  	kv := keybase1.StringKVPair{
  2072  		Key:   "ConvID",
  2073  		Value: e.ConvID.String(),
  2074  	}
  2075  	return keybase1.Status{
  2076  		Code:   SCChatConvExists,
  2077  		Name:   "SC_CHAT_CONVEXISTS",
  2078  		Desc:   e.Error(),
  2079  		Fields: []keybase1.StringKVPair{kv},
  2080  	}
  2081  }
  2082  
  2083  func (e ChatUnknownTLFIDError) ToStatus() keybase1.Status {
  2084  	kv := keybase1.StringKVPair{
  2085  		Key:   "TlfID",
  2086  		Value: e.TlfID.String(),
  2087  	}
  2088  	return keybase1.Status{
  2089  		Code:   SCChatUnknownTLFID,
  2090  		Name:   "SC_CHAT_UNKNOWN_TLFID",
  2091  		Desc:   e.Error(),
  2092  		Fields: []keybase1.StringKVPair{kv},
  2093  	}
  2094  }
  2095  
  2096  func (e ChatNotInConvError) ToStatus() keybase1.Status {
  2097  	kv := keybase1.StringKVPair{
  2098  		Key:   "UID",
  2099  		Value: e.UID.String(),
  2100  	}
  2101  	return keybase1.Status{
  2102  		Code:   SCChatNotInConv,
  2103  		Name:   "SC_CHAT_NOT_IN_CONV",
  2104  		Desc:   e.Error(),
  2105  		Fields: []keybase1.StringKVPair{kv},
  2106  	}
  2107  }
  2108  
  2109  func (e ChatNotInTeamError) ToStatus() keybase1.Status {
  2110  	kv := keybase1.StringKVPair{
  2111  		Key:   "UID",
  2112  		Value: e.UID.String(),
  2113  	}
  2114  	return keybase1.Status{
  2115  		Code:   SCChatNotInTeam,
  2116  		Name:   "SC_CHAT_NOT_IN_TEAM",
  2117  		Desc:   e.Error(),
  2118  		Fields: []keybase1.StringKVPair{kv},
  2119  	}
  2120  }
  2121  
  2122  func (e ChatBadMsgError) ToStatus() keybase1.Status {
  2123  	return keybase1.Status{
  2124  		Code: SCChatBadMsg,
  2125  		Name: "SC_CHAT_BADMSG",
  2126  		Desc: e.Error(),
  2127  	}
  2128  }
  2129  
  2130  func (e ChatBroadcastError) ToStatus() keybase1.Status {
  2131  	return keybase1.Status{
  2132  		Code: SCChatBroadcast,
  2133  		Name: "SC_CHAT_BROADCAST",
  2134  		Desc: e.Error(),
  2135  	}
  2136  }
  2137  
  2138  func (e ChatRateLimitError) ToStatus() keybase1.Status {
  2139  	b, _ := json.Marshal(e.RateLimit)
  2140  	kv := keybase1.StringKVPair{
  2141  		Key:   "RateLimit",
  2142  		Value: string(b),
  2143  	}
  2144  	return keybase1.Status{
  2145  		Code:   SCChatRateLimit,
  2146  		Name:   "SC_CHAT_RATELIMIT",
  2147  		Desc:   e.Error(),
  2148  		Fields: []keybase1.StringKVPair{kv},
  2149  	}
  2150  }
  2151  
  2152  func (e ChatAlreadySupersededError) ToStatus() keybase1.Status {
  2153  	return keybase1.Status{
  2154  		Code: SCChatAlreadySuperseded,
  2155  		Name: "SC_CHAT_ALREADY_SUPERSEDED",
  2156  		Desc: e.Error(),
  2157  	}
  2158  }
  2159  
  2160  func (e ChatAlreadyDeletedError) ToStatus() keybase1.Status {
  2161  	return keybase1.Status{
  2162  		Code: SCChatAlreadyDeleted,
  2163  		Name: "SC_CHAT_ALREADY_DELETED",
  2164  		Desc: e.Error(),
  2165  	}
  2166  }
  2167  
  2168  func (e ChatTLFFinalizedError) ToStatus() keybase1.Status {
  2169  	kv := keybase1.StringKVPair{
  2170  		Key:   "TlfID",
  2171  		Value: e.TlfID.String(),
  2172  	}
  2173  	return keybase1.Status{
  2174  		Code:   SCChatTLFFinalized,
  2175  		Name:   "SC_CHAT_TLF_FINALIZED",
  2176  		Desc:   e.Error(),
  2177  		Fields: []keybase1.StringKVPair{kv},
  2178  	}
  2179  }
  2180  
  2181  func (e ChatCollisionError) ToStatus() keybase1.Status {
  2182  	return keybase1.Status{
  2183  		Code: SCChatCollision,
  2184  		Name: "SC_CHAT_COLLISION",
  2185  		Desc: e.Error(),
  2186  	}
  2187  }
  2188  
  2189  func (e ChatMessageCollisionError) ToStatus() keybase1.Status {
  2190  	kv := keybase1.StringKVPair{
  2191  		Key:   "HeaderHash",
  2192  		Value: e.HeaderHash,
  2193  	}
  2194  	return keybase1.Status{
  2195  		Code:   SCChatMessageCollision,
  2196  		Name:   "SC_CHAT_MESSAGE_COLLISION",
  2197  		Desc:   e.Error(),
  2198  		Fields: []keybase1.StringKVPair{kv},
  2199  	}
  2200  }
  2201  
  2202  func (e ChatDuplicateMessageError) ToStatus() keybase1.Status {
  2203  	kv := keybase1.StringKVPair{
  2204  		Key:   "OutboxID",
  2205  		Value: e.OutboxID.String(),
  2206  	}
  2207  	return keybase1.Status{
  2208  		Code:   SCChatDuplicateMessage,
  2209  		Name:   "SC_CHAT_DUPLICATE_MESSAGE",
  2210  		Desc:   e.Error(),
  2211  		Fields: []keybase1.StringKVPair{kv},
  2212  	}
  2213  }
  2214  
  2215  func (e ChatClientError) ToStatus() keybase1.Status {
  2216  	return keybase1.Status{
  2217  		Code: SCChatClientError,
  2218  		Name: "SC_CHAT_CLIENT_ERROR",
  2219  		Desc: e.Msg,
  2220  	}
  2221  }
  2222  
  2223  func (e ChatUsersAlreadyInConversationError) ToStatus() keybase1.Status {
  2224  	fields := []keybase1.StringKVPair{}
  2225  	for _, uid := range e.Uids {
  2226  		fields = append(fields, keybase1.StringKVPair{Key: "uid", Value: uid.String()})
  2227  	}
  2228  	return keybase1.Status{
  2229  		Code:   SCChatUsersAlreadyInConversationError,
  2230  		Name:   "SC_CHAT_USERS_ALREADY_IN_CONVERSATION_ERROR",
  2231  		Fields: fields,
  2232  	}
  2233  }
  2234  
  2235  func (e ChatBadConversationError) ToStatus() keybase1.Status {
  2236  	return keybase1.Status{
  2237  		Code: SCChatBadConversationError,
  2238  		Name: "SC_CHAT_BAD_CONVERSATION_ERROR",
  2239  		Fields: []keybase1.StringKVPair{
  2240  			{
  2241  				Key:   "Msg",
  2242  				Value: e.Msg,
  2243  			},
  2244  		},
  2245  	}
  2246  }
  2247  
  2248  func (e BadEmailError) ToStatus() keybase1.Status {
  2249  	return keybase1.Status{
  2250  		Code: SCBadEmail,
  2251  		Name: "SC_BAD_EMAIL",
  2252  		Desc: e.Error(),
  2253  	}
  2254  }
  2255  
  2256  func (e ExistsError) ToStatus() keybase1.Status {
  2257  	return keybase1.Status{
  2258  		Code: SCExists,
  2259  		Name: "SC_EXISTS",
  2260  		Desc: e.Error(),
  2261  	}
  2262  }
  2263  
  2264  func (e InvalidAddressError) ToStatus() keybase1.Status {
  2265  	return keybase1.Status{
  2266  		Code: SCInvalidAddress,
  2267  		Name: "SC_INVALID_ADDRESS",
  2268  		Desc: e.Error(),
  2269  	}
  2270  }
  2271  
  2272  func (e NeedSelfRekeyError) ToStatus() keybase1.Status {
  2273  	return keybase1.Status{
  2274  		Code: SCNeedSelfRekey,
  2275  		Name: "SC_NEED_SELF_REKEY",
  2276  		Desc: e.Error(),
  2277  	}
  2278  }
  2279  
  2280  func (e NeedOtherRekeyError) ToStatus() keybase1.Status {
  2281  	return keybase1.Status{
  2282  		Code: SCNeedOtherRekey,
  2283  		Name: "SC_NEED_OTHER_REKEY",
  2284  		Desc: e.Error(),
  2285  	}
  2286  }
  2287  
  2288  func ImportDbKey(k keybase1.DbKey) DbKey {
  2289  	return DbKey{
  2290  		Typ: ObjType(k.ObjType),
  2291  		Key: k.Key,
  2292  	}
  2293  }
  2294  
  2295  func (e AccountResetError) ToStatus() keybase1.Status {
  2296  	return keybase1.Status{
  2297  		Code: SCAccountReset,
  2298  		Name: "ACCOUNT_RESET",
  2299  		Desc: e.Error(),
  2300  		Fields: []keybase1.StringKVPair{
  2301  			{Key: "e_uid", Value: string(e.expected.Uid)},
  2302  			{Key: "e_version", Value: fmt.Sprintf("%d", e.expected.EldestSeqno)},
  2303  			{Key: "r_version", Value: fmt.Sprintf("%d", e.received)},
  2304  		},
  2305  	}
  2306  }
  2307  
  2308  func (e LoginStateTimeoutError) ToStatus() keybase1.Status {
  2309  	return keybase1.Status{
  2310  		Code: SCLoginStateTimeout,
  2311  		Name: "LOGIN_STATE_TIMEOUT",
  2312  		Desc: e.Error(),
  2313  		Fields: []keybase1.StringKVPair{
  2314  			{Key: "ActiveRequest", Value: e.ActiveRequest},
  2315  			{Key: "AttemptedRequest", Value: e.AttemptedRequest},
  2316  			{Key: "Duration", Value: e.Duration.String()},
  2317  		},
  2318  	}
  2319  }
  2320  
  2321  func (e RevokeCurrentDeviceError) ToStatus() keybase1.Status {
  2322  	return keybase1.Status{
  2323  		Code: SCRevokeCurrentDevice,
  2324  		Name: "SC_DEVICE_REVOKE_CURRENT",
  2325  		Desc: e.Error(),
  2326  	}
  2327  }
  2328  
  2329  func (e RevokeLastDeviceError) ToStatus() keybase1.Status {
  2330  	x := keybase1.Status{
  2331  		Code: SCRevokeLastDevice,
  2332  		Name: "SC_DEVICE_REVOKE_LAST",
  2333  		Desc: e.Error(),
  2334  	}
  2335  
  2336  	if e.NoPassphrase {
  2337  		x.Fields = []keybase1.StringKVPair{
  2338  			{Key: "NoPassphrase", Value: "true"},
  2339  		}
  2340  	}
  2341  
  2342  	return x
  2343  }
  2344  
  2345  func (e RevokeLastDevicePGPError) ToStatus() keybase1.Status {
  2346  	return keybase1.Status{
  2347  		Code: SCRevokeLastDevicePGP,
  2348  		Name: "SC_DEVICE_REVOKE_LAST_PGP",
  2349  		Desc: e.Error(),
  2350  	}
  2351  }
  2352  
  2353  func (e KeyMaskNotFoundError) ToStatus() keybase1.Status {
  2354  	return keybase1.Status{
  2355  		Code: SCTeamKeyMaskNotFound,
  2356  		Name: "TEAM_KEY_MASK_NOT_FOUND",
  2357  		Desc: e.Error(),
  2358  		Fields: []keybase1.StringKVPair{
  2359  			{Key: "App", Value: strconv.Itoa(int(e.App))},
  2360  			{Key: "Gen", Value: strconv.Itoa(int(e.Gen))},
  2361  		},
  2362  	}
  2363  }
  2364  
  2365  func (e ProvisionFailedOfflineError) ToStatus() keybase1.Status {
  2366  	return keybase1.Status{
  2367  		Code: SCDeviceProvisionOffline,
  2368  		Name: "SC_DEVICE_PROVISION_OFFLINE",
  2369  		Desc: e.Error(),
  2370  	}
  2371  }
  2372  
  2373  func (e InvalidRepoNameError) ToStatus() (s keybase1.Status) {
  2374  	s.Code = int(keybase1.StatusCode_SCGitInvalidRepoName)
  2375  	s.Name = "GIT_INVALID_REPO_NAME"
  2376  	s.Desc = e.Error()
  2377  	s.Fields = []keybase1.StringKVPair{
  2378  		{Key: "Name", Value: e.Name},
  2379  	}
  2380  	return
  2381  }
  2382  
  2383  func (e RepoAlreadyExistsError) ToStatus() (s keybase1.Status) {
  2384  	s.Code = int(keybase1.StatusCode_SCGitRepoAlreadyExists)
  2385  	s.Name = "GIT_REPO_ALREADY_EXISTS"
  2386  	s.Desc = e.Error()
  2387  	s.Fields = []keybase1.StringKVPair{
  2388  		{Key: "DesiredName", Value: e.DesiredName},
  2389  		{Key: "ExistingName", Value: e.ExistingName},
  2390  		{Key: "ExistingID", Value: e.ExistingID},
  2391  	}
  2392  	return
  2393  }
  2394  
  2395  func (e RepoDoesntExistError) ToStatus() (s keybase1.Status) {
  2396  	s.Code = int(keybase1.StatusCode_SCGitRepoDoesntExist)
  2397  	s.Name = "GIT_REPO_DOESNT_EXIST"
  2398  	s.Desc = e.Error()
  2399  	s.Fields = []keybase1.StringKVPair{
  2400  		{Key: "Name", Value: e.Name},
  2401  	}
  2402  	return
  2403  }
  2404  
  2405  func (e NoOpError) ToStatus() (s keybase1.Status) {
  2406  	s.Code = SCNoOp
  2407  	s.Name = "SC_NO_OP"
  2408  	s.Desc = e.Desc
  2409  	return
  2410  }
  2411  
  2412  func (e NoSpaceOnDeviceError) ToStatus() (s keybase1.Status) {
  2413  	s.Code = SCNoSpaceOnDevice
  2414  	s.Name = "NO_SPACE_ON_DEVICE"
  2415  	s.Desc = e.Desc
  2416  	return
  2417  }
  2418  
  2419  func (e TeamInviteBadTokenError) ToStatus() (s keybase1.Status) {
  2420  	s.Code = SCTeamInviteBadToken
  2421  	s.Name = "TEAM_INVITE_BAD_TOKEN"
  2422  	return
  2423  }
  2424  
  2425  func (e TeamInviteTokenReusedError) ToStatus() (s keybase1.Status) {
  2426  	s.Code = SCTeamInviteTokenReused
  2427  	s.Name = "TEAM_INVITE_TOKEN_REUSED"
  2428  	return
  2429  }
  2430  
  2431  func (e TeamBadMembershipError) ToStatus() (s keybase1.Status) {
  2432  	s.Code = SCTeamBadMembership
  2433  	s.Name = "TEAM_BAD_MEMBERSHIP"
  2434  	return
  2435  }
  2436  
  2437  func (e TeamProvisionalError) ToStatus() keybase1.Status {
  2438  	var ret keybase1.Status
  2439  	if e.CanKey {
  2440  		ret.Code = SCTeamProvisionalCanKey
  2441  		ret.Name = "TEAM_PROVISIONAL_CAN_KEY"
  2442  		ret.Fields = append(ret.Fields, keybase1.StringKVPair{Key: "CanKey", Value: "1"})
  2443  	} else {
  2444  		ret.Code = SCTeamProvisionalCannotKey
  2445  		ret.Name = "TEAM_PROVISIONAL_CANNOT_KEY"
  2446  	}
  2447  	ret.Fields = append(ret.Fields, keybase1.StringKVPair{Key: "PreResolveDisplayName", Value: e.PreResolveDisplayName})
  2448  	if e.IsPublic {
  2449  		ret.Fields = append(ret.Fields, keybase1.StringKVPair{Key: "IsPublic", Value: "1"})
  2450  	}
  2451  	return ret
  2452  }
  2453  
  2454  func (e EphemeralPairwiseMACsMissingUIDsError) ToStatus() (ret keybase1.Status) {
  2455  	ret.Code = SCEphemeralPairwiseMACsMissingUIDs
  2456  	ret.Name = "EPHEMERAL_PAIRWISE_MACS_MISSING_UIDS"
  2457  	for _, uid := range e.UIDs {
  2458  		ret.Fields = append(ret.Fields, keybase1.StringKVPair{
  2459  			Key:   "uid",
  2460  			Value: uid.String(),
  2461  		})
  2462  	}
  2463  	return ret
  2464  }
  2465  
  2466  func (e MerkleClientError) ToStatus() (ret keybase1.Status) {
  2467  	ret.Code = SCMerkleClientError
  2468  	ret.Name = "MERKLE_CLIENT_ERROR"
  2469  	ret.Fields = append(ret.Fields, keybase1.StringKVPair{Key: "type", Value: fmt.Sprintf("%d", int(e.t))})
  2470  	ret.Desc = e.m
  2471  	return ret
  2472  }
  2473  
  2474  func (e FeatureFlagError) ToStatus() (ret keybase1.Status) {
  2475  	ret.Code = SCFeatureFlag
  2476  	ret.Name = "FEATURE_FLAG"
  2477  	ret.Desc = e.msg
  2478  	ret.Fields = []keybase1.StringKVPair{{Key: "feature", Value: string(e.feature)}}
  2479  	return ret
  2480  }
  2481  
  2482  func (e BadUsernameError) ToStatus() (ret keybase1.Status) {
  2483  	ret.Code = SCBadUsername
  2484  	ret.Name = "BAD_USERNAME"
  2485  	ret.Desc = e.Error()
  2486  	return ret
  2487  }
  2488  
  2489  func (e NoPaperKeysError) ToStatus() (ret keybase1.Status) {
  2490  	ret.Code = SCNoPaperKeys
  2491  	ret.Name = "NO_PAPER_KEYS"
  2492  	ret.Desc = e.Error()
  2493  	return
  2494  }
  2495  
  2496  func (e TeamContactSettingsBlockError) ToStatus() (ret keybase1.Status) {
  2497  	ret.Code = SCTeamContactSettingsBlock
  2498  	ret.Name = "TEAM_CONTACT_SETTINGS_BLOCK"
  2499  	ret.Desc = e.Error()
  2500  	ret.Fields = []keybase1.StringKVPair{
  2501  		{Key: "uids", Value: parseUIDsToString(e.blockedUIDs)},
  2502  		{Key: "usernames", Value: parseUsernamesToString(e.blockedUsernames)},
  2503  	}
  2504  	return
  2505  }
  2506  
  2507  func parseUIDsToString(input []keybase1.UID) string {
  2508  	uids := make([]string, len(input))
  2509  	for i, uid := range input {
  2510  		uids[i] = uid.String()
  2511  	}
  2512  	return strings.Join(uids, ",")
  2513  }
  2514  
  2515  func parseUsernamesToString(input []NormalizedUsername) string {
  2516  	usernames := make([]string, len(input))
  2517  	for i, username := range input {
  2518  		usernames[i] = username.String()
  2519  	}
  2520  	return strings.Join(usernames, ",")
  2521  }
  2522  
  2523  func (e AssertionParseError) ToStatus() (ret keybase1.Status) {
  2524  	ret.Code = SCAssertionParseError
  2525  	ret.Name = "ASSERTION_PARSE_ERROR"
  2526  	ret.Desc = e.Error()
  2527  	ret.Fields = append(ret.Fields, keybase1.StringKVPair{Key: "err", Value: e.err})
  2528  	ret.Fields = append(ret.Fields, keybase1.StringKVPair{Key: "reason", Value: fmt.Sprintf("%d", e.reason)})
  2529  	return
  2530  }