1
vendor/github.com/status-im/rendezvous/.gitignore
generated
vendored
Normal file
1
vendor/github.com/status-im/rendezvous/.gitignore
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
vendor/
|
||||
15
vendor/github.com/status-im/rendezvous/.travis.yml
generated
vendored
Normal file
15
vendor/github.com/status-im/rendezvous/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
notifications:
|
||||
email: false
|
||||
language: go
|
||||
go:
|
||||
- 1.11.x
|
||||
- 1.12.x
|
||||
install: true
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
sudo: false
|
||||
jobs:
|
||||
include:
|
||||
- stage: Unit tests
|
||||
script:
|
||||
- make test
|
||||
13
vendor/github.com/status-im/rendezvous/Dockerfile
generated
vendored
Normal file
13
vendor/github.com/status-im/rendezvous/Dockerfile
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
FROM golang:1.17.0-alpine as builder
|
||||
|
||||
RUN apk add --no-cache gcc musl-dev linux-headers
|
||||
|
||||
RUN mkdir -p /go/src/github.com/status-im/rendezvous
|
||||
ADD . /go/src/github.com/status-im/rendezvous
|
||||
RUN cd /go/src/github.com/status-im/rendezvous && go build -o rendezvous ./cmd/server/
|
||||
|
||||
FROM alpine:latest
|
||||
|
||||
RUN apk add --no-cache ca-certificates bash
|
||||
|
||||
COPY --from=builder /go/src/github.com/status-im/rendezvous/rendezvous /usr/local/bin/rendezvous
|
||||
16
vendor/github.com/status-im/rendezvous/Makefile
generated
vendored
Normal file
16
vendor/github.com/status-im/rendezvous/Makefile
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
test:
|
||||
go test ./...
|
||||
|
||||
image: AUTHOR = $(shell echo $$USER)
|
||||
image: GIT_COMMIT = $(shell tag=`git describe --exact-match --tag 2>/dev/null`; \
|
||||
if [ $$? -eq 0 ]; then echo $$tag | sed 's/^v\(.*\)$$/\1/'; \
|
||||
else git rev-parse --short HEAD; fi)
|
||||
image:
|
||||
docker build . \
|
||||
--label "commit=$(GIT_COMMIT)" \
|
||||
--label "author=$(AUTHOR)" \
|
||||
-t statusteam/rendezvous:$(GIT_COMMIT) \
|
||||
-t statusteam/rendezvous:latest
|
||||
|
||||
push:
|
||||
docker push statusteam/rendezvous:latest
|
||||
48
vendor/github.com/status-im/rendezvous/README.md
generated
vendored
Normal file
48
vendor/github.com/status-im/rendezvous/README.md
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
Rendezvous server
|
||||
=================
|
||||
|
||||
In order to build a docker image, run:
|
||||
|
||||
```bash
|
||||
make image
|
||||
```
|
||||
|
||||
Server usage:
|
||||
|
||||
```
|
||||
-a, --address string listener ip address (default "0.0.0.0")
|
||||
-d, --data string path where ENR infos will be stored. (default "/tmp/rendevouz")
|
||||
-g, --generate dump private key and exit.
|
||||
-h, --keyhex string private key hex
|
||||
-k, --keypath string path to load private key
|
||||
-p, --port int listener port (default 9090)
|
||||
-v, --verbosity string verbosity level, options: crit, error, warning, info, debug (default "info")
|
||||
```
|
||||
|
||||
Option `-g` can be used to generate hex of the private key for convenience.
|
||||
Option `-h` should be used only in tests.
|
||||
|
||||
The only mandatory parameter is keypath `-k`, and not mandatory but i suggest to change data path `-d` not to a temporary
|
||||
directory.
|
||||
|
||||
|
||||
# Differences with original rendezvous
|
||||
|
||||
Original rendezvous description by members of libp2p team - [rendezvous](https://github.com/libp2p/specs/pull/56).
|
||||
We are using current implementation for a similar purposes, but mainly as a light-peer discovery protocol for mobile
|
||||
devices. Discovery v5 that depends on the kademlia implementation was too slow for mobile and consumed noticeable amount
|
||||
of traffic to find peers.
|
||||
|
||||
Some differences with original implementation:
|
||||
1. We are using ENR ([Ethereum Node Records](https://eips.ethereum.org/EIPS/eip-778)) for encoding information
|
||||
about peers. ENR must be signed.
|
||||
2. We are using RLP instead of protobuf. Mainly for convenience, because ENR already had util for rlp serialization.
|
||||
3. Smaller liveness TTL for records. At the time of writing liveness TTL is set to be 20s.
|
||||
This way we want to provide minimal guarantees that peer is online and dialable.
|
||||
4. ENRs are fetched from storage randomly. And we don't provide a way to fetch "new" records.
|
||||
It was done as a naive measure against spamming rendezvous servers with invalid records.
|
||||
And at the same time spread load of new peers between multiple servers.
|
||||
5. We don't use UNREGISTER request, since we assume that TTL is very low.
|
||||
|
||||
Those are mostly implementation details while idea is pretty much the same, but it is important to note that this implementation
|
||||
is not compatible with one from libp2p team.
|
||||
178
vendor/github.com/status-im/rendezvous/client.go
generated
vendored
Normal file
178
vendor/github.com/status-im/rendezvous/client.go
generated
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
package rendezvous
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/p2p/enr"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
libp2p "github.com/libp2p/go-libp2p"
|
||||
"github.com/libp2p/go-libp2p/core/crypto"
|
||||
"github.com/libp2p/go-libp2p/core/host"
|
||||
"github.com/libp2p/go-libp2p/core/network"
|
||||
"github.com/libp2p/go-libp2p/core/peer"
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
ethv4 "github.com/status-im/go-multiaddr-ethv4"
|
||||
"github.com/status-im/rendezvous/protocol"
|
||||
)
|
||||
|
||||
var logger = log.New("package", "rendezvous/client")
|
||||
|
||||
func NewEphemeral() (c Client, err error) {
|
||||
priv, _, err := crypto.GenerateKeyPairWithReader(crypto.Secp256k1, 0, rand.Reader) // bits are ignored with edwards or secp251k1
|
||||
if err != nil {
|
||||
return Client{}, err
|
||||
}
|
||||
return New(priv)
|
||||
}
|
||||
|
||||
func New(identity crypto.PrivKey) (c Client, err error) {
|
||||
opts := []libp2p.Option{
|
||||
libp2p.Identity(identity),
|
||||
}
|
||||
h, err := libp2p.New(opts...)
|
||||
if err != nil {
|
||||
return c, err
|
||||
}
|
||||
return Client{
|
||||
h: h,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewWithHost(h host.Host) (c Client, err error) {
|
||||
return Client{
|
||||
h: h,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
h host.Host
|
||||
}
|
||||
|
||||
func (c Client) Register(ctx context.Context, srv ma.Multiaddr, topic string, record enr.Record, ttl time.Duration) error {
|
||||
s, err := c.newStream(ctx, srv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.Close()
|
||||
if err = rlp.Encode(s, protocol.REGISTER); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = rlp.Encode(s, protocol.Register{Topic: topic, Record: record, TTL: uint64(ttl)}); err != nil {
|
||||
return err
|
||||
}
|
||||
rs := rlp.NewStream(s, 0)
|
||||
typ, err := rs.Uint()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if protocol.MessageType(typ) != protocol.REGISTER_RESPONSE {
|
||||
return fmt.Errorf("expected %v as response, but got %v", protocol.REGISTER_RESPONSE, typ)
|
||||
}
|
||||
var val protocol.RegisterResponse
|
||||
if err = rs.Decode(&val); err != nil {
|
||||
return err
|
||||
}
|
||||
logger.Debug("received response to register", "status", val.Status, "message", val.Message)
|
||||
if val.Status != protocol.OK {
|
||||
return fmt.Errorf("register failed. status code %v", val.Status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c Client) Discover(ctx context.Context, srv ma.Multiaddr, topic string, limit int) (rst []enr.Record, err error) {
|
||||
s, err := c.newStream(ctx, srv)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
if err = rlp.Encode(s, protocol.DISCOVER); err != nil {
|
||||
return
|
||||
}
|
||||
if err = rlp.Encode(s, protocol.Discover{Topic: topic, Limit: uint(limit)}); err != nil {
|
||||
return
|
||||
}
|
||||
rs := rlp.NewStream(s, 0)
|
||||
typ, err := rs.Uint()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if protocol.MessageType(typ) != protocol.DISCOVER_RESPONSE {
|
||||
return nil, fmt.Errorf("expected %v as response, but got %v", protocol.REGISTER_RESPONSE, typ)
|
||||
}
|
||||
var val protocol.DiscoverResponse
|
||||
if err = rs.Decode(&val); err != nil {
|
||||
return
|
||||
}
|
||||
if val.Status != protocol.OK {
|
||||
return nil, fmt.Errorf("discover request failed. status code %v", val.Status)
|
||||
}
|
||||
logger.Debug("received response to discover request", "status", val.Status, "records lth", len(val.Records))
|
||||
return val.Records, nil
|
||||
}
|
||||
|
||||
func (c Client) RemoteIp(ctx context.Context, srv ma.Multiaddr) (value string, err error) {
|
||||
s, err := c.newStream(ctx, srv)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
if err = rlp.Encode(s, protocol.REMOTEIP); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
rs := rlp.NewStream(s, 0)
|
||||
typ, err := rs.Uint()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if protocol.MessageType(typ) != protocol.REMOTEIP_RESPONSE {
|
||||
err = fmt.Errorf("expected %v as response, but got %v", protocol.REMOTEIP_RESPONSE, typ)
|
||||
return
|
||||
}
|
||||
var val protocol.RemoteIpResponse
|
||||
if err = rs.Decode(&val); err != nil {
|
||||
return
|
||||
}
|
||||
if val.Status != protocol.OK {
|
||||
err = fmt.Errorf("remoteip request failed. status code %v", val.Status)
|
||||
return
|
||||
}
|
||||
logger.Debug("received response to remoteip request", "status", val.Status, "ip", val.IP)
|
||||
value = val.IP
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c Client) newStream(ctx context.Context, srv ma.Multiaddr) (rw network.Stream, err error) {
|
||||
pid, err := srv.ValueForProtocol(ethv4.P_ETHv4)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
peerid, err := peer.Decode(pid)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// TODO there must be a better interface
|
||||
targetPeerAddr, err := ma.NewMultiaddr(fmt.Sprintf("/ethv4/%s", pid))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
targetAddr := srv.Decapsulate(targetPeerAddr)
|
||||
c.h.Peerstore().AddAddr(peerid, targetAddr, 5*time.Second)
|
||||
s, err := c.h.NewStream(ctx, peerid, "/rend/0.1.0")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &InstrumentedStream{s}, nil
|
||||
}
|
||||
|
||||
// Close shutdowns the host and all open connections.
|
||||
func (c Client) Close() error {
|
||||
return c.h.Close()
|
||||
}
|
||||
58
vendor/github.com/status-im/rendezvous/protocol/protocol.go
generated
vendored
Normal file
58
vendor/github.com/status-im/rendezvous/protocol/protocol.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/p2p/enr"
|
||||
)
|
||||
|
||||
type ResponseStatus uint
|
||||
type MessageType uint64
|
||||
|
||||
const (
|
||||
VERSION = "/rend/0.1.0"
|
||||
|
||||
REGISTER MessageType = iota
|
||||
REGISTER_RESPONSE
|
||||
DISCOVER
|
||||
DISCOVER_RESPONSE
|
||||
REMOTEIP
|
||||
REMOTEIP_RESPONSE
|
||||
|
||||
OK ResponseStatus = 0
|
||||
E_INVALID_NAMESPACE ResponseStatus = 100
|
||||
E_INVALID_ENR ResponseStatus = 101
|
||||
E_INVALID_TTL ResponseStatus = 102
|
||||
E_INVALID_LIMIT ResponseStatus = 103
|
||||
E_INVALID_CONTENT ResponseStatus = 104
|
||||
E_NOT_AUTHORIZED ResponseStatus = 200
|
||||
E_INTERNAL_ERROR ResponseStatus = 300
|
||||
)
|
||||
|
||||
type Register struct {
|
||||
Topic string
|
||||
Record enr.Record
|
||||
TTL uint64
|
||||
}
|
||||
|
||||
type RegisterResponse struct {
|
||||
Status ResponseStatus
|
||||
Message string
|
||||
}
|
||||
|
||||
type Discover struct {
|
||||
Limit uint
|
||||
Topic string
|
||||
}
|
||||
|
||||
type DiscoverResponse struct {
|
||||
Status ResponseStatus
|
||||
Message string
|
||||
Records []enr.Record
|
||||
}
|
||||
|
||||
type RemoteIp struct {
|
||||
}
|
||||
|
||||
type RemoteIpResponse struct {
|
||||
Status ResponseStatus
|
||||
IP string
|
||||
}
|
||||
83
vendor/github.com/status-im/rendezvous/stream.go
generated
vendored
Normal file
83
vendor/github.com/status-im/rendezvous/stream.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
package rendezvous
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
"github.com/libp2p/go-libp2p/core/network"
|
||||
"github.com/libp2p/go-libp2p/core/protocol"
|
||||
)
|
||||
|
||||
var (
|
||||
ingressTrafficMeter = metrics.NewRegisteredMeter("rendezvous/InboundTraffic", nil)
|
||||
egressTrafficMeter = metrics.NewRegisteredMeter("rendezvous/OutboundTraffic", nil)
|
||||
)
|
||||
|
||||
// InstrumentedStream implements read writer interface and collects metrics.
|
||||
type InstrumentedStream struct {
|
||||
s network.Stream
|
||||
}
|
||||
|
||||
func (si InstrumentedStream) CloseWrite() error {
|
||||
return si.s.CloseWrite()
|
||||
}
|
||||
|
||||
func (si InstrumentedStream) CloseRead() error {
|
||||
return si.s.CloseRead()
|
||||
}
|
||||
|
||||
func (si InstrumentedStream) ID() string {
|
||||
return si.s.ID()
|
||||
}
|
||||
|
||||
func (si InstrumentedStream) Write(p []byte) (int, error) {
|
||||
n, err := si.s.Write(p)
|
||||
egressTrafficMeter.Mark(int64(n))
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (si InstrumentedStream) Read(p []byte) (int, error) {
|
||||
n, err := si.s.Read(p)
|
||||
ingressTrafficMeter.Mark(int64(n))
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (si InstrumentedStream) Close() error {
|
||||
return si.s.Close()
|
||||
}
|
||||
|
||||
func (si InstrumentedStream) Reset() error {
|
||||
return si.s.Reset()
|
||||
}
|
||||
|
||||
func (si InstrumentedStream) SetDeadline(timeout time.Time) error {
|
||||
return si.s.SetDeadline(timeout)
|
||||
}
|
||||
|
||||
func (si InstrumentedStream) SetReadDeadline(timeout time.Time) error {
|
||||
return si.s.SetReadDeadline(timeout)
|
||||
}
|
||||
|
||||
func (si InstrumentedStream) SetWriteDeadline(timeout time.Time) error {
|
||||
return si.s.SetWriteDeadline(timeout)
|
||||
}
|
||||
|
||||
func (si InstrumentedStream) Protocol() protocol.ID {
|
||||
return si.s.Protocol()
|
||||
}
|
||||
|
||||
func (si InstrumentedStream) SetProtocol(pid protocol.ID) error {
|
||||
return si.s.SetProtocol(pid)
|
||||
}
|
||||
|
||||
func (si InstrumentedStream) Conn() network.Conn {
|
||||
return si.s.Conn()
|
||||
}
|
||||
|
||||
func (si InstrumentedStream) Stat() network.Stats {
|
||||
return si.s.Stat()
|
||||
}
|
||||
|
||||
func (si InstrumentedStream) Scope() network.StreamScope {
|
||||
return si.s.Scope()
|
||||
}
|
||||
Reference in New Issue
Block a user