github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/libkbfs/interfaces.go (about)

     1  // Copyright 2016 Keybase Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD
     3  // license that can be found in the LICENSE file.
     4  
     5  package libkbfs
     6  
     7  import (
     8  	"context"
     9  	"os"
    10  	"time"
    11  
    12  	"github.com/keybase/client/go/kbfs/data"
    13  	"github.com/keybase/client/go/kbfs/favorites"
    14  	"github.com/keybase/client/go/kbfs/idutil"
    15  	"github.com/keybase/client/go/kbfs/kbfsblock"
    16  	"github.com/keybase/client/go/kbfs/kbfscodec"
    17  	"github.com/keybase/client/go/kbfs/kbfscrypto"
    18  	"github.com/keybase/client/go/kbfs/kbfsedits"
    19  	"github.com/keybase/client/go/kbfs/kbfsmd"
    20  	"github.com/keybase/client/go/kbfs/ldbutils"
    21  	"github.com/keybase/client/go/kbfs/libkey"
    22  	"github.com/keybase/client/go/kbfs/tlf"
    23  	"github.com/keybase/client/go/kbfs/tlfhandle"
    24  	"github.com/keybase/client/go/libkb"
    25  	"github.com/keybase/client/go/logger"
    26  	"github.com/keybase/client/go/protocol/chat1"
    27  	"github.com/keybase/client/go/protocol/keybase1"
    28  	"github.com/keybase/go-framed-msgpack-rpc/rpc"
    29  	metrics "github.com/rcrowley/go-metrics"
    30  	billy "gopkg.in/src-d/go-billy.v4"
    31  )
    32  
    33  type logMaker interface {
    34  	MakeLogger(module string) logger.Logger
    35  	MakeVLogger(logger.Logger) *libkb.VDebugLog
    36  	GetPerfLog() logger.Logger
    37  }
    38  
    39  type blockCacher interface {
    40  	BlockCache() data.BlockCache
    41  }
    42  
    43  type keyGetterGetter interface {
    44  	keyGetter() blockKeyGetter
    45  }
    46  
    47  type codecGetter interface {
    48  	Codec() kbfscodec.Codec
    49  }
    50  
    51  type blockOpsGetter interface {
    52  	BlockOps() BlockOps
    53  }
    54  
    55  type blockServerGetter interface {
    56  	BlockServer() BlockServer
    57  }
    58  
    59  type cryptoPureGetter interface {
    60  	cryptoPure() cryptoPure
    61  }
    62  
    63  type cryptoGetter interface {
    64  	Crypto() Crypto
    65  }
    66  
    67  type chatGetter interface {
    68  	Chat() Chat
    69  }
    70  
    71  type currentSessionGetterGetter interface {
    72  	CurrentSessionGetter() idutil.CurrentSessionGetter
    73  }
    74  
    75  type signerGetter interface {
    76  	Signer() kbfscrypto.Signer
    77  }
    78  
    79  type diskBlockCacheGetter interface {
    80  	DiskBlockCache() DiskBlockCache
    81  }
    82  
    83  type diskBlockCacheSetter interface {
    84  	MakeDiskBlockCacheIfNotExists() error
    85  }
    86  
    87  type diskBlockCacheFractionSetter interface {
    88  	SetDiskBlockCacheFraction(float64)
    89  }
    90  
    91  type syncBlockCacheFractionSetter interface {
    92  	SetSyncBlockCacheFraction(float64)
    93  }
    94  
    95  type diskMDCacheGetter interface {
    96  	DiskMDCache() DiskMDCache
    97  }
    98  
    99  type diskMDCacheSetter interface {
   100  	MakeDiskMDCacheIfNotExists() error
   101  }
   102  
   103  type diskQuotaCacheGetter interface {
   104  	DiskQuotaCache() DiskQuotaCache
   105  }
   106  
   107  type diskQuotaCacheSetter interface {
   108  	MakeDiskQuotaCacheIfNotExists() error
   109  }
   110  
   111  type blockMetadataStoreGetSeter interface {
   112  	MakeBlockMetadataStoreIfNotExists() error
   113  	XattrStore() XattrStore
   114  	// Other metadata store types goes here.
   115  }
   116  
   117  type clockGetter interface {
   118  	Clock() Clock
   119  }
   120  
   121  type reporterGetter interface {
   122  	Reporter() Reporter
   123  }
   124  
   125  type diskLimiterGetter interface {
   126  	DiskLimiter() DiskLimiter
   127  }
   128  
   129  type syncedTlfGetterSetter interface {
   130  	IsSyncedTlf(tlfID tlf.ID) bool
   131  	IsSyncedTlfPath(tlfPath string) bool
   132  	GetTlfSyncState(tlfID tlf.ID) FolderSyncConfig
   133  	SetTlfSyncState(
   134  		ctx context.Context, tlfID tlf.ID, config FolderSyncConfig) (
   135  		<-chan error, error)
   136  	GetAllSyncedTlfs() []tlf.ID
   137  
   138  	idutil.OfflineStatusGetter
   139  }
   140  
   141  type blockRetrieverGetter interface {
   142  	BlockRetriever() BlockRetriever
   143  }
   144  
   145  type settingsDBGetter interface {
   146  	GetSettingsDB() *SettingsDB
   147  }
   148  
   149  // SubscriptionManagerClientID identifies a subscriptionManager client.
   150  type SubscriptionManagerClientID string
   151  
   152  type subscriptionManagerGetter interface {
   153  	// SubscriptionManager returns a subscription manager that can be used to
   154  	// subscribe to events.
   155  	//
   156  	// clientID identifies a subscriptionManager client. Each user of the
   157  	// subscription manager should specify a unique clientID. When a
   158  	// notification happens, the client ID is provided.
   159  	//
   160  	// This is helpful for caller to filter out notifications that other clients
   161  	// subscribe.
   162  	//
   163  	// If purgeable is true, the client is marked as purgeable. We keep a
   164  	// maximum of 3 purgeable clients (FIFO). This is useful as a way to purge
   165  	// old, likely dead, clients, which happens a lot with electron refreshes.
   166  	//
   167  	// notifier specifies how a notification should be delivered when things
   168  	// change. If different notifiers are used across multiple calls to get the
   169  	// subscription manager for the same clientID, only the first one is
   170  	// effective.
   171  	SubscriptionManager(clientID SubscriptionManagerClientID, purgeable bool,
   172  		notifier SubscriptionNotifier) SubscriptionManager
   173  }
   174  
   175  type subscriptionManagerPublisherGetter interface {
   176  	SubscriptionManagerPublisher() SubscriptionManagerPublisher
   177  }
   178  
   179  // NodeID is a unique but transient ID for a Node. That is, two Node
   180  // objects in memory at the same time represent the same file or
   181  // directory if and only if their NodeIDs are equal (by pointer).
   182  type NodeID interface {
   183  	// ParentID returns the NodeID of the directory containing the
   184  	// pointed-to file or directory, or nil if none exists.
   185  	ParentID() NodeID
   186  }
   187  
   188  // NodeFSReadOnly is the subset of billy.Filesystem that is actually
   189  // used by libkbfs.  The method comments are copied from go-billy.
   190  type NodeFSReadOnly interface {
   191  	// ReadDir reads the directory named by dirname and returns a list of
   192  	// directory entries sorted by filename.
   193  	ReadDir(path string) ([]os.FileInfo, error)
   194  	// Lstat returns a FileInfo describing the named file. If the file is a
   195  	// symbolic link, the returned FileInfo describes the symbolic link. Lstat
   196  	// makes no attempt to follow the link.
   197  	Lstat(filename string) (os.FileInfo, error)
   198  	// Readlink returns the target path of link.
   199  	Readlink(link string) (string, error)
   200  	// Open opens the named file for reading. If successful, methods on the
   201  	// returned file can be used for reading; the associated file descriptor has
   202  	// mode O_RDONLY.
   203  	Open(filename string) (billy.File, error)
   204  	// OpenFile is the generalized open call; most users will use Open or Create
   205  	// instead. It opens the named file with specified flag (O_RDONLY etc.) and
   206  	// perm, (0666 etc.) if applicable. If successful, methods on the returned
   207  	// File can be used for I/O.
   208  	OpenFile(filename string, flags int, mode os.FileMode) (billy.File, error)
   209  }
   210  
   211  // Node represents a direct pointer to a file or directory in KBFS.
   212  // It is somewhat like an inode in a regular file system.  Users of
   213  // KBFS can use Node as a handle when accessing files or directories
   214  // they have previously looked up.
   215  type Node interface {
   216  	// GetID returns the ID of this Node. This should be used as a
   217  	// map key instead of the Node itself.
   218  	GetID() NodeID
   219  	// GetFolderBranch returns the folder ID and branch for this Node.
   220  	GetFolderBranch() data.FolderBranch
   221  	// GetBasename returns the current basename of the node, or ""
   222  	// if the node has been unlinked.
   223  	GetBasename() data.PathPartString
   224  	// GetPathPlaintextSansTlf returns the cleaned path of the node in
   225  	// plaintext.
   226  	GetPathPlaintextSansTlf() (string, bool)
   227  	// Readonly returns true if KBFS should outright reject any write
   228  	// attempts on data or directory structures of this node.  Though
   229  	// note that even if it returns false, KBFS can reject writes to
   230  	// the node for other reasons, such as TLF permissions.  An
   231  	// implementation that wraps another `Node` (`inner`) must return
   232  	// `inner.Readonly()` if it decides not to return `true` on its
   233  	// own.
   234  	Readonly(ctx context.Context) bool
   235  	// ShouldCreateMissedLookup is called for Nodes representing
   236  	// directories, whenever `name` is looked up but is not found in
   237  	// the directory.  If the Node decides a new entry should be
   238  	// created matching this lookup, it should return `true` as well
   239  	// as a context to use for the creation, the type of the new entry
   240  	// and the symbolic link contents if the entry is a Sym; the
   241  	// caller should then create this entry.  Otherwise it should
   242  	// return false.  It may return the types `FakeDir` or `FakeFile`
   243  	// to indicate that the caller should pretend the entry exists,
   244  	// even if it really does not.  In the case of fake files, a
   245  	// non-nil `fi` can be returned and used by the caller to
   246  	// construct the dir entry for the file.  It can also return the
   247  	// type `RealDir`, along with a non-zero `ptr`, to indicate a real
   248  	// directory corresponding to that pointer should be used.  An
   249  	// implementation that wraps another `Node` (`inner`) must return
   250  	// `inner.ShouldCreateMissedLookup()` if it decides not to return
   251  	// `true` on its own.
   252  	ShouldCreateMissedLookup(ctx context.Context, name data.PathPartString) (
   253  		shouldCreate bool, newCtx context.Context, et data.EntryType,
   254  		fi os.FileInfo, sympath data.PathPartString, ptr data.BlockPointer)
   255  	// ShouldRetryOnDirRead is called for Nodes representing
   256  	// directories, whenever a `Lookup` or `GetDirChildren` is done on
   257  	// them.  It should return true to instruct the caller that it
   258  	// should re-sync its view of the directory and retry the
   259  	// operation.
   260  	ShouldRetryOnDirRead(ctx context.Context) bool
   261  	// RemoveDir is called on a `Node` before going through the normal
   262  	// `RemoveDir` flow, to give the Node a chance to handle it in a
   263  	// custom way.  If the `Node` handles it internally, it should
   264  	// return `true`.
   265  	RemoveDir(ctx context.Context, dirName data.PathPartString) (
   266  		removeHandled bool, err error)
   267  	// WrapChild returns a wrapped version of child, if desired, to
   268  	// add custom behavior to the child node. An implementation that
   269  	// wraps another `Node` (`inner`) must first call
   270  	// `inner.WrapChild(child)` before performing its own wrapping
   271  	// operation, to ensure that all wrapping is preserved and that it
   272  	// happens in the correct order.
   273  	WrapChild(child Node) Node
   274  	// Unwrap returns the initial, unwrapped Node that was used to
   275  	// create this Node.
   276  	Unwrap() Node
   277  	// GetFS returns a file system interface that, if non-nil, should
   278  	// be used to satisfy any directory-related calls on this Node,
   279  	// instead of the standard, block-based method of acessing data.
   280  	// The provided context will be used, if possible, for any
   281  	// subsequent calls on the file system.
   282  	GetFS(ctx context.Context) NodeFSReadOnly
   283  	// GetFile returns a file interface that, if non-nil, should be
   284  	// used to satisfy any file-related calls on this Node, instead of
   285  	// the standard, block-based method of accessing data.  The
   286  	// provided context will be used, if possible, for any subsequent
   287  	// calls on the file.
   288  	GetFile(ctx context.Context) billy.File
   289  	// EntryType is the type of the entry represented by this node.
   290  	EntryType() data.EntryType
   291  	// GetBlockID returns the block ID of the node.
   292  	GetBlockID() kbfsblock.ID
   293  	// FillCacheDuration sets `d` to the suggested cache time for this
   294  	// node, if desired.
   295  	FillCacheDuration(d *time.Duration)
   296  	// Obfuscator returns something that can obfuscate the child
   297  	// entries of this Node in the case of directories; for other
   298  	// types, it returns nil.
   299  	Obfuscator() data.Obfuscator
   300  	// ChildName returns an obfuscatable version of the given name of
   301  	// a child entry of this node.
   302  	ChildName(name string) data.PathPartString
   303  }
   304  
   305  // SyncedTlfMD contains the node metadata and handle for a given synced TLF.
   306  type SyncedTlfMD struct {
   307  	MD     NodeMetadata
   308  	Handle *tlfhandle.Handle
   309  }
   310  
   311  // KBFSOps handles all file system operations.  Expands all indirect
   312  // pointers.  Operations that modify the server data change all the
   313  // block IDs along the path, and so must return a path with the new
   314  // BlockIds so the caller can update their references.
   315  //
   316  // KBFSOps implementations must guarantee goroutine-safety of calls on
   317  // a per-top-level-folder basis.
   318  //
   319  // There are two types of operations that could block:
   320  //   - remote-sync operations, that need to synchronously update the
   321  //     MD for the corresponding top-level folder.  When these
   322  //     operations return successfully, they will have guaranteed to
   323  //     have successfully written the modification to the KBFS servers.
   324  //   - remote-access operations, that don't sync any modifications to KBFS
   325  //     servers, but may block on reading data from the servers.
   326  //
   327  // KBFSOps implementations are supposed to give git-like consistency
   328  // semantics for modification operations; they will be visible to
   329  // other clients immediately after the remote-sync operations succeed,
   330  // if and only if there was no other intervening modification to the
   331  // same folder.  If not, the change will be sync'd to the server in a
   332  // special per-device "unmerged" area before the operation succeeds.
   333  // In this case, the modification will not be visible to other clients
   334  // until the KBFS code on this device performs automatic conflict
   335  // resolution in the background.
   336  //
   337  // All methods take a Context (see https://blog.golang.org/context),
   338  // and if that context is cancelled during the operation, KBFSOps will
   339  // abort any blocking calls and return ctx.Err(). Any notifications
   340  // resulting from an operation will also include this ctx (or a
   341  // Context derived from it), allowing the caller to determine whether
   342  // the notification is a result of their own action or an external
   343  // action.
   344  //
   345  // Each directory and file name is specified with a
   346  // `data.PathPartString`, to protect against accidentally logging
   347  // plaintext filenames.  These can be easily created from the parent
   348  // node's `Node` object with the `ChildName` function.
   349  type KBFSOps interface {
   350  	// GetFavorites returns the logged-in user's list of favorite
   351  	// top-level folders.  This is a remote-access operation when the cache
   352  	// is empty or expired.
   353  	GetFavorites(ctx context.Context) ([]favorites.Folder, error)
   354  	// GetFolderWithFavFlags returns a keybase1.FolderWithFavFlags for given
   355  	// handle.
   356  	GetFolderWithFavFlags(ctx context.Context,
   357  		handle *tlfhandle.Handle) (keybase1.FolderWithFavFlags, error)
   358  	// GetFavoritesAll returns the logged-in user's lists of favorite, ignored,
   359  	// and new top-level folders.  This is a remote-access operation when the
   360  	// cache is empty or expired.
   361  	GetFavoritesAll(ctx context.Context) (keybase1.FavoritesResult, error)
   362  	// GetBadge returns the overall KBFS badge state for this device.
   363  	// It's cheaper than the other favorites methods.
   364  	GetBadge(ctx context.Context) (keybase1.FilesTabBadge, error)
   365  	// RefreshCachedFavorites tells the instances to forget any cached
   366  	// favorites list and fetch a new list from the server.  The
   367  	// effects are asychronous; if there's an error refreshing the
   368  	// favorites, the cached favorites will become empty.
   369  	RefreshCachedFavorites(ctx context.Context, mode FavoritesRefreshMode)
   370  	// ClearCachedFavorites tells the instances to forget any cached
   371  	// favorites list, e.g. when a user logs out.
   372  	ClearCachedFavorites(ctx context.Context)
   373  	// AddFavorite adds the favorite to both the server and
   374  	// the local cache.
   375  	AddFavorite(ctx context.Context, fav favorites.Folder, data favorites.Data) error
   376  	// DeleteFavorite deletes the favorite from both the server and
   377  	// the local cache.  Idempotent, so it succeeds even if the folder
   378  	// isn't favorited.
   379  	DeleteFavorite(ctx context.Context, fav favorites.Folder) error
   380  	// SetFavoritesHomeTLFInfo sets the home TLF TeamIDs to initialize the
   381  	// favorites cache on login.
   382  	SetFavoritesHomeTLFInfo(ctx context.Context, info homeTLFInfo)
   383  	// RefreshEditHistory asks the FBO for the given favorite to reload its
   384  	// edit history.
   385  	RefreshEditHistory(fav favorites.Folder)
   386  
   387  	// GetTLFCryptKeys gets crypt key of all generations as well as
   388  	// TLF ID for tlfHandle. The returned keys (the keys slice) are ordered by
   389  	// generation, starting with the key for FirstValidKeyGen.
   390  	GetTLFCryptKeys(ctx context.Context, tlfHandle *tlfhandle.Handle) (
   391  		keys []kbfscrypto.TLFCryptKey, id tlf.ID, err error)
   392  
   393  	// GetTLFID gets the TLF ID for tlfHandle.
   394  	GetTLFID(ctx context.Context, tlfHandle *tlfhandle.Handle) (tlf.ID, error)
   395  
   396  	// GetTLFHandle returns the TLF handle for a given node.
   397  	GetTLFHandle(ctx context.Context, node Node) (*tlfhandle.Handle, error)
   398  
   399  	// GetOrCreateRootNode returns the root node and root entry
   400  	// info associated with the given TLF handle and branch, if
   401  	// the logged-in user has read permissions to the top-level
   402  	// folder. It creates the folder if one doesn't exist yet (and
   403  	// branch == MasterBranch), and the logged-in user has write
   404  	// permissions to the top-level folder.  This is a
   405  	// remote-access operation.
   406  	GetOrCreateRootNode(
   407  		ctx context.Context, h *tlfhandle.Handle, branch data.BranchName) (
   408  		node Node, ei data.EntryInfo, err error)
   409  	// GetRootNode is like GetOrCreateRootNode but if the root node
   410  	// does not exist it will return a nil Node and not create it.
   411  	GetRootNode(
   412  		ctx context.Context, h *tlfhandle.Handle, branch data.BranchName) (
   413  		node Node, ei data.EntryInfo, err error)
   414  	// GetDirChildren returns a map of children in the directory,
   415  	// mapped to their EntryInfo, if the logged-in user has read
   416  	// permission for the top-level folder.  This is a remote-access
   417  	// operation.
   418  	GetDirChildren(ctx context.Context, dir Node) (
   419  		map[data.PathPartString]data.EntryInfo, error)
   420  	// Lookup returns the Node and entry info associated with a
   421  	// given name in a directory, if the logged-in user has read
   422  	// permissions to the top-level folder.  The returned Node is nil
   423  	// if the name is a symlink.  This is a remote-access operation.
   424  	Lookup(ctx context.Context, dir Node, name data.PathPartString) (
   425  		Node, data.EntryInfo, error)
   426  	// Stat returns the entry info associated with a
   427  	// given Node, if the logged-in user has read permissions to the
   428  	// top-level folder.  This is a remote-access operation.
   429  	Stat(ctx context.Context, node Node) (data.EntryInfo, error)
   430  	// CreateDir creates a new subdirectory under the given node, if
   431  	// the logged-in user has write permission to the top-level
   432  	// folder.  Returns the new Node for the created subdirectory, and
   433  	// its new entry info.  This is a remote-sync operation.
   434  	CreateDir(ctx context.Context, dir Node, name data.PathPartString) (
   435  		Node, data.EntryInfo, error)
   436  	// CreateFile creates a new file under the given node, if the
   437  	// logged-in user has write permission to the top-level folder.
   438  	// Returns the new Node for the created file, and its new
   439  	// entry info. excl (when implemented) specifies whether this is an exclusive
   440  	// create.  Semantically setting excl to WithExcl is like O_CREAT|O_EXCL in a
   441  	// Unix open() call.
   442  	//
   443  	// This is a remote-sync operation.
   444  	CreateFile(
   445  		ctx context.Context, dir Node, name data.PathPartString, isExec bool,
   446  		excl Excl) (Node, data.EntryInfo, error)
   447  	// CreateLink creates a new symlink under the given node, if the
   448  	// logged-in user has write permission to the top-level folder.
   449  	// Returns the new entry info for the created symlink.  The
   450  	// symlink is represented as a single `data.PathPartString`
   451  	// (generally obfuscated by `dir`'s Obfuscator) to avoid
   452  	// accidental logging, even though it could point outside of the
   453  	// directory.  The deobfuscate command will inspect symlinks when
   454  	// deobfuscating to make this easier to debug.  This is a
   455  	// remote-sync operation.
   456  	CreateLink(
   457  		ctx context.Context, dir Node, fromName, toPath data.PathPartString) (
   458  		data.EntryInfo, error)
   459  	// RemoveDir removes the subdirectory represented by the given
   460  	// node, if the logged-in user has write permission to the
   461  	// top-level folder.  Will return an error if the subdirectory is
   462  	// not empty.  This is a remote-sync operation.
   463  	RemoveDir(ctx context.Context, dir Node, dirName data.PathPartString) error
   464  	// RemoveEntry removes the directory entry represented by the
   465  	// given node, if the logged-in user has write permission to the
   466  	// top-level folder.  This is a remote-sync operation.
   467  	RemoveEntry(ctx context.Context, dir Node, name data.PathPartString) error
   468  	// Rename performs an atomic rename operation with a given
   469  	// top-level folder if the logged-in user has write permission to
   470  	// that folder, and will return an error if nodes from different
   471  	// folders are passed in.  Also returns an error if the new name
   472  	// already has an entry corresponding to an existing directory
   473  	// (only non-dir types may be renamed over).  This is a
   474  	// remote-sync operation.
   475  	Rename(
   476  		ctx context.Context, oldParent Node, oldName data.PathPartString,
   477  		newParent Node, newName data.PathPartString) error
   478  	// Read fills in the given buffer with data from the file at the
   479  	// given node starting at the given offset, if the logged-in user
   480  	// has read permission to the top-level folder.  The read data
   481  	// reflects any outstanding writes and truncates to that file that
   482  	// have been written through this KBFSOps object, even if those
   483  	// writes have not yet been sync'd.  There is no guarantee that
   484  	// Read returns all of the requested data; it will return the
   485  	// number of bytes that it wrote to the dest buffer.  Reads on an
   486  	// unlinked file may or may not succeed, depending on whether or
   487  	// not the data has been cached locally.  If (0, nil) is returned,
   488  	// that means EOF has been reached. This is a remote-access
   489  	// operation.
   490  	Read(ctx context.Context, file Node, dest []byte, off int64) (int64, error)
   491  	// Write modifies the file at the given node, by writing the given
   492  	// buffer at the given offset within the file, if the logged-in
   493  	// user has write permission to the top-level folder.  It
   494  	// overwrites any data already there, and extends the file size as
   495  	// necessary to accomodate the new data.  It guarantees to write
   496  	// the entire buffer in one operation.  Writes on an unlinked file
   497  	// may or may not succeed as no-ops, depending on whether or not
   498  	// the necessary blocks have been locally cached.  This is a
   499  	// remote-access operation.
   500  	Write(ctx context.Context, file Node, data []byte, off int64) error
   501  	// Truncate modifies the file at the given node, by either
   502  	// shrinking or extending its size to match the given size, if the
   503  	// logged-in user has write permission to the top-level folder.
   504  	// If extending the file, it pads the new data with 0s.  Truncates
   505  	// on an unlinked file may or may not succeed as no-ops, depending
   506  	// on whether or not the necessary blocks have been locally
   507  	// cached.  This is a remote-access operation.
   508  	Truncate(ctx context.Context, file Node, size uint64) error
   509  	// SetEx turns on or off the executable bit on the file
   510  	// represented by a given node, if the logged-in user has write
   511  	// permissions to the top-level folder.  This is a remote-sync
   512  	// operation.
   513  	SetEx(ctx context.Context, file Node, ex bool) error
   514  	// SetMtime sets the modification time on the file represented by
   515  	// a given node, if the logged-in user has write permissions to
   516  	// the top-level folder.  If mtime is nil, it is a noop.  This is
   517  	// a remote-sync operation.
   518  	SetMtime(ctx context.Context, file Node, mtime *time.Time) error
   519  	// SyncAll flushes all outstanding writes and truncates for any
   520  	// dirty files to the KBFS servers within the given folder, if the
   521  	// logged-in user has write permissions to the top-level folder.
   522  	// If done through a file system interface, this may include
   523  	// modifications done via multiple file handles.  This is a
   524  	// remote-sync operation.
   525  	SyncAll(ctx context.Context, folderBranch data.FolderBranch) error
   526  	// FolderStatus returns the status of a particular folder/branch, along
   527  	// with a channel that will be closed when the status has been
   528  	// updated (to eliminate the need for polling this method).
   529  	FolderStatus(ctx context.Context, folderBranch data.FolderBranch) (
   530  		FolderBranchStatus, <-chan StatusUpdate, error)
   531  	// FolderConflictStatus is a lightweight method to return the
   532  	// conflict status of a particular folder/branch.  (The conflict
   533  	// status is also available in `FolderBranchStatus`.)
   534  	FolderConflictStatus(ctx context.Context, folderBranch data.FolderBranch) (
   535  		keybase1.FolderConflictType, error)
   536  	// Status returns the status of KBFS, along with a channel that will be
   537  	// closed when the status has been updated (to eliminate the need for
   538  	// polling this method). Note that this channel only applies to
   539  	// connection status changes.
   540  	//
   541  	// KBFSStatus can be non-empty even if there is an error.
   542  	Status(ctx context.Context) (
   543  		KBFSStatus, <-chan StatusUpdate, error)
   544  	// UnstageForTesting clears out this device's staged state, if
   545  	// any, and fast-forwards to the current head of this
   546  	// folder-branch.
   547  	UnstageForTesting(ctx context.Context, folderBranch data.FolderBranch) error
   548  	// RequestRekey requests to rekey this folder. Note that this asynchronously
   549  	// requests a rekey, so canceling ctx doesn't cancel the rekey.
   550  	RequestRekey(ctx context.Context, id tlf.ID)
   551  	// SyncFromServer blocks until the local client has contacted the
   552  	// server and guaranteed that all known updates for the given
   553  	// top-level folder have been applied locally (and notifications
   554  	// sent out to any observers).  It returns an error if this
   555  	// folder-branch is currently unmerged or dirty locally. If
   556  	// lockBeforeGet is non-nil, it blocks on idempotently taking the
   557  	// lock from server at the time it gets any metadata.
   558  	SyncFromServer(ctx context.Context,
   559  		folderBranch data.FolderBranch, lockBeforeGet *keybase1.LockID) error
   560  	// GetUpdateHistory returns a complete history of all the merged
   561  	// updates of the given folder, in a data structure that's
   562  	// suitable for encoding directly into JSON.  This is an expensive
   563  	// operation, and should only be used for ocassional debugging.
   564  	// Note that the history does not include any unmerged changes or
   565  	// outstanding writes from the local device.  To get all the
   566  	// revisions after `start`, use `kbfsmd.RevisionUninitialized` for
   567  	// the `end` parameter.
   568  	GetUpdateHistory(
   569  		ctx context.Context, folderBranch data.FolderBranch,
   570  		start, end kbfsmd.Revision) (history TLFUpdateHistory, err error)
   571  	// GetEditHistory returns the edit history of the TLF, clustered
   572  	// by writer.
   573  	GetEditHistory(ctx context.Context, folderBranch data.FolderBranch) (
   574  		tlfHistory keybase1.FSFolderEditHistory, err error)
   575  
   576  	// GetNodeMetadata gets metadata associated with a Node.
   577  	GetNodeMetadata(ctx context.Context, node Node) (NodeMetadata, error)
   578  	// GetRootNodeMetadata gets metadata associated with the root node
   579  	// of a FolderBranch, and for convenience the TLF handle as well.
   580  	GetRootNodeMetadata(ctx context.Context, folderBranch data.FolderBranch) (
   581  		NodeMetadata, *tlfhandle.Handle, error)
   582  	// Shutdown is called to clean up any resources associated with
   583  	// this KBFSOps instance.
   584  	Shutdown(ctx context.Context) error
   585  	// PushConnectionStatusChange updates the status of a service for
   586  	// human readable connection status tracking.
   587  	PushConnectionStatusChange(service string, newStatus error)
   588  	// PushStatusChange causes Status listeners to be notified via closing
   589  	// the status channel.
   590  	PushStatusChange()
   591  	// ClearPrivateFolderMD clears any cached private folder metadata,
   592  	// e.g. on a logout.
   593  	ClearPrivateFolderMD(ctx context.Context)
   594  	// ForceFastForward forwards the nodes of all folders that have
   595  	// been previously cleared with `ClearPrivateFolderMD` to their
   596  	// newest version.  It works asynchronously, so no error is
   597  	// returned.
   598  	ForceFastForward(ctx context.Context)
   599  	// InvalidateNodeAndChildren sends invalidation messages for the
   600  	// given node and all of its children that are currently in the
   601  	// NodeCache.  It's useful if the caller has outside knowledge of
   602  	// data changes to that node or its children that didn't come
   603  	// through the usual MD update channels (e.g., autogit nodes need
   604  	// invalidation when the corresponding git repo is updated).
   605  	InvalidateNodeAndChildren(ctx context.Context, node Node) error
   606  	// TeamNameChanged indicates that a team has changed its name, and
   607  	// we should clean up any outstanding handle info associated with
   608  	// the team ID.
   609  	TeamNameChanged(ctx context.Context, tid keybase1.TeamID)
   610  	// TeamAbandoned indicates that a team has been abandoned, and
   611  	// shouldn't be referred to by its previous name anymore.
   612  	TeamAbandoned(ctx context.Context, tid keybase1.TeamID)
   613  	// CheckMigrationPerms returns an error if this device cannot
   614  	// perform implicit team migration for the given TLF.
   615  	CheckMigrationPerms(ctx context.Context, id tlf.ID) (err error)
   616  	// MigrateToImplicitTeam migrates the given folder from a private-
   617  	// or public-keyed folder, to a team-keyed folder.  If it's
   618  	// already a private/public team-keyed folder, nil is returned.
   619  	MigrateToImplicitTeam(ctx context.Context, id tlf.ID) error
   620  	// KickoffAllOutstandingRekeys kicks off all outstanding rekeys. It does
   621  	// nothing to folders that have not scheduled a rekey. This should be
   622  	// called when we receive an event of "paper key cached" from service.
   623  	KickoffAllOutstandingRekeys() error
   624  	// NewNotificationChannel is called to notify any existing TLF
   625  	// matching `handle` that a new kbfs-edits channel is available.
   626  	NewNotificationChannel(
   627  		ctx context.Context, handle *tlfhandle.Handle,
   628  		convID chat1.ConversationID, channelName string)
   629  	// ClearConflictView moves the conflict view of the given TLF out of the
   630  	// way and resets the state of the TLF.
   631  	ClearConflictView(ctx context.Context, tlfID tlf.ID) error
   632  	// FinishResolvingConflict removes the local view of a
   633  	// previously-cleared conflict.
   634  	FinishResolvingConflict(ctx context.Context, fb data.FolderBranch) error
   635  	// ForceStuckConflictForTesting forces the local view of the given
   636  	// TLF into a stuck conflict view, in order to test the above
   637  	// `ClearConflictView` method and related state changes.
   638  	ForceStuckConflictForTesting(ctx context.Context, tlfID tlf.ID) error
   639  	// CancelUploads stops journal uploads for the given TLF, reverts
   640  	// the local view of the TLF to the server's view, and clears the
   641  	// journal from the disk.  Note that this could result in
   642  	// partially-uploaded changes, and may leak blocks on the bserver.
   643  	CancelUploads(ctx context.Context, fb data.FolderBranch) error
   644  	// Reset completely resets the given folder.  Should only be
   645  	// called after explicit user confirmation.  After the call,
   646  	// `handle` has the new TLF ID.  If `*newTlfID` is non-nil, that
   647  	// will be the new TLF ID of the reset TLF, if it already points
   648  	// to a MD object that matches the same handle as the original TLF
   649  	// (see HOTPOT-685 for an example of how this can happen -- it
   650  	// should be very rare).
   651  	Reset(ctx context.Context, handle *tlfhandle.Handle, newTlfID *tlf.ID) error
   652  
   653  	// GetSyncConfig returns the sync state configuration for the
   654  	// given TLF.
   655  	GetSyncConfig(ctx context.Context, tlfID tlf.ID) (
   656  		keybase1.FolderSyncConfig, error)
   657  	// SetSyncConfig sets the sync state configuration for the given
   658  	// TLF to either fully enabled, fully disabled, or partially
   659  	// syncing selected paths.  If syncing is disabled, it returns a
   660  	// channel that is closed when all of the TLF's blocks have been
   661  	// removed from the sync cache.  For a partially-synced folder,
   662  	// the config must contain no absolute paths, no duplicate paths,
   663  	// and no relative paths that go out of the TLF.
   664  	SetSyncConfig(
   665  		ctx context.Context, tlfID tlf.ID, config keybase1.FolderSyncConfig) (
   666  		<-chan error, error)
   667  	// GetAllSyncedTlfMDs returns the synced TLF metadata (and
   668  	// handle), only for those synced TLFs to which the current
   669  	// logged-in user has access.
   670  	GetAllSyncedTlfMDs(ctx context.Context) map[tlf.ID]SyncedTlfMD
   671  
   672  	// AddRootNodeWrapper adds a new root node wrapper for every
   673  	// existing TLF.  Any Nodes that have already been returned by
   674  	// `KBFSOps` won't use these wrappers.
   675  	AddRootNodeWrapper(func(Node) Node)
   676  
   677  	// StatusOfServices returns the current status of various connected
   678  	// services.
   679  	StatusOfServices() (map[string]error, chan StatusUpdate)
   680  }
   681  
   682  type gitMetadataPutter interface {
   683  	PutGitMetadata(ctx context.Context, folder keybase1.FolderHandle,
   684  		repoID keybase1.RepoID, metadata keybase1.GitLocalMetadata) error
   685  }
   686  
   687  // KeybaseService is an interface for communicating with the keybase
   688  // service.
   689  type KeybaseService interface {
   690  	idutil.KeybaseService
   691  	gitMetadataPutter
   692  	SubscriptionNotifier
   693  
   694  	// FavoriteAdd adds the given folder to the list of favorites.
   695  	FavoriteAdd(ctx context.Context, folder keybase1.FolderHandle) error
   696  
   697  	// FavoriteAdd removes the given folder from the list of
   698  	// favorites.
   699  	FavoriteDelete(ctx context.Context, folder keybase1.FolderHandle) error
   700  
   701  	// FavoriteList returns the current list of favorites.
   702  	FavoriteList(ctx context.Context, sessionID int) (keybase1.FavoritesResult,
   703  		error)
   704  
   705  	// EncryptFavorites encrypts cached favorites to store on disk.
   706  	EncryptFavorites(ctx context.Context, dataToEncrypt []byte) ([]byte, error)
   707  
   708  	// DecryptFavorites decrypts cached favorites stored on disk.
   709  	DecryptFavorites(ctx context.Context, dataToDecrypt []byte) ([]byte, error)
   710  
   711  	// NotifyOnlineStatusChanged notifies about online/offline status
   712  	// changes.
   713  	NotifyOnlineStatusChanged(ctx context.Context, online bool) error
   714  	// Notify sends a filesystem notification.
   715  	Notify(ctx context.Context, notification *keybase1.FSNotification) error
   716  
   717  	// NotifyPathUpdated sends a path updated notification.
   718  	NotifyPathUpdated(ctx context.Context, path string) error
   719  
   720  	// NotifySyncStatus sends a sync status notification.
   721  	NotifySyncStatus(ctx context.Context,
   722  		status *keybase1.FSPathSyncStatus) error
   723  
   724  	// NotifyOverallSyncStatus sends an overall sync status
   725  	// notification.
   726  	NotifyOverallSyncStatus(
   727  		ctx context.Context, status keybase1.FolderSyncStatus) error
   728  
   729  	// NotifyFavoritesChanged sends a notification that favorites have
   730  	// changed.
   731  	NotifyFavoritesChanged(ctx context.Context) error
   732  
   733  	// FlushUserFromLocalCache instructs this layer to clear any
   734  	// KBFS-side, locally-cached information about the given user.
   735  	// This does NOT involve communication with the daemon, this is
   736  	// just to force future calls loading this user to fall through to
   737  	// the daemon itself, rather than being served from the cache.
   738  	FlushUserFromLocalCache(ctx context.Context, uid keybase1.UID)
   739  
   740  	// ClearCaches flushes all user and team info from KBFS-side
   741  	// caches.
   742  	ClearCaches(ctx context.Context)
   743  
   744  	// TODO: Add CryptoClient methods, too.
   745  
   746  	// EstablishMountDir asks the service for the current mount path
   747  	// and sets it if not established.
   748  	EstablishMountDir(ctx context.Context) (string, error)
   749  
   750  	// GetKVStoreClient returns a client for accessing the KVStore service.
   751  	GetKVStoreClient() keybase1.KvstoreInterface
   752  
   753  	// GetKeybaseDaemonRawClient returns the raw RPC client that can be used to
   754  	// construct protocol clients.
   755  	GetKeybaseDaemonRawClient() rpc.GenericClient
   756  
   757  	// Shutdown frees any resources associated with this
   758  	// instance. No other methods may be called after this is
   759  	// called.
   760  	Shutdown()
   761  }
   762  
   763  // KeybaseServiceCn defines methods needed to construct KeybaseService
   764  // and Crypto implementations.
   765  type KeybaseServiceCn interface {
   766  	NewKeybaseService(
   767  		config Config, params InitParams, ctx Context, log logger.Logger) (
   768  		KeybaseService, error)
   769  	NewCrypto(
   770  		config Config, params InitParams, ctx Context, log logger.Logger) (
   771  		Crypto, error)
   772  	NewChat(
   773  		config Config, params InitParams, ctx Context, log logger.Logger) (
   774  		Chat, error)
   775  }
   776  
   777  // teamMembershipChecker is a copy of kbfsmd.TeamMembershipChecker for
   778  // embedding in KBPKI. Unfortunately, this is necessary since mockgen
   779  // can't handle embedded interfaces living in other packages.
   780  type teamMembershipChecker interface {
   781  	// IsTeamWriter is a copy of
   782  	// kbfsmd.TeamMembershipChecker.IsTeamWriter.
   783  	//
   784  	// If the caller knows that the writership needs to be checked
   785  	// while offline, they should pass in
   786  	// `keybase1.OfflineAvailability_BEST_EFFORT` as the `offline`
   787  	// parameter.  Otherwise `IsTeamWriter` might block on a network
   788  	// call.
   789  	IsTeamWriter(
   790  		ctx context.Context, tid keybase1.TeamID, uid keybase1.UID,
   791  		verifyingKey kbfscrypto.VerifyingKey,
   792  		offline keybase1.OfflineAvailability) (bool, error)
   793  	// NoLongerTeamWriter returns the global Merkle root of the
   794  	// most-recent time the given user (with the given device key,
   795  	// which implies an eldest seqno) transitioned from being a writer
   796  	// to not being a writer on the given team.  If the user was never
   797  	// a writer of the team, it returns an error.
   798  	//
   799  	// If the caller knows that the writership needs to be checked
   800  	// while offline, they should pass in
   801  	// `keybase1.OfflineAvailability_BEST_EFFORT` as the `offline`
   802  	// parameter.  Otherwise `NoLongerTeamWriter` might block on a
   803  	// network call.
   804  	NoLongerTeamWriter(
   805  		ctx context.Context, tid keybase1.TeamID, tlfType tlf.Type,
   806  		uid keybase1.UID, verifyingKey kbfscrypto.VerifyingKey,
   807  		offline keybase1.OfflineAvailability) (keybase1.MerkleRootV2, error)
   808  	// IsTeamReader is a copy of
   809  	// kbfsmd.TeamMembershipChecker.IsTeamWriter.
   810  	//
   811  	// If the caller knows that the readership needs to be checked
   812  	// while offline, they should pass in
   813  	// `keybase1.OfflineAvailability_BEST_EFFORT` as the `offline`
   814  	// parameter.  Otherwise `IsTeamReader` might block on a
   815  	// network call.
   816  	IsTeamReader(
   817  		ctx context.Context, tid keybase1.TeamID, uid keybase1.UID,
   818  		offline keybase1.OfflineAvailability) (bool, error)
   819  }
   820  
   821  type teamKeysGetter interface {
   822  	// GetTeamTLFCryptKeys gets all of a team's secret crypt keys, by
   823  	// generation, as well as the latest key generation number for the
   824  	// team.  The caller can specify `desiredKeyGen` to force a server
   825  	// check if that particular key gen isn't yet known; it may be set
   826  	// to UnspecifiedKeyGen if no server check is required.
   827  	//
   828  	// If the caller knows that the keys need to be retrieved while
   829  	// offline, they should pass in
   830  	// `keybase1.OfflineAvailability_BEST_EFFORT` as the `offline`
   831  	// parameter.  Otherwise `GetTeamTLFCryptKeys` might block on a
   832  	// network call.
   833  	GetTeamTLFCryptKeys(ctx context.Context, tid keybase1.TeamID,
   834  		desiredKeyGen kbfsmd.KeyGen, offline keybase1.OfflineAvailability) (
   835  		map[kbfsmd.KeyGen]kbfscrypto.TLFCryptKey, kbfsmd.KeyGen, error)
   836  }
   837  
   838  type teamRootIDGetter interface {
   839  	// GetTeamRootID returns the root team ID for the given (sub)team
   840  	// ID.
   841  	//
   842  	// If the caller knows that the root needs to be retrieved while
   843  	// offline, they should pass in
   844  	// `keybase1.OfflineAvailability_BEST_EFFORT` as the `offline`
   845  	// parameter.  Otherwise `GetTeamRootID` might block on a network
   846  	// call.
   847  	GetTeamRootID(
   848  		ctx context.Context, tid keybase1.TeamID,
   849  		offline keybase1.OfflineAvailability) (keybase1.TeamID, error)
   850  }
   851  
   852  // KBPKI interacts with the Keybase daemon to fetch user info.
   853  type KBPKI interface {
   854  	idutil.KBPKI
   855  	idutil.MerkleRootGetter
   856  	teamMembershipChecker
   857  	teamKeysGetter
   858  	teamRootIDGetter
   859  	gitMetadataPutter
   860  
   861  	// HasVerifyingKey returns nil if the given user has the given
   862  	// VerifyingKey, and an error otherwise.  If the revoked key was
   863  	// valid according to the untrusted server timestamps, a special
   864  	// error type `RevokedDeviceVerificationError` is returned, which
   865  	// includes information the caller can use to verify the key using
   866  	// the merkle tree.
   867  	//
   868  	// If the caller knows that the keys needs to be verified while
   869  	// offline, they should pass in
   870  	// `keybase1.OfflineAvailability_BEST_EFFORT` as the `offline`
   871  	// parameter.  Otherwise `HasVerifyingKey` might block on a
   872  	// network call.
   873  	HasVerifyingKey(ctx context.Context, uid keybase1.UID,
   874  		verifyingKey kbfscrypto.VerifyingKey,
   875  		atServerTime time.Time, offline keybase1.OfflineAvailability) error
   876  
   877  	// GetCryptPublicKeys gets all of a user's crypt public keys (including
   878  	// paper keys).
   879  	//
   880  	// If the caller knows that the keys needs to be retrieved while
   881  	// offline, they should pass in
   882  	// `keybase1.OfflineAvailability_BEST_EFFORT` as the `offline`
   883  	// parameter.  Otherwise `GetCryptPublicKeys` might block on a
   884  	// network call.
   885  	GetCryptPublicKeys(
   886  		ctx context.Context, uid keybase1.UID,
   887  		offline keybase1.OfflineAvailability) (
   888  		[]kbfscrypto.CryptPublicKey, error)
   889  
   890  	// TODO: Split the methods below off into a separate
   891  	// FavoriteOps interface.
   892  
   893  	// FavoriteAdd adds folder to the list of the logged in user's
   894  	// favorite folders.  It is idempotent.
   895  	FavoriteAdd(ctx context.Context, folder keybase1.FolderHandle) error
   896  
   897  	// FavoriteDelete deletes folder from the list of the logged in user's
   898  	// favorite folders.  It is idempotent.
   899  	FavoriteDelete(ctx context.Context, folder keybase1.FolderHandle) error
   900  
   901  	// FavoriteList returns the list of all favorite folders for
   902  	// the logged in user.
   903  	FavoriteList(ctx context.Context) (keybase1.FavoritesResult, error)
   904  
   905  	// CreateTeamTLF associates the given TLF ID with the team ID in
   906  	// the team's sigchain.  If the team already has a TLF ID
   907  	// associated with it, this overwrites it.
   908  	CreateTeamTLF(
   909  		ctx context.Context, teamID keybase1.TeamID, tlfID tlf.ID) error
   910  
   911  	// Notify sends a filesystem notification.
   912  	Notify(ctx context.Context, notification *keybase1.FSNotification) error
   913  
   914  	// NotifyPathUpdated sends a path updated notification.
   915  	NotifyPathUpdated(ctx context.Context, path string) error
   916  
   917  	// InvalidateTeamCacheForID instructs KBPKI to discard any cached
   918  	// information about the given team ID.
   919  	InvalidateTeamCacheForID(tid keybase1.TeamID)
   920  }
   921  
   922  // KeyMetadataWithRootDirEntry is like KeyMetadata, but can also
   923  // return the root dir entry for the associated MD update.
   924  type KeyMetadataWithRootDirEntry interface {
   925  	libkey.KeyMetadata
   926  
   927  	// GetRootDirEntry returns the root directory entry for the
   928  	// associated MD.
   929  	GetRootDirEntry() data.DirEntry
   930  }
   931  
   932  type encryptionKeyGetter interface {
   933  	// GetTLFCryptKeyForEncryption gets the crypt key to use for
   934  	// encryption (i.e., with the latest key generation) for the
   935  	// TLF with the given metadata.
   936  	GetTLFCryptKeyForEncryption(ctx context.Context, kmd libkey.KeyMetadata) (
   937  		kbfscrypto.TLFCryptKey, error)
   938  }
   939  
   940  type mdDecryptionKeyGetter interface {
   941  	// GetTLFCryptKeyForMDDecryption gets the crypt key to use for the
   942  	// TLF with the given metadata to decrypt the private portion of
   943  	// the metadata.  It finds the appropriate key from mdWithKeys
   944  	// (which in most cases is the same as mdToDecrypt) if it's not
   945  	// already cached.
   946  	GetTLFCryptKeyForMDDecryption(ctx context.Context,
   947  		kmdToDecrypt, kmdWithKeys libkey.KeyMetadata) (
   948  		kbfscrypto.TLFCryptKey, error)
   949  	// GetFirstTLFCryptKey gets the first valid crypt key for the
   950  	// TLF with the given metadata.
   951  	GetFirstTLFCryptKey(ctx context.Context, kmd libkey.KeyMetadata) (
   952  		kbfscrypto.TLFCryptKey, error)
   953  }
   954  
   955  type blockDecryptionKeyGetter interface {
   956  	// GetTLFCryptKeyForBlockDecryption gets the crypt key to use
   957  	// for the TLF with the given metadata to decrypt the block
   958  	// pointed to by the given pointer.
   959  	GetTLFCryptKeyForBlockDecryption(ctx context.Context, kmd libkey.KeyMetadata,
   960  		blockPtr data.BlockPointer) (kbfscrypto.TLFCryptKey, error)
   961  }
   962  
   963  type blockKeyGetter interface {
   964  	encryptionKeyGetter
   965  	blockDecryptionKeyGetter
   966  }
   967  
   968  // KeyManager fetches and constructs the keys needed for KBFS file
   969  // operations.
   970  type KeyManager interface {
   971  	blockKeyGetter
   972  	mdDecryptionKeyGetter
   973  
   974  	// GetTLFCryptKeyOfAllGenerations gets the crypt keys of all generations
   975  	// for current devices. keys contains crypt keys from all generations, in
   976  	// order, starting from FirstValidKeyGen.
   977  	GetTLFCryptKeyOfAllGenerations(ctx context.Context, kmd libkey.KeyMetadata) (
   978  		keys []kbfscrypto.TLFCryptKey, err error)
   979  
   980  	// Rekey checks the given MD object, if it is a private TLF,
   981  	// against the current set of device keys for all valid
   982  	// readers and writers.  If there are any new devices, it
   983  	// updates all existing key generations to include the new
   984  	// devices.  If there are devices that have been removed, it
   985  	// creates a new epoch of keys for the TLF.  If there was an
   986  	// error, or the RootMetadata wasn't changed, it returns false.
   987  	// Otherwise, it returns true. If a new key generation is
   988  	// added the second return value points to this new key. This
   989  	// is to allow for caching of the TLF crypt key only after a
   990  	// successful merged write of the metadata. Otherwise we could
   991  	// prematurely pollute the key cache.
   992  	//
   993  	// If the given MD object is a public TLF, it simply updates
   994  	// the TLF's handle with any newly-resolved writers.
   995  	//
   996  	// If promptPaper is set, prompts for any unlocked paper keys.
   997  	// promptPaper shouldn't be set if md is for a public TLF.
   998  	Rekey(ctx context.Context, md *RootMetadata, promptPaper bool) (
   999  		bool, *kbfscrypto.TLFCryptKey, error)
  1000  }
  1001  
  1002  // Reporter exports events (asynchronously) to any number of sinks
  1003  type Reporter interface {
  1004  	// ReportErr records that a given error happened.
  1005  	ReportErr(ctx context.Context, tlfName tlf.CanonicalName, t tlf.Type,
  1006  		mode ErrorModeType, err error)
  1007  	// AllKnownErrors returns all errors known to this Reporter.
  1008  	AllKnownErrors() []ReportedError
  1009  	// NotifyOnlineStatusChanged sends the given notification to any sink.
  1010  	OnlineStatusChanged(ctx context.Context, online bool)
  1011  	// Notify sends the given notification to any sink.
  1012  	Notify(ctx context.Context, notification *keybase1.FSNotification)
  1013  	// NotifyPathUpdated sends the given notification to any sink.
  1014  	NotifyPathUpdated(ctx context.Context, path string)
  1015  	// NotifySyncStatus sends the given path sync status to any sink.
  1016  	NotifySyncStatus(ctx context.Context, status *keybase1.FSPathSyncStatus)
  1017  	// NotifyOverallSyncStatus sends the given path overall sync
  1018  	// status to any sink.
  1019  	NotifyOverallSyncStatus(
  1020  		ctx context.Context, status keybase1.FolderSyncStatus)
  1021  	// NotifyFavoritesChanged sends the a favorites invalidation to any sink.
  1022  	NotifyFavoritesChanged(ctx context.Context)
  1023  	// Shutdown frees any resources allocated by a Reporter.
  1024  	Shutdown()
  1025  }
  1026  
  1027  // MDCache gets and puts plaintext top-level metadata into the cache.
  1028  type MDCache interface {
  1029  	// Get gets the metadata object associated with the given TLF ID,
  1030  	// revision number, and branch ID (kbfsmd.NullBranchID for merged MD).
  1031  	Get(tlf tlf.ID, rev kbfsmd.Revision, bid kbfsmd.BranchID) (ImmutableRootMetadata, error)
  1032  	// Put stores the metadata object, only if an MD matching that TLF
  1033  	// ID, revision number, and branch ID isn't already cached.  If
  1034  	// there is already a matching item in the cache, we require that
  1035  	// caller manages the cache explicitly by deleting or replacing it
  1036  	// explicitly.  This should be used when putting existing MDs
  1037  	// being fetched from the server.
  1038  	Put(md ImmutableRootMetadata) error
  1039  	// Delete removes the given metadata object from the cache if it exists.
  1040  	Delete(tlf tlf.ID, rev kbfsmd.Revision, bid kbfsmd.BranchID)
  1041  	// Replace replaces the entry matching the md under the old branch
  1042  	// ID with the new one.  If the old entry doesn't exist, this is
  1043  	// equivalent to a Put, except that it overrides anything else
  1044  	// that's already in the cache.  This should be used when putting
  1045  	// new MDs created locally.
  1046  	Replace(newRmd ImmutableRootMetadata, oldBID kbfsmd.BranchID) error
  1047  	// MarkPutToServer sets `PutToServer` to true for the specified
  1048  	// MD, if it already exists in the cache.
  1049  	MarkPutToServer(tlf tlf.ID, rev kbfsmd.Revision, bid kbfsmd.BranchID)
  1050  	// GetIDForHandle retrieves a cached, trusted TLF ID for the given
  1051  	// handle, if one exists.
  1052  	GetIDForHandle(handle *tlfhandle.Handle) (tlf.ID, error)
  1053  	// PutIDForHandle caches a trusted TLF ID for the given handle.
  1054  	PutIDForHandle(handle *tlfhandle.Handle, id tlf.ID) error
  1055  	// ChangeHandleForID moves an ID to be under a new handle, if the
  1056  	// ID is cached already.
  1057  	ChangeHandleForID(oldHandle *tlfhandle.Handle, newHandle *tlfhandle.Handle)
  1058  	// GetNextMD returns a cached view of the next MD following the
  1059  	// given global Merkle root.
  1060  	GetNextMD(tlfID tlf.ID, rootSeqno keybase1.Seqno) (
  1061  		nextKbfsRoot *kbfsmd.MerkleRoot, nextMerkleNodes [][]byte,
  1062  		nextRootSeqno keybase1.Seqno, err error)
  1063  	// PutNextMD caches a view of the next MD following the given
  1064  	// global Merkle root.
  1065  	PutNextMD(tlfID tlf.ID, rootSeqno keybase1.Seqno,
  1066  		nextKbfsRoot *kbfsmd.MerkleRoot, nextMerkleNodes [][]byte,
  1067  		nextRootSeqno keybase1.Seqno) error
  1068  }
  1069  
  1070  // KeyCache handles caching for both TLFCryptKeys and BlockCryptKeys.
  1071  type KeyCache interface {
  1072  	// GetTLFCryptKey gets the crypt key for the given TLF.
  1073  	GetTLFCryptKey(tlf.ID, kbfsmd.KeyGen) (kbfscrypto.TLFCryptKey, error)
  1074  	// PutTLFCryptKey stores the crypt key for the given TLF.
  1075  	PutTLFCryptKey(tlf.ID, kbfsmd.KeyGen, kbfscrypto.TLFCryptKey) error
  1076  }
  1077  
  1078  // DiskBlockCacheType specifies a type of an on-disk block cache.
  1079  type DiskBlockCacheType int
  1080  
  1081  const (
  1082  	// DiskBlockAnyCache indicates that any disk block cache is fine.
  1083  	DiskBlockAnyCache DiskBlockCacheType = iota
  1084  	// DiskBlockWorkingSetCache indicates that the working set cache
  1085  	// should be used.
  1086  	DiskBlockWorkingSetCache
  1087  	// DiskBlockSyncCache indicates that the sync cache should be
  1088  	// used.
  1089  	DiskBlockSyncCache
  1090  )
  1091  
  1092  func (dbct DiskBlockCacheType) String() string {
  1093  	switch dbct {
  1094  	case DiskBlockSyncCache:
  1095  		return "DiskBlockSyncCache"
  1096  	case DiskBlockWorkingSetCache:
  1097  		return "DiskBlockWorkingSetCache"
  1098  	case DiskBlockAnyCache:
  1099  		return "DiskBlockAnyCache"
  1100  	default:
  1101  		return "unknown DiskBlockCacheType"
  1102  	}
  1103  }
  1104  
  1105  // DiskBlockCache caches blocks to the disk.
  1106  type DiskBlockCache interface {
  1107  	// Get gets a block from the disk cache.  If a specific preferred
  1108  	// cache type is given, the block and its metadata are moved to
  1109  	// that cache if they're not yet in it.
  1110  	Get(ctx context.Context, tlfID tlf.ID, blockID kbfsblock.ID,
  1111  		preferredCacheType DiskBlockCacheType) (
  1112  		buf []byte, serverHalf kbfscrypto.BlockCryptKeyServerHalf,
  1113  		prefetchStatus PrefetchStatus, err error)
  1114  	// GetPrefetchStatus returns just the prefetchStatus for the
  1115  	// block. If a specific preferred cache type is given, the block
  1116  	// and its metadata are moved to that cache if they're not yet in
  1117  	// it.
  1118  	GetPrefetchStatus(
  1119  		ctx context.Context, tlfID tlf.ID, blockID kbfsblock.ID,
  1120  		cacheType DiskBlockCacheType) (PrefetchStatus, error)
  1121  	// Put puts a block to the disk cache. Returns after it has
  1122  	// updated the metadata but before it has finished writing the
  1123  	// block.  If cacheType is specified, the block is put into that
  1124  	// cache; by default, block are put into the working set cache.
  1125  	Put(ctx context.Context, tlfID tlf.ID, blockID kbfsblock.ID, buf []byte,
  1126  		serverHalf kbfscrypto.BlockCryptKeyServerHalf,
  1127  		cacheType DiskBlockCacheType) error
  1128  	// Delete deletes some blocks from the disk cache.
  1129  	Delete(
  1130  		ctx context.Context, blockIDs []kbfsblock.ID,
  1131  		cacheType DiskBlockCacheType) (
  1132  		numRemoved int, sizeRemoved int64, err error)
  1133  	// UpdateMetadata updates metadata for a given block in the disk
  1134  	// cache.  If a specific preferred cache type is given, the block
  1135  	// and its metadata are moved to that cache if they're not yet in
  1136  	// it.
  1137  	UpdateMetadata(ctx context.Context, tlfID tlf.ID, blockID kbfsblock.ID,
  1138  		prefetchStatus PrefetchStatus, cacheType DiskBlockCacheType) error
  1139  	// ClearAllTlfBlocks deletes all the synced blocks corresponding
  1140  	// to the given TLF ID from the cache.  It doesn't affect
  1141  	// transient blocks for unsynced TLFs.
  1142  	ClearAllTlfBlocks(
  1143  		ctx context.Context, tlfID tlf.ID, cacheType DiskBlockCacheType) error
  1144  	// GetLastUnrefRev returns the last revision that has been marked
  1145  	// unref'd for the given TLF.
  1146  	GetLastUnrefRev(
  1147  		ctx context.Context, tlfID tlf.ID, cacheType DiskBlockCacheType) (
  1148  		kbfsmd.Revision, error)
  1149  	// PutLastUnrefRev saves the given revision as the last unref'd
  1150  	// revision for the given TLF.
  1151  	PutLastUnrefRev(
  1152  		ctx context.Context, tlfID tlf.ID, rev kbfsmd.Revision,
  1153  		cacheType DiskBlockCacheType) error
  1154  	// Status returns the current status of the disk cache.
  1155  	Status(ctx context.Context) map[string]DiskBlockCacheStatus
  1156  	// DoesCacheHaveSpace returns whether the given cache has
  1157  	// space.
  1158  	DoesCacheHaveSpace(ctx context.Context,
  1159  		cacheType DiskBlockCacheType) (bool, int64, error)
  1160  	// Mark tags a given block in the disk cache with the given tag.
  1161  	Mark(
  1162  		ctx context.Context, blockID kbfsblock.ID, tag string,
  1163  		cacheType DiskBlockCacheType) error
  1164  	// DeleteUnmarked deletes all the given TLF's blocks in the disk
  1165  	// cache without the given tag.
  1166  	DeleteUnmarked(
  1167  		ctx context.Context, tlfID tlf.ID, tag string,
  1168  		cacheType DiskBlockCacheType) error
  1169  	// AddHomeTLF adds a TLF marked as "home" so that the blocks from it are
  1170  	// less likely to be evicted, as well as whether this is their public or
  1171  	// private TLF, where the public TLF's files are more likely to be evicted
  1172  	// than the private one's.
  1173  	AddHomeTLF(ctx context.Context, tlfID tlf.ID) error
  1174  	// ClearHomeTLFs should be called on logout so that the old user's TLFs
  1175  	// are not still marked as home.
  1176  	ClearHomeTLFs(ctx context.Context) error
  1177  	// GetTlfSize returns the number of bytes stored for the given TLF
  1178  	// in the cache of the given type.  If `DiskBlockAnyCache` is
  1179  	// specified, it returns the total sum of bytes across all caches.
  1180  	GetTlfSize(
  1181  		ctx context.Context, tlfID tlf.ID, cacheType DiskBlockCacheType) (
  1182  		uint64, error)
  1183  	// GetTlfIDs returns the TLF IDs with blocks in the cache.  If
  1184  	// `DiskBlockAnyCache` is specified, it returns the set of
  1185  	// TLF IDs across all caches.
  1186  	GetTlfIDs(
  1187  		ctx context.Context, cacheType DiskBlockCacheType) ([]tlf.ID, error)
  1188  	// WaitUntilStarted waits until the block cache of the given type
  1189  	// has finished starting. If `DiskBlockAnyCache` is specified, it
  1190  	// waits for all caches to start.
  1191  	WaitUntilStarted(cacheType DiskBlockCacheType) error
  1192  	// Shutdown cleanly shuts down the disk block cache.
  1193  	Shutdown(ctx context.Context) <-chan struct{}
  1194  }
  1195  
  1196  // DiskMDCache caches encrypted MD objects to the disk.
  1197  type DiskMDCache interface {
  1198  	// Get gets the latest cached MD for the given TLF from the disk
  1199  	// cache. `ver` is the version of the encoded MD, and `timestamp`
  1200  	// is the server timestamp for the MD.
  1201  	Get(ctx context.Context, tlfID tlf.ID) (
  1202  		buf []byte, ver kbfsmd.MetadataVer, timestamp time.Time, err error)
  1203  	// Stage asks the disk cache to store the given MD in memory, but
  1204  	// not yet write it to disk.  A later call to `Commit` or
  1205  	// `Unstage` for `rev` or higher is required to avoid memory leaks.
  1206  	Stage(ctx context.Context, tlfID tlf.ID, rev kbfsmd.Revision, buf []byte,
  1207  		ver kbfsmd.MetadataVer, timestamp time.Time) error
  1208  	// Commit writes a previously-staged MD to disk.  Trying to commit
  1209  	// a revision that hasn't been staged is a no-op, to allow callers
  1210  	// to call Commit without knowing whether Stage was called first
  1211  	// (e.g., if the revision came from the cache in the first place).
  1212  	// If older revisions (or other copies of this same revision) are
  1213  	// staged, they will become unstaged.
  1214  	Commit(ctx context.Context, tlfID tlf.ID, rev kbfsmd.Revision) error
  1215  	// Unstage unstages and forgets about a previously-staged MD.  (If
  1216  	// multiple copies of the same revision have been staged, it only
  1217  	// unstages the first of them.)
  1218  	Unstage(ctx context.Context, tlfID tlf.ID, rev kbfsmd.Revision) error
  1219  	// Status returns the current status of the disk cache.
  1220  	Status(ctx context.Context) DiskMDCacheStatus
  1221  	// Shutdown cleanly shuts down the disk MD cache.
  1222  	Shutdown(ctx context.Context)
  1223  }
  1224  
  1225  // DiskQuotaCache caches encrypts per-ID quotas to the disk.
  1226  type DiskQuotaCache interface {
  1227  	// Get gets the latest cached quota for the given ID from the disk
  1228  	// cache.
  1229  	Get(ctx context.Context, id keybase1.UserOrTeamID) (
  1230  		info kbfsblock.QuotaInfo, err error)
  1231  	// Put stores the latest cached quota for the given ID to the disk
  1232  	// cache.
  1233  	Put(ctx context.Context, id keybase1.UserOrTeamID,
  1234  		info kbfsblock.QuotaInfo) (err error)
  1235  	// Status returns the current status of the disk cache.
  1236  	Status(ctx context.Context) DiskQuotaCacheStatus
  1237  	// Shutdown cleanly shuts down the disk quota cache.
  1238  	Shutdown(ctx context.Context)
  1239  }
  1240  
  1241  // BlockMetadataStore defines a type that stores block metadata locally on
  1242  // device.
  1243  type BlockMetadataStore interface {
  1244  	// GetMetadata looks for and returns the block metadata for blockID if it's
  1245  	// found, and an error whose Cause is ldberrors.ErrNotFound if it's not
  1246  	// found.
  1247  	GetMetadata(ctx context.Context, blockID kbfsblock.ID) (BlockMetadataValue, error)
  1248  	// UpdateMetadata updates the block metadata for blockID using updater.
  1249  	// Specifically, it looks for existing block metdata for blockID. If it's
  1250  	// found, it's passed into updater. Otherwise, a zero value of
  1251  	// BlockMetadataValue is passed into the updater. After if updater returns
  1252  	// nil, the updated metadata is stored.
  1253  	UpdateMetadata(ctx context.Context, blockID kbfsblock.ID, updater BlockMetadataUpdater) error
  1254  	// Shutdown cleanly shuts down the disk block metadata cache.
  1255  	Shutdown()
  1256  }
  1257  
  1258  // XattrStore defines a type that handles locally stored xattr
  1259  // values by interacting with a BlockMetadataStore.
  1260  type XattrStore interface {
  1261  	// GetXattr looks for and returns the Xattr value of xattrType for blockID
  1262  	// if it's found, and an error whose Cause is ldberrors.ErrNotFound if it's
  1263  	// not found.
  1264  	GetXattr(ctx context.Context,
  1265  		blockID kbfsblock.ID, xattrType XattrType) ([]byte, error)
  1266  	// SetXattr sets xattrType Xattr to xattrValue for blockID.
  1267  	SetXattr(ctx context.Context,
  1268  		blockID kbfsblock.ID, xattrType XattrType, xattrValue []byte) error
  1269  }
  1270  
  1271  // cryptoPure contains all methods of Crypto that don't depend on
  1272  // implicit state, i.e. they're pure functions of the input.
  1273  type cryptoPure interface {
  1274  	// MakeRandomTlfID generates a dir ID using a CSPRNG.
  1275  	MakeRandomTlfID(t tlf.Type) (tlf.ID, error)
  1276  
  1277  	// MakeRandomBranchID generates a per-device branch ID using a
  1278  	// CSPRNG.  It will not return LocalSquashBranchID or
  1279  	// kbfsmd.NullBranchID.
  1280  	MakeRandomBranchID() (kbfsmd.BranchID, error)
  1281  
  1282  	// MakeTemporaryBlockID generates a temporary block ID using a
  1283  	// CSPRNG. This is used for indirect blocks before they're
  1284  	// committed to the server.
  1285  	MakeTemporaryBlockID() (kbfsblock.ID, error)
  1286  
  1287  	// MakeRefNonce generates a block reference nonce using a
  1288  	// CSPRNG. This is used for distinguishing different references to
  1289  	// the same BlockID.
  1290  	MakeBlockRefNonce() (kbfsblock.RefNonce, error)
  1291  
  1292  	// MakeRandomTLFEphemeralKeys generates ephemeral keys using a
  1293  	// CSPRNG for a TLF. These keys can then be used to key/rekey
  1294  	// the TLF.
  1295  	MakeRandomTLFEphemeralKeys() (kbfscrypto.TLFEphemeralPublicKey,
  1296  		kbfscrypto.TLFEphemeralPrivateKey, error)
  1297  
  1298  	// MakeRandomTLFKeys generates keys using a CSPRNG for a
  1299  	// single key generation of a TLF.
  1300  	MakeRandomTLFKeys() (kbfscrypto.TLFPublicKey,
  1301  		kbfscrypto.TLFPrivateKey, kbfscrypto.TLFCryptKey, error)
  1302  
  1303  	// MakeRandomBlockCryptKeyServerHalf generates the server-side of
  1304  	// a block crypt key.
  1305  	MakeRandomBlockCryptKeyServerHalf() (
  1306  		kbfscrypto.BlockCryptKeyServerHalf, error)
  1307  
  1308  	// EncryptPrivateMetadata encrypts a PrivateMetadata object.
  1309  	EncryptPrivateMetadata(
  1310  		pmd PrivateMetadata, key kbfscrypto.TLFCryptKey) (
  1311  		kbfscrypto.EncryptedPrivateMetadata, error)
  1312  	// DecryptPrivateMetadata decrypts a PrivateMetadata object.
  1313  	DecryptPrivateMetadata(
  1314  		encryptedPMD kbfscrypto.EncryptedPrivateMetadata,
  1315  		key kbfscrypto.TLFCryptKey) (PrivateMetadata, error)
  1316  
  1317  	// EncryptBlocks encrypts a block. plainSize is the size of the encoded
  1318  	// block; EncryptBlock() must guarantee that plainSize <=
  1319  	// len(encryptedBlock).
  1320  	EncryptBlock(
  1321  		block data.Block, tlfCryptKey kbfscrypto.TLFCryptKey,
  1322  		blockServerHalf kbfscrypto.BlockCryptKeyServerHalf) (
  1323  		plainSize int, encryptedBlock kbfscrypto.EncryptedBlock, err error)
  1324  
  1325  	// DecryptBlock decrypts a block. Similar to EncryptBlock(),
  1326  	// DecryptBlock() must guarantee that (size of the decrypted
  1327  	// block) <= len(encryptedBlock).
  1328  	DecryptBlock(
  1329  		encryptedBlock kbfscrypto.EncryptedBlock,
  1330  		tlfCryptKey kbfscrypto.TLFCryptKey,
  1331  		blockServerHalf kbfscrypto.BlockCryptKeyServerHalf, block data.Block) error
  1332  }
  1333  
  1334  // Crypto signs, verifies, encrypts, and decrypts stuff.
  1335  type Crypto interface {
  1336  	cryptoPure
  1337  
  1338  	// Duplicate kbfscrypto.Signer here to work around gomock's
  1339  	// limitations.
  1340  	Sign(context.Context, []byte) (kbfscrypto.SignatureInfo, error)
  1341  	SignForKBFS(context.Context, []byte) (kbfscrypto.SignatureInfo, error)
  1342  	SignToString(context.Context, []byte) (string, error)
  1343  
  1344  	// DecryptTLFCryptKeyClientHalf decrypts a
  1345  	// kbfscrypto.TLFCryptKeyClientHalf using the current device's
  1346  	// private key and the TLF's ephemeral public key.
  1347  	DecryptTLFCryptKeyClientHalf(ctx context.Context,
  1348  		publicKey kbfscrypto.TLFEphemeralPublicKey,
  1349  		encryptedClientHalf kbfscrypto.EncryptedTLFCryptKeyClientHalf) (
  1350  		kbfscrypto.TLFCryptKeyClientHalf, error)
  1351  
  1352  	// DecryptTLFCryptKeyClientHalfAny decrypts one of the
  1353  	// kbfscrypto.TLFCryptKeyClientHalf using the available
  1354  	// private keys and the ephemeral public key.  If promptPaper
  1355  	// is true, the service will prompt the user for any unlocked
  1356  	// paper keys.
  1357  	DecryptTLFCryptKeyClientHalfAny(ctx context.Context,
  1358  		keys []EncryptedTLFCryptKeyClientAndEphemeral,
  1359  		promptPaper bool) (
  1360  		kbfscrypto.TLFCryptKeyClientHalf, int, error)
  1361  
  1362  	// DecryptTeamMerkleLeaf decrypts a team-encrypted Merkle leaf
  1363  	// using some team key generation greater than `minKeyGen`, and
  1364  	// the provided ephemeral public key.
  1365  	DecryptTeamMerkleLeaf(ctx context.Context, teamID keybase1.TeamID,
  1366  		publicKey kbfscrypto.TLFEphemeralPublicKey,
  1367  		encryptedMerkleLeaf kbfscrypto.EncryptedMerkleLeaf,
  1368  		minKeyGen keybase1.PerTeamKeyGeneration) ([]byte, error)
  1369  
  1370  	// Shutdown frees any resources associated with this instance.
  1371  	Shutdown()
  1372  }
  1373  
  1374  // MDOps gets and puts root metadata to an MDServer.  On a get, it
  1375  // verifies the metadata is signed by the metadata's signing key.
  1376  type MDOps interface {
  1377  	tlfhandle.IDGetter
  1378  
  1379  	// GetForTLF returns the current metadata object
  1380  	// corresponding to the given top-level folder, if the logged-in
  1381  	// user has read permission on the folder.
  1382  	//
  1383  	// If lockBeforeGet is not nil, it causes mdserver to take the lock on the
  1384  	// lock ID before the get.
  1385  	GetForTLF(ctx context.Context, id tlf.ID, lockBeforeGet *keybase1.LockID) (
  1386  		ImmutableRootMetadata, error)
  1387  
  1388  	// GetForTLFByTime returns the newest merged MD update with a
  1389  	// server timestamp less than or equal to `serverTime`.
  1390  	GetForTLFByTime(ctx context.Context, id tlf.ID, serverTime time.Time) (
  1391  		ImmutableRootMetadata, error)
  1392  
  1393  	// GetUnmergedForTLF is the same as the above but for unmerged
  1394  	// metadata.
  1395  	GetUnmergedForTLF(ctx context.Context, id tlf.ID, bid kbfsmd.BranchID) (
  1396  		ImmutableRootMetadata, error)
  1397  
  1398  	// GetRange returns a range of metadata objects corresponding to
  1399  	// the passed revision numbers (inclusive).
  1400  	//
  1401  	// If lockBeforeGet is not nil, it causes mdserver to take the lock on the
  1402  	// lock ID before the get.
  1403  	GetRange(ctx context.Context, id tlf.ID, start, stop kbfsmd.Revision,
  1404  		lockID *keybase1.LockID) ([]ImmutableRootMetadata, error)
  1405  
  1406  	// GetUnmergedRange is the same as the above but for unmerged
  1407  	// metadata history (inclusive).
  1408  	GetUnmergedRange(ctx context.Context, id tlf.ID, bid kbfsmd.BranchID,
  1409  		start, stop kbfsmd.Revision) ([]ImmutableRootMetadata, error)
  1410  
  1411  	// Put stores the metadata object for the given top-level folder.
  1412  	// This also adds the resulting ImmutableRootMetadata object to
  1413  	// the mdcache, if the Put is successful.  Note that constructing
  1414  	// the ImmutableRootMetadata requires knowing the verifying key,
  1415  	// which might not be the same as the local user's verifying key
  1416  	// if the MD has been copied from a previous update.
  1417  	//
  1418  	// If lockContext is not nil, it causes the mdserver to check a lockID at
  1419  	// the time of the put, and optionally (if specified in lockContext)
  1420  	// releases the lock on the lock ID if the put is successful. Releasing the
  1421  	// lock in mdserver is idempotent. Note that journalMDOps doesn't support
  1422  	// lockContext for now. If journaling is enabled, use FinishSinbleOp to
  1423  	// require locks.
  1424  	//
  1425  	// The priority parameter specifies the priority of this particular MD put
  1426  	// operation. When conflict happens, mdserver tries to prioritize writes
  1427  	// with higher priorities. Caller should use pre-defined (or define new)
  1428  	// constants in keybase1 package, such as keybase1.MDPriorityNormal. Note
  1429  	// that journalMDOps doesn't support any priority other than
  1430  	// MDPriorityNormal for now. If journaling is enabled, use FinishSinbleOp
  1431  	// to override priority.
  1432  	Put(
  1433  		ctx context.Context, rmd *RootMetadata,
  1434  		verifyingKey kbfscrypto.VerifyingKey, lockContext *keybase1.LockContext,
  1435  		priority keybase1.MDPriority, bps data.BlockPutState) (
  1436  		ImmutableRootMetadata, error)
  1437  
  1438  	// PutUnmerged is the same as the above but for unmerged metadata
  1439  	// history.  This also adds the resulting ImmutableRootMetadata
  1440  	// object to the mdcache, if the PutUnmerged is successful.  Note
  1441  	// that constructing the ImmutableRootMetadata requires knowing
  1442  	// the verifying key, which might not be the same as the local
  1443  	// user's verifying key if the MD has been copied from a previous
  1444  	// update.
  1445  	PutUnmerged(
  1446  		ctx context.Context, rmd *RootMetadata,
  1447  		verifyingKey kbfscrypto.VerifyingKey, bps data.BlockPutState) (
  1448  		ImmutableRootMetadata, error)
  1449  
  1450  	// PruneBranch prunes all unmerged history for the given TLF
  1451  	// branch.
  1452  	PruneBranch(ctx context.Context, id tlf.ID, bid kbfsmd.BranchID) error
  1453  
  1454  	// ResolveBranch prunes all unmerged history for the given TLF
  1455  	// branch, and also deletes any blocks in `blocksToDelete` that
  1456  	// are still in the local journal.  In addition, it appends the
  1457  	// given MD to the journal.  This also adds the resulting
  1458  	// ImmutableRootMetadata object to the mdcache, if the
  1459  	// ResolveBranch is successful.  Note that constructing the
  1460  	// ImmutableRootMetadata requires knowing the verifying key, which
  1461  	// might not be the same as the local user's verifying key if the
  1462  	// MD has been copied from a previous update.
  1463  	ResolveBranch(
  1464  		ctx context.Context, id tlf.ID, bid kbfsmd.BranchID,
  1465  		blocksToDelete []kbfsblock.ID, rmd *RootMetadata,
  1466  		verifyingKey kbfscrypto.VerifyingKey, bps data.BlockPutState) (
  1467  		ImmutableRootMetadata, error)
  1468  
  1469  	// GetLatestHandleForTLF returns the server's idea of the latest
  1470  	// handle for the TLF, which may not yet be reflected in the MD if
  1471  	// the TLF hasn't been rekeyed since it entered into a conflicting
  1472  	// state.
  1473  	GetLatestHandleForTLF(ctx context.Context, id tlf.ID) (tlf.Handle, error)
  1474  }
  1475  
  1476  // Prefetcher is an interface to a block prefetcher.
  1477  type Prefetcher interface {
  1478  	// ProcessBlockForPrefetch potentially triggers and monitors a prefetch.
  1479  	ProcessBlockForPrefetch(ctx context.Context, ptr data.BlockPointer, block data.Block,
  1480  		kmd libkey.KeyMetadata, priority int, lifetime data.BlockCacheLifetime,
  1481  		prefetchStatus PrefetchStatus, action BlockRequestAction)
  1482  	// WaitChannelForBlockPrefetch returns a channel that can be used
  1483  	// to wait for a block to finish prefetching or be canceled.  If
  1484  	// the block isn't currently being prefetched, it will return an
  1485  	// already-closed channel.  When the channel is closed, the caller
  1486  	// should still verify that the prefetch status of the block is
  1487  	// what they expect it to be, in case there was an error.
  1488  	WaitChannelForBlockPrefetch(ctx context.Context, ptr data.BlockPointer) (
  1489  		<-chan struct{}, error)
  1490  	// Status returns the current status of the prefetch for the block
  1491  	// tree rooted at the given pointer.
  1492  	Status(ctx context.Context, ptr data.BlockPointer) (PrefetchProgress, error)
  1493  	// OverallSyncStatus returns the current status of all sync
  1494  	// prefetches.
  1495  	OverallSyncStatus() PrefetchProgress
  1496  	// CancelPrefetch notifies the prefetcher that a prefetch should be
  1497  	// canceled.
  1498  	CancelPrefetch(data.BlockPointer)
  1499  	// CancelTlfPrefetches notifies the prefetcher that all prefetches
  1500  	// for a given TLF should be canceled.
  1501  	CancelTlfPrefetches(context.Context, tlf.ID) error
  1502  	// Shutdown shuts down the prefetcher idempotently. Future calls to
  1503  	// the various Prefetch* methods will return io.EOF. The returned channel
  1504  	// allows upstream components to block until all pending prefetches are
  1505  	// complete. This feature is mainly used for testing, but also to toggle
  1506  	// the prefetcher on and off.
  1507  	Shutdown() <-chan struct{}
  1508  }
  1509  
  1510  // BlockOps gets and puts data blocks to a BlockServer. It performs
  1511  // the necessary crypto operations on each block.
  1512  type BlockOps interface {
  1513  	blockRetrieverGetter
  1514  	data.ReadyProvider
  1515  
  1516  	// Get gets the block associated with the given block pointer
  1517  	// (which belongs to the TLF with the given key metadata),
  1518  	// decrypts it if necessary, and fills in the provided block
  1519  	// object with its contents, if the logged-in user has read
  1520  	// permission for that block. cacheLifetime controls the behavior of the
  1521  	// write-through cache once a Get completes.
  1522  	//
  1523  	// TODO: Make a `BlockRequestParameters` object to encapsulate the
  1524  	// cache lifetime and branch name, to avoid future plumbing.  Or
  1525  	// maybe just get rid of the `Get()` method entirely and have
  1526  	// everyone use the block retrieval queue directly.
  1527  	Get(ctx context.Context, kmd libkey.KeyMetadata, blockPtr data.BlockPointer,
  1528  		block data.Block, cacheLifetime data.BlockCacheLifetime,
  1529  		branch data.BranchName) error
  1530  
  1531  	// GetEncodedSizes gets the encoded sizes and statuses of the
  1532  	// block associated with the given block pointers (which belongs
  1533  	// to the TLF with the given key metadata).  If a block is not
  1534  	// found, it gets a size of 0 and an UNKNOWN status.
  1535  	GetEncodedSizes(ctx context.Context, kmd libkey.KeyMetadata,
  1536  		blockPtrs []data.BlockPointer) ([]uint32, []keybase1.BlockStatus, error)
  1537  
  1538  	// Delete instructs the server to delete the given block references.
  1539  	// It returns the number of not-yet deleted references to
  1540  	// each block reference
  1541  	Delete(ctx context.Context, tlfID tlf.ID, ptrs []data.BlockPointer) (
  1542  		liveCounts map[kbfsblock.ID]int, err error)
  1543  
  1544  	// Archive instructs the server to mark the given block references
  1545  	// as "archived"; that is, they are not being used in the current
  1546  	// view of the folder, and shouldn't be served to anyone other
  1547  	// than folder writers.
  1548  	Archive(ctx context.Context, tlfID tlf.ID, ptrs []data.BlockPointer) error
  1549  
  1550  	// GetLiveCount returns the number of "live"
  1551  	// (non-archived, non-deleted) references for each given block.
  1552  	GetLiveCount(
  1553  		ctx context.Context, tlfID tlf.ID, ptrs []data.BlockPointer) (
  1554  		liveCounts map[kbfsblock.ID]int, err error)
  1555  
  1556  	// TogglePrefetcher activates or deactivates the prefetcher.
  1557  	TogglePrefetcher(enable bool) <-chan struct{}
  1558  
  1559  	// Prefetcher retrieves this BlockOps' Prefetcher.
  1560  	Prefetcher() Prefetcher
  1561  
  1562  	// Shutdown shuts down all the workers performing Get operations
  1563  	Shutdown(ctx context.Context) error
  1564  }
  1565  
  1566  // Duplicate kbfscrypto.AuthTokenRefreshHandler here to work around
  1567  // gomock's limitations.
  1568  type authTokenRefreshHandler interface {
  1569  	RefreshAuthToken(context.Context)
  1570  }
  1571  
  1572  // MDServer gets and puts metadata for each top-level directory.  The
  1573  // instantiation should be able to fetch session/user details via KBPKI.  On a
  1574  // put, the server is responsible for 1) ensuring the user has appropriate
  1575  // permissions for whatever modifications were made; 2) ensuring that
  1576  // LastModifyingWriter and LastModifyingUser are updated appropriately; and 3)
  1577  // detecting conflicting writes based on the previous root block ID (i.e., when
  1578  // it supports strict consistency).  On a get, it verifies the logged-in user
  1579  // has read permissions.
  1580  //
  1581  // TODO: Add interface for searching by time
  1582  type MDServer interface {
  1583  	authTokenRefreshHandler
  1584  
  1585  	// GetForHandle returns the current (signed/encrypted) metadata
  1586  	// object corresponding to the given top-level folder's handle, if
  1587  	// the logged-in user has read permission on the folder.  It
  1588  	// creates the folder if one doesn't exist yet, and the logged-in
  1589  	// user has permission to do so.
  1590  	//
  1591  	// If lockBeforeGet is not nil, it takes a lock on the lock ID before
  1592  	// trying to get anything. If taking the lock fails, an error is returned.
  1593  	// Note that taking a lock from the mdserver is idempotent.
  1594  	//
  1595  	// If there is no returned error, then the returned ID must
  1596  	// always be non-null. A nil *RootMetadataSigned may be
  1597  	// returned, but if it is non-nil, then its ID must match the
  1598  	// returned ID.
  1599  	GetForHandle(ctx context.Context, handle tlf.Handle,
  1600  		mStatus kbfsmd.MergeStatus, lockBeforeGet *keybase1.LockID) (
  1601  		tlf.ID, *RootMetadataSigned, error)
  1602  
  1603  	// GetForTLF returns the current (signed/encrypted) metadata object
  1604  	// corresponding to the given top-level folder, if the logged-in
  1605  	// user has read permission on the folder.
  1606  	//
  1607  	// If lockBeforeGet is not nil, it takes a lock on the lock ID before
  1608  	// trying to get anything. If taking the lock fails, an error is returned.
  1609  	// Note that taking a lock from the mdserver is idempotent.
  1610  	GetForTLF(ctx context.Context, id tlf.ID, bid kbfsmd.BranchID, mStatus kbfsmd.MergeStatus,
  1611  		lockBeforeGet *keybase1.LockID) (*RootMetadataSigned, error)
  1612  
  1613  	// GetForTLFByTime returns the earliest merged MD update with a
  1614  	// server timestamp equal or greater to `serverTime`.
  1615  	GetForTLFByTime(ctx context.Context, id tlf.ID, serverTime time.Time) (
  1616  		*RootMetadataSigned, error)
  1617  
  1618  	// GetRange returns a range of (signed/encrypted) metadata objects
  1619  	// corresponding to the passed revision numbers (inclusive).
  1620  	//
  1621  	// If lockBeforeGet is not nil, it takes a lock on the lock ID before
  1622  	// trying to get anything. If taking the lock fails, an error is returned.
  1623  	// Note that taking a lock from the mdserver is idempotent.
  1624  	GetRange(ctx context.Context, id tlf.ID, bid kbfsmd.BranchID, mStatus kbfsmd.MergeStatus,
  1625  		start, stop kbfsmd.Revision, lockBeforeGet *keybase1.LockID) (
  1626  		[]*RootMetadataSigned, error)
  1627  
  1628  	// Put stores the (signed/encrypted) metadata object for the given
  1629  	// top-level folder. Note: If the unmerged bit is set in the metadata
  1630  	// block's flags bitmask it will be appended to the unmerged per-device
  1631  	// history.
  1632  	//
  1633  	// If lockContext is not nil, it causes the mdserver to check a lockID at
  1634  	// the time of the put, and optionally (if specified in lockContext)
  1635  	// releases the lock on the lock ID if the put is successful. Releasing the
  1636  	// lock in mdserver is idempotent.
  1637  	Put(ctx context.Context, rmds *RootMetadataSigned, extra kbfsmd.ExtraMetadata,
  1638  		lockContext *keybase1.LockContext, priority keybase1.MDPriority) error
  1639  
  1640  	// Lock ensures lockID for tlfID is taken by this session, i.e.,
  1641  	// idempotently take the lock. If the lock is already taken by *another*
  1642  	// session, mdserver returns a throttle error, causing RPC layer at client
  1643  	// to retry. So caller of this method should observe a behavior similar to
  1644  	// blocking call, which upon successful return, makes sure the lock is
  1645  	// taken on the server. Note that the lock expires after certain time, so
  1646  	// it's important to make writes contingent to the lock by requiring the
  1647  	// lockID in Put.
  1648  	Lock(ctx context.Context, tlfID tlf.ID, lockID keybase1.LockID) error
  1649  
  1650  	// Release Lock ensures lockID for tlfID is not taken by this session, i.e.,
  1651  	// idempotently release the lock. If the lock is already released or
  1652  	// expired, this is a no-op.
  1653  	ReleaseLock(ctx context.Context, tlfID tlf.ID, lockID keybase1.LockID) error
  1654  
  1655  	// StartImplicitTeamMigration tells mdserver to put a implicit team
  1656  	// migration lock on id, which prevents any rekey MD writes from going
  1657  	// in. Normal classic MD updates can still happen after implicit team
  1658  	// migration has started, until a iTeam-style MD is written.
  1659  	StartImplicitTeamMigration(ctx context.Context, id tlf.ID) (err error)
  1660  
  1661  	// PruneBranch prunes all unmerged history for the given TLF branch.
  1662  	PruneBranch(ctx context.Context, id tlf.ID, bid kbfsmd.BranchID) error
  1663  
  1664  	// RegisterForUpdate tells the MD server to inform the caller when
  1665  	// there is a merged update with a revision number greater than
  1666  	// currHead, which did NOT originate from this same MD server
  1667  	// session.  This method returns a chan which can receive only a
  1668  	// single error before it's closed.  If the received err is nil,
  1669  	// then there is updated MD ready to fetch which didn't originate
  1670  	// locally; if it is non-nil, then the previous registration
  1671  	// cannot send the next notification (e.g., the connection to the
  1672  	// MD server may have failed). In either case, the caller must
  1673  	// re-register to get a new chan that can receive future update
  1674  	// notifications.
  1675  	RegisterForUpdate(ctx context.Context, id tlf.ID,
  1676  		currHead kbfsmd.Revision) (<-chan error, error)
  1677  
  1678  	// CancelRegistration lets the local MDServer instance know that
  1679  	// we are no longer interested in updates for the specified
  1680  	// folder.  It does not necessarily forward this cancellation to
  1681  	// remote servers.
  1682  	CancelRegistration(ctx context.Context, id tlf.ID)
  1683  
  1684  	// CheckForRekeys initiates the rekey checking process on the
  1685  	// server.  The server is allowed to delay this request, and so it
  1686  	// returns a channel for returning the error. Actual rekey
  1687  	// requests are expected to come in asynchronously.
  1688  	CheckForRekeys(ctx context.Context) <-chan error
  1689  
  1690  	// TruncateLock attempts to take the history truncation lock for
  1691  	// this folder, for a TTL defined by the server.  Returns true if
  1692  	// the lock was successfully taken.
  1693  	TruncateLock(ctx context.Context, id tlf.ID) (bool, error)
  1694  	// TruncateUnlock attempts to release the history truncation lock
  1695  	// for this folder.  Returns true if the lock was successfully
  1696  	// released.
  1697  	TruncateUnlock(ctx context.Context, id tlf.ID) (bool, error)
  1698  
  1699  	// DisableRekeyUpdatesForTesting disables processing rekey updates
  1700  	// received from the mdserver while testing.
  1701  	DisableRekeyUpdatesForTesting()
  1702  
  1703  	// Shutdown is called to shutdown an MDServer connection.
  1704  	Shutdown()
  1705  
  1706  	// IsConnected returns whether the MDServer is connected.
  1707  	IsConnected() bool
  1708  
  1709  	// GetLatestHandleForTLF returns the server's idea of the latest handle for the TLF,
  1710  	// which may not yet be reflected in the MD if the TLF hasn't been rekeyed since it
  1711  	// entered into a conflicting state.  For the highest level of confidence, the caller
  1712  	// should verify the mapping with a Merkle tree lookup.
  1713  	GetLatestHandleForTLF(ctx context.Context, id tlf.ID) (tlf.Handle, error)
  1714  
  1715  	// OffsetFromServerTime is the current estimate for how off our
  1716  	// local clock is from the mdserver clock.  Add this to any
  1717  	// mdserver-provided timestamps to get the "local" time of the
  1718  	// corresponding event.  If the returned bool is false, then we
  1719  	// don't have a current estimate for the offset.
  1720  	OffsetFromServerTime() (time.Duration, bool)
  1721  
  1722  	// GetKeyBundles looks up the key bundles for the given key
  1723  	// bundle IDs. tlfID must be non-zero but either or both wkbID
  1724  	// and rkbID can be zero, in which case nil will be returned
  1725  	// for the respective bundle. If a bundle cannot be found, an
  1726  	// error is returned and nils are returned for both bundles.
  1727  	GetKeyBundles(ctx context.Context, tlfID tlf.ID,
  1728  		wkbID kbfsmd.TLFWriterKeyBundleID, rkbID kbfsmd.TLFReaderKeyBundleID) (
  1729  		*kbfsmd.TLFWriterKeyBundleV3, *kbfsmd.TLFReaderKeyBundleV3, error)
  1730  
  1731  	// CheckReachability is called when the Keybase service sends a notification
  1732  	// that network connectivity has changed.
  1733  	CheckReachability(ctx context.Context)
  1734  
  1735  	// FastForwardBackoff fast forwards any existing backoff timer for
  1736  	// connecting to the mdserver. If mdserver is connected at the time this
  1737  	// is called, it's essentially a no-op.
  1738  	FastForwardBackoff()
  1739  
  1740  	// FindNextMD finds the serialized (and possibly encrypted) root
  1741  	// metadata object from the leaf node of the second KBFS merkle
  1742  	// tree to be produced after a given Keybase global merkle tree
  1743  	// sequence number `rootSeqno` (and all merkle nodes between it
  1744  	// and the root, and the root itself).  It also returns the global
  1745  	// merkle tree sequence number of the root that first included the
  1746  	// returned metadata object.
  1747  	FindNextMD(ctx context.Context, tlfID tlf.ID, rootSeqno keybase1.Seqno) (
  1748  		nextKbfsRoot *kbfsmd.MerkleRoot, nextMerkleNodes [][]byte,
  1749  		nextRootSeqno keybase1.Seqno, err error)
  1750  
  1751  	// GetMerkleRootLatest returns the latest KBFS merkle root for the
  1752  	// given tree ID.
  1753  	GetMerkleRootLatest(ctx context.Context, treeID keybase1.MerkleTreeID) (
  1754  		root *kbfsmd.MerkleRoot, err error)
  1755  }
  1756  
  1757  type mdServerLocal interface {
  1758  	MDServer
  1759  	addNewAssertionForTest(
  1760  		uid keybase1.UID, newAssertion keybase1.SocialAssertion) error
  1761  	getCurrentMergedHeadRevision(ctx context.Context, id tlf.ID) (
  1762  		rev kbfsmd.Revision, err error)
  1763  	isShutdown() bool
  1764  	copy(config mdServerLocalConfig) mdServerLocal
  1765  	enableImplicitTeams()
  1766  	setKbfsMerkleRoot(treeID keybase1.MerkleTreeID, root *kbfsmd.MerkleRoot)
  1767  }
  1768  
  1769  // BlockServer gets and puts opaque data blocks.  The instantiation
  1770  // should be able to fetch session/user details via KBPKI.  On a
  1771  // put/delete, the server is reponsible for: 1) checking that the ID
  1772  // matches the hash of the buffer; and 2) enforcing writer quotas.
  1773  type BlockServer interface {
  1774  	authTokenRefreshHandler
  1775  
  1776  	// FastForwardBackoff fast forwards any existing backoff timer for
  1777  	// connecting to bserver. If bserver is connected at the time this is
  1778  	// called, it's essentially a no-op.
  1779  	FastForwardBackoff()
  1780  
  1781  	// Get gets the (encrypted) block data associated with the given
  1782  	// block ID and context, uses the provided block key to decrypt
  1783  	// the block, and fills in the provided block object with its
  1784  	// contents, if the logged-in user has read permission for that
  1785  	// block.
  1786  	Get(ctx context.Context, tlfID tlf.ID, id kbfsblock.ID,
  1787  		context kbfsblock.Context, cacheType DiskBlockCacheType) (
  1788  		[]byte, kbfscrypto.BlockCryptKeyServerHalf, error)
  1789  
  1790  	// GetEncodedSizes gets the encoded sizes and statuses of the
  1791  	// blocks associated with the given block IDs (which belong to the
  1792  	// TLF with the given key metadata).  If a block is not found, it
  1793  	// gets a size of 0 and an UNKNOWN status.
  1794  	GetEncodedSizes(
  1795  		ctx context.Context, tlfID tlf.ID, ids []kbfsblock.ID,
  1796  		contexts []kbfsblock.Context) ([]uint32, []keybase1.BlockStatus, error)
  1797  
  1798  	// Put stores the (encrypted) block data under the given ID
  1799  	// and context on the server, along with the server half of
  1800  	// the block key.  context should contain a kbfsblock.RefNonce
  1801  	// of zero.  There will be an initial reference for this block
  1802  	// for the given context.
  1803  	//
  1804  	// Put should be idempotent, although it should also return an
  1805  	// error if, for a given ID, any of the other arguments differ
  1806  	// from previous Put calls with the same ID.
  1807  	//
  1808  	// If this returns a kbfsblock.ServerErrorOverQuota, with
  1809  	// Throttled=false, the caller can treat it as informational
  1810  	// and otherwise ignore the error.
  1811  	Put(ctx context.Context, tlfID tlf.ID, id kbfsblock.ID,
  1812  		context kbfsblock.Context, buf []byte,
  1813  		serverHalf kbfscrypto.BlockCryptKeyServerHalf,
  1814  		cacheType DiskBlockCacheType) error
  1815  
  1816  	// PutAgain re-stores a previously deleted block under the same ID
  1817  	// with the same data.
  1818  	PutAgain(ctx context.Context, tlfID tlf.ID, id kbfsblock.ID,
  1819  		context kbfsblock.Context, buf []byte,
  1820  		serverHalf kbfscrypto.BlockCryptKeyServerHalf,
  1821  		cacheType DiskBlockCacheType) error
  1822  
  1823  	// AddBlockReference adds a new reference to the given block,
  1824  	// defined by the given context (which should contain a
  1825  	// non-zero kbfsblock.RefNonce).  (Contexts with a
  1826  	// kbfsblock.RefNonce of zero should be used when putting the
  1827  	// block for the first time via Put().)  Returns a
  1828  	// kbfsblock.ServerErrorBlockNonExistent if id is unknown within this
  1829  	// folder.
  1830  	//
  1831  	// AddBlockReference should be idempotent, although it should
  1832  	// also return an error if, for a given ID and refnonce, any
  1833  	// of the other fields of context differ from previous
  1834  	// AddBlockReference calls with the same ID and refnonce.
  1835  	//
  1836  	// If this returns a kbfsblock.ServerErrorOverQuota, with
  1837  	// Throttled=false, the caller can treat it as informational
  1838  	// and otherwise ignore the error.
  1839  	AddBlockReference(ctx context.Context, tlfID tlf.ID, id kbfsblock.ID,
  1840  		context kbfsblock.Context) error
  1841  	// RemoveBlockReferences removes the references to the given block
  1842  	// ID defined by the given contexts.  If no references to the block
  1843  	// remain after this call, the server is allowed to delete the
  1844  	// corresponding block permanently.  If the reference defined by
  1845  	// the count has already been removed, the call is a no-op.
  1846  	// It returns the number of remaining not-yet-deleted references after this
  1847  	// reference has been removed
  1848  	RemoveBlockReferences(ctx context.Context, tlfID tlf.ID,
  1849  		contexts kbfsblock.ContextMap) (liveCounts map[kbfsblock.ID]int, err error)
  1850  
  1851  	// ArchiveBlockReferences marks the given block references as
  1852  	// "archived"; that is, they are not being used in the current
  1853  	// view of the folder, and shouldn't be served to anyone other
  1854  	// than folder writers.
  1855  	//
  1856  	// For a given ID/refnonce pair, ArchiveBlockReferences should
  1857  	// be idempotent, although it should also return an error if
  1858  	// any of the other fields of the context differ from previous
  1859  	// calls with the same ID/refnonce pair.
  1860  	ArchiveBlockReferences(ctx context.Context, tlfID tlf.ID,
  1861  		contexts kbfsblock.ContextMap) error
  1862  
  1863  	// GetLiveBlockReferences returns the number of "live"
  1864  	// (non-archived, non-deleted) references for each given block.
  1865  	GetLiveBlockReferences(ctx context.Context, tlfID tlf.ID,
  1866  		contexts kbfsblock.ContextMap) (
  1867  		liveCounts map[kbfsblock.ID]int, err error)
  1868  
  1869  	// IsUnflushed returns whether a given block is being queued
  1870  	// locally for later flushing to another block server.  If the
  1871  	// block is currently being flushed to the server, this should
  1872  	// return `true`, so that the caller will try to clean it up from
  1873  	// the server if it's no longer needed.
  1874  	IsUnflushed(ctx context.Context, tlfID tlf.ID, id kbfsblock.ID) (
  1875  		bool, error)
  1876  
  1877  	// Shutdown is called to shutdown a BlockServer connection.
  1878  	Shutdown(ctx context.Context)
  1879  
  1880  	// GetUserQuotaInfo returns the quota for the logged-in user.
  1881  	GetUserQuotaInfo(ctx context.Context) (info *kbfsblock.QuotaInfo, err error)
  1882  
  1883  	// GetTeamQuotaInfo returns the quota for a team.
  1884  	GetTeamQuotaInfo(ctx context.Context, tid keybase1.TeamID) (
  1885  		info *kbfsblock.QuotaInfo, err error)
  1886  }
  1887  
  1888  // blockServerLocal is the interface for BlockServer implementations
  1889  // that store data locally.
  1890  type blockServerLocal interface {
  1891  	BlockServer
  1892  	// getAllRefsForTest returns all the known block references
  1893  	// for the given TLF, and should only be used during testing.
  1894  	getAllRefsForTest(ctx context.Context, tlfID tlf.ID) (
  1895  		map[kbfsblock.ID]blockRefMap, error)
  1896  }
  1897  
  1898  // NodeChange represents a change made to a node as part of an atomic
  1899  // file system operation.
  1900  type NodeChange struct {
  1901  	Node Node
  1902  	// Basenames of entries added/removed.
  1903  	DirUpdated  []data.PathPartString
  1904  	FileUpdated []WriteRange
  1905  }
  1906  
  1907  // Observer can be notified that there is an available update for a
  1908  // given directory.  The notification callbacks should not block, or
  1909  // make any calls to the Notifier interface.  Nodes passed to the
  1910  // observer should not be held past the end of the notification
  1911  // callback.
  1912  type Observer interface {
  1913  	// LocalChange announces that the file at this Node has been
  1914  	// updated locally, but not yet saved at the server.
  1915  	LocalChange(ctx context.Context, node Node, write WriteRange)
  1916  	// BatchChanges announces that the nodes have all been updated
  1917  	// together atomically.  Each NodeChange in `changes` affects the
  1918  	// same top-level folder and branch. `allAffectedNodeIDs` is a
  1919  	// list of all the nodes that had their underlying data changed,
  1920  	// even if it wasn't an user-visible change (e.g., if a
  1921  	// subdirectory was updated, the directory block for the TLF root
  1922  	// is updated but that wouldn't be visible to a user).
  1923  	BatchChanges(ctx context.Context, changes []NodeChange,
  1924  		allAffectedNodeIDs []NodeID)
  1925  	// TlfHandleChange announces that the handle of the corresponding
  1926  	// folder branch has changed, likely due to previously-unresolved
  1927  	// assertions becoming resolved.  This indicates that the listener
  1928  	// should switch over any cached paths for this folder-branch to
  1929  	// the new name.  Nodes that were acquired under the old name will
  1930  	// still continue to work, but new lookups on the old name may
  1931  	// either encounter alias errors or entirely new TLFs (in the case
  1932  	// of conflicts).
  1933  	TlfHandleChange(ctx context.Context, newHandle *tlfhandle.Handle)
  1934  }
  1935  
  1936  // SyncedTlfObserver can be notified when a sync has started for a
  1937  // synced TLF, or when a TLF becomes unsynced.  The notification
  1938  // callbacks should not block, or make any calls to the Notifier
  1939  // interface.
  1940  type SyncedTlfObserver interface {
  1941  	// FullSyncStarted announces that a new full sync has begun for
  1942  	// the given tlf ID.  The provided `waitCh` will be completed (or
  1943  	// canceled) once `waitCh` is closed.
  1944  	FullSyncStarted(
  1945  		ctx context.Context, tlfID tlf.ID, rev kbfsmd.Revision,
  1946  		waitCh <-chan struct{})
  1947  	// SyncModeChanged announces that the sync mode has changed for
  1948  	// the given tlf ID.
  1949  	SyncModeChanged(
  1950  		ctx context.Context, tlfID tlf.ID, newMode keybase1.FolderSyncMode)
  1951  }
  1952  
  1953  // Notifier notifies registrants of directory changes
  1954  type Notifier interface {
  1955  	// RegisterForChanges declares that the given Observer wants to
  1956  	// subscribe to updates for the given top-level folders.
  1957  	RegisterForChanges(folderBranches []data.FolderBranch, obs Observer) error
  1958  	// UnregisterFromChanges declares that the given Observer no
  1959  	// longer wants to subscribe to updates for the given top-level
  1960  	// folders.
  1961  	UnregisterFromChanges(folderBranches []data.FolderBranch, obs Observer) error
  1962  	// RegisterForSyncedTlfs declares that the given
  1963  	// `SyncedTlfObserver` wants to subscribe to updates about synced
  1964  	// TLFs.
  1965  	RegisterForSyncedTlfs(obs SyncedTlfObserver) error
  1966  	// UnregisterFromChanges declares that the given
  1967  	// `SyncedTlfObserver` no longer wants to subscribe to updates
  1968  	// about synced TLFs.
  1969  	UnregisterFromSyncedTlfs(obs SyncedTlfObserver) error
  1970  }
  1971  
  1972  // Clock is an interface for getting the current time
  1973  type Clock interface {
  1974  	// Now returns the current time.
  1975  	Now() time.Time
  1976  }
  1977  
  1978  // ConflictRenamer deals with names for conflicting directory entries.
  1979  type ConflictRenamer interface {
  1980  	// ConflictRename returns the appropriately modified filename.
  1981  	ConflictRename(
  1982  		ctx context.Context, op op, original string) (string, error)
  1983  }
  1984  
  1985  // Tracer maybe adds traces to contexts.
  1986  type Tracer interface {
  1987  	// MaybeStartTrace, if tracing is on, returns a new context
  1988  	// based on the given one with an attached trace made with the
  1989  	// given family and title. Otherwise, it returns the given
  1990  	// context unchanged.
  1991  	MaybeStartTrace(ctx context.Context, family, title string) context.Context
  1992  	// MaybeFinishTrace, finishes the trace attached to the given
  1993  	// context, if any.
  1994  	MaybeFinishTrace(ctx context.Context, err error)
  1995  }
  1996  
  1997  // InitMode encapsulates mode differences.
  1998  type InitMode interface {
  1999  	// Type returns the InitModeType of this mode.
  2000  	Type() InitModeType
  2001  	// IsTestMode returns whether we are running a test.
  2002  	IsTestMode() bool
  2003  	// IsSingleOp returns whether this is a single-op mode (only one
  2004  	// write is expected at a time).
  2005  	IsSingleOp() bool
  2006  	// BlockWorkers returns the number of block workers to run.
  2007  	BlockWorkers() int
  2008  	// PrefetchWorkers returns the number of prefetch workers to run.
  2009  	PrefetchWorkers() int
  2010  	// ThrottledPrefetchTime returns the period for each prefetch
  2011  	// worker to start a throttled prefetch request.
  2012  	ThrottledPrefetchPeriod() time.Duration
  2013  	// DefaultBlockRequestAction returns the action to be used by
  2014  	// default whenever fetching a block.
  2015  	DefaultBlockRequestAction() BlockRequestAction
  2016  	// RekeyWorkers returns the number of rekey workers to run.
  2017  	RekeyWorkers() int
  2018  	// RekeyQueueSize returns the size of the rekey queue.
  2019  	RekeyQueueSize() int
  2020  	// DirtyBlockCacheEnabled indicates if we should run a dirty block
  2021  	// cache.
  2022  	DirtyBlockCacheEnabled() bool
  2023  	// BackgroundFlushesEnabled indicates if we should periodically be
  2024  	// flushing unsynced dirty writes to the server or journal.
  2025  	BackgroundFlushesEnabled() bool
  2026  	// MetricsEnabled indicates if we should be collecting metrics.
  2027  	MetricsEnabled() bool
  2028  	// ConflictResolutionEnabled indicated if we should be running
  2029  	// the conflict resolution background process.
  2030  	ConflictResolutionEnabled() bool
  2031  	// BlockManagementEnabled indicates whether we should be running
  2032  	// the block archive/delete background process, and whether we
  2033  	// should be re-embedding block change blocks in MDs.
  2034  	BlockManagementEnabled() bool
  2035  	// MaxBlockPtrsToManageAtOnce indicates how many block pointers
  2036  	// the block manager should try to hold in memory at once. -1
  2037  	// indicates that there is no limit.
  2038  	MaxBlockPtrsToManageAtOnce() int
  2039  	// QuotaReclamationEnabled indicates whether we should be running
  2040  	// the quota reclamation background process.
  2041  	QuotaReclamationEnabled() bool
  2042  	// QuotaReclamationPeriod indicates how often should each TLF
  2043  	// should check for quota to reclaim.  If the Duration.Seconds()
  2044  	// == 0, quota reclamation should not run automatically.
  2045  	QuotaReclamationPeriod() time.Duration
  2046  	// QuotaReclamationMinUnrefAge indicates the minimum time a block
  2047  	// must have been unreferenced before it can be reclaimed.
  2048  	QuotaReclamationMinUnrefAge() time.Duration
  2049  	// QuotaReclamationMinHeadAge indicates the minimum age of the
  2050  	// most recently merged MD update before we can run reclamation,
  2051  	// to avoid conflicting with a currently active writer.
  2052  	QuotaReclamationMinHeadAge() time.Duration
  2053  	// NodeCacheEnabled indicates whether we should be caching data nodes.
  2054  	NodeCacheEnabled() bool
  2055  	// TLFUpdatesEnabled indicates whether we should be registering
  2056  	// ourselves with the mdserver for TLF updates.
  2057  	TLFUpdatesEnabled() bool
  2058  	// KBFSServiceEnabled indicates whether we should launch a local
  2059  	// service for answering incoming KBFS-related RPCs.
  2060  	KBFSServiceEnabled() bool
  2061  	// JournalEnabled indicates whether this mode supports a journal.
  2062  	JournalEnabled() bool
  2063  	// UnmergedTLFsEnabled indicates whether it's possible for a
  2064  	// device in this mode to have unmerged TLFs.
  2065  	UnmergedTLFsEnabled() bool
  2066  	// ServiceKeepaliveEnabled indicates whether we need to send
  2067  	// keepalive probes to the Keybase service daemon.
  2068  	ServiceKeepaliveEnabled() bool
  2069  	// TLFEditHistoryEnabled indicates whether we should be running
  2070  	// the background TLF edit history process.
  2071  	TLFEditHistoryEnabled() bool
  2072  	// SendEditNotificationsEnabled indicates whether we should send
  2073  	// edit notifications on FS writes.
  2074  	SendEditNotificationsEnabled() bool
  2075  	// ClientType indicates the type we should advertise to the
  2076  	// Keybase service.
  2077  	ClientType() keybase1.ClientType
  2078  	// LocalHTTPServerEnabled represents whether we should launch an HTTP
  2079  	// server.
  2080  	LocalHTTPServerEnabled() bool
  2081  	// MaxCleanBlockCacheCapacity is the maximum number of bytes to be taken up
  2082  	// by the clean block cache.
  2083  	MaxCleanBlockCacheCapacity() uint64
  2084  	// OldStorageRootCleaningEnabled indicates whether we should clean
  2085  	// old temporary storage root directories.
  2086  	OldStorageRootCleaningEnabled() bool
  2087  	// DoRefreshFavoritesOnInit indicates whether we should refresh
  2088  	// our cached versions of the favorites immediately upon a login.
  2089  	DoRefreshFavoritesOnInit() bool
  2090  	// DoLogObfuscation indicates whether senstive data like filenames
  2091  	// should be obfuscated in log messages.
  2092  	DoLogObfuscation() bool
  2093  	// BlockTLFEditHistoryIntialization indicates where we should
  2094  	// delay initializing the edit histories of the most recent TLFs
  2095  	// until the first request that uses them is made.
  2096  	BlockTLFEditHistoryIntialization() bool
  2097  	// InitialDelayForBackgroundWork indicates how long non-critical
  2098  	// work that happens in the background on startup should wait
  2099  	// before it begins.
  2100  	InitialDelayForBackgroundWork() time.Duration
  2101  	// BackgroundWorkPeriod indicates how long to wait between
  2102  	// non-critical background work tasks.
  2103  	BackgroundWorkPeriod() time.Duration
  2104  	// IndexingEnabled indicates whether or not synced TLFs are
  2105  	// indexed and searchable.
  2106  	IndexingEnabled() bool
  2107  	// DelayInitialConnect indicates whether the initial connection to KBFS
  2108  	// servers should be delayed.
  2109  	DelayInitialConnect() bool
  2110  	// DiskCacheCompactionEnabled indicates whether the local disk
  2111  	// block cache should trigger compaction automatically.
  2112  	DiskCacheCompactionEnabled() bool
  2113  	// EditHistoryPrefetchingEnabled indicates whether we should
  2114  	// auto-prefetch the most recently-edited files.
  2115  	EditHistoryPrefetchingEnabled() bool
  2116  
  2117  	ldbutils.DbWriteBufferSizeGetter
  2118  }
  2119  
  2120  type initModeGetter interface {
  2121  	// Mode indicates how KBFS is configured to run.
  2122  	Mode() InitMode
  2123  
  2124  	// IsTestMode() inidicates whether KBFS is running in a test.
  2125  	IsTestMode() bool
  2126  }
  2127  
  2128  type blockCryptVersioner interface {
  2129  	// BlockCryptVersion returns the block encryption version to be used for
  2130  	// new blocks.
  2131  	BlockCryptVersion() kbfscrypto.EncryptionVer
  2132  }
  2133  
  2134  // SubscriptionID identifies a subscription.
  2135  type SubscriptionID string
  2136  
  2137  // SubscriptionNotifier defines a group of methods for notifying about changes
  2138  // on subscribed topics.
  2139  type SubscriptionNotifier interface {
  2140  	// OnPathChange notifies about a change that's related to a specific path.
  2141  	// Multiple subscriptionIDs may be sent because a client can subscribe on
  2142  	// the same path multiple times. In the future topics will become a single
  2143  	// topic but we don't differeciate between the two topics for now so they
  2144  	// are just sent together if both topics are subscribed.
  2145  	OnPathChange(
  2146  		clientID SubscriptionManagerClientID, subscriptionIDs []SubscriptionID,
  2147  		path string, topics []keybase1.PathSubscriptionTopic)
  2148  	// OnNonPathChange notifies about a change that's not related to a specific
  2149  	// path.
  2150  	OnNonPathChange(
  2151  		clientID SubscriptionManagerClientID, subscriptionIDs []SubscriptionID,
  2152  		topic keybase1.SubscriptionTopic)
  2153  }
  2154  
  2155  // OnlineStatusTracker tracks the online status for the GUI.
  2156  type OnlineStatusTracker interface {
  2157  	GetOnlineStatus() keybase1.KbfsOnlineStatus
  2158  	UserIn(ctx context.Context, clientKey string)
  2159  	UserOut(ctx context.Context, clientKey string)
  2160  }
  2161  
  2162  // SubscriptionManager manages subscriptions associated with one clientID.
  2163  // Multiple subscribers can be used with the same SubscriptionManager.
  2164  // If multiple subscriptions exist on the same topic (and for the same path, if
  2165  // applicable), notifications are deduplicated.
  2166  //
  2167  // The two Subscribe methods are for path and non-path subscriptions
  2168  // respectively. Notes on some common arguments:
  2169  //  1. subscriptionID needs to be unique among all subscriptions that happens
  2170  //     with this process. A UUID or even just a timestamp might work. If
  2171  //     duplicate subscriptionIDs are used, an error is returned.
  2172  //  2. Optionally a deduplicateInterval can be used. When this arg is set, we
  2173  //     debounce the events so it doesn't send more frequently than the interval.
  2174  //     If deduplicateInterval is not set, i.e. nil, no deduplication is done and
  2175  //     all events will be delivered.
  2176  type SubscriptionManager interface {
  2177  	// SubscribePath subscribes to changes about path, when topic happens.
  2178  	SubscribePath(
  2179  		ctx context.Context, subscriptionID SubscriptionID,
  2180  		path string, topic keybase1.PathSubscriptionTopic,
  2181  		deduplicateInterval *time.Duration) error
  2182  	// SubscribeNonPath subscribes to changes when topic happens.
  2183  	SubscribeNonPath(ctx context.Context, subscriptionID SubscriptionID,
  2184  		topic keybase1.SubscriptionTopic,
  2185  		deduplicateInterval *time.Duration) error
  2186  	// Unsubscribe unsubscribes a previsous subscription. The subscriptionID
  2187  	// should be the same as when caller subscribed. Otherwise, it's a no-op.
  2188  	Unsubscribe(context.Context, SubscriptionID)
  2189  	// OnlineStatusTracker returns the OnlineStatusTracker for getting the
  2190  	// current online status for GUI.
  2191  	OnlineStatusTracker() OnlineStatusTracker
  2192  	// Shutdown shuts the subscription manager down.
  2193  	Shutdown(ctx context.Context)
  2194  }
  2195  
  2196  // SubscriptionManagerPublisher associates with one SubscriptionManager, and is
  2197  // used to publish changes to subscribers mangaged by it.
  2198  type SubscriptionManagerPublisher interface {
  2199  	PublishChange(topic keybase1.SubscriptionTopic)
  2200  }
  2201  
  2202  type kbContextGetter interface {
  2203  	// KbContext returns the Keybase Context.
  2204  	KbContext() Context
  2205  }
  2206  
  2207  // ResetForLoginer defines ResetForLogin.
  2208  type ResetForLoginer interface {
  2209  	ResetForLogin(ctx context.Context, username libkb.NormalizedUsername) (err error)
  2210  }
  2211  
  2212  // Config collects all the singleton instance instantiations needed to
  2213  // run KBFS in one place.  The methods below are self-explanatory and
  2214  // do not require comments.
  2215  type Config interface {
  2216  	data.Versioner
  2217  	blockCryptVersioner
  2218  	logMaker
  2219  	blockCacher
  2220  	blockServerGetter
  2221  	blockOpsGetter
  2222  	codecGetter
  2223  	cryptoPureGetter
  2224  	keyGetterGetter
  2225  	cryptoGetter
  2226  	chatGetter
  2227  	signerGetter
  2228  	currentSessionGetterGetter
  2229  	diskBlockCacheGetter
  2230  	diskBlockCacheSetter
  2231  	diskBlockCacheFractionSetter
  2232  	syncBlockCacheFractionSetter
  2233  	diskMDCacheGetter
  2234  	diskMDCacheSetter
  2235  	diskQuotaCacheGetter
  2236  	diskQuotaCacheSetter
  2237  	blockMetadataStoreGetSeter
  2238  	clockGetter
  2239  	diskLimiterGetter
  2240  	syncedTlfGetterSetter
  2241  	initModeGetter
  2242  	settingsDBGetter
  2243  	SetMode(mode InitMode)
  2244  	Tracer
  2245  	KBFSOps() KBFSOps
  2246  	SetKBFSOps(KBFSOps)
  2247  	KBPKI() KBPKI
  2248  	SetKBPKI(KBPKI)
  2249  	KeyManager() KeyManager
  2250  	SetKeyManager(KeyManager)
  2251  	SetReporter(Reporter)
  2252  	reporterGetter
  2253  	MDCache() MDCache
  2254  	SetMDCache(MDCache)
  2255  	KeyCache() KeyCache
  2256  	SetKeyBundleCache(kbfsmd.KeyBundleCache)
  2257  	KeyBundleCache() kbfsmd.KeyBundleCache
  2258  	SetKeyCache(KeyCache)
  2259  	SetBlockCache(data.BlockCache)
  2260  	DirtyBlockCache() data.DirtyBlockCache
  2261  	SetDirtyBlockCache(data.DirtyBlockCache)
  2262  	SetCrypto(Crypto)
  2263  	SetChat(Chat)
  2264  	SetCodec(kbfscodec.Codec)
  2265  	MDOps() MDOps
  2266  	SetMDOps(MDOps)
  2267  	KeyOps() libkey.KeyOps
  2268  	SetKeyOps(libkey.KeyOps)
  2269  	SetBlockOps(BlockOps)
  2270  	MDServer() MDServer
  2271  	SetMDServer(MDServer)
  2272  	SetBlockServer(BlockServer)
  2273  	KeyServer() libkey.KeyServer
  2274  	SetKeyServer(libkey.KeyServer)
  2275  	KeybaseService() KeybaseService
  2276  	SetKeybaseService(KeybaseService)
  2277  	BlockSplitter() data.BlockSplitter
  2278  	SetBlockSplitter(data.BlockSplitter)
  2279  	Notifier() Notifier
  2280  	SetNotifier(Notifier)
  2281  	SetClock(Clock)
  2282  	ConflictRenamer() ConflictRenamer
  2283  	SetConflictRenamer(ConflictRenamer)
  2284  	UserHistory() *kbfsedits.UserHistory
  2285  	SetUserHistory(*kbfsedits.UserHistory)
  2286  	MetadataVersion() kbfsmd.MetadataVer
  2287  	SetMetadataVersion(kbfsmd.MetadataVer)
  2288  	SetBlockCryptVersion(kbfscrypto.EncryptionVer)
  2289  	DefaultBlockType() keybase1.BlockType
  2290  	SetDefaultBlockType(blockType keybase1.BlockType)
  2291  	// GetConflictResolutionDB gets the levelDB in which conflict resolution
  2292  	// status is stored.
  2293  	GetConflictResolutionDB() (db *ldbutils.LevelDb)
  2294  	RekeyQueue() RekeyQueue
  2295  	SetRekeyQueue(RekeyQueue)
  2296  	// ReqsBufSize indicates the number of read or write operations
  2297  	// that can be buffered per folder
  2298  	ReqsBufSize() int
  2299  	// MaxNameBytes indicates the maximum supported size of a
  2300  	// directory entry name in bytes.
  2301  	MaxNameBytes() uint32
  2302  	// DoBackgroundFlushes says whether we should periodically try to
  2303  	// flush dirty files, even without a sync from the user.  Should
  2304  	// be true except for during some testing.
  2305  	DoBackgroundFlushes() bool
  2306  	SetDoBackgroundFlushes(bool)
  2307  	// RekeyWithPromptWaitTime indicates how long to wait, after
  2308  	// setting the rekey bit, before prompting for a paper key.
  2309  	RekeyWithPromptWaitTime() time.Duration
  2310  	SetRekeyWithPromptWaitTime(time.Duration)
  2311  	// PrefetchStatus returns the prefetch status of a block.
  2312  	PrefetchStatus(context.Context, tlf.ID, data.BlockPointer) PrefetchStatus
  2313  	GetQuotaUsage(keybase1.UserOrTeamID) *EventuallyConsistentQuotaUsage
  2314  
  2315  	// GracePeriod specifies a grace period for which a delayed cancellation
  2316  	// waits before actual cancels the context. This is useful for giving
  2317  	// critical portion of a slow remote operation some extra time to finish as
  2318  	// an effort to avoid conflicting. Example include an O_EXCL Create call
  2319  	// interrupted by ALRM signal actually makes it to the server, while
  2320  	// application assumes not since EINTR is returned. A delayed cancellation
  2321  	// allows us to distinguish between successful cancel (where remote operation
  2322  	// didn't make to server) or failed cancel (where remote operation made to
  2323  	// the server). However, the optimal value of this depends on the network
  2324  	// conditions. A long grace period for really good network condition would
  2325  	// just unnecessarily slow down Ctrl-C.
  2326  	//
  2327  	// TODO: make this adaptive and self-change over time based on network
  2328  	// conditions.
  2329  	DelayedCancellationGracePeriod() time.Duration
  2330  	SetDelayedCancellationGracePeriod(time.Duration)
  2331  
  2332  	// ResetCaches clears and re-initializes all data and key caches.
  2333  	ResetCaches()
  2334  
  2335  	// StorageRoot returns the path to the storage root for this config.
  2336  	StorageRoot() string
  2337  
  2338  	// MetricsRegistry may be nil, which should be interpreted as
  2339  	// not using metrics at all. (i.e., as if UseNilMetrics were
  2340  	// set). This differs from how go-metrics treats nil Registry
  2341  	// objects, which is to use the default registry.
  2342  	MetricsRegistry() metrics.Registry
  2343  	SetMetricsRegistry(metrics.Registry)
  2344  
  2345  	// SetTraceOptions set the options for tracing (via x/net/trace).
  2346  	SetTraceOptions(enabled bool)
  2347  
  2348  	// TLFValidDuration is the time TLFs are valid before identification needs to be redone.
  2349  	TLFValidDuration() time.Duration
  2350  	// SetTLFValidDuration sets TLFValidDuration.
  2351  	SetTLFValidDuration(time.Duration)
  2352  
  2353  	// BGFlushDirOpBatchSize returns the directory op batch size for
  2354  	// background flushes.
  2355  	BGFlushDirOpBatchSize() int
  2356  	// SetBGFlushDirOpBatchSize sets the directory op batch size for
  2357  	// background flushes.
  2358  	SetBGFlushDirOpBatchSize(s int)
  2359  
  2360  	// BGFlushPeriod returns how long to wait for a batch to fill up
  2361  	// before syncing a set of changes to the servers.
  2362  	BGFlushPeriod() time.Duration
  2363  	// SetBGFlushPeriod sets how long to wait for a batch to fill up
  2364  	// before syncing a set of changes to the servers.
  2365  	SetBGFlushPeriod(p time.Duration)
  2366  
  2367  	// Shutdown is called to free config resources.
  2368  	Shutdown(context.Context) error
  2369  	// CheckStateOnShutdown tells the caller whether or not it is safe
  2370  	// to check the state of the system on shutdown.
  2371  	CheckStateOnShutdown() bool
  2372  
  2373  	// GetRekeyFSMLimiter returns the global rekey FSM limiter.
  2374  	GetRekeyFSMLimiter() *OngoingWorkLimiter
  2375  
  2376  	// RootNodeWrappers returns the set of root node wrapper functions
  2377  	// that will be applied to each newly-created root node.
  2378  	RootNodeWrappers() []func(Node) Node
  2379  	// AddRootNodeWrapper adds a new wrapper function that will be
  2380  	// applied whenever a root Node is created.  This will only apply
  2381  	// to TLFs that are first accessed after `AddRootNodeWrapper` is
  2382  	// called.
  2383  	AddRootNodeWrapper(func(Node) Node)
  2384  
  2385  	// SetVLogLevel sets the vdebug level for all logs.  The possible
  2386  	// strings are hard-coded in go/libkb/vdebug.go, but include
  2387  	// "mobile", "vlog1", "vlog2", etc.
  2388  	SetVLogLevel(levelString string)
  2389  
  2390  	// VLogLevel gets the vdebug level for this config.  The possible
  2391  	// strings are hard-coded in go/libkb/vdebug.go, but include
  2392  	// "mobile", "vlog1", "vlog2", etc.
  2393  	VLogLevel() string
  2394  
  2395  	subscriptionManagerGetter
  2396  
  2397  	// SubscriptionManagerPublisher retursn a publisher that can be used to
  2398  	// publish events to the subscription manager.
  2399  	SubscriptionManagerPublisher() SubscriptionManagerPublisher
  2400  	// KbEnv returns the *libkb.Env.
  2401  	KbEnv() *libkb.Env
  2402  
  2403  	kbContextGetter
  2404  
  2405  	// AddResetForLoginTarget adds t as a target when config.ResetForLogin is called.
  2406  	AddResetForLoginTarget(t ResetForLoginer)
  2407  
  2408  	// ResetForLogin calls ResetForLogin on additional protocols.
  2409  	ResetForLogin(context.Context, libkb.NormalizedUsername)
  2410  }
  2411  
  2412  // NodeCache holds Nodes, and allows libkbfs to update them when
  2413  // things change about the underlying KBFS blocks.  It is probably
  2414  // most useful to instantiate this on a per-folder-branch basis, so
  2415  // that it can create a Path with the correct DirId and Branch name.
  2416  type NodeCache interface {
  2417  	// GetOrCreate either makes a new Node for the given
  2418  	// BlockPointer, or returns an existing one. TODO: If we ever
  2419  	// support hard links, we will have to revisit the "name" and
  2420  	// "parent" parameters here.  name must not be empty. Returns
  2421  	// an error if parent cannot be found.
  2422  	GetOrCreate(
  2423  		ptr data.BlockPointer, name data.PathPartString, parent Node,
  2424  		et data.EntryType) (Node, error)
  2425  	// Get returns the Node associated with the given ptr if one
  2426  	// already exists.  Otherwise, it returns nil.
  2427  	Get(ref data.BlockRef) Node
  2428  	// UpdatePointer updates the BlockPointer for the corresponding
  2429  	// Node.  NodeCache ignores this call when oldRef is not cached in
  2430  	// any Node. Returns whether the ID of the node that was updated,
  2431  	// or `nil` if nothing was updated.
  2432  	UpdatePointer(oldRef data.BlockRef, newPtr data.BlockPointer) NodeID
  2433  	// Move swaps the parent node for the corresponding Node, and
  2434  	// updates the node's name.  NodeCache ignores the call when ptr
  2435  	// is not cached.  If newParent is nil, it treats the ptr's
  2436  	// corresponding node as being unlinked from the old parent
  2437  	// completely. If successful, it returns a function that can be
  2438  	// called to undo the effect of the move (or `nil` if nothing
  2439  	// needs to be done); if newParent cannot be found, it returns an
  2440  	// error and a `nil` undo function.
  2441  	Move(ref data.BlockRef, newParent Node, newName data.PathPartString) (
  2442  		undoFn func(), err error)
  2443  	// Unlink set the corresponding node's parent to nil and caches
  2444  	// the provided path in case the node is still open. NodeCache
  2445  	// ignores the call when ptr is not cached.  The path is required
  2446  	// because the caller may have made changes to the parent nodes
  2447  	// already that shouldn't be reflected in the cached path.  It
  2448  	// returns a function that can be called to undo the effect of the
  2449  	// unlink (or `nil` if nothing needs to be done).
  2450  	Unlink(ref data.BlockRef, oldPath data.Path, oldDe data.DirEntry) (
  2451  		undoFn func())
  2452  	// IsUnlinked returns whether `Unlink` has been called for the
  2453  	// reference behind this node.
  2454  	IsUnlinked(node Node) bool
  2455  	// UnlinkedDirEntry returns a directory entry if `Unlink` has been
  2456  	// called for the reference behind this node.
  2457  	UnlinkedDirEntry(node Node) data.DirEntry
  2458  	// UpdateUnlinkedDirEntry modifies a cached directory entry for a
  2459  	// node that has already been unlinked.
  2460  	UpdateUnlinkedDirEntry(node Node, newDe data.DirEntry)
  2461  	// PathFromNode creates the path up to a given Node.
  2462  	PathFromNode(node Node) data.Path
  2463  	// AllNodes returns the complete set of nodes currently in the
  2464  	// cache.  The returned Nodes are not wrapped, and shouldn't be
  2465  	// used for data access.
  2466  	AllNodes() []Node
  2467  	// AllNodeChildren returns the complete set of nodes currently in
  2468  	// the cache, for which the given node `n` is a parent (direct or
  2469  	// indirect).  The returned slice does not include `n` itself.
  2470  	// The returned Nodes are not wrapped, and shouldn't be used for
  2471  	// data access.
  2472  	AllNodeChildren(n Node) []Node
  2473  	// AddRootWrapper adds a new wrapper function that will be applied
  2474  	// whenever a root Node is created.
  2475  	AddRootWrapper(func(Node) Node)
  2476  	// SetObfuscatorMaker sets the obfuscator-making function for this cache.
  2477  	SetObfuscatorMaker(func() data.Obfuscator)
  2478  	// ObfuscatorMaker sets the obfuscator-making function for this cache.
  2479  	ObfuscatorMaker() func() data.Obfuscator
  2480  }
  2481  
  2482  // fileBlockDeepCopier fetches a file block, makes a deep copy of it
  2483  // (duplicating pointer for any indirect blocks) and generates a new
  2484  // random temporary block ID for it.  It returns the new BlockPointer,
  2485  // and internally saves the block for future uses.
  2486  type fileBlockDeepCopier func(
  2487  	context.Context, data.PathPartString, data.BlockPointer) (
  2488  	data.BlockPointer, error)
  2489  
  2490  // crAction represents a specific action to take as part of the
  2491  // conflict resolution process.
  2492  type crAction interface {
  2493  	// swapUnmergedBlock should be called before do(), and if it
  2494  	// returns true, the caller must use the merged block
  2495  	// corresponding to the returned BlockPointer instead of
  2496  	// unmergedBlock when calling do().  If BlockPointer{} is zeroPtr
  2497  	// (and true is returned), just swap in the regular mergedBlock.
  2498  	swapUnmergedBlock(
  2499  		ctx context.Context, unmergedChains, mergedChains *crChains,
  2500  		unmergedDir *data.DirData) (bool, data.BlockPointer, error)
  2501  	// do modifies the given merged `dirData` in place to resolve the
  2502  	// conflict, and potentially uses the provided
  2503  	// `fileBlockDeepCopier`s to obtain copies of other blocks (along
  2504  	// with new BlockPointers) when requiring a block copy.  It
  2505  	// returns a set of block infos that need to be unreferenced as
  2506  	// part of this conflict resolution.
  2507  	do(
  2508  		ctx context.Context, unmergedCopier, mergedCopier fileBlockDeepCopier,
  2509  		unmergedDir, mergedDir *data.DirData) (unrefs []data.BlockInfo, err error)
  2510  	// updateOps potentially modifies, in place, the slices of
  2511  	// unmerged and merged operations stored in the corresponding
  2512  	// crChains for the given unmerged and merged most recent
  2513  	// pointers.  Eventually, the "unmerged" ops will be pushed as
  2514  	// part of a MD update, and so should contain any necessarily
  2515  	// operations to fully merge the unmerged data, including any
  2516  	// conflict resolution.  The "merged" ops will be played through
  2517  	// locally, to notify any caches about the newly-obtained merged
  2518  	// data (and any changes to local data that were required as part
  2519  	// of conflict resolution, such as renames).  A few things to note:
  2520  	// * A particular action's updateOps method may be called more than
  2521  	//   once for different sets of chains, however it should only add
  2522  	//   new directory operations (like create/rm/rename) into directory
  2523  	//   chains.
  2524  	// * updateOps doesn't necessarily result in correct BlockPointers within
  2525  	//   each of those ops; that must happen in a later phase.
  2526  	// * mergedDir can be nil if the chain is for a file.
  2527  	updateOps(
  2528  		ctx context.Context, unmergedMostRecent, mergedMostRecent data.BlockPointer,
  2529  		unmergedDir, mergedDir *data.DirData,
  2530  		unmergedChains, mergedChains *crChains) error
  2531  	// String returns a string representation for this crAction, used
  2532  	// for debugging.
  2533  	String() string
  2534  }
  2535  
  2536  // RekeyQueue is a managed queue of folders needing some rekey action taken
  2537  // upon them by the current client.
  2538  type RekeyQueue interface {
  2539  	// Enqueue enqueues a folder for rekey action. If the TLF is already in the
  2540  	// rekey queue, the error channel of the existing one is returned.
  2541  	Enqueue(tlf.ID)
  2542  	// IsRekeyPending returns true if the given folder is in the rekey queue.
  2543  	// Note that an ongoing rekey doesn't count as "pending".
  2544  	IsRekeyPending(tlf.ID) bool
  2545  	// Shutdown cancels all pending rekey actions and clears the queue. It
  2546  	// doesn't cancel ongoing rekeys. After Shutdown() is called, the same
  2547  	// RekeyQueue shouldn't be used anymore.
  2548  	Shutdown()
  2549  }
  2550  
  2551  // RekeyFSM is a Finite State Machine (FSM) for housekeeping rekey states for a
  2552  // FolderBranch. Each FolderBranch has its own FSM for rekeys.
  2553  //
  2554  // See rekey_fsm.go for implementation details.
  2555  //
  2556  // TODO: report FSM status in FolderBranchStatus?
  2557  type RekeyFSM interface {
  2558  	// Event sends an event to the FSM.
  2559  	Event(event RekeyEvent)
  2560  	// Shutdown shuts down the FSM. No new event should be sent into the FSM
  2561  	// after this method is called.
  2562  	Shutdown()
  2563  
  2564  	// listenOnEvent adds a listener (callback) to the FSM so that when
  2565  	// event happens, callback is called with the received event. If repeatedly
  2566  	// is set to false, callback is called only once. Otherwise it's called every
  2567  	// time event happens.
  2568  	//
  2569  	// Currently this is only used in tests and for RekeyFile. See comment for
  2570  	// RequestRekeyAndWaitForOneFinishEvent for more details.
  2571  	listenOnEvent(
  2572  		event rekeyEventType, callback func(RekeyEvent), repeatedly bool)
  2573  }
  2574  
  2575  // BlockRetriever specifies how to retrieve blocks.
  2576  type BlockRetriever interface {
  2577  	// Request retrieves blocks asynchronously.  `action` determines
  2578  	// what happens after the block is fetched successfully.
  2579  	Request(ctx context.Context, priority int, kmd libkey.KeyMetadata,
  2580  		ptr data.BlockPointer, block data.Block, lifetime data.BlockCacheLifetime,
  2581  		action BlockRequestAction) <-chan error
  2582  	// PutInCaches puts the block into the in-memory cache, and ensures that
  2583  	// the disk cache metadata is updated.
  2584  	PutInCaches(ctx context.Context, ptr data.BlockPointer, tlfID tlf.ID,
  2585  		block data.Block, lifetime data.BlockCacheLifetime,
  2586  		prefetchStatus PrefetchStatus, cacheType DiskBlockCacheType) error
  2587  	// TogglePrefetcher creates a new prefetcher.
  2588  	TogglePrefetcher(enable bool, syncCh <-chan struct{}, doneCh chan<- struct{}) <-chan struct{}
  2589  }
  2590  
  2591  // ChatChannelNewMessageCB is a callback function that can be called
  2592  // when there's a new message on a given conversation.
  2593  type ChatChannelNewMessageCB func(convID chat1.ConversationID, body string)
  2594  
  2595  // Chat specifies a minimal interface for Keybase chatting.
  2596  type Chat interface {
  2597  	// GetConversationID returns the chat conversation ID associated
  2598  	// with the given TLF name, type, chat type and channel name.
  2599  	GetConversationID(
  2600  		ctx context.Context, tlfName tlf.CanonicalName, tlfType tlf.Type,
  2601  		channelName string, chatType chat1.TopicType) (
  2602  		chat1.ConversationID, error)
  2603  
  2604  	// SendTextMessage (asynchronously) sends a text chat message to
  2605  	// the given conversation and channel.
  2606  	SendTextMessage(
  2607  		ctx context.Context, tlfName tlf.CanonicalName, tlfType tlf.Type,
  2608  		convID chat1.ConversationID, body string) error
  2609  
  2610  	// GetGroupedInbox returns the TLFs with the most-recent chat
  2611  	// messages of the given type, up to `maxChats` of them.
  2612  	GetGroupedInbox(
  2613  		ctx context.Context, chatType chat1.TopicType, maxChats int) (
  2614  		[]*tlfhandle.Handle, error)
  2615  
  2616  	// GetChannels returns a list of all the channels for a given
  2617  	// chat. The entries in `convIDs` and `channelNames` have a 1-to-1
  2618  	// correspondence.
  2619  	GetChannels(
  2620  		ctx context.Context, tlfName tlf.CanonicalName, tlfType tlf.Type,
  2621  		chatType chat1.TopicType) (
  2622  		convIDs []chat1.ConversationID, channelNames []string, err error)
  2623  
  2624  	// ReadChannel returns a set of text messages from a channel, and
  2625  	// a `nextPage` pointer to the following set of messages.  If the
  2626  	// given `startPage` is non-nil, it's used to specify the starting
  2627  	// point for the set of messages returned.
  2628  	ReadChannel(
  2629  		ctx context.Context, convID chat1.ConversationID, startPage []byte) (
  2630  		messages []string, nextPage []byte, err error)
  2631  
  2632  	// RegisterForMessages registers a callback that will be called
  2633  	// for each new messages that reaches convID.
  2634  	RegisterForMessages(convID chat1.ConversationID, cb ChatChannelNewMessageCB)
  2635  
  2636  	// ClearCache is called to force this instance to forget
  2637  	// everything it might have cached, e.g. when a user logs out.
  2638  	ClearCache()
  2639  }
  2640  
  2641  // blockPutState is an interface for keeping track of readied blocks
  2642  // before putting them to the bserver.
  2643  type blockPutState interface {
  2644  	data.BlockPutState
  2645  	oldPtr(ctx context.Context, blockPtr data.BlockPointer) (data.BlockPointer, error)
  2646  	getReadyBlockData(
  2647  		ctx context.Context, blockPtr data.BlockPointer) (data.ReadyBlockData, error)
  2648  	synced(blockPtr data.BlockPointer) error
  2649  	numBlocks() int
  2650  }
  2651  
  2652  // blockPutStateCopiable is a more manipulatable interface around
  2653  // `blockPutState`, allowing copying as well as merging/unmerging.
  2654  type blockPutStateCopiable interface {
  2655  	blockPutState
  2656  
  2657  	mergeOtherBps(ctx context.Context, other blockPutStateCopiable) error
  2658  	removeOtherBps(ctx context.Context, other blockPutStateCopiable) error
  2659  	deepCopy(ctx context.Context) (blockPutStateCopiable, error)
  2660  	deepCopyWithBlacklist(
  2661  		ctx context.Context, blacklist map[data.BlockPointer]bool) (
  2662  		blockPutStateCopiable, error)
  2663  }
  2664  
  2665  type fileBlockMap interface {
  2666  	putTopBlock(
  2667  		ctx context.Context, parentPtr data.BlockPointer,
  2668  		childName data.PathPartString, topBlock *data.FileBlock) error
  2669  	GetTopBlock(
  2670  		ctx context.Context, parentPtr data.BlockPointer,
  2671  		childName data.PathPartString) (*data.FileBlock, error)
  2672  	getFilenames(
  2673  		ctx context.Context, parentPtr data.BlockPointer) (
  2674  		[]data.PathPartString, error)
  2675  }
  2676  
  2677  type dirBlockMap interface {
  2678  	putBlock(
  2679  		ctx context.Context, ptr data.BlockPointer, block *data.DirBlock) error
  2680  	getBlock(
  2681  		ctx context.Context, ptr data.BlockPointer) (*data.DirBlock, error)
  2682  	hasBlock(ctx context.Context, ptr data.BlockPointer) (bool, error)
  2683  	deleteBlock(ctx context.Context, ptr data.BlockPointer) error
  2684  	numBlocks() int
  2685  }