mirror of https://github.com/status-im/go-waku.git
chore: add docs. pt - 1 (#230)
This commit is contained in:
parent
bbab0f1714
commit
3a0fc81889
15
README.md
15
README.md
|
@ -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
|
||||
|
|
|
@ -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 Push’s 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
|
||||
|
||||
|
||||
|
|
@ -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 Relay’s 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
|
||||
|
|
@ -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...)
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue