chore: add docs. pt - 1 (#230)

This commit is contained in:
Richard Ramos 2022-05-04 17:08:24 -04:00 committed by GitHub
parent bbab0f1714
commit 3a0fc81889
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 241 additions and 2 deletions

View File

@ -49,8 +49,21 @@ make static-library
make dynamic-library
```
## Tutorials and documentation
- [Receive and send messages using Waku Relay](docs/relay.md)
- [Send messages using Waku Lightpush](docs/lightpush.md)
- [C Bindings](library/README.md)
## Examples
Examples of usage of go-waku as a library can be found in the examples folder. There is a fully featured chat example.
Examples of usage of go-waku as a library can be found in the `examples/` folder:
- [**basic2**](../examples/basic2) - demonstrates how to send and receive messages
- [**chat2**](../examples/chat2) - simple chat client using waku relay / lightpush + filter / store protocol to send/receive messages and retrieve message history
- [**filter2**](../examples/filter2) - demonstrates how to use filter protocol
- [**c-bindings**](../examples/c-bindings) - simple program to demonstrate how to consume the go-waku library via C FFI
- [**waku-csharp**](../examples/csharp) - C# console application that uses the go-waku library via FFI
- [**android-kotlin**](../examples/android-kotlin) - android app that uses a .jar generated by gomobile using kotlin
## Waku Protocol Support

88
docs/lightpush.md Normal file
View File

@ -0,0 +1,88 @@
Send messages using Waku Lightpush
===
Waku Light Push enables a client to receive a confirmation when sending a message.
The Waku Relay protocol sends messages to connected peers but does not provide any information on whether said peers have received messages. This can be an issue when facing potential connectivity issues. For example, when the connection drops easily, or it is connected to a small number of relay peers.
Waku Light Push allows a client to get a response from a remote peer when sending a message. Note this only guarantees that the remote peer has received the message, it cannot guarantee propagation to the network.
It also means weaker privacy properties as the remote peer knows the client is the originator of the message. Whereas with Waku Relay, a remote peer would not know whether the client created or forwarded the message.
You can find Waku Light Pushs specifications on [Vac RFC](https://rfc.vac.dev/spec/19/).
## Create a waku instance
```go
package main
import (
"context"
"fmt"
"github.com/status-im/go-waku/waku/v2/node"
"github.com/status-im/go-waku/waku/v2/protocol/lightpush"
)
...
wakuNode, err := node.New(context.Background(),
node.WithLightPush(),
)
if err != nil {
fmt.Println(err)
return
}
if err := wakuNode.Start(); err != nil {
fmt.Println(err)
return
}
...
```
> If the node also has the relay protocol enabled, it will be able to receive lightpush request to broadcast messages to other relay nodes
## Sending messages
```go
import (
"github.com/status-im/go-waku/waku/v2/protocol/pb"
"github.com/status-im/go-waku/waku/v2/utils"
)
...
msg := &pb.WakuMessage{
Payload: []byte("Hello World"),
Version: 0,
ContentTopic: protocol.NewContentTopic("basic2", 1, "test", "proto").String(),
Timestamp: utils.GetUnixEpoch(),
}
msgId, err = wakuNode.Lightpush().Publish(context.Background(), msg)
if err != nil {
log.Error("Error sending a message: ", err)
}
```
To send a message, it needs to be wrapped into a [`WakuMessage`](https://rfc.vac.dev/spec/14/) protobuffer. The payload of the message is not limited to strings. Any kind of data that can be serialized
into a `[]byte` can be sent as long as it does not exceed the maximum length a message can have (~1MB)
The following functions can be used to publish a message:
- `wakuNode.Lightpush().Publish(ctx, msg, opts...)` - to send a message to the default waku pubsub topic
- `wakuNode.Lightpush().PublishToTopic(ctx, msg, topic, opts...)` - to send a message to a custom pubsub topic
Both of these functions will return a message id on success, or an error if the message could not be published.
If no options are specified, go-waku will automatically choose the peer used to broadcast the message via Lightpush. This behaviour can be controlled via options:
### Options
- `lightpush.WithPeer(peerID)` - use an specific peer ID (which should be part of the node peerstore) to broadcast the message with
- `lightpush.WithAutomaticPeerSelection(host)` - automatically select a peer that supports lightpush protocol from the peerstore to broadcast the message with
- `lightpush.WithFastestPeerSelection(ctx)` - automatically select a peer based on its ping reply time

120
docs/relay.md Normal file
View File

@ -0,0 +1,120 @@
Receive and send messages using Waku Relay
===
Waku Relay is a gossip protocol that enables you to send and receive messages. You can find Waku Relays specifications on [Vac RFC](https://rfc.vac.dev/spec/11/).
## Create a waku instance
```go
package main
import (
"context"
"fmt"
"github.com/status-im/go-waku/waku/v2/node"
"github.com/status-im/go-waku/waku/v2/protocol/relay"
)
...
wakuNode, err := node.New(context.Background(),
node.WithWakuRelay(),
)
if err != nil {
fmt.Println(err)
return
}
if err := wakuNode.Start(); err != nil {
fmt.Println(err)
return
}
...
```
### Options
One of these options must be specified when instantiating a node supporting the waku relay protocol
- `WithWakuRelay(opts ...pubsub.Option)` - enables the waku relay protocol and receives an optional list of pubsub options to tune or configure the gossipsub parameters. Supported options can be seen [here](https://pkg.go.dev/github.com/libp2p/go-libp2p-pubsub#Option). The recommended [parameter configuration](https://rfc.vac.dev/spec/29/) is used by default.
- `WithWakuRelayAndMinPeers(minRelayPeersToPublish int, opts ...pubsub.Option)` - enables the waku relay protocol, specifying the minimum number of peers a topic should have to send a message. It also receives an optional list of pubsub [options](https://pkg.go.dev/github.com/libp2p/go-libp2p-pubsub#Option)
## Receiving messages
```go
...
sub, err := wakuNode.Relay().Subscribe(context.Background())
if err != nil {
fmt.Println(err)
return
}
for value := range sub.C {
fmt.Println("Received msg:", string(value.Message().Payload))
}
...
```
To receive messages sent via the relay protocol, you need to subscribe to a pubsub topic. This can be done via any of these functions:
- `wakuNode.Relay().Subscribe(ctx)` - subscribes to the default waku pubsub topic `/waku/2/default-waku/proto`
- `wakuNode.Relay().SubscribeToTopic(ctx, topic)` - subscribes to a custom pubsub topic
These functions return a `Subscription` struct containing a channel on which messages will be received. To stop receiving messages in this channel `sub.Unsubscribe()` can be executed which will close the channel (without unsubscribing from the pubsub topic)
> Pubsub topics should follow the [recommended usage](https://rfc.vac.dev/spec/23/) structure. For this purpose, the `NewPubsubTopic` helper function was created:
```go
import "github.com/status-im/go-waku/waku/v2/protocol"
topic := protocol.NewPubsubTopic("the_topic_name", "the_encoding")
/*
fmt.Println(topic.String()) // => `/waku/2/the_topic_name/the_encoding`
*/
```
## Sending messages
```go
import (
"github.com/status-im/go-waku/waku/v2/protocol/pb"
"github.com/status-im/go-waku/waku/v2/utils"
)
...
msg := &pb.WakuMessage{
Payload: []byte("Hello World"),
Version: 0,
ContentTopic: protocol.NewContentTopic("basic2", 1, "test", "proto").String(),
Timestamp: utils.GetUnixEpoch(),
}
msgId, err = wakuNode.Relay().Publish(context.Background(), msg)
if err != nil {
log.Error("Error sending a message: ", err)
}
```
To send a message, it needs to be wrapped into a [`WakuMessage`](https://rfc.vac.dev/spec/14/) protobuffer. The payload of the message is not limited to strings. Any kind of data that can be serialized
into a `[]byte` can be sent as long as it does not exceed the maximum length a message can have (~1MB)
The following functions can be used to publish a message:
- `wakuNode.Relay().Publish(ctx, msg)` - to send a message to the default waku pubsub topic
- `wakuNode.Relay().PublishToTopic(ctx, msg, topic)` - to send a message to a custom pubsub topic
Both of these functions will return a message id on success, or an error if the message could not be published.
> If `WithWakuRelayAndMinPeers` was used during the instantiation of the wakuNode, it should be possible to verify if there's enough peers for publishing to a topic with `wakuNode.Relay().EnoughPeersToPublish()` and `wakuNode.Relay().EnoughPeersToPublishToTopic(topic)`
## Stop receiving messages
```go
...
err := wakuNode.Relay().Unsubscribe(context.Background(), theTopic)
if err != nil {
fmt.Println(err)
return
}
...
```
> To stop receiving messages from the default topic, use `relay.DefaultWakuTopic` as the topic parameter

View File

@ -35,6 +35,7 @@ type WakuLightPush struct {
started bool
}
// NewWakuRelay returns a new instance of Waku Lightpush struct
func NewWakuLightPush(ctx context.Context, h host.Host, relay *relay.WakuRelay, log *zap.SugaredLogger) *WakuLightPush {
wakuLP := new(WakuLightPush)
wakuLP.relay = relay
@ -45,6 +46,7 @@ func NewWakuLightPush(ctx context.Context, h host.Host, relay *relay.WakuRelay,
return wakuLP
}
// Start inits the lighpush protocol
func (wakuLP *WakuLightPush) Start() error {
if wakuLP.IsClientOnly() {
return errors.New("relay is required, without it, it is only a client and cannot be started")
@ -57,6 +59,7 @@ func (wakuLP *WakuLightPush) Start() error {
return nil
}
// IsClientOnly determines if this node supports relaying messages for other lightpush clients
func (wakuLp *WakuLightPush) IsClientOnly() bool {
return wakuLp.relay == nil
}
@ -189,15 +192,18 @@ func (wakuLP *WakuLightPush) request(ctx context.Context, req *pb.PushRequest, o
return pushResponseRPC.Response, nil
}
// IsStarted returns if the lightpush protocol has been mounted or not
func (wakuLP *WakuLightPush) IsStarted() bool {
return wakuLP.started
}
// Stop unmounts the lightpush protocol
func (wakuLP *WakuLightPush) Stop() {
wakuLP.h.RemoveStreamHandler(LightPushID_v20beta1)
wakuLP.started = false
}
// PublishToTopic is used to broadcast a WakuMessage to a pubsub topic via lightpush protocol
func (wakuLP *WakuLightPush) PublishToTopic(ctx context.Context, message *pb.WakuMessage, topic string, opts ...LightPushOption) ([]byte, error) {
if message == nil {
return nil, errors.New("message can't be null")
@ -220,6 +226,7 @@ func (wakuLP *WakuLightPush) PublishToTopic(ctx context.Context, message *pb.Wak
}
}
// Publish is used to broadcast a WakuMessage to the default waku pubsub topic via lightpush protocol
func (wakuLP *WakuLightPush) Publish(ctx context.Context, message *pb.WakuMessage, opts ...LightPushOption) ([]byte, error) {
return wakuLP.PublishToTopic(ctx, message, relay.DefaultWakuTopic, opts...)
}

View File

@ -46,12 +46,12 @@ type WakuRelay struct {
subscriptionsMutex sync.Mutex
}
// Once https://github.com/status-im/nim-waku/issues/420 is fixed, implement a custom messageIdFn
func msgIdFn(pmsg *pubsub_pb.Message) string {
hash := sha256.Sum256(pmsg.Data)
return string(hash[:])
}
// NewWakuRelay returns a new instance of a WakuRelay struct
func NewWakuRelay(ctx context.Context, h host.Host, bcaster v2.Broadcaster, minPeersToPublish int, log *zap.SugaredLogger, opts ...pubsub.Option) (*WakuRelay, error) {
w := new(WakuRelay)
w.host = h
@ -92,10 +92,12 @@ func NewWakuRelay(ctx context.Context, h host.Host, bcaster v2.Broadcaster, minP
return w, nil
}
// PubSub returns the implementation of the pubsub system
func (w *WakuRelay) PubSub() *pubsub.PubSub {
return w.pubsub
}
// Topics returns a list of all the pubsub topics currently subscribed to
func (w *WakuRelay) Topics() []string {
defer w.topicsMutex.Unlock()
w.topicsMutex.Lock()
@ -107,6 +109,7 @@ func (w *WakuRelay) Topics() []string {
return result
}
// SetPubSub is used to set an aimplementation of the pubsub system
func (w *WakuRelay) SetPubSub(pubSub *pubsub.PubSub) {
w.pubsub = pubSub
}
@ -147,6 +150,7 @@ func (w *WakuRelay) subscribe(topic string) (subs *pubsub.Subscription, err erro
return sub, nil
}
// PublishToTopic is used to broadcast a WakuMessage to a pubsub topic
func (w *WakuRelay) PublishToTopic(ctx context.Context, message *pb.WakuMessage, topic string) ([]byte, error) {
// Publish a `WakuMessage` to a PubSub topic.
if w.pubsub == nil {
@ -182,10 +186,12 @@ func (w *WakuRelay) PublishToTopic(ctx context.Context, message *pb.WakuMessage,
return hash, nil
}
// Publish is used to broadcast a WakuMessage to the default waku pubsub topic
func (w *WakuRelay) Publish(ctx context.Context, message *pb.WakuMessage) ([]byte, error) {
return w.PublishToTopic(ctx, message, DefaultWakuTopic)
}
// Stop unmounts the relay protocol and stops all subscriptions
func (w *WakuRelay) Stop() {
w.host.RemoveStreamHandler(WakuRelayID_v200)
w.subscriptionsMutex.Lock()
@ -199,14 +205,17 @@ func (w *WakuRelay) Stop() {
w.subscriptions = nil
}
// EnoughPeersToPublish returns whether there are enough peers connected in the default waku pubsub topic
func (w *WakuRelay) EnoughPeersToPublish() bool {
return w.EnoughPeersToPublishToTopic(DefaultWakuTopic)
}
// EnoughPeersToPublish returns whether there are enough peers connected in a pubsub topic
func (w *WakuRelay) EnoughPeersToPublishToTopic(topic string) bool {
return len(w.PubSub().ListPeers(topic)) >= w.minPeersToPublish
}
// SubscribeToTopic returns a Subscription to receive messages from a pubsub topic
func (w *WakuRelay) SubscribeToTopic(ctx context.Context, topic string) (*Subscription, error) {
// Subscribes to a PubSub topic.
// NOTE The data field SHOULD be decoded as a WakuMessage.
@ -236,10 +245,12 @@ func (w *WakuRelay) SubscribeToTopic(ctx context.Context, topic string) (*Subscr
return subscription, nil
}
// SubscribeToTopic returns a Subscription to receive messages from the default waku pubsub topic
func (w *WakuRelay) Subscribe(ctx context.Context) (*Subscription, error) {
return w.SubscribeToTopic(ctx, DefaultWakuTopic)
}
// Unsubscribe closes a subscription to a pubsub topic
func (w *WakuRelay) Unsubscribe(ctx context.Context, topic string) error {
if _, ok := w.relaySubs[topic]; !ok {
return fmt.Errorf("topics %s is not subscribed", (string)(topic))