p2p/enr: sort pairs prior to RLP encoding; binary search on Load

This commit is contained in:
Anton Evangelatov 2017-12-04 14:17:32 +01:00 committed by Felix Lange
parent d960c08a24
commit bd9696c33d
2 changed files with 48 additions and 10 deletions

View file

@ -69,11 +69,10 @@ func (r *Record) SetSeq(s uint32) {
}
func (r *Record) Load(k Key) (bool, error) {
for _, p := range r.pairs {
if p.k == k.ENRKey() {
err := rlp.DecodeBytes(p.v, k)
return true, err
}
i := sort.Search(len(r.pairs), func(i int) bool { return r.pairs[i].k >= k.ENRKey() })
if i < len(r.pairs) && r.pairs[i].k == k.ENRKey() {
return true, rlp.DecodeBytes(r.pairs[i].v, k)
}
return false, errors.New("record does not exist")
@ -85,7 +84,29 @@ func (r *Record) Set(k Key) error {
if err != nil {
return err
}
r.pairs = append(r.pairs, pair{k.ENRKey(), blob})
var inserted bool
for i, p := range r.pairs {
if p.k == k.ENRKey() {
// replace value of pair
r.pairs[i].v = blob
inserted = true
break
} else if p.k > k.ENRKey() {
// insert pair before i-th elem
el := pair{k.ENRKey(), blob}
r.pairs = append(r.pairs, pair{})
copy(r.pairs[i+1:], r.pairs[i:])
r.pairs[i] = el
inserted = true
break
}
}
if !inserted {
r.pairs = append(r.pairs, pair{k.ENRKey(), blob})
}
return nil
}
@ -213,10 +234,6 @@ func (r *Record) Sign(privkey *ecdsa.PrivateKey) error {
}
func (r *Record) serialisedContent() ([]byte, error) {
sort.Slice(r.pairs, func(i, j int) bool {
return r.pairs[i].k < r.pairs[j].k
})
list := []interface{}{r.seq}
for _, p := range r.pairs {

View file

@ -151,6 +151,27 @@ func TestDirty(t *testing.T) {
}
}
func TestGetSetOverwrite(t *testing.T) {
var r Record
ip := IP4(net.IP{192, 168, 0, 3})
r.Set(ip)
ip2 := IP4(net.IP{192, 168, 0, 4})
r.Set(ip2)
var ip3 IP4
_, err := r.Load(&ip3)
if err != nil {
t.Fatal(err)
}
if bytes.Compare(ip2, ip3) != 0 {
t.Fatalf("got %#v, expected %#v", ip2, ip3)
}
}
func TestSignEncodeAndDecode(t *testing.T) {
privkey, err := crypto.HexToECDSA(privkeyHex)
if err != nil {