swarm/pss: Exorcise evil bitwise logic and revert kad consts

This commit is contained in:
lash 2018-11-20 11:32:44 +01:00
parent 3e6d23eb4f
commit b13b05c297
5 changed files with 89 additions and 70 deletions

View file

@ -29,16 +29,6 @@ import (
"github.com/ethereum/go-ethereum/swarm/pot" "github.com/ethereum/go-ethereum/swarm/pot"
) )
const (
defaultMaxProxDisplay = 16
defaultMinProxBinSize = 2
defaultMinBinSize = 2
defaultMaxBinSize = 4
defaultRetryInterval = 4200000000 // 4.2 sec
defaultMaxRetries = 42
defaultRetryExponent = 2
)
/* /*
Taking the proximity order relative to a fix point x classifies the points in Taking the proximity order relative to a fix point x classifies the points in
@ -78,13 +68,13 @@ type KadParams struct {
// NewKadParams returns a params struct with default values // NewKadParams returns a params struct with default values
func NewKadParams() *KadParams { func NewKadParams() *KadParams {
return &KadParams{ return &KadParams{
MaxProxDisplay: defaultMaxProxDisplay, MaxProxDisplay: 16,
MinProxBinSize: defaultMinProxBinSize, MinProxBinSize: 2,
MinBinSize: defaultMinBinSize, MinBinSize: 2,
MaxBinSize: defaultMaxBinSize, MaxBinSize: 4,
RetryInterval: defaultRetryInterval, RetryInterval: 4200000000, // 4.2 sec
MaxRetries: defaultMaxRetries, MaxRetries: 42,
RetryExponent: defaultRetryExponent, RetryExponent: 2,
} }
} }

View file

@ -59,24 +59,22 @@ func (pssapi *API) Receive(ctx context.Context, topic Topic, raw bool, prox bool
psssub := notifier.CreateSubscription() psssub := notifier.CreateSubscription()
hndlr := &handler{ hndlr := NewHandler(func(msg []byte, p *p2p.Peer, asymmetric bool, keyid string) error {
f: func(msg []byte, p *p2p.Peer, asymmetric bool, keyid string) error { apimsg := &APIMsg{
apimsg := &APIMsg{ Msg: hexutil.Bytes(msg),
Msg: hexutil.Bytes(msg), Asymmetric: asymmetric,
Asymmetric: asymmetric, Key: keyid,
Key: keyid, }
} if err := notifier.Notify(psssub.ID, apimsg); err != nil {
if err := notifier.Notify(psssub.ID, apimsg); err != nil { log.Warn(fmt.Sprintf("notification on pss sub topic rpc (sub %v) msg %v failed!", psssub.ID, msg))
log.Warn(fmt.Sprintf("notification on pss sub topic rpc (sub %v) msg %v failed!", psssub.ID, msg)) }
} return nil
return nil })
},
}
if raw { if raw {
hndlr.caps |= handlerCapRaw hndlr.caps.raw = true
} }
if prox { if prox {
hndlr.caps |= handlerCapProx hndlr.caps.prox = true
} }
deregf := pssapi.Register(&topic, hndlr) deregf := pssapi.Register(&topic, hndlr)

View file

@ -141,7 +141,7 @@ type Pss struct {
handlers map[Topic]map[*handler]bool // topic and version based pss payload handlers. See pss.Handle() handlers map[Topic]map[*handler]bool // topic and version based pss payload handlers. See pss.Handle()
handlersMu sync.RWMutex handlersMu sync.RWMutex
hashPool sync.Pool hashPool sync.Pool
topicHandlerCaps map[Topic]byte // caches capabilities of each topic's handlers (see handlerCap* consts in types.go) topicHandlerCaps map[Topic]*handlerCaps // caches capabilities of each topic's handlers (see handlerCap* consts in types.go)
// process // process
quitC chan struct{} quitC chan struct{}
@ -183,7 +183,8 @@ func NewPss(k *network.Kademlia, params *PssParams) (*Pss, error) {
symKeyDecryptCacheCapacity: params.SymKeyCacheCapacity, symKeyDecryptCacheCapacity: params.SymKeyCacheCapacity,
handlers: make(map[Topic]map[*handler]bool), handlers: make(map[Topic]map[*handler]bool),
topicHandlerCaps: make(map[Topic]byte), topicHandlerCaps: make(map[Topic]*handlerCaps),
hashPool: sync.Pool{ hashPool: sync.Pool{
New: func() interface{} { New: func() interface{} {
return sha3.NewKeccak256() return sha3.NewKeccak256()
@ -324,20 +325,36 @@ func (p *Pss) Register(topic *Topic, hndlr *handler) func() {
p.handlers[*topic] = handlers p.handlers[*topic] = handlers
log.Debug("registered handler", "caps", hndlr.caps) log.Debug("registered handler", "caps", hndlr.caps)
} }
if hndlr.caps == nil {
hndlr.caps = &handlerCaps{}
}
handlers[hndlr] = true handlers[hndlr] = true
p.topicHandlerCaps[*topic] |= hndlr.caps if _, ok := p.topicHandlerCaps[*topic]; !ok {
p.topicHandlerCaps[*topic] = &handlerCaps{}
}
if !p.topicHandlerCaps[*topic].raw && hndlr.caps.raw {
p.topicHandlerCaps[*topic].raw = true
}
if !p.topicHandlerCaps[*topic].prox && hndlr.caps.prox {
p.topicHandlerCaps[*topic].prox = true
}
return func() { p.deregister(topic, hndlr) } return func() { p.deregister(topic, hndlr) }
} }
func (p *Pss) deregister(topic *Topic, hndlr *handler) { func (p *Pss) deregister(topic *Topic, hndlr *handler) {
p.handlersMu.Lock() p.handlersMu.Lock()
defer p.handlersMu.Unlock() defer p.handlersMu.Unlock()
handlers := p.handlers[*topic] handlers := p.handlers[*topic]
if len(handlers) == 1 { if len(handlers) > 1 {
delete(p.handlers, *topic) delete(p.handlers, *topic)
// topic caps might have changed now that a handler is gone // topic caps might have changed now that a handler is gone
var caps byte caps := &handlerCaps{}
for h := range handlers { for h := range handlers {
caps |= h.caps if h.caps.raw {
caps.raw = true
}
if h.caps.prox {
caps.prox = true
}
} }
p.topicHandlerCaps[*topic] = caps p.topicHandlerCaps[*topic] = caps
return return
@ -379,7 +396,7 @@ func (p *Pss) handlePssMsg(ctx context.Context, msg interface{}) error {
// raw is simplest handler contingency to check, so check that first // raw is simplest handler contingency to check, so check that first
var isRaw bool var isRaw bool
if pssmsg.isRaw() { if pssmsg.isRaw() {
if p.topicHandlerCaps[psstopic]&handlerCapRaw == 0 { if !p.topicHandlerCaps[psstopic].raw {
log.Debug("No handler for raw message", "topic", psstopic) log.Debug("No handler for raw message", "topic", psstopic)
return nil return nil
} }
@ -390,7 +407,10 @@ func (p *Pss) handlePssMsg(ctx context.Context, msg interface{}) error {
// - no prox handler on message and partial address matches // - no prox handler on message and partial address matches
// - prox handler on message and we are in prox regardless of partial address match // - prox handler on message and we are in prox regardless of partial address match
// store this result so we don't calculate again on every handler // store this result so we don't calculate again on every handler
isProx := p.topicHandlerCaps[psstopic]&handlerCapProx != 0 var isProx bool
if _, ok := p.topicHandlerCaps[psstopic]; ok {
isProx = p.topicHandlerCaps[psstopic].prox
}
isRecipient := p.isSelfPossibleRecipient(pssmsg, isProx) isRecipient := p.isSelfPossibleRecipient(pssmsg, isProx)
if !isRecipient { if !isRecipient {
log.Trace("pss was for someone else :'( ... forwarding", "pss", common.ToHex(p.BaseAddr()), "prox", isProx) log.Trace("pss was for someone else :'( ... forwarding", "pss", common.ToHex(p.BaseAddr()), "prox", isProx)
@ -457,12 +477,12 @@ func (p *Pss) executeHandlers(topic Topic, payload []byte, from *PssAddress, raw
handlers := p.getHandlers(topic) handlers := p.getHandlers(topic)
peer := p2p.NewPeer(enode.ID{}, fmt.Sprintf("%x", from), []p2p.Cap{}) peer := p2p.NewPeer(enode.ID{}, fmt.Sprintf("%x", from), []p2p.Cap{})
for h := range handlers { for h := range handlers {
if h.caps&handlerCapRaw == 0 && raw { if !h.caps.raw && raw {
log.Trace("norawhandler") log.Warn("norawhandler")
continue continue
} }
if h.caps&handlerCapProx == 0 && prox { if !h.caps.prox && prox {
log.Trace("noproxhandler") log.Warn("noproxhandler")
continue continue
} }
err := (h.f)(payload, peer, asymmetric, keyid) err := (h.f)(payload, peer, asymmetric, keyid)
@ -750,7 +770,7 @@ func (p *Pss) SendRaw(address PssAddress, topic Topic, msg []byte) error {
if err != nil { if err != nil {
return err return err
} }
if p.isSelfPossibleRecipient(pssMsg, true) && p.topicHandlerCaps[topic]&handlerCapProx != 0 { if p.isSelfPossibleRecipient(pssMsg, true) && p.topicHandlerCaps[topic].prox {
return p.process(pssMsg, true, true) return p.process(pssMsg, true, true)
} }
return nil return nil
@ -858,8 +878,10 @@ func (p *Pss) send(to []byte, topic Topic, msg []byte, asymmetric bool, key []by
if err != nil { if err != nil {
return err return err
} }
if p.isSelfPossibleRecipient(pssMsg, true) && p.topicHandlerCaps[topic]&handlerCapProx != 0 { if _, ok := p.topicHandlerCaps[topic]; ok {
return p.process(pssMsg, true, true) if p.isSelfPossibleRecipient(pssMsg, true) && p.topicHandlerCaps[topic].prox {
return p.process(pssMsg, true, true)
}
} }
return nil return nil
} }

View file

@ -366,8 +366,11 @@ func TestProxShortCircuit(t *testing.T) {
} }
topic := BytesToTopic([]byte{0x2a}) topic := BytesToTopic([]byte{0x2a})
hndlrProxDereg := ps.Register(&topic, &handler{ hndlrProxDereg := ps.Register(&topic, &handler{
f: rawHandlerFunc, f: rawHandlerFunc,
caps: handlerCapProx | handlerCapRaw, caps: &handlerCaps{
raw: true,
prox: true,
},
}) })
defer hndlrProxDereg() defer hndlrProxDereg()
@ -553,8 +556,11 @@ func TestAddressMatchProx(t *testing.T) {
// register it marking prox capability // register it marking prox capability
topic := BytesToTopic([]byte{0x2a}) topic := BytesToTopic([]byte{0x2a})
hndlrProxDereg := ps.Register(&topic, &handler{ hndlrProxDereg := ps.Register(&topic, &handler{
f: rawHandlerFunc, f: rawHandlerFunc,
caps: handlerCapProx | handlerCapRaw, caps: &handlerCaps{
raw: true,
prox: true,
},
}) })
// test the distances // test the distances
@ -583,8 +589,10 @@ func TestAddressMatchProx(t *testing.T) {
// now add a non prox-capable handler and test // now add a non prox-capable handler and test
ps.Register(&topic, &handler{ ps.Register(&topic, &handler{
f: rawHandlerFunc, f: rawHandlerFunc,
caps: handlerCapRaw, caps: &handlerCaps{
raw: true,
},
}) })
receives = 0 receives = 0
prevReceive = 0 prevReceive = 0
@ -982,8 +990,10 @@ func TestRawAllow(t *testing.T) {
// now wrap the same handler function with raw capabilities and register it // now wrap the same handler function with raw capabilities and register it
hndlrRaw := &handler{ hndlrRaw := &handler{
f: rawHandlerFunc, f: rawHandlerFunc,
caps: handlerCapRaw, caps: &handlerCaps{
raw: true,
},
} }
deregRawHandler := ps.Register(&topic, hndlrRaw) deregRawHandler := ps.Register(&topic, hndlrRaw)
@ -1974,8 +1984,10 @@ func newServices(allowRaw bool) adapters.Services {
SetHandshakeController(ps, NewHandshakeParams()) SetHandshakeController(ps, NewHandshakeParams())
} }
ps.Register(&PingTopic, &handler{ ps.Register(&PingTopic, &handler{
f: pp.Handle, f: pp.Handle,
caps: handlerCapRaw, caps: &handlerCaps{
raw: true,
},
}) })
ps.addAPI(rpc.API{ ps.addAPI(rpc.API{
Namespace: "psstest", Namespace: "psstest",

View file

@ -38,11 +38,6 @@ const (
pssControlRaw = 1 << 1 pssControlRaw = 1 << 1
) )
const (
handlerCapRaw = 1 << 0
handlerCapProx = 1 << 1
)
var ( var (
topicHashMutex = sync.Mutex{} topicHashMutex = sync.Mutex{}
topicHashFunc = storage.MakeHashFunc("SHA256")() topicHashFunc = storage.MakeHashFunc("SHA256")()
@ -167,32 +162,34 @@ func (msg *PssMsg) String() string {
// Implementations of this type are passed to Pss.Register together with a topic, // Implementations of this type are passed to Pss.Register together with a topic,
type HandlerFunc func(msg []byte, p *p2p.Peer, asymmetric bool, keyid string) error type HandlerFunc func(msg []byte, p *p2p.Peer, asymmetric bool, keyid string) error
type handlerCaps struct {
raw bool
prox bool
}
// Handler defines code to be executed upon reception of content. // Handler defines code to be executed upon reception of content.
type handler struct { type handler struct {
f HandlerFunc f HandlerFunc
caps byte caps *handlerCaps
//raw bool // if true, will allow raw messages to be handled
//prox bool // if true, explicit recipient address will be truncated to minproxsize depth
} }
// NewHandler returns a new message handler // NewHandler returns a new message handler
func NewHandler(f HandlerFunc) *handler { func NewHandler(f HandlerFunc) *handler {
return &handler{ return &handler{
f: f, f: f,
caps: &handlerCaps{},
} }
} }
// WithRaw is a chainable method that allows raw messages to be handled. // WithRaw is a chainable method that allows raw messages to be handled.
func (h *handler) WithRaw() *handler { func (h *handler) WithRaw() *handler {
//h.raw = true h.caps.raw = true
h.caps |= handlerCapRaw
return h return h
} }
// WithProxBin is a chainable method that allows sending messages with full addresses to neighbourhoods using the kademlia depth as reference // WithProxBin is a chainable method that allows sending messages with full addresses to neighbourhoods using the kademlia depth as reference
func (h *handler) WithProxBin() *handler { func (h *handler) WithProxBin() *handler {
//h.prox = true h.caps.prox = true
h.caps |= handlerCapProx
return h return h
} }