Implement waku/1
Why make the change? This implements waku/1 which is a breaking change as waku/0 diverged from the specs. What has changed? - Added v1 namespace - Changed the testing code to test from the outside rather than stubbing p2p specific messages, so that any version specific code is under `vx` namespaces - Split waku vs waku/x test code - Added a test suite that can be used for different versions Things still to do I kept the tests we have for the versioned aspect of waku, probably we want to add some or change other to provide the optimal test coverage.
This commit is contained in:
parent
8aa42e4148
commit
299b3fc093
|
@ -1,4 +1,3 @@
|
|||
### waku/1
|
||||
|
||||
This namespace implements `waku` 1.0 as described in https://github.com/vacp2p/specs/blob/master/specs/waku/waku-1.md.
|
||||
|
||||
This namespace implements `waku` 1.0 as described in https://github.com/vacp2p/specs/blob/master/specs/waku/waku-1.md
|
||||
|
|
|
@ -2,8 +2,8 @@ package v1
|
|||
|
||||
// Waku protocol parameters
|
||||
const (
|
||||
Version = uint64(0) // Peer version number
|
||||
VersionStr = "0" // The same, as a string
|
||||
Version = uint64(1) // Peer version number
|
||||
VersionStr = "1" // The same, as a string
|
||||
Name = "waku" // Nickname of the protocol
|
||||
|
||||
// Waku protocol message codes, according to https://github.com/vacp2p/specs/blob/master/specs/waku/waku-0.md
|
||||
|
|
|
@ -389,7 +389,7 @@ func (p *Peer) handshake() error {
|
|||
errc := make(chan error, 1)
|
||||
opts := StatusOptionsFromHost(p.host)
|
||||
go func() {
|
||||
errc <- p2p.SendItems(p.rw, statusCode, Version, opts)
|
||||
errc <- p2p.Send(p.rw, statusCode, opts)
|
||||
}()
|
||||
|
||||
// Fetch the remote status packet and verify protocol match
|
||||
|
@ -401,34 +401,21 @@ func (p *Peer) handshake() error {
|
|||
return fmt.Errorf("p [%x] sent packet %x before status packet", p.ID(), packet.Code)
|
||||
}
|
||||
|
||||
var (
|
||||
peerProtocolVersion uint64
|
||||
peerOptions StatusOptions
|
||||
)
|
||||
var peerOptions StatusOptions
|
||||
s := rlp.NewStream(packet.Payload, uint64(packet.Size))
|
||||
if _, err := s.List(); err != nil {
|
||||
return fmt.Errorf("p [%x]: failed to decode status packet: %v", p.ID(), err)
|
||||
}
|
||||
// Validate protocol version.
|
||||
if err := s.Decode(&peerProtocolVersion); err != nil {
|
||||
return fmt.Errorf("p [%x]: failed to decode peer protocol version: %v", p.ID(), err)
|
||||
}
|
||||
if peerProtocolVersion != Version {
|
||||
return fmt.Errorf("p [%x]: protocol version mismatch %d != %d", p.ID(), peerProtocolVersion, Version)
|
||||
}
|
||||
|
||||
// Decode and validate other status packet options.
|
||||
if err := s.Decode(&peerOptions); err != nil {
|
||||
return fmt.Errorf("p [%x]: failed to decode status options: %v", p.ID(), err)
|
||||
}
|
||||
if err := s.ListEnd(); err != nil {
|
||||
return fmt.Errorf("p [%x]: failed to decode status packet: %v", p.ID(), err)
|
||||
}
|
||||
if err := p.setOptions(peerOptions.WithDefaults()); err != nil {
|
||||
return fmt.Errorf("p [%x]: failed to set options: %v", p.ID(), err)
|
||||
}
|
||||
if err := <-errc; err != nil {
|
||||
return fmt.Errorf("p [%x] failed to send status packet: %v", p.ID(), err)
|
||||
}
|
||||
|
||||
_ = packet.Discard()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -19,11 +19,25 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
mrand "math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
|
||||
"github.com/status-im/status-go/waku/common"
|
||||
)
|
||||
|
||||
var seed int64
|
||||
|
||||
// initSingleTest should be called in the beginning of every
|
||||
// test, which uses RNG, in order to make the tests
|
||||
// reproduciblity independent of their sequence.
|
||||
func initSingleTest() {
|
||||
seed = time.Now().Unix()
|
||||
mrand.Seed(seed)
|
||||
}
|
||||
|
||||
var sharedTopic = common.TopicType{0xF, 0x1, 0x2, 0}
|
||||
var wrongTopic = common.TopicType{0, 0, 0, 0}
|
||||
|
||||
|
@ -58,3 +72,54 @@ func TestTopicOrBloomMatchFullNode(t *testing.T) {
|
|||
t.Fatal("envelope should not match")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPeerBasic(t *testing.T) {
|
||||
initSingleTest()
|
||||
|
||||
params, err := generateMessageParams()
|
||||
if err != nil {
|
||||
t.Fatalf("failed generateMessageParams with seed %d.", seed)
|
||||
}
|
||||
|
||||
params.PoW = 0.001
|
||||
msg, err := common.NewSentMessage(params)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create new message with seed %d: %s.", seed, err)
|
||||
}
|
||||
env, err := msg.Wrap(params, time.Now())
|
||||
if err != nil {
|
||||
t.Fatalf("failed Wrap with seed %d.", seed)
|
||||
}
|
||||
|
||||
p := NewPeer(nil, nil, nil, nil)
|
||||
p.Mark(env)
|
||||
if !p.Marked(env) {
|
||||
t.Fatalf("failed mark with seed %d.", seed)
|
||||
}
|
||||
}
|
||||
|
||||
func generateMessageParams() (*common.MessageParams, error) {
|
||||
// set all the parameters except p.Dst and p.Padding
|
||||
|
||||
buf := make([]byte, 4)
|
||||
mrand.Read(buf) // nolint: gosec
|
||||
sz := mrand.Intn(400)
|
||||
|
||||
var p common.MessageParams
|
||||
p.PoW = 0.01
|
||||
p.WorkTime = 1
|
||||
p.TTL = uint32(mrand.Intn(1024))
|
||||
p.Payload = make([]byte, sz)
|
||||
p.KeySym = make([]byte, common.AESKeyLength)
|
||||
mrand.Read(p.Payload) // nolint: gosec
|
||||
mrand.Read(p.KeySym) // nolint: gosec
|
||||
p.Topic = common.BytesToTopic(buf)
|
||||
|
||||
var err error
|
||||
p.Src, err = crypto.GenerateKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &p, nil
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
|
@ -14,7 +15,7 @@ import (
|
|||
)
|
||||
|
||||
// statusOptionKey is a current type used in StatusOptions as a key.
|
||||
type statusOptionKey string
|
||||
type statusOptionKey uint64
|
||||
|
||||
var (
|
||||
defaultMinPoW = math.Float64bits(0.001)
|
||||
|
@ -84,10 +85,14 @@ func initRLPKeyFields() {
|
|||
if len(keys) != 2 || keys[0] != "key" {
|
||||
panic("invalid value of \"rlp\" tag, expected \"key=N\" where N is uint")
|
||||
}
|
||||
key, err := strconv.ParseUint(keys[1], 10, 64)
|
||||
if err != nil {
|
||||
panic("could not parse \"rlp\" key")
|
||||
}
|
||||
|
||||
// typecast key to be of statusOptionKey type
|
||||
keyFieldIdx[statusOptionKey(keys[1])] = i
|
||||
idxFieldKey[i] = statusOptionKey(keys[1])
|
||||
keyFieldIdx[statusOptionKey(key)] = i
|
||||
idxFieldKey[i] = statusOptionKey(key)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,12 +189,12 @@ loop:
|
|||
// Read the rest of the list items and dump peer.
|
||||
_, err := s.Raw()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read the value of key %s: %v", key, err)
|
||||
return fmt.Errorf("failed to read the value of key %d: %v", key, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err := s.Decode(v.Elem().Field(idx).Addr().Interface()); err != nil {
|
||||
return fmt.Errorf("failed to decode an option %s: %v", key, err)
|
||||
return fmt.Errorf("failed to decode an option %d: %v", key, err)
|
||||
}
|
||||
if err := s.ListEnd(); err != nil {
|
||||
return err
|
||||
|
|
|
@ -38,7 +38,7 @@ func TestEncodeDecodeRLP(t *testing.T) {
|
|||
|
||||
func TestBackwardCompatibility(t *testing.T) {
|
||||
alist := []interface{}{
|
||||
[]interface{}{"0", math.Float64bits(2.05)},
|
||||
[]interface{}{uint64(0), math.Float64bits(2.05)},
|
||||
}
|
||||
data, err := rlp.EncodeToBytes(alist)
|
||||
require.NoError(t, err)
|
||||
|
@ -53,8 +53,8 @@ func TestBackwardCompatibility(t *testing.T) {
|
|||
func TestForwardCompatibility(t *testing.T) {
|
||||
pow := math.Float64bits(2.05)
|
||||
alist := []interface{}{
|
||||
[]interface{}{"0", pow},
|
||||
[]interface{}{"99", uint(10)}, // some future option
|
||||
[]interface{}{uint64(0), pow},
|
||||
[]interface{}{uint64(99), uint(10)}, // some future option
|
||||
}
|
||||
data, err := rlp.EncodeToBytes(alist)
|
||||
require.NoError(t, err)
|
||||
|
@ -67,20 +67,20 @@ func TestForwardCompatibility(t *testing.T) {
|
|||
|
||||
func TestInitRLPKeyFields(t *testing.T) {
|
||||
ifk := map[int]statusOptionKey{
|
||||
0: "0",
|
||||
1: "1",
|
||||
2: "2",
|
||||
3: "3",
|
||||
4: "4",
|
||||
5: "5",
|
||||
0: 0,
|
||||
1: 1,
|
||||
2: 2,
|
||||
3: 3,
|
||||
4: 4,
|
||||
5: 5,
|
||||
}
|
||||
kfi := map[statusOptionKey]int{
|
||||
"0": 0,
|
||||
"1": 1,
|
||||
"2": 2,
|
||||
"3": 3,
|
||||
"4": 4,
|
||||
"5": 5,
|
||||
0: 0,
|
||||
1: 1,
|
||||
2: 2,
|
||||
3: 3,
|
||||
4: 4,
|
||||
5: 5,
|
||||
}
|
||||
|
||||
// Test that the kfi length matches the inited global keyFieldIdx length
|
||||
|
|
Loading…
Reference in New Issue