Implemented RLP key field initialisation

This replaces the statically declared values, which previously replaced function varialbes see https://github.com/status-im/status-go/pull/1931#discussion_r406123786
This commit is contained in:
Samuel Hawksby-Robinson 2020-04-09 16:26:02 +01:00 committed by Andrea Maria Piana
parent 91e1bdc8ce
commit c16eba55f6
3 changed files with 72 additions and 61 deletions

View File

@ -7,6 +7,7 @@ import (
"math"
"reflect"
"strconv"
"strings"
"github.com/ethereum/go-ethereum/rlp"
)
@ -25,27 +26,13 @@ type statusOptionKeyToType struct {
const (
sOKTS statusOptionKeyType = iota + 1 // Status Option Key Type String
sOKTU // Status Option Key Type Uint
sOKTU // Status Option Key Type Uint
)
var (
defaultMinPoW = math.Float64bits(0.001)
idxFieldKey = map[int]statusOptionKey{
0: 0,
1: 1,
2: 2,
3: 3,
4: 4,
5: 5,
}
keyFieldIdx = map[statusOptionKey]int{
0: 0,
1: 1,
2: 2,
3: 3,
4: 4,
5: 5,
}
idxFieldKey = make(map[int]statusOptionKey)
keyFieldIdx = make(map[statusOptionKey]int)
)
type keyTypeMapping struct {
@ -69,6 +56,38 @@ type statusOptions struct {
keyTypeMapping keyTypeMapping
}
// initFLPKeyFields initialises the values of `idxFieldKey` and `keyFieldIdx`
func initRLPKeyFields() error {
o := statusOptions{}
v := reflect.ValueOf(o)
for i := 0; i < v.NumField(); i++ {
// skip unexported fields
if !v.Field(i).CanInterface() {
continue
}
rlpTag := v.Type().Field(i).Tag.Get("rlp")
// skip fields without rlp field tag
if rlpTag == "" {
continue
}
keys := strings.Split(rlpTag, "=")
// parse keys[1] as an int
key, err := strconv.ParseUint(keys[1], 10, 64)
if err != nil {
return fmt.Errorf("malformed rlp tag '%s', tag should be formatted 'rlp:\"key=0\"': %v", rlpTag, err)
}
// typecast key to be of statusOptionKey type
keyFieldIdx[statusOptionKey(key)] = i
idxFieldKey[i] = statusOptionKey(key)
}
return nil
}
// WithDefaults adds the default values for a given peer.
// This are not the host default values, but the default values that ought to
// be used when receiving from an update from a peer.

View File

@ -2,9 +2,6 @@ package waku
import (
"math"
"reflect"
"strconv"
"strings"
"testing"
"github.com/stretchr/testify/require"
@ -67,60 +64,47 @@ func TestForwardCompatibility(t *testing.T) {
require.EqualValues(t, statusOptions{PoWRequirement: &pow}, optsDecoded)
}
func TestStatusOptionKeys(t *testing.T) {
o := statusOptions{}
kfi := make(map[statusOptionKey]int)
ifk := make(map[int]statusOptionKey)
v := reflect.ValueOf(o)
for i := 0; i < v.NumField(); i++ {
// skip unexported fields
if !v.Field(i).CanInterface() {
continue
}
rlpTag := v.Type().Field(i).Tag.Get("rlp")
// skip fields without rlp field tag
if rlpTag == "" {
continue
}
keys := strings.Split(rlpTag, "=")
require.Equal(t, 2, len(keys))
// parse keys[1] as an int
key, err := strconv.ParseUint(keys[1], 10, 64)
require.NoError(t, err)
// typecast key to be of statusOptionKey type
kfi[statusOptionKey(key)] = i
ifk[i] = statusOptionKey(key)
func TestInitRLPKeyFields(t *testing.T) {
ifk := map[int]statusOptionKey{
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,
}
// Test that the statusOptions' derived kfi length matches the global keyFieldIdx length
require.Equal(t, len(keyFieldIdx), len(kfi))
// Test that the kfi length matches the inited global keyFieldIdx length
require.Equal(t, len(kfi), len(keyFieldIdx))
// Test that each index of the statusOptions' derived kfi values matches the global keyFieldIdx of the same index
// Test that each index of the kfi values matches the inited global keyFieldIdx of the same index
for k, v := range kfi {
require.Exactly(t, keyFieldIdx[k], v)
require.Exactly(t, v, keyFieldIdx[k])
}
// Test that each index of the global keyFieldIdx values matches statusOptions' derived kfi values of the same index
// Test that each index of the inited global keyFieldIdx values matches kfi values of the same index
for k, v := range keyFieldIdx {
require.Exactly(t, kfi[k], v)
require.Exactly(t, v, kfi[k])
}
// Test that the statusOptions' derived ifk length matches the global idxFieldKey length
require.Equal(t, len(idxFieldKey), len(ifk))
// Test that the ifk length matches the inited global idxFieldKey length
require.Equal(t, len(ifk), len(idxFieldKey))
// Test that each index of the statusOptions' derived ifk values matches the global idxFieldKey of the same index
// Test that each index of the ifk values matches the inited global idxFieldKey of the same index
for k, v := range ifk {
require.Exactly(t, idxFieldKey[k], v)
require.Exactly(t, v, idxFieldKey[k])
}
// Test that each index of the global idxFieldKey values matches statusOptions' derived ifk values of the same index
// Test that each index of the inited global idxFieldKey values matches ifk values of the same index
for k, v := range idxFieldKey {
require.Exactly(t, ifk[k], v)
require.Exactly(t, v, ifk[k])
}
}

View File

@ -108,6 +108,14 @@ type Waku struct {
logger *zap.Logger
}
// init initialises the waku package
func init() {
err := initRLPKeyFields()
if err != nil {
panic(err)
}
}
// New creates a Waku client ready to communicate through the Ethereum P2P network.
func New(cfg *Config, logger *zap.Logger) *Waku {
if cfg == nil {