Skip to content
This repository has been archived by the owner on Mar 28, 2023. It is now read-only.

Commit

Permalink
add end-to-end test / ipld schema for signing/validation
Browse files Browse the repository at this point in the history
  • Loading branch information
willscott committed Jul 31, 2022
1 parent 372d78d commit 56594d1
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 34 deletions.
3 changes: 3 additions & 0 deletions client/findproviders.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ func ParseNodeAddresses(n *proto.Peer) []peer.AddrInfo {
}
infos = append(infos, peer.AddrInfo{ID: peerID, Addrs: []multiaddr.Multiaddr{ma}})
}
if len(n.Multiaddresses) == 0 {
infos = append(infos, peer.AddrInfo{ID: peerID})
}
return infos
}

Expand Down
95 changes: 64 additions & 31 deletions client/provide.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@ import (
"context"
"crypto/sha256"
"errors"
"fmt"
"time"

"github.com/ipfs/go-cid"
"github.com/ipfs/go-delegated-routing/gen/proto"
"github.com/ipld/edelweiss/values"
"github.com/ipld/go-ipld-prime"
"github.com/ipld/go-ipld-prime/codec/dagjson"
"github.com/ipld/go-ipld-prime/node/bindnode"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/multiformats/go-multiaddr"
"github.com/multiformats/go-multicodec"
"github.com/polydawn/refmt/cbor"
)
Expand Down Expand Up @@ -99,25 +102,50 @@ func parseProtocol(tp *proto.TransferProtocol) TransferProtocol {
type ProvideRequest struct {
Key cid.Cid
Provider
TTL time.Duration
signature struct {
At time.Time
Bytes []byte
Timestamp int64
AdvisoryTTL time.Duration
Signature []byte
}

var provideSchema, _ = ipld.LoadSchemaBytes([]byte(`
type ProvideRequest struct {
Key &Any
Provider Provider
Timestamp Int
AdvisoryTTL Int
Signature Bytes
}
type Provider struct {
Peer Peer
ProviderProto [TransferProtocol]
}
type Peer struct {
ID String
Multiaddresses [Bytes]
}
type TransferProtocol struct {
Codec Int
Payload Bytes
}
`))

func bytesToMA(b []byte) (interface{}, error) {
return multiaddr.NewMultiaddrBytes(b)
}
func maToBytes(iface interface{}) ([]byte, error) {
if ma, ok := iface.(multiaddr.Multiaddr); ok {
return ma.Bytes(), nil
}
return nil, fmt.Errorf("did not get expected MA type")
}

// Sign a provide request
func (pr *ProvideRequest) Sign(key crypto.PrivKey) error {
if pr.IsSigned() {
return errors.New("already Signed")
}
pr.signature = struct {
At time.Time
Bytes []byte
}{
At: time.Now(),
Bytes: []byte{},
}
pr.Timestamp = time.Now().Unix()
pr.Signature = []byte{}

sid, err := peer.IDFromPrivateKey(key)
if err != nil {
Expand All @@ -127,7 +155,12 @@ func (pr *ProvideRequest) Sign(key crypto.PrivKey) error {
return errors.New("not the correct signing key")
}

node := bindnode.Wrap(pr, nil)
ma, _ := multiaddr.NewMultiaddr("/")
opts := []bindnode.Option{
bindnode.TypedBytesConverter(&ma, bytesToMA, maToBytes),
}

node := bindnode.Wrap(pr, provideSchema.TypeByName("ProvideRequest"), opts...)
nodeRepr := node.Representation()
outBuf := bytes.NewBuffer(nil)
if err = dagjson.Encode(nodeRepr, outBuf); err != nil {
Expand All @@ -138,21 +171,26 @@ func (pr *ProvideRequest) Sign(key crypto.PrivKey) error {
if err != nil {
return err
}
pr.signature.Bytes = sig
pr.Signature = sig
return nil
}

func (pr *ProvideRequest) Verify() error {
if !pr.IsSigned() {
return errors.New("not signed")
}
sig := pr.signature.Bytes
pr.signature.Bytes = []byte{}
sig := pr.Signature
pr.Signature = []byte{}
defer func() {
pr.signature.Bytes = sig
pr.Signature = sig
}()

node := bindnode.Wrap(pr, nil)
ma, _ := multiaddr.NewMultiaddr("/")
opts := []bindnode.Option{
bindnode.TypedBytesConverter(&ma, bytesToMA, maToBytes),
}

node := bindnode.Wrap(pr, provideSchema.TypeByName("ProvideRequest"), opts...)
nodeRepr := node.Representation()
outBuf := bytes.NewBuffer(nil)
if err := dagjson.Encode(nodeRepr, outBuf); err != nil {
Expand All @@ -178,21 +216,16 @@ func (pr *ProvideRequest) Verify() error {

// IsSigned indicates if the ProvideRequest has been signed
func (pr *ProvideRequest) IsSigned() bool {
return pr.signature.Bytes != nil
return pr.Signature != nil
}

func ParseProvideRequest(req *proto.ProvideRequest) (*ProvideRequest, error) {
pr := ProvideRequest{
Key: cid.Cid(req.Key),
Provider: parseProvider(&req.Provider),
TTL: time.Duration(req.AdvisoryTTL),
signature: struct {
At time.Time
Bytes []byte
}{
At: time.Unix(int64(req.Timestamp), 0),
Bytes: req.Signature,
},
Key: cid.Cid(req.Key),
Provider: parseProvider(&req.Provider),
AdvisoryTTL: time.Duration(req.AdvisoryTTL),
Timestamp: int64(req.Timestamp),
Signature: req.Signature,
}

if err := pr.Verify(); err != nil {
Expand Down Expand Up @@ -225,9 +258,9 @@ func (fp *Client) Provide(ctx context.Context, req *ProvideRequest) (<-chan Prov
ch0, err := fp.client.Provide_Async(ctx, &proto.ProvideRequest{
Key: proto.LinkToAny(req.Key),
Provider: *req.Provider.ToProto(),
Timestamp: values.Int(req.signature.At.Unix()),
AdvisoryTTL: values.Int(req.TTL),
Signature: req.signature.Bytes,
Timestamp: values.Int(req.Timestamp),
AdvisoryTTL: values.Int(req.AdvisoryTTL),
Signature: req.Signature,
})
if err != nil {
return nil, err
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ require (
github.com/ipfs/go-ipns v0.1.2
github.com/ipfs/go-log/v2 v2.5.1
github.com/ipld/edelweiss v0.1.5
github.com/ipld/go-ipld-prime v0.17.0
github.com/ipld/go-ipld-prime v0.17.1-0.20220627233435-adf99676901e
github.com/libp2p/go-libp2p-core v0.16.1
github.com/libp2p/go-libp2p-record v0.1.3
github.com/multiformats/go-multiaddr v0.5.0
github.com/multiformats/go-multicodec v0.5.0
github.com/multiformats/go-multihash v0.1.0
github.com/multiformats/go-multihash v0.2.0
github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e
)

Expand Down Expand Up @@ -42,7 +42,7 @@ require (
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.19.1 // indirect
golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf // indirect
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
lukechampine.com/blake3 v1.1.6 // indirect
)
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ github.com/ipld/edelweiss v0.1.5/go.mod h1:IVSfo5e7vJrTKKRjR1lrtfgc2UbEMvvatNycf
github.com/ipld/go-ipld-prime v0.9.0/go.mod h1:KvBLMr4PX1gWptgkzRjVZCrLmSGcZCb/jioOQwCqZN8=
github.com/ipld/go-ipld-prime v0.17.0 h1:+U2peiA3aQsE7mrXjD2nYZaZrCcakoz2Wge8K42Ld8g=
github.com/ipld/go-ipld-prime v0.17.0/go.mod h1:aYcKm5TIvGfY8P3QBKz/2gKcLxzJ1zDaD+o0bOowhgs=
github.com/ipld/go-ipld-prime v0.17.1-0.20220627233435-adf99676901e h1:p5qepdt1UEk6UadNwNBFDlm/uC+GwSmdVB4wqyt2JLA=
github.com/ipld/go-ipld-prime v0.17.1-0.20220627233435-adf99676901e/go.mod h1:735yXW548CKrLwVCYXzqx90p5deRJMVVxM9eJ4Qe+qE=
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY=
github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
Expand Down Expand Up @@ -205,6 +207,8 @@ github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUj
github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg=
github.com/multiformats/go-multihash v0.1.0 h1:CgAgwqk3//SVEw3T+6DqI4mWMyRuDwZtOWcJT0q9+EA=
github.com/multiformats/go-multihash v0.1.0/go.mod h1:RJlXsxt6vHGaia+S8We0ErjhojtKzPP2AH4+kYM7k84=
github.com/multiformats/go-multihash v0.2.0 h1:oytJb9ZA1OUW0r0f9ea18GiaPOo4SXyc7p2movyUuo4=
github.com/multiformats/go-multihash v0.2.0/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc=
github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY=
Expand Down Expand Up @@ -296,6 +300,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf h1:B2n+Zi5QeYRDAEodEu72OS36gmTWjgpXr2+cWcBW90o=
golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
Expand Down
54 changes: 54 additions & 0 deletions test/provide_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package test

import (
"context"
"crypto/rand"
"testing"
"time"

"github.com/ipfs/go-cid"
"github.com/ipfs/go-delegated-routing/client"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/multiformats/go-multihash"
)

func TestProvideRoundtrip(t *testing.T) {
priv, _, err := crypto.GenerateEd25519Key(rand.Reader)
if err != nil {
t.Fatal(err)
}
pID, err := peer.IDFromPrivateKey(priv)
if err != nil {
t.Fatal(err)
}

c, s := createClientAndServer(t, testDelegatedRoutingService{})
defer s.Close()

testMH, _ := multihash.Encode([]byte("test"), multihash.IDENTITY)
testCid := cid.NewCidV1(cid.Raw, testMH)
req := client.ProvideRequest{
Key: testCid,
Provider: client.Provider{
Peer: peer.AddrInfo{ID: pID},
},
AdvisoryTTL: time.Hour,
}
rc, err := c.Provide(context.Background(), &req)
if err == nil {
t.Fatal("should get sync error on unsigned provide request.")
}

if err = req.Sign(priv); err != nil {
t.Fatal(err)
}
if rc, err = c.Provide(context.Background(), &req); err != nil {
t.Fatal(err)
}

res := <-rc
if res.Err != nil {
t.Fatal(err)
}
}

0 comments on commit 56594d1

Please sign in to comment.