Skip to content

Commit

Permalink
feat: seed-based automatic peering
Browse files Browse the repository at this point in the history
  • Loading branch information
hacdias committed Apr 17, 2024
1 parent c011630 commit 3b34fc8
Show file tree
Hide file tree
Showing 5 changed files with 323 additions and 123 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ require (
github.com/libp2p/go-libp2p-kad-dht v0.25.2
github.com/libp2p/go-libp2p-record v0.2.0
github.com/libp2p/go-libp2p-routing-helpers v0.7.3
github.com/libp2p/go-libp2p-testing v0.12.0
github.com/mitchellh/go-server-timing v1.0.1
github.com/mr-tron/base58 v1.2.0
github.com/multiformats/go-multiaddr v0.12.2
Expand Down
29 changes: 28 additions & 1 deletion keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"io"

libp2p "github.com/libp2p/go-libp2p/core/crypto"
peer "github.com/libp2p/go-libp2p/core/peer"
"github.com/mr-tron/base58"
"golang.org/x/crypto/hkdf"
)
Expand All @@ -25,7 +26,7 @@ func newSeed() (string, error) {
return base58.Encode(bs), nil
}

// derive derives libp2p keys from a b58-encoded seed.
// deriveKey derives libp2p keys from a b58-encoded seed.
func deriveKey(b58secret string, info []byte) (libp2p.PrivKey, error) {
secret, err := base58.Decode(b58secret)
if err != nil {
Expand All @@ -45,6 +46,32 @@ func deriveKey(b58secret string, info []byte) (libp2p.PrivKey, error) {
return libp2p.UnmarshalEd25519PrivateKey(key)
}

// derivePeerIDs derives the peer IDs of all the peers with the same seed up to
// maxIndex. Our peer ID (with index 'ourIndex') is not generated.
func derivePeerIDs(seed string, ourIndex int, maxIndex int) ([]peer.ID, error) {
peerIDs := []peer.ID{}

Check warning on line 52 in keys.go

View check run for this annotation

Codecov / codecov/patch

keys.go#L51-L52

Added lines #L51 - L52 were not covered by tests

for i := 0; i <= maxIndex; i++ {
if i == ourIndex {
continue

Check warning on line 56 in keys.go

View check run for this annotation

Codecov / codecov/patch

keys.go#L54-L56

Added lines #L54 - L56 were not covered by tests
}

peerPriv, err := deriveKey(seed, deriveKeyInfo(i))
if err != nil {
return nil, err

Check warning on line 61 in keys.go

View check run for this annotation

Codecov / codecov/patch

keys.go#L59-L61

Added lines #L59 - L61 were not covered by tests
}

pid, err := peer.IDFromPrivateKey(peerPriv)
if err != nil {
return nil, err

Check warning on line 66 in keys.go

View check run for this annotation

Codecov / codecov/patch

keys.go#L64-L66

Added lines #L64 - L66 were not covered by tests
}

peerIDs = append(peerIDs, pid)

Check warning on line 69 in keys.go

View check run for this annotation

Codecov / codecov/patch

keys.go#L69

Added line #L69 was not covered by tests
}

return peerIDs, nil

Check warning on line 72 in keys.go

View check run for this annotation

Codecov / codecov/patch

keys.go#L72

Added line #L72 was not covered by tests
}

func deriveKeyInfo(index int) []byte {
return []byte(fmt.Sprintf("rainbow-%d", index))
}
31 changes: 31 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,18 @@ Generate an identity seed and launch a gateway:
EnvVars: []string{"RAINBOW_SEED_INDEX"},
Usage: "Index to derivate the peerID (needs --seed)",
},
&cli.BoolFlag{
Name: "seed-peering",
Value: false,
EnvVars: []string{"RAINBOW_SEED_PEERING"},
Usage: "Automatic peering with peers with the same seed (requires --seed and --seed-index). Runs a separate light DHT for peer routing with the main host if --dht-routing or --dht-shared-host are disabled",
},
&cli.UintFlag{
Name: "seed-peering-max-index",
Value: 100,
EnvVars: []string{"RAINBOW_SEED_PEERING_MAX_INDEX"},
Usage: "Largest index to derive automatic peering peer IDs for",
},

Check warning on line 105 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L94-L105

Added lines #L94 - L105 were not covered by tests
&cli.StringSliceFlag{
Name: "gateway-domains",
Value: cli.NewStringSlice(),
Expand Down Expand Up @@ -315,6 +327,24 @@ share the same seed as long as the indexes are different.
peeringAddrs = append(peeringAddrs, *ai)
}

if cctx.Bool("seed-peering") {
if !cctx.IsSet("seed") || !cctx.IsSet("seed-index") {
return errors.New("--seed and --seed-index must be explicitly defined when --seed-peering is enabled")

Check warning on line 332 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L330-L332

Added lines #L330 - L332 were not covered by tests
}

maxIndex := cctx.Uint("seed-peering-max-index")
peeringIDs, err := derivePeerIDs(seed, index, int(maxIndex))
if err != nil {
return err

Check warning on line 338 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L335-L338

Added lines #L335 - L338 were not covered by tests
}

for _, pid := range peeringIDs {

Check warning on line 341 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L341

Added line #L341 was not covered by tests
// The peering module will automatically perform lookups to find the
// addresses of the given peers.
peeringAddrs = append(peeringAddrs, peer.AddrInfo{ID: pid})

Check warning on line 344 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L344

Added line #L344 was not covered by tests
}
}

cfg := Config{
DataDir: ddir,
BlockstoreType: cctx.String("blockstore"),
Expand All @@ -334,6 +364,7 @@ share the same seed as long as the indexes are different.
DenylistSubs: cctx.StringSlice("denylists"),
Peering: peeringAddrs,
PeeringCache: cctx.Bool("peering-shared-cache"),
SeedPeering: cctx.Bool("seed-peering"),

Check warning on line 367 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L366-L367

Added lines #L366 - L367 were not covered by tests
GCInterval: cctx.Duration("gc-interval"),
GCThreshold: cctx.Float64("gc-threshold"),
}
Expand Down
Loading

0 comments on commit 3b34fc8

Please sign in to comment.