Skip to content

Commit 6646cc7

Browse files
committed
pss: refactor msgParams to message.Flags and RLP serialization
1 parent bf854b8 commit 6646cc7

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/p2p/protocols"
1313
"github.com/ethersphere/swarm/pot"
1414
"github.com/ethersphere/swarm/pss/crypto"
15+
"github.com/ethersphere/swarm/pss/internal/message"
1516
)
1617

1718
type testCase struct {
@@ -349,7 +350,7 @@ func newTestDiscoveryPeer(addr pot.Address, kad *network.Kademlia) *network.Peer
349350
}
350351

351352
func newTestMsg(addr []byte) *PssMsg {
352-
msg := newPssMsg(&msgParams{})
353+
msg := newPssMsg(message.Flags{})
353354
msg.To = addr[:]
354355
msg.Expire = uint32(time.Now().Add(time.Second * 60).Unix())
355356
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
@@ -36,6 +36,7 @@ import (
3636
"github.com/ethersphere/swarm/p2p/protocols"
3737
"github.com/ethersphere/swarm/pot"
3838
"github.com/ethersphere/swarm/pss/crypto"
39+
"github.com/ethersphere/swarm/pss/internal/message"
3940
"github.com/ethersphere/swarm/storage"
4041
"golang.org/x/crypto/sha3"
4142
)
@@ -482,7 +483,7 @@ func (p *Pss) handle(ctx context.Context, msg interface{}) error {
482483

483484
// raw is simplest handler contingency to check, so check that first
484485
var isRaw bool
485-
if pssmsg.isRaw() {
486+
if pssmsg.Flags.Raw {
486487
if capabilities, ok := p.getTopicHandlerCaps(psstopic); ok {
487488
if !capabilities.raw {
488489
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
@@ -634,8 +635,8 @@ func (p *Pss) SendRaw(address PssAddress, topic Topic, msg []byte) error {
634635
return err
635636
}
636637

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

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

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

pss/pss_test.go

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import (
4646
"github.com/ethersphere/swarm/p2p/protocols"
4747
"github.com/ethersphere/swarm/pot"
4848
"github.com/ethersphere/swarm/pss/crypto"
49+
"github.com/ethersphere/swarm/pss/internal/message"
4950
"github.com/ethersphere/swarm/state"
5051
)
5152

@@ -127,29 +128,6 @@ func TestTopic(t *testing.T) {
127128
}
128129
}
129130

130-
// test bit packing of message control flags
131-
func TestMsgParams(t *testing.T) {
132-
var ctrl byte
133-
ctrl |= pssControlRaw
134-
p := newMsgParamsFromBytes([]byte{ctrl})
135-
m := newPssMsg(p)
136-
if !m.isRaw() || m.isSym() {
137-
t.Fatal("expected raw=true and sym=false")
138-
}
139-
ctrl |= pssControlSym
140-
p = newMsgParamsFromBytes([]byte{ctrl})
141-
m = newPssMsg(p)
142-
if !m.isRaw() || !m.isSym() {
143-
t.Fatal("expected raw=true and sym=true")
144-
}
145-
ctrl &= 0xff &^ pssControlRaw
146-
p = newMsgParamsFromBytes([]byte{ctrl})
147-
m = newPssMsg(p)
148-
if m.isRaw() || !m.isSym() {
149-
t.Fatal("expected raw=false and sym=true")
150-
}
151-
}
152-
153131
// test if we can insert into cache, match items with cache and cache expiry
154132
func TestCache(t *testing.T) {
155133
var err error
@@ -376,7 +354,7 @@ func TestAddressMatchProx(t *testing.T) {
376354

377355
// first the unit test on the method that calculates possible receipient using prox
378356
for i, distance := range remoteDistances {
379-
pssMsg := newPssMsg(&msgParams{})
357+
pssMsg := newPssMsg(message.Flags{})
380358
pssMsg.To = make([]byte, len(localAddr))
381359
copy(pssMsg.To, localAddr)
382360
var byteIdx = distance / 8
@@ -416,7 +394,7 @@ func TestAddressMatchProx(t *testing.T) {
416394

417395
var data [32]byte
418396
rand.Read(data[:])
419-
pssMsg := newPssMsg(&msgParams{raw: true})
397+
pssMsg := newPssMsg(message.Flags{Raw: true})
420398
pssMsg.To = remoteAddr
421399
pssMsg.Expire = uint32(time.Now().Unix() + 4200)
422400
pssMsg.Payload = data[:]
@@ -445,7 +423,7 @@ func TestAddressMatchProx(t *testing.T) {
445423

446424
var data [32]byte
447425
rand.Read(data[:])
448-
pssMsg := newPssMsg(&msgParams{raw: true})
426+
pssMsg := newPssMsg(message.Flags{Raw: true})
449427
pssMsg.To = remoteAddr
450428
pssMsg.Expire = uint32(time.Now().Unix() + 4200)
451429
pssMsg.Payload = data[:]
@@ -467,7 +445,7 @@ func TestAddressMatchProx(t *testing.T) {
467445
remotePotAddr := pot.RandomAddressAt(localPotAddr, distance)
468446
remoteAddr := remotePotAddr.Bytes()
469447

470-
pssMsg := newPssMsg(&msgParams{raw: true})
448+
pssMsg := newPssMsg(message.Flags{Raw: true})
471449
pssMsg.To = remoteAddr
472450
pssMsg.Expire = uint32(time.Now().Unix() + 4200)
473451
pssMsg.Payload = []byte(remotePotAddr.String())
@@ -818,8 +796,8 @@ func TestRawAllow(t *testing.T) {
818796
ps.Register(&topic, hndlrNoRaw)
819797

820798
// test it with a raw message, should be poo-poo
821-
pssMsg := newPssMsg(&msgParams{
822-
raw: true,
799+
pssMsg := newPssMsg(message.Flags{
800+
Raw: true,
823801
})
824802
pssMsg.To = baseAddr.OAddr
825803
pssMsg.Expire = uint32(time.Now().Unix() + 4200)
@@ -1733,7 +1711,7 @@ func benchmarkSymkeyBruteforceSameaddr(b *testing.B) {
17331711
func testRandomMessage() *PssMsg {
17341712
addr := make([]byte, 32)
17351713
addr[0] = 0x01
1736-
msg := newPssMsg(&msgParams{})
1714+
msg := newPssMsg(message.Flags{})
17371715
msg.To = addr
17381716
msg.Expire = uint32(time.Now().Add(time.Second * 60).Unix())
17391717
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)