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 }