From 0ea879b4a1d8bee9ca2ef52d44bc96942d87aa73 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Fri, 26 Jan 2024 11:20:34 +0100 Subject: [PATCH] feat: add Ipns.MaxCacheTTL --- config/ipns.go | 12 ++++++++++ core/coreapi/coreapi.go | 13 +++++++---- core/corehttp/gateway.go | 10 +++++--- core/node/groups.go | 4 ++-- core/node/ipns.go | 3 ++- docs/changelogs/v0.27.md | 4 ++++ docs/config.md | 32 +++++++++++++++++++++++++- docs/examples/kubo-as-a-library/go.mod | 2 +- docs/examples/kubo-as-a-library/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- test/dependencies/go.mod | 2 +- test/dependencies/go.sum | 4 ++-- 13 files changed, 76 insertions(+), 20 deletions(-) diff --git a/config/ipns.go b/config/ipns.go index d5191088409..28842197310 100644 --- a/config/ipns.go +++ b/config/ipns.go @@ -1,11 +1,23 @@ package config +import ( + "math" + "time" +) + +const ( + DefaultIpnsMaxCacheTTL = time.Duration(math.MaxInt64) +) + type Ipns struct { RepublishPeriod string RecordLifetime string ResolveCacheSize int + // MaxCacheTTL is the maximum duration IPNS entries are valid in the cache. + MaxCacheTTL *OptionalDuration `json:",omitempty"` + // Enable namesys pubsub (--enable-namesys-pubsub) UsePubsub Flag `json:",omitempty"` } diff --git a/core/coreapi/coreapi.go b/core/coreapi/coreapi.go index 3efe0377862..0723ab65984 100644 --- a/core/coreapi/coreapi.go +++ b/core/coreapi/coreapi.go @@ -26,6 +26,7 @@ import ( provider "github.com/ipfs/boxo/provider" offlineroute "github.com/ipfs/boxo/routing/offline" ipld "github.com/ipfs/go-ipld-format" + "github.com/ipfs/kubo/config" coreiface "github.com/ipfs/kubo/core/coreiface" "github.com/ipfs/kubo/core/coreiface/options" pubsub "github.com/libp2p/go-libp2p-pubsub" @@ -225,12 +226,16 @@ func (api *CoreAPI) WithOptions(opts ...options.ApiOption) (coreiface.CoreAPI, e return nil, fmt.Errorf("cannot specify negative resolve cache size") } - subAPI.routing = offlineroute.NewOfflineRouter(subAPI.repo.Datastore(), subAPI.recordValidator) - - subAPI.namesys, err = namesys.NewNameSystem(subAPI.routing, + nsOptions := []namesys.Option{ namesys.WithDatastore(subAPI.repo.Datastore()), namesys.WithDNSResolver(subAPI.dnsResolver), - namesys.WithCache(cs)) + namesys.WithCache(cs), + namesys.WithMaxCacheTTL(cfg.Ipns.MaxCacheTTL.WithDefault(config.DefaultIpnsMaxCacheTTL)), + } + + subAPI.routing = offlineroute.NewOfflineRouter(subAPI.repo.Datastore(), subAPI.recordValidator) + + subAPI.namesys, err = namesys.NewNameSystem(subAPI.routing, nsOptions...) if err != nil { return nil, fmt.Errorf("error constructing namesys: %w", err) } diff --git a/core/corehttp/gateway.go b/core/corehttp/gateway.go index c08d71806da..67e3c242d7b 100644 --- a/core/corehttp/gateway.go +++ b/core/corehttp/gateway.go @@ -135,11 +135,15 @@ func newGatewayBackend(n *core.IpfsNode) (gateway.IPFSBackend, error) { return nil, fmt.Errorf("cannot specify negative resolve cache size") } - vsRouting = offlineroute.NewOfflineRouter(n.Repo.Datastore(), n.RecordValidator) - nsys, err = namesys.NewNameSystem(vsRouting, + nsOptions := []namesys.Option{ namesys.WithDatastore(n.Repo.Datastore()), namesys.WithDNSResolver(n.DNSResolver), - namesys.WithCache(cs)) + namesys.WithCache(cs), + namesys.WithMaxCacheTTL(cfg.Ipns.MaxCacheTTL.WithDefault(config.DefaultIpnsMaxCacheTTL)), + } + + vsRouting = offlineroute.NewOfflineRouter(n.Repo.Datastore(), n.RecordValidator) + nsys, err = namesys.NewNameSystem(vsRouting, nsOptions...) if err != nil { return nil, fmt.Errorf("error constructing namesys: %w", err) } diff --git a/core/node/groups.go b/core/node/groups.go index 4572a2ddd80..061087c276b 100644 --- a/core/node/groups.go +++ b/core/node/groups.go @@ -273,7 +273,7 @@ func Online(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part fx.Provide(BitswapOptions(cfg, shouldBitswapProvide)), fx.Provide(OnlineExchange()), fx.Provide(DNSResolver), - fx.Provide(Namesys(ipnsCacheSize)), + fx.Provide(Namesys(ipnsCacheSize, cfg.Ipns.MaxCacheTTL.WithDefault(config.DefaultIpnsMaxCacheTTL))), fx.Provide(Peering), PeerWith(cfg.Peering.Peers...), @@ -296,7 +296,7 @@ func Offline(cfg *config.Config) fx.Option { return fx.Options( fx.Provide(offline.Exchange), fx.Provide(DNSResolver), - fx.Provide(Namesys(0)), + fx.Provide(Namesys(0, 0)), fx.Provide(libp2p.Routing), fx.Provide(libp2p.ContentRouting), fx.Provide(libp2p.OfflineRouting), diff --git a/core/node/ipns.go b/core/node/ipns.go index b1b5ee6e045..5f516d0354b 100644 --- a/core/node/ipns.go +++ b/core/node/ipns.go @@ -28,11 +28,12 @@ func RecordValidator(ps peerstore.Peerstore) record.Validator { } // Namesys creates new name system -func Namesys(cacheSize int) func(rt irouting.ProvideManyRouter, rslv *madns.Resolver, repo repo.Repo) (namesys.NameSystem, error) { +func Namesys(cacheSize int, cacheMaxTTL time.Duration) func(rt irouting.ProvideManyRouter, rslv *madns.Resolver, repo repo.Repo) (namesys.NameSystem, error) { return func(rt irouting.ProvideManyRouter, rslv *madns.Resolver, repo repo.Repo) (namesys.NameSystem, error) { opts := []namesys.Option{ namesys.WithDatastore(repo.Datastore()), namesys.WithDNSResolver(rslv), + namesys.WithMaxCacheTTL(cacheMaxTTL), } if cacheSize > 0 { diff --git a/docs/changelogs/v0.27.md b/docs/changelogs/v0.27.md index 1d7c5b10185..26a607f8abb 100644 --- a/docs/changelogs/v0.27.md +++ b/docs/changelogs/v0.27.md @@ -20,6 +20,10 @@ Support for exposing the legacy subset of Kubo RPC via the Gateway port is depre If you have a legacy software that relies on this behavior, and want to expose parts of `/api/v0` next to `/ipfs`, use reverse-proxy in front of Kubo to mount both Gateway and RPC on the same port. NOTE: exposing RPC to the internet comes with security risk: make sure to specify access control via [API.Authorizations](https://github.com/ipfs/kubo/blob/master/docs/config.md#apiauthorizations). +#### IPNS resolver cache's TTL can now be configured + +You can now configure the upper-bound of a cached IPNS entry's Time-To-Live via [`Ipns.MaxCacheTTL`](https://github.com/ipfs/kubo/blob/master/docs/config.md#ipnsmaxcachettl). + ### ๐Ÿ“ Changelog ### ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Contributors diff --git a/docs/config.md b/docs/config.md index d6c1567f1b9..82e5c0cdb22 100644 --- a/docs/config.md +++ b/docs/config.md @@ -84,6 +84,7 @@ config file at runtime. - [`Ipns.RepublishPeriod`](#ipnsrepublishperiod) - [`Ipns.RecordLifetime`](#ipnsrecordlifetime) - [`Ipns.ResolveCacheSize`](#ipnsresolvecachesize) + - [`Ipns.MaxCacheTTL`](#ipnsmaxcachettl) - [`Ipns.UsePubsub`](#ipnsusepubsub) - [`Migration`](#migration) - [`Migration.DownloadSources`](#migrationdownloadsources) @@ -1138,6 +1139,35 @@ Default: `128` Type: `integer` (non-negative, 0 means the default) +### `Ipns.MaxCacheTTL` + +Maximum duration for which entries are valid in the name system cache. Applied +to everything under `/ipns/` namespace, allows you to cap +the [Time-To-Live (TTL)](https://specs.ipfs.tech/ipns/ipns-record/#ttl-uint64) of +[IPNS Records](https://specs.ipfs.tech/ipns/ipns-record/) +AND also DNSLink TXT records (when DoH-specific [`DNS.MaxCacheTTL`](https://github.com/ipfs/kubo/blob/master/docs/config.md#dnsmaxcachettl) +is not set to a lower value). + +When `Ipns.MaxCacheTTL` is set, it defines the upper bound limit of how long a +[IPNS Name](https://specs.ipfs.tech/ipns/ipns-record/#ipns-name) lookup result +will be cached and read from cache before checking for updates. + +**Examples:** +* `"1m"` IPNS results are cached 1m or less (good compromise for system where + faster updates are desired). +* `"0s"` IPNS caching is effectively turned off (useful for testing, bad for production use) + - **Note:** setting this to `0` will turn off TTL-based caching entirely. + This is discouraged in production environments. It will make IPNS websites + artificially slow because IPNS resolution results will expire as soon as + they are retrieved, forcing expensive IPNS lookup to happen on every + request. If you want near-real-time IPNS, set it to a low, but still + sensible value, such as `1m`. + +Default: No upper bound, [TTL from IPNS Record](https://specs.ipfs.tech/ipns/ipns-record/#ttl-uint64) (see `ipns name publish --help`) is always respected. + + +Type: `optionalDuration` + ### `Ipns.UsePubsub` Enables IPFS over pubsub experiment for publishing IPNS records in real time. @@ -2317,7 +2347,7 @@ If present, the upper bound is applied to DoH resolvers in [`DNS.Resolvers`](#dn Note: this does NOT work with Go's default DNS resolver. To make this a global setting, add a `.` entry to `DNS.Resolvers` first. **Examples:** -* `"5m"` DNS entries are kept for 5 minutes or less. +* `"1m"` DNS entries are kept for 1 minute or less. * `"0s"` DNS entries expire as soon as they are retrieved. Default: Respect DNS Response TTL diff --git a/docs/examples/kubo-as-a-library/go.mod b/docs/examples/kubo-as-a-library/go.mod index a134ccd25f8..edaed2de6e7 100644 --- a/docs/examples/kubo-as-a-library/go.mod +++ b/docs/examples/kubo-as-a-library/go.mod @@ -7,7 +7,7 @@ go 1.20 replace github.com/ipfs/kubo => ./../../.. require ( - github.com/ipfs/boxo v0.17.1-0.20240125173442-bf34cd0777d8 + github.com/ipfs/boxo v0.17.1-0.20240126101119-fdfcfcc0708a github.com/ipfs/kubo v0.0.0-00010101000000-000000000000 github.com/libp2p/go-libp2p v0.32.2 github.com/multiformats/go-multiaddr v0.12.1 diff --git a/docs/examples/kubo-as-a-library/go.sum b/docs/examples/kubo-as-a-library/go.sum index f1b2b9a04c7..491ac004cc9 100644 --- a/docs/examples/kubo-as-a-library/go.sum +++ b/docs/examples/kubo-as-a-library/go.sum @@ -260,8 +260,8 @@ github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c h1:7Uy github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c/go.mod h1:6EekK/jo+TynwSE/ZOiOJd4eEvRXoavEC3vquKtv4yI= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= -github.com/ipfs/boxo v0.17.1-0.20240125173442-bf34cd0777d8 h1:/d+3/JOYsHS4Uo+6WIxu2oHHlM5WjWOySYItN9V+YHs= -github.com/ipfs/boxo v0.17.1-0.20240125173442-bf34cd0777d8/go.mod h1:pIZgTWdm3k3pLF9Uq6MB8JEcW07UDwNJjlXW1HELW80= +github.com/ipfs/boxo v0.17.1-0.20240126101119-fdfcfcc0708a h1:BMxa0aXrjyGh5gAkzxVsjDN71YhAWGfjbOoNvZt4/jg= +github.com/ipfs/boxo v0.17.1-0.20240126101119-fdfcfcc0708a/go.mod h1:pIZgTWdm3k3pLF9Uq6MB8JEcW07UDwNJjlXW1HELW80= github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU= github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk= diff --git a/go.mod b/go.mod index 68cfbfa5d71..5e85e91b564 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 github.com/ipfs-shipyard/nopfs v0.0.12 github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c - github.com/ipfs/boxo v0.17.1-0.20240125173442-bf34cd0777d8 + github.com/ipfs/boxo v0.17.1-0.20240126101119-fdfcfcc0708a github.com/ipfs/go-block-format v0.2.0 github.com/ipfs/go-cid v0.4.1 github.com/ipfs/go-cidutil v0.1.0 diff --git a/go.sum b/go.sum index e2029764779..54243afb8f7 100644 --- a/go.sum +++ b/go.sum @@ -325,8 +325,8 @@ github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c h1:7Uy github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c/go.mod h1:6EekK/jo+TynwSE/ZOiOJd4eEvRXoavEC3vquKtv4yI= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= -github.com/ipfs/boxo v0.17.1-0.20240125173442-bf34cd0777d8 h1:/d+3/JOYsHS4Uo+6WIxu2oHHlM5WjWOySYItN9V+YHs= -github.com/ipfs/boxo v0.17.1-0.20240125173442-bf34cd0777d8/go.mod h1:pIZgTWdm3k3pLF9Uq6MB8JEcW07UDwNJjlXW1HELW80= +github.com/ipfs/boxo v0.17.1-0.20240126101119-fdfcfcc0708a h1:BMxa0aXrjyGh5gAkzxVsjDN71YhAWGfjbOoNvZt4/jg= +github.com/ipfs/boxo v0.17.1-0.20240126101119-fdfcfcc0708a/go.mod h1:pIZgTWdm3k3pLF9Uq6MB8JEcW07UDwNJjlXW1HELW80= github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU= github.com/ipfs/go-bitswap v0.11.0 h1:j1WVvhDX1yhG32NTC9xfxnqycqYIlhzEzLXG/cU1HyQ= diff --git a/test/dependencies/go.mod b/test/dependencies/go.mod index f069c130307..58735de6c9e 100644 --- a/test/dependencies/go.mod +++ b/test/dependencies/go.mod @@ -103,7 +103,7 @@ require ( github.com/hexops/gotextdiff v1.0.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/ipfs/bbloom v0.0.4 // indirect - github.com/ipfs/boxo v0.17.1-0.20240125173442-bf34cd0777d8 // indirect + github.com/ipfs/boxo v0.17.1-0.20240126101119-fdfcfcc0708a // indirect github.com/ipfs/go-block-format v0.2.0 // indirect github.com/ipfs/go-cid v0.4.1 // indirect github.com/ipfs/go-datastore v0.6.0 // indirect diff --git a/test/dependencies/go.sum b/test/dependencies/go.sum index 35a9ed95520..98ef579f5b9 100644 --- a/test/dependencies/go.sum +++ b/test/dependencies/go.sum @@ -342,8 +342,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= -github.com/ipfs/boxo v0.17.1-0.20240125173442-bf34cd0777d8 h1:/d+3/JOYsHS4Uo+6WIxu2oHHlM5WjWOySYItN9V+YHs= -github.com/ipfs/boxo v0.17.1-0.20240125173442-bf34cd0777d8/go.mod h1:pIZgTWdm3k3pLF9Uq6MB8JEcW07UDwNJjlXW1HELW80= +github.com/ipfs/boxo v0.17.1-0.20240126101119-fdfcfcc0708a h1:BMxa0aXrjyGh5gAkzxVsjDN71YhAWGfjbOoNvZt4/jg= +github.com/ipfs/boxo v0.17.1-0.20240126101119-fdfcfcc0708a/go.mod h1:pIZgTWdm3k3pLF9Uq6MB8JEcW07UDwNJjlXW1HELW80= github.com/ipfs/go-block-format v0.2.0 h1:ZqrkxBA2ICbDRbK8KJs/u0O3dlp6gmAuuXUJNiW1Ycs= github.com/ipfs/go-block-format v0.2.0/go.mod h1:+jpL11nFx5A/SPpsoBn6Bzkra/zaArfSmsknbPMYgzM= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=