Skip to content

Commit

Permalink
extract ipns record logic to go-ipns
Browse files Browse the repository at this point in the history
License: MIT
Signed-off-by: Steven Allen <[email protected]>
  • Loading branch information
Stebalien committed Jun 16, 2018
1 parent d643c04 commit dafe495
Show file tree
Hide file tree
Showing 15 changed files with 56 additions and 704 deletions.
3 changes: 0 additions & 3 deletions Rules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,6 @@ ifneq ($(filter coverage% clean distclean,$(MAKECMDGOALS)),)
include $(dir)/Rules.mk
endif

dir := namesys/pb
include $(dir)/Rules.mk

dir := unixfs/pb
include $(dir)/Rules.mk

Expand Down
9 changes: 6 additions & 3 deletions core/commands/dht_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ import (
"testing"

"github.com/ipfs/go-ipfs/namesys"

tu "gx/ipfs/QmPdxCaVp4jZ9RbxqZADvKH6kiCR5jHvdR5f2ycjAY6T2a/go-testutil"
ipns "gx/ipfs/QmRAPFFaF7nrezCZQaLihyp2qbAXqSJU5WpvSpwroMv1Xt/go-ipns"
)

func TestKeyTranslation(t *testing.T) {
pid := tu.RandPeerIDFatal(t)
a, b := namesys.IpnsKeysForID(pid)
pkname := namesys.PkKeyForID(pid)
ipnsname := ipns.RecordKey(pid)

pkk, err := escapeDhtKey("/pk/" + pid.Pretty())
if err != nil {
Expand All @@ -21,11 +24,11 @@ func TestKeyTranslation(t *testing.T) {
t.Fatal(err)
}

if pkk != a {
if pkk != pkname {
t.Fatal("keys didnt match!")
}

if ipnsk != b {
if ipnsk != ipnsname {
t.Fatal("keys didnt match!")
}
}
3 changes: 2 additions & 1 deletion core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import (
circuit "gx/ipfs/QmPavh4h3Edx5cv8GJQPC35AQAws7faXmzEZyru7k9b9Mn/go-libp2p-circuit"
u "gx/ipfs/QmPdKqUcHGFdeSpvjVoaTRPPstGif9GBZb5Q56RVw9o69A/go-ipfs-util"
p2phost "gx/ipfs/QmQQGtcp6nVUrQjNsnU53YWV1q8fK1Kd9S7FEkYbRZzxry/go-libp2p-host"
ipns "gx/ipfs/QmRAPFFaF7nrezCZQaLihyp2qbAXqSJU5WpvSpwroMv1Xt/go-ipns"
floodsub "gx/ipfs/QmRFEBGcNjtWPupwHA7zGHeGVLuUyE4ZRFi2MgtrPM6pfb/go-libp2p-floodsub"
pnet "gx/ipfs/QmRGvSwDpN4eunxgDNfmQhayZ6Z9F5a2v31V2D7y77osLg/go-libp2p-pnet"
goprocess "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess"
Expand Down Expand Up @@ -459,7 +460,7 @@ func (n *IpfsNode) startOnlineServicesWithHost(ctx context.Context, host p2phost

validator := record.NamespacedValidator{
"pk": record.PublicKeyValidator{},
"ipns": namesys.IpnsValidator{KeyBook: host.Peerstore()},
"ipns": ipns.Validator{KeyBook: host.Peerstore()},
}

// setup routing service
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,171 +2,26 @@ package namesys

import (
"context"
"fmt"
"math/rand"
"strings"
"testing"
"time"

opts "github.com/ipfs/go-ipfs/namesys/opts"
pb "github.com/ipfs/go-ipfs/namesys/pb"
path "github.com/ipfs/go-ipfs/path"

record "gx/ipfs/QmPWjVzxHeJdrjp4Jr2R2sPxBrMbBgGPWQtKwCKHHCBF7x/go-libp2p-record"
u "gx/ipfs/QmPdKqUcHGFdeSpvjVoaTRPPstGif9GBZb5Q56RVw9o69A/go-ipfs-util"
testutil "gx/ipfs/QmPdxCaVp4jZ9RbxqZADvKH6kiCR5jHvdR5f2ycjAY6T2a/go-testutil"
ipns "gx/ipfs/QmRAPFFaF7nrezCZQaLihyp2qbAXqSJU5WpvSpwroMv1Xt/go-ipns"
routing "gx/ipfs/QmUV9hDAAyjeGbxbXkJ2sYqZ6dTd1DXJ2REhYEkRm178Tg/go-libp2p-routing"
ropts "gx/ipfs/QmUV9hDAAyjeGbxbXkJ2sYqZ6dTd1DXJ2REhYEkRm178Tg/go-libp2p-routing/options"
peer "gx/ipfs/QmVf8hTAsLLFtn4WPCRNdnaF2Eag2qTBS6uR8AiHPZARXy/go-libp2p-peer"
proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
pstore "gx/ipfs/QmZhsmorLpD9kmQ4ynbAu4vbKv2goMUnXazwGA4gnWHDjB/go-libp2p-peerstore"
mockrouting "gx/ipfs/Qmb1N7zdjG2FexpzWNj8T289u9QnQLEiSsTRadDGQxX32D/go-ipfs-routing/mock"
ci "gx/ipfs/Qme1knMqwt1hKZbc1BmQFmnm9f36nyQGwXxPGVpVJ9rMK5/go-libp2p-crypto"
ds "gx/ipfs/QmeiCcJfDW1GJnWUArudsv5rQsihpi4oyddPhdqo3CfX6i/go-datastore"
dssync "gx/ipfs/QmeiCcJfDW1GJnWUArudsv5rQsihpi4oyddPhdqo3CfX6i/go-datastore/sync"
)

func testValidatorCase(t *testing.T, priv ci.PrivKey, kbook pstore.KeyBook, key string, val []byte, eol time.Time, exp error) {
t.Helper()

match := func(t *testing.T, err error) {
t.Helper()
if err != exp {
params := fmt.Sprintf("key: %s\neol: %s\n", key, eol)
if exp == nil {
t.Fatalf("Unexpected error %s for params %s", err, params)
} else if err == nil {
t.Fatalf("Expected error %s but there was no error for params %s", exp, params)
} else {
t.Fatalf("Expected error %s but got %s for params %s", exp, err, params)
}
}
}

testValidatorCaseMatchFunc(t, priv, kbook, key, val, eol, match)
}

func testValidatorCaseMatchFunc(t *testing.T, priv ci.PrivKey, kbook pstore.KeyBook, key string, val []byte, eol time.Time, matchf func(*testing.T, error)) {
t.Helper()
validator := IpnsValidator{kbook}

data := val
if data == nil {
p := path.Path("/ipfs/QmfM2r8seH2GiRaC4esTjeraXEachRt8ZsSeGaWTPLyMoG")
entry, err := CreateRoutingEntryData(priv, p, 1, eol)
if err != nil {
t.Fatal(err)
}

data, err = proto.Marshal(entry)
if err != nil {
t.Fatal(err)
}
}

matchf(t, validator.Validate(key, data))
}

func TestValidator(t *testing.T) {
ts := time.Now()

priv, id, _, _ := genKeys(t)
priv2, id2, _, _ := genKeys(t)
kbook := pstore.NewPeerstore()
kbook.AddPubKey(id, priv.GetPublic())
emptyKbook := pstore.NewPeerstore()

testValidatorCase(t, priv, kbook, "/ipns/"+string(id), nil, ts.Add(time.Hour), nil)
testValidatorCase(t, priv, kbook, "/ipns/"+string(id), nil, ts.Add(time.Hour*-1), ErrExpiredRecord)
testValidatorCase(t, priv, kbook, "/ipns/"+string(id), []byte("bad data"), ts.Add(time.Hour), ErrBadRecord)
testValidatorCase(t, priv, kbook, "/ipns/"+"bad key", nil, ts.Add(time.Hour), ErrKeyFormat)
testValidatorCase(t, priv, emptyKbook, "/ipns/"+string(id), nil, ts.Add(time.Hour), ErrPublicKeyNotFound)
testValidatorCase(t, priv2, kbook, "/ipns/"+string(id2), nil, ts.Add(time.Hour), ErrPublicKeyNotFound)
testValidatorCase(t, priv2, kbook, "/ipns/"+string(id), nil, ts.Add(time.Hour), ErrSignature)
testValidatorCase(t, priv, kbook, "//"+string(id), nil, ts.Add(time.Hour), ErrInvalidPath)
testValidatorCase(t, priv, kbook, "/wrong/"+string(id), nil, ts.Add(time.Hour), ErrInvalidPath)
}

func mustMarshal(t *testing.T, entry *pb.IpnsEntry) []byte {
t.Helper()
data, err := proto.Marshal(entry)
if err != nil {
t.Fatal(err)
}
return data
}

func TestEmbeddedPubKeyValidate(t *testing.T) {
goodeol := time.Now().Add(time.Hour)
kbook := pstore.NewPeerstore()

pth := path.Path("/ipfs/QmfM2r8seH2GiRaC4esTjeraXEachRt8ZsSeGaWTPLyMoG")

priv, _, _, ipnsk := genKeys(t)

entry, err := CreateRoutingEntryData(priv, pth, 1, goodeol)
if err != nil {
t.Fatal(err)
}

testValidatorCase(t, priv, kbook, ipnsk, mustMarshal(t, entry), goodeol, ErrPublicKeyNotFound)

pubkb, err := priv.GetPublic().Bytes()
if err != nil {
t.Fatal(err)
}

entry.PubKey = pubkb
testValidatorCase(t, priv, kbook, ipnsk, mustMarshal(t, entry), goodeol, nil)

entry.PubKey = []byte("probably not a public key")
testValidatorCaseMatchFunc(t, priv, kbook, ipnsk, mustMarshal(t, entry), goodeol, func(t *testing.T, err error) {
if !strings.Contains(err.Error(), "unmarshaling pubkey in record:") {
t.Fatal("expected pubkey unmarshaling to fail")
}
})

opriv, _, _, _ := genKeys(t)
wrongkeydata, err := opriv.GetPublic().Bytes()
if err != nil {
t.Fatal(err)
}

entry.PubKey = wrongkeydata
testValidatorCase(t, priv, kbook, ipnsk, mustMarshal(t, entry), goodeol, ErrPublicKeyMismatch)
}

func TestPeerIDPubKeyValidate(t *testing.T) {
goodeol := time.Now().Add(time.Hour)
kbook := pstore.NewPeerstore()

pth := path.Path("/ipfs/QmfM2r8seH2GiRaC4esTjeraXEachRt8ZsSeGaWTPLyMoG")

sk, pk, err := ci.GenerateEd25519Key(rand.New(rand.NewSource(42)))
if err != nil {
t.Fatal(err)
}

pid, err := peer.IDFromPublicKey(pk)
if err != nil {
t.Fatal(err)
}

ipnsk := "/ipns/" + string(pid)

entry, err := CreateRoutingEntryData(sk, pth, 1, goodeol)
if err != nil {
t.Fatal(err)
}

dataNoKey, err := proto.Marshal(entry)
if err != nil {
t.Fatal(err)
}

testValidatorCase(t, sk, kbook, ipnsk, dataNoKey, goodeol, nil)
}

func TestResolverValidation(t *testing.T) {
ctx := context.Background()
rid := testutil.RandIdentityOrFatal(t)
Expand All @@ -179,8 +34,8 @@ func TestResolverValidation(t *testing.T) {
// Create entry with expiry in one hour
priv, id, _, ipnsDHTPath := genKeys(t)
ts := time.Now()
p := path.Path("/ipfs/QmfM2r8seH2GiRaC4esTjeraXEachRt8ZsSeGaWTPLyMoG")
entry, err := CreateRoutingEntryData(priv, p, 1, ts.Add(time.Hour))
p := []byte("/ipfs/QmfM2r8seH2GiRaC4esTjeraXEachRt8ZsSeGaWTPLyMoG")
entry, err := ipns.Create(priv, p, 1, ts.Add(time.Hour))
if err != nil {
t.Fatal(err)
}
Expand All @@ -202,12 +57,12 @@ func TestResolverValidation(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if resp != p {
if resp != path.Path(p) {
t.Fatalf("Mismatch between published path %s and resolved path %s", p, resp)
}

// Create expired entry
expiredEntry, err := CreateRoutingEntryData(priv, p, 1, ts.Add(-1*time.Hour))
expiredEntry, err := ipns.Create(priv, p, 1, ts.Add(-1*time.Hour))
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -248,7 +103,7 @@ func TestResolverValidation(t *testing.T) {

// Publish entry without making public key available in peer store
priv3, id3, pubkDHTPath3, ipnsDHTPath3 := genKeys(t)
entry3, err := CreateRoutingEntryData(priv3, p, 1, ts.Add(time.Hour))
entry3, err := ipns.Create(priv3, p, 1, ts.Add(time.Hour))
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -292,9 +147,8 @@ func genKeys(t *testing.T) (ci.PrivKey, peer.ID, string, string) {
if err != nil {
t.Fatal(err)
}
pubkDHTPath, ipnsDHTPath := IpnsKeysForID(pid)

return priv, pid, pubkDHTPath, ipnsDHTPath
return priv, pid, PkKeyForID(pid), ipns.RecordKey(pid)
}

type mockValueStore struct {
Expand All @@ -307,7 +161,7 @@ func newMockValueStore(id testutil.Identity, dstore ds.Datastore, kbook pstore.K
serv := mockrouting.NewServer()
r := serv.ClientWithDatastore(context.Background(), id, dstore)
return &mockValueStore{r, kbook, record.NamespacedValidator{
"ipns": IpnsValidator{kbook},
"ipns": ipns.Validator{KeyBook: kbook},
"pk": record.PublicKeyValidator{},
}}
}
Expand Down
Loading

0 comments on commit dafe495

Please sign in to comment.