@cryptotaxi247 / kubo / commits / 3b9ad3000

Addressing comments from CR

License: MIT Signed-off-by: Jeromy <jeromyj@gmail.com>

Jeromy committed Sep 30, 2015 at 10:59 UTC 3b9ad300059d09f9ed4a1e25da9a377fc8b56f38
4 files changed +157 -21
namesys/ipns_select_test.go new
+127
@@ -0,0 +1,127 @@
1 +package namesys
2 +
3 +import (
4 + "fmt"
5 + "math/rand"
6 + "testing"
7 + "time"
8 +
9 + proto "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/gogo/protobuf/proto"
10 +
11 + pb "github.com/ipfs/go-ipfs/namesys/pb"
12 + ci "github.com/ipfs/go-ipfs/p2p/crypto"
13 + path "github.com/ipfs/go-ipfs/path"
14 + u "github.com/ipfs/go-ipfs/util"
15 +)
16 +
17 +func shuffle(a []*pb.IpnsEntry) {
18 + for n := 0; n < 5; n++ {
19 + for i, _ := range a {
20 + j := rand.Intn(len(a))
21 + a[i], a[j] = a[j], a[i]
22 + }
23 + }
24 +}
25 +
26 +func AssertSelected(r *pb.IpnsEntry, from ...*pb.IpnsEntry) error {
27 + shuffle(from)
28 + var vals [][]byte
29 + for _, r := range from {
30 + data, err := proto.Marshal(r)
31 + if err != nil {
32 + return err
33 + }
34 + vals = append(vals, data)
35 + }
36 +
37 + i, err := selectRecord(from, vals)
38 + if err != nil {
39 + return err
40 + }
41 +
42 + if from[i] != r {
43 + return fmt.Errorf("selected incorrect record %d", i)
44 + }
45 +
46 + return nil
47 +}
48 +
49 +func TestOrdering(t *testing.T) {
50 + // select timestamp so selection is deterministic
51 + ts := time.Unix(1000000, 0)
52 +
53 + // generate a key for signing the records
54 + r := u.NewSeededRand(15) // generate deterministic keypair
55 + priv, _, err := ci.GenerateKeyPairWithReader(ci.RSA, 1024, r)
56 + if err != nil {
57 + t.Fatal(err)
58 + }
59 +
60 + e1, err := CreateRoutingEntryData(priv, path.Path("foo"), 1, ts.Add(time.Hour))
61 + if err != nil {
62 + t.Fatal(err)
63 + }
64 +
65 + e2, err := CreateRoutingEntryData(priv, path.Path("bar"), 2, ts.Add(time.Hour))
66 + if err != nil {
67 + t.Fatal(err)
68 + }
69 +
70 + e3, err := CreateRoutingEntryData(priv, path.Path("baz"), 3, ts.Add(time.Hour))
71 + if err != nil {
72 + t.Fatal(err)
73 + }
74 +
75 + e4, err := CreateRoutingEntryData(priv, path.Path("cat"), 3, ts.Add(time.Hour*2))
76 + if err != nil {
77 + t.Fatal(err)
78 + }
79 +
80 + e5, err := CreateRoutingEntryData(priv, path.Path("dog"), 4, ts.Add(time.Hour*3))
81 + if err != nil {
82 + t.Fatal(err)
83 + }
84 +
85 + e6, err := CreateRoutingEntryData(priv, path.Path("fish"), 4, ts.Add(time.Hour*3))
86 + if err != nil {
87 + t.Fatal(err)
88 + }
89 +
90 + // e1 is the only record, i hope it gets this right
91 + err = AssertSelected(e1, e1)
92 + if err != nil {
93 + t.Fatal(err)
94 + }
95 +
96 + // e2 has the highest sequence number
97 + err = AssertSelected(e2, e1, e2)
98 + if err != nil {
99 + t.Fatal(err)
100 + }
101 +
102 + // e3 has the highest sequence number
103 + err = AssertSelected(e3, e1, e2, e3)
104 + if err != nil {
105 + t.Fatal(err)
106 + }
107 +
108 + // e4 has a higher timeout
109 + err = AssertSelected(e4, e1, e2, e3, e4)
110 + if err != nil {
111 + t.Fatal(err)
112 + }
113 +
114 + // e5 has the highest sequence number
115 + err = AssertSelected(e5, e1, e2, e3, e4, e5)
116 + if err != nil {
117 + t.Fatal(err)
118 + }
119 +
120 + // e6 should be selected as its signauture will win in the comparison
121 + err = AssertSelected(e6, e1, e2, e3, e4, e5, e6)
122 + if err != nil {
123 + t.Fatal(err)
124 + }
125 +
126 + _ = []interface{}{e1, e2, e3, e4, e5, e6}
127 +}
namesys/publisher.go
+18 -5
@@ -60,7 +60,7 @@ func (p *ipnsPublisher) PublishWithEOL(ctx context.Context, k ci.PrivKey, value
60 return err
61 }
62
63 - namekey, ipnskey := IpnsKeysForID(id)
63 + _, ipnskey := IpnsKeysForID(id)
64
65 // get previous records sequence number, and add one to it
66 var seqnum uint64
@@ -77,17 +77,22 @@ func (p *ipnsPublisher) PublishWithEOL(ctx context.Context, k ci.PrivKey, value
77 return err
78 }
79
80 + return PutRecordToRouting(ctx, k, value, seqnum, eol, p.routing, id)
81 +}
82 +
83 +func PutRecordToRouting(ctx context.Context, k ci.PrivKey, value path.Path, seqnum uint64, eol time.Time, r routing.IpfsRouting, id peer.ID) error {
84 + namekey, ipnskey := IpnsKeysForID(id)
85 entry, err := CreateRoutingEntryData(k, value, seqnum, eol)
86 if err != nil {
87 return err
88 }
89
85 - err = PublishEntry(ctx, p.routing, ipnskey, entry)
90 + err = PublishEntry(ctx, r, ipnskey, entry)
91 if err != nil {
92 return err
93 }
94
90 - err = PublishPublicKey(ctx, p.routing, namekey, k.GetPublic())
95 + err = PublishPublicKey(ctx, r, namekey, k.GetPublic())
96 if err != nil {
97 return err
98 }
@@ -174,13 +179,18 @@ func IpnsSelectorFunc(k key.Key, vals [][]byte) (int, error) {
179 }
180 }
181
182 + return selectRecord(recs, vals)
183 +}
184 +
185 +func selectRecord(recs []*pb.IpnsEntry, vals [][]byte) (int, error) {
186 var best_seq uint64
187 best_i := -1
188
189 for i, r := range recs {
181 - if r == nil {
190 + if r == nil || r.GetSequence() < best_seq {
191 continue
192 }
193 +
194 if best_i == -1 || r.GetSequence() > best_seq {
195 best_seq = r.GetSequence()
196 best_i = i
@@ -196,8 +206,11 @@ func IpnsSelectorFunc(k key.Key, vals [][]byte) (int, error) {
206 }
207
208 if rt.After(bestt) {
199 - best_seq = r.GetSequence()
209 best_i = i
210 + } else if rt == bestt {
211 + if bytes.Compare(vals[i], vals[best_i]) > 0 {
212 + best_i = i
213 + }
214 }
215 }
216 }
namesys/republisher/repub.go
+3 -15
@@ -69,7 +69,7 @@ func (rp *Republisher) Run(proc goprocess.Process) {
69 case <-tick.C:
70 err := rp.republishEntries(proc)
71 if err != nil {
72 - log.Error(err)
72 + log.Error("Republisher failed to republish: ", err)
73 }
74 case <-proc.Closing():
75 return
@@ -86,7 +86,7 @@ func (rp *Republisher) republishEntries(p goprocess.Process) error {
86 priv := rp.ps.PrivKey(id)
87
88 // Look for it locally only
89 - namekey, ipnskey := namesys.IpnsKeysForID(id)
89 + _, ipnskey := namesys.IpnsKeysForID(id)
90 p, seq, err := rp.getLastVal(ipnskey)
91 if err != nil {
92 if err == errNoEntry {
@@ -97,19 +97,7 @@ func (rp *Republisher) republishEntries(p goprocess.Process) error {
97
98 // update record with same sequence number
99 eol := time.Now().Add(rp.RecordLifetime)
100 - entry, err := namesys.CreateRoutingEntryData(priv, p, seq, eol)
101 - if err != nil {
102 - return err
103 - }
104 -
105 - // republish public key
106 - err = namesys.PublishPublicKey(ctx, rp.r, namekey, priv.GetPublic())
107 - if err != nil {
108 - return err
109 - }
110 -
111 - // republish ipns entry
112 - err = namesys.PublishEntry(ctx, rp.r, ipnskey, entry)
100 + err = namesys.PutRecordToRouting(ctx, priv, p, seq, eol, rp.r, id)
101 if err != nil {
102 return err
103 }
routing/dht/routing.go
+9 -1
@@ -3,6 +3,7 @@ package dht
3 import (
4 "bytes"
5 "sync"
6 + "time"
7
8 context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
9 key "github.com/ipfs/go-ipfs/blocks/key"
@@ -60,6 +61,8 @@ func (dht *IpfsDHT) PutValue(ctx context.Context, key key.Key, value []byte) err
61 for p := range pchan {
62 wg.Add(1)
63 go func(p peer.ID) {
64 + ctx, cancel := context.WithCancel(ctx)
65 + defer cancel()
66 defer wg.Done()
67 notif.PublishQueryEvent(ctx, &notif.QueryEvent{
68 Type: notif.Value,
@@ -78,7 +81,10 @@ func (dht *IpfsDHT) PutValue(ctx context.Context, key key.Key, value []byte) err
81
82 // GetValue searches for the value corresponding to given Key.
83 func (dht *IpfsDHT) GetValue(ctx context.Context, key key.Key) ([]byte, error) {
81 - vals, err := dht.GetValues(ctx, key, 3)
84 + ctx, cancel := context.WithTimeout(ctx, time.Minute)
85 + defer cancel()
86 +
87 + vals, err := dht.GetValues(ctx, key, 16)
88 if err != nil {
89 return nil, err
90 }
@@ -111,6 +117,8 @@ func (dht *IpfsDHT) GetValue(ctx context.Context, key key.Key) ([]byte, error) {
117 // if someone sent us a different 'less-valid' record, lets correct them
118 if !bytes.Equal(v.Val, best) {
119 go func(v routing.RecvdVal) {
120 + ctx, cancel := context.WithTimeout(dht.Context(), time.Second*30)
121 + defer cancel()
122 err := dht.putValueToPeer(ctx, v.From, key, fixupRec)
123 if err != nil {
124 log.Error("Error correcting DHT entry: ", err)