Skip to content

Commit

Permalink
feat: remote backend
Browse files Browse the repository at this point in the history
  • Loading branch information
hacdias committed May 15, 2024
1 parent b71f33f commit ce5155a
Show file tree
Hide file tree
Showing 9 changed files with 329 additions and 124 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ The following emojis are used to highlight certain changes:

### Added

- Now supports remote backends (using RAW block or CAR requests) via `--remote-backends` (`RAINBOW_REMOTE_BACKENDS`).

### Changed

### Removed
Expand Down
7 changes: 6 additions & 1 deletion gc.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ import (
)

// GC is a really stupid simple algorithm where we just delete things until
// weve deleted enough things
// we've deleted enough things. It is no-op if the current setup does not have
// a blockstore.
func (nd *Node) GC(ctx context.Context, todelete int64) error {
if nd.blockstore == nil {
return nil

Check warning on line 15 in gc.go

View check run for this annotation

Codecov / codecov/patch

gc.go#L15

Added line #L15 was not covered by tests
}

keys, err := nd.blockstore.AllKeysChan(ctx)
if err != nil {
return err
Expand Down
4 changes: 3 additions & 1 deletion gc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import (
func TestPeriodicGC(t *testing.T) {
t.Parallel()

gnd := mustTestNode(t, Config{})
gnd := mustTestNode(t, Config{
Bitswap: true,
})

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
Expand Down
1 change: 1 addition & 0 deletions handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func TestTrustless(t *testing.T) {
t.Parallel()

ts, gnd := mustTestServer(t, Config{
Bitswap: true,
TrustlessGatewayDomains: []string{"trustless.com"},
})

Expand Down
23 changes: 19 additions & 4 deletions handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,27 @@ func withRequestLogger(next http.Handler) http.Handler {
}

func setupGatewayHandler(cfg Config, nd *Node) (http.Handler, error) {
backend, err := gateway.NewBlocksBackend(
nd.bsrv,
var (
backend gateway.IPFSBackend
err error
)

options := []gateway.BackendOption{
gateway.WithValueStore(nd.vs),
gateway.WithNameSystem(nd.ns),
gateway.WithResolver(nd.resolver),
)
gateway.WithResolver(nd.resolver), // May be nil, but that is fine.
}

if len(cfg.RemoteBackends) > 0 && cfg.RemoteBackendMode == RemoteBackendCAR {
var fetcher gateway.CarFetcher
fetcher, err = gateway.NewRemoteCarFetcher(cfg.RemoteBackends, nil)
if err != nil {
return nil, err

Check warning on line 103 in handlers.go

View check run for this annotation

Codecov / codecov/patch

handlers.go#L100-L103

Added lines #L100 - L103 were not covered by tests
}
backend, err = gateway.NewCarBackend(fetcher, options...)

Check warning on line 105 in handlers.go

View check run for this annotation

Codecov / codecov/patch

handlers.go#L105

Added line #L105 was not covered by tests
} else {
backend, err = gateway.NewBlocksBackend(nd.bsrv, options...)
}
if err != nil {
return nil, err
}
Expand Down
139 changes: 93 additions & 46 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,32 @@ Generate an identity seed and launch a gateway:
EnvVars: []string{"RAINBOW_IPNS_MAX_CACHE_TTL"},
Usage: "Optional cap on caching duration for IPNS/DNSLink lookups. Set to 0 to respect original TTLs",
},
&cli.BoolFlag{
Name: "bitswap",
Value: true,
EnvVars: []string{"RAINBOW_BITSWAP"},
Usage: "Enable or disable Bitswap. Disabling Bitswap is incompatible with --peering-shared-cache",
},
&cli.StringSliceFlag{
Name: "remote-backends",
Value: cli.NewStringSlice(),
EnvVars: []string{"RAINBOW_REMOTE_BACKENDS"},
Usage: "Trustless remote gateways to use as backend (comma-separated). You must set --bitswap=false to use this option. You can configure the mode with --remote-backends-mode",
},
&cli.StringFlag{
Name: "remote-backends-mode",
Value: "block",
EnvVars: []string{"RAINBOW_REMOTE_BACKENDS_MODE"},
Usage: "Whether to fetch raw blocks or CARs from the remote backends. Options are 'block' or 'car'",
Action: func(ctx *cli.Context, s string) error {
switch RemoteBackendMode(s) {
case RemoteBackendBlock, RemoteBackendCAR:
return nil
default:
return errors.New("invalid value for --remote-backend-mode: use 'block' or 'car'")

Check warning on line 273 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L268-L273

Added lines #L268 - L273 were not covered by tests
}
},
},
}

app.Commands = []*cli.Command{
Expand Down Expand Up @@ -289,57 +315,66 @@ share the same seed as long as the indexes are different.

var seed string
var priv crypto.PrivKey
var peeringAddrs []peer.AddrInfo
var index int

Check warning on line 319 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L318-L319

Added lines #L318 - L319 were not covered by tests
var err error

credDir := os.Getenv("CREDENTIALS_DIRECTORY")
secretsDir := ddir
bitswap := cctx.Bool("bitswap")
dhtRouting := DHTRouting(cctx.String("dht-routing"))
seedPeering := cctx.Bool("seed-peering")
noLibp2p := !bitswap && dhtRouting == DHTOff && !seedPeering

Check warning on line 325 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L322-L325

Added lines #L322 - L325 were not covered by tests

if len(credDir) > 0 {
secretsDir = credDir
}
// Only load secrets if we need Libp2p.
if !noLibp2p {
credDir := os.Getenv("CREDENTIALS_DIRECTORY")
secretsDir := ddir

Check warning on line 330 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L328-L330

Added lines #L328 - L330 were not covered by tests

// attempt to read seed from disk
seedBytes, err := os.ReadFile(filepath.Join(secretsDir, "seed"))
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
// set seed from command line or env-var
seed = cctx.String("seed")
} else {
return fmt.Errorf("error reading seed credentials: %w", err)
if len(credDir) > 0 {
secretsDir = credDir

Check warning on line 333 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L332-L333

Added lines #L332 - L333 were not covered by tests
}
} else {
seed = strings.TrimSpace(string(seedBytes))
}

index := cctx.Int("seed-index")
if len(seed) > 0 && index >= 0 {
fmt.Printf("Deriving identity from seed[%d]\n", index)
priv, err = deriveKey(seed, deriveKeyInfo(index))
} else {
fmt.Println("Setting identity from libp2p.key")
keyFile := filepath.Join(secretsDir, "libp2p.key")
priv, err = loadOrInitPeerKey(keyFile)
}
if err != nil {
return err
}

var peeringAddrs []peer.AddrInfo
for _, maStr := range cctx.StringSlice("peering") {
if len(seed) > 0 && index >= 0 {
maStr, err = replaceRainbowSeedWithPeer(maStr, seed)
if err != nil {
return err
// attempt to read seed from disk
seedBytes, err := os.ReadFile(filepath.Join(secretsDir, "seed"))
if err != nil {
if errors.Is(err, fs.ErrNotExist) {

Check warning on line 339 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L337-L339

Added lines #L337 - L339 were not covered by tests
// set seed from command line or env-var
seed = cctx.String("seed")
} else {
return fmt.Errorf("error reading seed credentials: %w", err)

Check warning on line 343 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L341-L343

Added lines #L341 - L343 were not covered by tests
}
} else if rainbowSeedRegex.MatchString(maStr) {
return fmt.Errorf("unable to peer with %q without defining --seed-index of this instance first", maStr)
} else {
seed = strings.TrimSpace(string(seedBytes))

Check warning on line 346 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L345-L346

Added lines #L345 - L346 were not covered by tests
}

ai, err := peer.AddrInfoFromString(maStr)
index = cctx.Int("seed-index")
if len(seed) > 0 && index >= 0 {
fmt.Println("Deriving identity from seed")
priv, err = deriveKey(seed, deriveKeyInfo(index))
} else {
fmt.Println("Setting identity from libp2p.key")
keyFile := filepath.Join(secretsDir, "libp2p.key")
priv, err = loadOrInitPeerKey(keyFile)

Check warning on line 356 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L349-L356

Added lines #L349 - L356 were not covered by tests
}
if err != nil {
return err
}
peeringAddrs = append(peeringAddrs, *ai)

for _, maStr := range cctx.StringSlice("peering") {
if len(seed) > 0 && index >= 0 {
maStr, err = replaceRainbowSeedWithPeer(maStr, seed)
if err != nil {
return err

Check warning on line 366 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L362-L366

Added lines #L362 - L366 were not covered by tests
}
} else if rainbowSeedRegex.MatchString(maStr) {
return fmt.Errorf("unable to peer with %q without defining --seed-index of this instance first", maStr)

Check warning on line 369 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L368-L369

Added lines #L368 - L369 were not covered by tests
}

ai, err := peer.AddrInfoFromString(maStr)
if err != nil {
return err

Check warning on line 374 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L372-L374

Added lines #L372 - L374 were not covered by tests
}
peeringAddrs = append(peeringAddrs, *ai)

Check warning on line 376 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L376

Added line #L376 was not covered by tests
}
}

cfg := Config{
Expand All @@ -355,23 +390,32 @@ share the same seed as long as the indexes are different.
MaxFD: cctx.Int("max-fd"),
InMemBlockCache: cctx.Int64("inmem-block-cache"),
RoutingV1Endpoints: cctx.StringSlice("http-routers"),
DHTRouting: DHTRouting(cctx.String("dht-routing")),
DHTRouting: dhtRouting,

Check warning on line 393 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L393

Added line #L393 was not covered by tests
DHTSharedHost: cctx.Bool("dht-shared-host"),
Bitswap: bitswap,

Check warning on line 395 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L395

Added line #L395 was not covered by tests
IpnsMaxCacheTTL: cctx.Duration("ipns-max-cache-ttl"),
DenylistSubs: cctx.StringSlice("denylists"),
Peering: peeringAddrs,
PeeringSharedCache: cctx.Bool("peering-shared-cache"),
Seed: seed,
SeedIndex: index,
SeedPeering: cctx.Bool("seed-peering"),
SeedPeering: seedPeering,

Check warning on line 402 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L402

Added line #L402 was not covered by tests
SeedPeeringMaxIndex: cctx.Int("seed-peering-max-index"),
RemoteBackends: cctx.StringSlice("remote-backends"),
RemoteBackendMode: RemoteBackendMode(cctx.String("remote-backends-mode")),

Check warning on line 405 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L404-L405

Added lines #L404 - L405 were not covered by tests
GCInterval: cctx.Duration("gc-interval"),
GCThreshold: cctx.Float64("gc-threshold"),
}

var gnd *Node

Check warning on line 410 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L410

Added line #L410 was not covered by tests

goLog.Debugf("Rainbow config: %+v", cfg)

gnd, err := Setup(cctx.Context, cfg, priv, cdns)
if noLibp2p {
gnd, err = SetupNoLibp2p(cctx.Context, cfg, cdns)
} else {
gnd, err = Setup(cctx.Context, cfg, priv, cdns)

Check warning on line 417 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L414-L417

Added lines #L414 - L417 were not covered by tests
}
if err != nil {
return err
}
Expand All @@ -389,11 +433,14 @@ share the same seed as long as the indexes are different.
Handler: handler,
}

pid, err := peer.IDFromPublicKey(priv.GetPublic())
if err != nil {
return err
fmt.Printf("Starting %s %s\n", name, version)
if priv != nil {
pid, err := peer.IDFromPublicKey(priv.GetPublic())
if err != nil {
return err

Check warning on line 440 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L436-L440

Added lines #L436 - L440 were not covered by tests
}
fmt.Printf("PeerID: %s\n\n", pid)

Check warning on line 442 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L442

Added line #L442 was not covered by tests
}
fmt.Printf("PeerID: %s\n\n", pid)
registerVersionMetric(version)
registerIpfsNodeCollector(gnd)

Expand Down
Loading

0 comments on commit ce5155a

Please sign in to comment.