From d674dd7e1fe3c72080b8ba0c18de2a63da498640 Mon Sep 17 00:00:00 2001 From: Kevin Atkinson Date: Wed, 7 Jun 2017 14:23:58 -0400 Subject: [PATCH 1/2] repub: iterate through all keys in keystore Iterate through all keys in the keystore so keys added with "ipfs key gen" behave the same as the key. Don't maintain a separate repub list as it does not really serve a purpose at this point in time. See #3808. License: MIT Signed-off-by: Kevin Atkinson --- core/core.go | 3 +- namesys/republisher/repub.go | 83 ++++++++++++++++++++---------- namesys/republisher/repub_test.go | 3 +- test/sharness/t0240-republisher.sh | 23 +++++++++ 4 files changed, 80 insertions(+), 32 deletions(-) diff --git a/core/core.go b/core/core.go index 525dce20c..da612ac0f 100644 --- a/core/core.go +++ b/core/core.go @@ -366,8 +366,7 @@ func (n *IpfsNode) setupIpnsRepublisher() error { return err } - n.IpnsRepub = ipnsrp.NewRepublisher(n.Routing, n.Repo.Datastore(), n.Peerstore) - n.IpnsRepub.AddName(n.Identity) + n.IpnsRepub = ipnsrp.NewRepublisher(n.Routing, n.Repo.Datastore(), n.PrivateKey, n.Repo.Keystore()) if cfg.Ipns.RepublishPeriod != "" { d, err := time.ParseDuration(cfg.Ipns.RepublishPeriod) diff --git a/namesys/republisher/repub.go b/namesys/republisher/repub.go index 94ad4e8e0..9fa0907da 100644 --- a/namesys/republisher/repub.go +++ b/namesys/republisher/repub.go @@ -6,18 +6,19 @@ import ( "sync" "time" + keystore "github.com/ipfs/go-ipfs/keystore" namesys "github.com/ipfs/go-ipfs/namesys" pb "github.com/ipfs/go-ipfs/namesys/pb" path "github.com/ipfs/go-ipfs/path" dshelp "github.com/ipfs/go-ipfs/thirdparty/ds-help" routing "gx/ipfs/QmNdaQ8itUU9jEZUwTsG4gHMaPmRfi6FEe89QjQAFbep3M/go-libp2p-routing" + ic "gx/ipfs/QmP1DfoUjiWH2ZBo1PBH6FupdBucbDepx3HpWmEY6JMUpY/go-libp2p-crypto" ds "gx/ipfs/QmRWDav6mzWseLWeYfVd5fvUKiVe9xNH29YfMF438fG364/go-datastore" goprocess "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess" gpctx "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess/context" logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log" recpb "gx/ipfs/QmWYCqr6UDqqD1bfRybaAPtbAqcN3TSJpveaBXMwbQ3ePZ/go-libp2p-record/pb" - pstore "gx/ipfs/QmXZSd1qR5BxZkPyuwfT5jpqQFScZccoZvDneXsKzCNHWX/go-libp2p-peerstore" proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto" peer "gx/ipfs/QmdS9KpbDyPrieswibZhkod1oXqRwZJrUPzxCofAMWpFGq/go-libp2p-peer" ) @@ -31,9 +32,10 @@ var DefaultRebroadcastInterval = time.Hour * 4 const DefaultRecordLifetime = time.Hour * 24 type Republisher struct { - r routing.ValueStore - ds ds.Datastore - ps pstore.Peerstore + r routing.ValueStore + ds ds.Datastore + self ic.PrivKey + ks keystore.Keystore Interval time.Duration @@ -44,23 +46,18 @@ type Republisher struct { entries map[peer.ID]struct{} } -func NewRepublisher(r routing.ValueStore, ds ds.Datastore, ps pstore.Peerstore) *Republisher { +// NewRepublisher creates a new Republisher +func NewRepublisher(r routing.ValueStore, ds ds.Datastore, self ic.PrivKey, ks keystore.Keystore) *Republisher { return &Republisher{ r: r, - ps: ps, ds: ds, - entries: make(map[peer.ID]struct{}), + self: self, + ks: ks, Interval: DefaultRebroadcastInterval, RecordLifetime: DefaultRecordLifetime, } } -func (rp *Republisher) AddName(id peer.ID) { - rp.entrylock.Lock() - defer rp.entrylock.Unlock() - rp.entries[id] = struct{}{} -} - func (rp *Republisher) Run(proc goprocess.Process) { tick := time.NewTicker(rp.Interval) defer tick.Stop() @@ -82,31 +79,61 @@ func (rp *Republisher) republishEntries(p goprocess.Process) error { ctx, cancel := context.WithCancel(gpctx.OnClosingContext(p)) defer cancel() - for id, _ := range rp.entries { - log.Debugf("republishing ipns entry for %s", id) - priv := rp.ps.PrivKey(id) + err := rp.republishEntry(ctx, rp.self) + if err != nil { + return err + } - // Look for it locally only - _, ipnskey := namesys.IpnsKeysForID(id) - p, seq, err := rp.getLastVal(ipnskey) + if rp.ks != nil { + keyNames, err := rp.ks.List() if err != nil { - if err == errNoEntry { - continue + return err + } + for _, name := range keyNames { + priv, err := rp.ks.Get(name) + if err != nil { + return err + } + err = rp.republishEntry(ctx, priv) + if err != nil { + return err } - return err - } - // update record with same sequence number - eol := time.Now().Add(rp.RecordLifetime) - err = namesys.PutRecordToRouting(ctx, priv, p, seq, eol, rp.r, id) - if err != nil { - return err } } return nil } +func (rp *Republisher) republishEntry(ctx context.Context, priv ic.PrivKey) error { + id, err := peer.IDFromPrivateKey(priv) + if err != nil { + return err + } + + log.Debugf("republishing ipns entry for %s", id) + + // Look for it locally only + _, ipnskey := namesys.IpnsKeysForID(id) + p, seq, err := rp.getLastVal(ipnskey) + if err != nil { + if err == errNoEntry { + return nil + } + return err + } + + // update record with same sequence number + eol := time.Now().Add(rp.RecordLifetime) + err = namesys.PutRecordToRouting(ctx, priv, p, seq, eol, rp.r, id) + if err != nil { + println("put record to routing error: " + err.Error()) + return err + } + + return nil +} + func (rp *Republisher) getLastVal(k string) (path.Path, uint64, error) { ival, err := rp.ds.Get(dshelp.NewKeyFromBinary([]byte(k))) if err != nil { diff --git a/namesys/republisher/repub_test.go b/namesys/republisher/repub_test.go index a4810e8ba..d4d7e1282 100644 --- a/namesys/republisher/repub_test.go +++ b/namesys/republisher/repub_test.go @@ -78,10 +78,9 @@ func TestRepublish(t *testing.T) { // The republishers that are contained within the nodes have their timeout set // to 12 hours. Instead of trying to tweak those, we're just going to pretend // they dont exist and make our own. - repub := NewRepublisher(publisher.Routing, publisher.Repo.Datastore(), publisher.Peerstore) + repub := NewRepublisher(publisher.Routing, publisher.Repo.Datastore(), publisher.PrivateKey, publisher.Repo.Keystore()) repub.Interval = time.Second repub.RecordLifetime = time.Second * 5 - repub.AddName(publisher.Identity) proc := goprocess.Go(repub.Run) defer proc.Close() diff --git a/test/sharness/t0240-republisher.sh b/test/sharness/t0240-republisher.sh index 6bb5f60e4..0d0f3661f 100755 --- a/test/sharness/t0240-republisher.sh +++ b/test/sharness/t0240-republisher.sh @@ -94,6 +94,29 @@ go-sleep 15s verify_can_resolve "$num_test_nodes" "$id" "$HASH" "republisher fires after twenty seconds" +# + +test_expect_success "generate new key" ' +KEY2=`ipfsi 1 key gen beepboop --type ed25519` +' + +test_expect_success "publish with new key succeeds" ' + HASH=$(echo "barfoo" | ipfsi 1 add -q) && + ipfsi 1 name publish -t 5s -k "$KEY2" $HASH +' + +verify_can_resolve "$num_test_nodes" "$KEY2" "$HASH" "new key just after publishing" + +go-sleep 5s + +verify_cannot_resolve "$num_test_nodes" "$KEY2" "new key cannot resolve after 5 seconds" + +go-sleep 15s + +verify_can_resolve "$num_test_nodes" "$KEY2" "$HASH" "new key can resolve again after republish" + +# + teardown_iptb test_done From 1fe6e18d441bf319b39bc8798f642590554c964e Mon Sep 17 00:00:00 2001 From: Kevin Atkinson Date: Sat, 10 Jun 2017 01:55:04 -0400 Subject: [PATCH 2/2] repub: remove unused field License: MIT Signed-off-by: Kevin Atkinson --- namesys/republisher/repub.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/namesys/republisher/repub.go b/namesys/republisher/repub.go index 9fa0907da..b33328b68 100644 --- a/namesys/republisher/repub.go +++ b/namesys/republisher/repub.go @@ -3,7 +3,6 @@ package republisher import ( "context" "errors" - "sync" "time" keystore "github.com/ipfs/go-ipfs/keystore" @@ -41,9 +40,6 @@ type Republisher struct { // how long records that are republished should be valid for RecordLifetime time.Duration - - entrylock sync.Mutex - entries map[peer.ID]struct{} } // NewRepublisher creates a new Republisher