Skip to content

Commit 5cbd42e

Browse files
committed
pss: refactor msgParams to message.Flags and RLP serialization
1 parent 4622538 commit 5cbd42e

File tree

7 files changed

+123
-81
lines changed

7 files changed

+123
-81
lines changed

pss/forwarding_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/ethersphere/swarm/network"
1313
"github.com/ethersphere/swarm/p2p/protocols"
1414
"github.com/ethersphere/swarm/pot"
15+
"github.com/ethersphere/swarm/pss/internal/message"
1516
)
1617

1718
type testCase struct {
@@ -347,7 +348,7 @@ func newTestDiscoveryPeer(addr pot.Address, kad *network.Kademlia) *network.Peer
347348
}
348349

349350
func newTestMsg(addr []byte) *PssMsg {
350-
msg := newPssMsg(&msgParams{})
351+
msg := newPssMsg(message.Flags{})
351352
msg.To = addr[:]
352353
msg.Expire = uint32(time.Now().Add(time.Second * 60).Unix())
353354
msg.Topic = [4]byte{}

pss/internal/message/flags.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package message
2+
3+
import (
4+
"errors"
5+
"io"
6+
7+
"github.com/ethereum/go-ethereum/rlp"
8+
)
9+
10+
// Flags represents the possible PSS message flags
11+
type Flags struct {
12+
Raw bool // message is flagged as raw or with external encryption
13+
Symmetric bool // message is symmetrically encrypted
14+
}
15+
16+
const flagsLength = 1
17+
const flagSymmetric = 1 << 0
18+
const flagRaw = 1 << 1
19+
20+
// ErrIncorrectFlagsFieldLength is returned when the incoming flags field length is incorrect
21+
var ErrIncorrectFlagsFieldLength = errors.New("Incorrect flags field length in message")
22+
23+
// DecodeRLP implements the rlp.Decoder interface
24+
func (f *Flags) DecodeRLP(s *rlp.Stream) error {
25+
flagsBytes, err := s.Bytes()
26+
if err != nil {
27+
return err
28+
}
29+
if len(flagsBytes) != flagsLength {
30+
return ErrIncorrectFlagsFieldLength
31+
}
32+
f.Symmetric = flagsBytes[0]&flagSymmetric != 0
33+
f.Raw = flagsBytes[0]&flagRaw != 0
34+
return nil
35+
}
36+
37+
// EncodeRLP implements the rlp.Encoder interface
38+
func (f *Flags) EncodeRLP(w io.Writer) error {
39+
flagsBytes := []byte{0}
40+
if f.Raw {
41+
flagsBytes[0] |= flagRaw
42+
}
43+
if f.Symmetric {
44+
flagsBytes[0] |= flagSymmetric
45+
}
46+
47+
return rlp.Encode(w, flagsBytes)
48+
}

pss/internal/message/flags_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package message_test
2+
3+
import (
4+
"encoding/hex"
5+
"fmt"
6+
"testing"
7+
8+
"github.com/epiclabs-io/ut"
9+
"github.com/ethereum/go-ethereum/rlp"
10+
"github.com/ethersphere/swarm/pss/internal/message"
11+
)
12+
13+
func TestFlags(tx *testing.T) {
14+
t := ut.BeginTest(tx, false)
15+
defer t.FinishTest()
16+
17+
bools := []bool{true, false}
18+
for _, r := range bools {
19+
for _, s := range bools {
20+
f := message.Flags{
21+
Symmetric: s,
22+
Raw: r,
23+
}
24+
// Test encoding:
25+
bytes, err := rlp.EncodeToBytes(&f)
26+
t.Ok(err)
27+
t.EqualsKey(fmt.Sprintf("r=%t; s=%t", r, s), hex.EncodeToString(bytes))
28+
29+
// Test decoding:
30+
31+
var f2 message.Flags
32+
err = rlp.DecodeBytes(bytes, &f2)
33+
t.Ok(err)
34+
t.Equals(f, f2)
35+
}
36+
}
37+
38+
}
39+
40+
func TestFlagsErrors(tx *testing.T) {
41+
t := ut.BeginTest(tx, false)
42+
defer t.FinishTest()
43+
44+
var f2 message.Flags
45+
err := rlp.DecodeBytes([]byte{0x82, 0xFF, 0xFF}, &f2)
46+
t.MustFailWith(err, message.ErrIncorrectFlagsFieldLength)
47+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"r=false; s=false": "00",
3+
"r=false; s=true": "01",
4+
"r=true; s=false": "02",
5+
"r=true; s=true": "03"
6+
}

pss/pss.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"github.com/ethersphere/swarm/p2p/protocols"
3838
"github.com/ethersphere/swarm/pot"
3939
"github.com/ethersphere/swarm/pss/crypto"
40+
"github.com/ethersphere/swarm/pss/internal/message"
4041
"github.com/ethersphere/swarm/storage"
4142
"golang.org/x/crypto/sha3"
4243
)
@@ -483,7 +484,7 @@ func (p *Pss) handle(ctx context.Context, msg interface{}) error {
483484

484485
// raw is simplest handler contingency to check, so check that first
485486
var isRaw bool
486-
if pssmsg.isRaw() {
487+
if pssmsg.Flags.Raw {
487488
if capabilities, ok := p.getTopicHandlerCaps(psstopic); ok {
488489
if !capabilities.raw {
489490
log.Debug("No handler for raw message", "topic", psstopic)
@@ -535,7 +536,7 @@ func (p *Pss) process(pssmsg *PssMsg, raw bool, prox bool) error {
535536
if raw {
536537
payload = pssmsg.Payload
537538
} else {
538-
if pssmsg.isSym() {
539+
if pssmsg.Flags.Symmetric {
539540
keyFunc = p.processSym
540541
} else {
541542
asymmetric = true
@@ -633,8 +634,8 @@ func (p *Pss) SendRaw(address PssAddress, topic Topic, msg []byte) error {
633634
return err
634635
}
635636

636-
pssMsgParams := &msgParams{
637-
raw: true,
637+
pssMsgParams := message.Flags{
638+
Raw: true,
638639
}
639640

640641
pssMsg := newPssMsg(pssMsgParams)
@@ -707,8 +708,8 @@ func (p *Pss) send(to []byte, topic Topic, msg []byte, asymmetric bool, key []by
707708
log.Trace("pssmsg wrap done", "env", envelope, "mparams payload", hex.EncodeToString(msg), "to", hex.EncodeToString(to), "asym", asymmetric, "key", hex.EncodeToString(key))
708709

709710
// prepare for devp2p transport
710-
pssMsgParams := &msgParams{
711-
sym: !asymmetric,
711+
pssMsgParams := message.Flags{
712+
Symmetric: !asymmetric,
712713
}
713714
pssMsg := newPssMsg(pssMsgParams)
714715
pssMsg.To = to

pss/pss_test.go

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import (
4545
"github.com/ethersphere/swarm/p2p/protocols"
4646
"github.com/ethersphere/swarm/pot"
4747
"github.com/ethersphere/swarm/pss/crypto"
48+
"github.com/ethersphere/swarm/pss/internal/message"
4849
"github.com/ethersphere/swarm/state"
4950
"github.com/ethersphere/swarm/testutil"
5051
)
@@ -118,29 +119,6 @@ func TestTopic(t *testing.T) {
118119
}
119120
}
120121

121-
// test bit packing of message control flags
122-
func TestMsgParams(t *testing.T) {
123-
var ctrl byte
124-
ctrl |= pssControlRaw
125-
p := newMsgParamsFromBytes([]byte{ctrl})
126-
m := newPssMsg(p)
127-
if !m.isRaw() || m.isSym() {
128-
t.Fatal("expected raw=true and sym=false")
129-
}
130-
ctrl |= pssControlSym
131-
p = newMsgParamsFromBytes([]byte{ctrl})
132-
m = newPssMsg(p)
133-
if !m.isRaw() || !m.isSym() {
134-
t.Fatal("expected raw=true and sym=true")
135-
}
136-
ctrl &= 0xff &^ pssControlRaw
137-
p = newMsgParamsFromBytes([]byte{ctrl})
138-
m = newPssMsg(p)
139-
if m.isRaw() || !m.isSym() {
140-
t.Fatal("expected raw=false and sym=true")
141-
}
142-
}
143-
144122
// test if we can insert into cache, match items with cache and cache expiry
145123
func TestCache(t *testing.T) {
146124
var err error
@@ -361,7 +339,7 @@ func TestAddressMatchProx(t *testing.T) {
361339

362340
// first the unit test on the method that calculates possible receipient using prox
363341
for i, distance := range remoteDistances {
364-
pssMsg := newPssMsg(&msgParams{})
342+
pssMsg := newPssMsg(message.Flags{})
365343
pssMsg.To = make([]byte, len(localAddr))
366344
copy(pssMsg.To, localAddr)
367345
var byteIdx = distance / 8
@@ -401,7 +379,7 @@ func TestAddressMatchProx(t *testing.T) {
401379

402380
var data [32]byte
403381
rand.Read(data[:])
404-
pssMsg := newPssMsg(&msgParams{raw: true})
382+
pssMsg := newPssMsg(message.Flags{Raw: true})
405383
pssMsg.To = remoteAddr
406384
pssMsg.Expire = uint32(time.Now().Unix() + 4200)
407385
pssMsg.Payload = data[:]
@@ -430,7 +408,7 @@ func TestAddressMatchProx(t *testing.T) {
430408

431409
var data [32]byte
432410
rand.Read(data[:])
433-
pssMsg := newPssMsg(&msgParams{raw: true})
411+
pssMsg := newPssMsg(message.Flags{Raw: true})
434412
pssMsg.To = remoteAddr
435413
pssMsg.Expire = uint32(time.Now().Unix() + 4200)
436414
pssMsg.Payload = data[:]
@@ -452,7 +430,7 @@ func TestAddressMatchProx(t *testing.T) {
452430
remotePotAddr := pot.RandomAddressAt(localPotAddr, distance)
453431
remoteAddr := remotePotAddr.Bytes()
454432

455-
pssMsg := newPssMsg(&msgParams{raw: true})
433+
pssMsg := newPssMsg(message.Flags{Raw: true})
456434
pssMsg.To = remoteAddr
457435
pssMsg.Expire = uint32(time.Now().Unix() + 4200)
458436
pssMsg.Payload = []byte(remotePotAddr.String())
@@ -791,8 +769,8 @@ func TestRawAllow(t *testing.T) {
791769
ps.Register(&topic, hndlrNoRaw)
792770

793771
// test it with a raw message, should be poo-poo
794-
pssMsg := newPssMsg(&msgParams{
795-
raw: true,
772+
pssMsg := newPssMsg(message.Flags{
773+
Raw: true,
796774
})
797775
pssMsg.To = baseAddr.OAddr
798776
pssMsg.Expire = uint32(time.Now().Unix() + 4200)
@@ -1694,7 +1672,7 @@ func benchmarkSymkeyBruteforceSameaddr(b *testing.B) {
16941672
func testRandomMessage() *PssMsg {
16951673
addr := make([]byte, 32)
16961674
addr[0] = 0x01
1697-
msg := newPssMsg(&msgParams{})
1675+
msg := newPssMsg(message.Flags{})
16981676
msg.To = addr
16991677
msg.Expire = uint32(time.Now().Add(time.Second * 60).Unix())
17001678
msg.Topic = [4]byte{}

pss/types.go

Lines changed: 5 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,12 @@ import (
2626
"github.com/ethereum/go-ethereum/common/hexutil"
2727
"github.com/ethereum/go-ethereum/p2p"
2828
"github.com/ethereum/go-ethereum/rlp"
29+
"github.com/ethersphere/swarm/pss/internal/message"
2930
"github.com/ethersphere/swarm/storage"
3031
)
3132

3233
const (
33-
pssControlSym = 1
34-
pssControlRaw = 1 << 1
35-
TopicLength = 4 // in bytes Taken from Whisper
34+
TopicLength = 4 // in bytes Taken from Whisper
3635
)
3736

3837
var (
@@ -86,34 +85,6 @@ func (a *PssAddress) UnmarshalJSON(input []byte) error {
8685
// holds the digest of a message used for caching
8786
type digest [digestLength]byte
8887

89-
// conceals bitwise operations on the control flags byte
90-
type msgParams struct {
91-
raw bool
92-
sym bool
93-
}
94-
95-
func newMsgParamsFromBytes(paramBytes []byte) *msgParams {
96-
if len(paramBytes) != 1 {
97-
return nil
98-
}
99-
return &msgParams{
100-
raw: paramBytes[0]&pssControlRaw > 0,
101-
sym: paramBytes[0]&pssControlSym > 0,
102-
}
103-
}
104-
105-
func (m *msgParams) Bytes() (paramBytes []byte) {
106-
var b byte
107-
if m.raw {
108-
b |= pssControlRaw
109-
}
110-
if m.sym {
111-
b |= pssControlSym
112-
}
113-
paramBytes = append(paramBytes, b)
114-
return paramBytes
115-
}
116-
11788
type outboxMsg struct {
11889
msg *PssMsg
11990
startedAt time.Time
@@ -129,28 +100,18 @@ func newOutboxMsg(msg *PssMsg) *outboxMsg {
129100
// PssMsg encapsulates messages transported over pss.
130101
type PssMsg struct {
131102
To []byte
132-
Control []byte
103+
Flags message.Flags
133104
Expire uint32
134105
Topic Topic
135106
Payload []byte
136107
}
137108

138-
func newPssMsg(param *msgParams) *PssMsg {
109+
func newPssMsg(flags message.Flags) *PssMsg {
139110
return &PssMsg{
140-
Control: param.Bytes(),
111+
Flags: flags,
141112
}
142113
}
143114

144-
// message is flagged as raw / external encryption
145-
func (msg *PssMsg) isRaw() bool {
146-
return msg.Control[0]&pssControlRaw > 0
147-
}
148-
149-
// message is flagged as symmetrically encrypted
150-
func (msg *PssMsg) isSym() bool {
151-
return msg.Control[0]&pssControlSym > 0
152-
}
153-
154115
// serializes the message for use in cache
155116
func (msg *PssMsg) serialize() []byte {
156117
rlpdata, _ := rlp.EncodeToBytes(struct {

0 commit comments

Comments
 (0)