kubo/namesys/selector.go
Dirk McCormick 7b99538f3c namesys: discard records with invalid EOL in record selection
License: MIT
Signed-off-by: Dirk McCormick <dirkmdev@gmail.com>
2018-02-07 16:18:12 -05:00

64 lines
1.4 KiB
Go

package namesys
import (
"bytes"
"errors"
pb "github.com/ipfs/go-ipfs/namesys/pb"
u "gx/ipfs/QmNiJuT8Ja3hMVpBHXv3Q6dwmperaQ6JjLtpMQgMCD7xvx/go-ipfs-util"
proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
)
// IpnsSelectorFunc selects the best record by checking which has the highest
// sequence number and latest EOL
func IpnsSelectorFunc(k string, vals [][]byte) (int, error) {
var recs []*pb.IpnsEntry
for _, v := range vals {
e := new(pb.IpnsEntry)
err := proto.Unmarshal(v, e)
if err == nil {
recs = append(recs, e)
} else {
recs = append(recs, nil)
}
}
return selectRecord(recs, vals)
}
func selectRecord(recs []*pb.IpnsEntry, vals [][]byte) (int, error) {
var bestSeq uint64
besti := -1
for i, r := range recs {
if r == nil || r.GetSequence() < bestSeq {
continue
}
rt, err := u.ParseRFC3339(string(r.GetValidity()))
if err != nil {
log.Errorf("failed to parse ipns record EOL %s", r.GetValidity())
continue
}
if besti == -1 || r.GetSequence() > bestSeq {
bestSeq = r.GetSequence()
besti = i
} else if r.GetSequence() == bestSeq {
bestt, _ := u.ParseRFC3339(string(recs[besti].GetValidity()))
if rt.After(bestt) {
besti = i
} else if rt == bestt {
if bytes.Compare(vals[i], vals[besti]) > 0 {
besti = i
}
}
}
}
if besti == -1 {
return 0, errors.New("no usable records in given set")
}
return besti, nil
}