| 1 | package node |
| 2 | |
| 3 | import ( |
| 4 | blockstore "github.com/ipfs/boxo/blockstore" |
| 5 | "github.com/ipfs/go-datastore" |
| 6 | config "github.com/ipfs/kubo/config" |
| 7 | "go.uber.org/fx" |
| 8 | |
| 9 | "github.com/ipfs/boxo/filestore" |
| 10 | "github.com/ipfs/boxo/provider" |
| 11 | "github.com/ipfs/kubo/core/node/helpers" |
| 12 | "github.com/ipfs/kubo/repo" |
| 13 | "github.com/ipfs/kubo/thirdparty/verifbs" |
| 14 | ) |
| 15 | |
| 16 | // RepoConfig loads configuration from the repo |
| 17 | func RepoConfig(repo repo.Repo) (*config.Config, error) { |
| 18 | cfg, err := repo.Config() |
| 19 | return cfg, err |
| 20 | } |
| 21 | |
| 22 | // Datastore provides the datastore |
| 23 | func Datastore(repo repo.Repo) datastore.Datastore { |
| 24 | return repo.Datastore() |
| 25 | } |
| 26 | |
| 27 | // BaseBlocks is the lower level blockstore without GC or Filestore layers |
| 28 | type BaseBlocks blockstore.Blockstore |
| 29 | |
| 30 | // BaseBlockstoreCtor creates cached blockstore backed by the provided datastore |
| 31 | func BaseBlockstoreCtor( |
| 32 | cacheOpts blockstore.CacheOpts, |
| 33 | hashOnRead bool, |
| 34 | writeThrough bool, |
| 35 | providingStrategy string, |
| 36 | ) func(mctx helpers.MetricsCtx, repo repo.Repo, prov DHTProvider, lc fx.Lifecycle) (bs BaseBlocks, err error) { |
| 37 | return func(mctx helpers.MetricsCtx, repo repo.Repo, prov DHTProvider, lc fx.Lifecycle) (bs BaseBlocks, err error) { |
| 38 | opts := []blockstore.Option{blockstore.WriteThrough(writeThrough)} |
| 39 | |
| 40 | // Blockstore providing integration: |
| 41 | // When strategy includes "all" the blockstore directly provides blocks as they're Put. |
| 42 | // Important: Provide calls from blockstore are intentionally BLOCKING. |
| 43 | // The Provider implementation (not the blockstore) should handle concurrency/queuing. |
| 44 | // This avoids spawning unbounded goroutines for concurrent block additions. |
| 45 | strategyFlag := config.MustParseProvideStrategy(providingStrategy) |
| 46 | if strategyFlag&config.ProvideStrategyAll != 0 { |
| 47 | opts = append(opts, blockstore.Provider(prov)) |
| 48 | } |
| 49 | |
| 50 | // hash security |
| 51 | bs = blockstore.NewBlockstore( |
| 52 | repo.Datastore(), |
| 53 | opts..., |
| 54 | ) |
| 55 | bs = &verifbs.VerifBS{Blockstore: bs} |
| 56 | bs, err = blockstore.CachedBlockstore(helpers.LifecycleCtx(mctx, lc), bs, cacheOpts) |
| 57 | if err != nil { |
| 58 | return nil, err |
| 59 | } |
| 60 | |
| 61 | bs = blockstore.NewIdStore(bs) |
| 62 | |
| 63 | if hashOnRead { |
| 64 | bs = &blockstore.ValidatingBlockstore{Blockstore: bs} |
| 65 | } |
| 66 | |
| 67 | return |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | // GcBlockstoreCtor wraps the base blockstore with GC and Filestore layers |
| 72 | func GcBlockstoreCtor(bb BaseBlocks) (gclocker blockstore.GCLocker, gcbs blockstore.GCBlockstore, bs blockstore.Blockstore) { |
| 73 | gclocker = blockstore.NewGCLocker() |
| 74 | gcbs = blockstore.NewGCBlockstore(bb, gclocker) |
| 75 | |
| 76 | bs = gcbs |
| 77 | return |
| 78 | } |
| 79 | |
| 80 | // FilestoreBlockstoreCtor wraps GcBlockstore and adds Filestore support |
| 81 | func FilestoreBlockstoreCtor( |
| 82 | providingStrategy string, |
| 83 | ) func(repo repo.Repo, bb BaseBlocks, prov DHTProvider) (gclocker blockstore.GCLocker, gcbs blockstore.GCBlockstore, bs blockstore.Blockstore, fstore *filestore.Filestore) { |
| 84 | return func(repo repo.Repo, bb BaseBlocks, prov DHTProvider) (gclocker blockstore.GCLocker, gcbs blockstore.GCBlockstore, bs blockstore.Blockstore, fstore *filestore.Filestore) { |
| 85 | gclocker = blockstore.NewGCLocker() |
| 86 | |
| 87 | var fstoreProv provider.MultihashProvider |
| 88 | strategyFlag := config.MustParseProvideStrategy(providingStrategy) |
| 89 | if strategyFlag&config.ProvideStrategyAll != 0 { |
| 90 | fstoreProv = prov |
| 91 | } |
| 92 | |
| 93 | fstore = filestore.NewFilestore(bb, repo.FileManager(), fstoreProv) |
| 94 | |
| 95 | // hash security |
| 96 | gcbs = blockstore.NewGCBlockstore(fstore, gclocker) |
| 97 | gcbs = &verifbs.VerifBSGC{GCBlockstore: gcbs} |
| 98 | |
| 99 | bs = gcbs |
| 100 | return |
| 101 | } |
| 102 | } |