Security API additions.

-Principal can now get a slice of blessings that match a name.
-Principal can now get a name for a blessing that belongs to it.
-BlessingStore exports a map of all the pattern/blessings that have been added.

Change-Id: Idaa8d9ddf8acd03a7d2b72d5bf408566d1a8cdc1
diff --git a/security/agent/agent_test.go b/security/agent/agent_test.go
index d0acb43..18b61ea 100644
--- a/security/agent/agent_test.go
+++ b/security/agent/agent_test.go
@@ -69,6 +69,8 @@
 		{"Sign", V{make([]byte, 10)}, security.Signature{Purpose: []byte{}, R: []byte{1}, S: []byte{1}}, nil},
 		{"MintDischarge", V{thirdPartyCaveat, security.UnconstrainedUse()}, discharge, nil},
 		{"PublicKey", V{}, mockP.PublicKey(), nil},
+		{"BlessingsByName", V{security.BlessingPattern("self")}, []security.Blessings{newBlessing(t, "blessing")}, nil},
+		{"BlessingsInfo", V{newBlessing(t, "blessing")}, []string{"blessing"}, nil},
 		{"AddToRoots", V{newBlessing(t, "blessing")}, nil, verror2.Make(addToRootsErr, nil)},
 	}
 	for _, test := range tests {
@@ -84,6 +86,7 @@
 		{"SetDefault", V{newBlessing(t, "blessing")}, nil, verror2.Make(storeSetDefaultErr, nil)},
 		{"Default", V{}, newBlessing(t, "root/extension"), nil},
 		{"PublicKey", V{}, mockP.PublicKey(), nil},
+		{"PeerBlessings", V{}, map[security.BlessingPattern]security.Blessings{"test": newBlessing(t, "root/extension")}, nil},
 		{"DebugString", V{}, "StoreString", nil},
 	}
 	for _, test := range storeTests {
@@ -176,6 +179,18 @@
 	return d, p.NextError
 }
 
+func (p *mockPrincipal) BlessingsByName(name security.BlessingPattern) []security.Blessings {
+	defer p.reset()
+	b, _ := p.NextResult.([]security.Blessings)
+	return b
+}
+
+func (p *mockPrincipal) BlessingsInfo(blessings security.Blessings) []string {
+	defer p.reset()
+	s, _ := p.NextResult.([]string)
+	return s
+}
+
 func (p *mockPrincipal) PublicKey() security.PublicKey         { return p.Key }
 func (p *mockPrincipal) Roots() security.BlessingRoots         { return p.MockRoots }
 func (p *mockPrincipal) BlessingStore() security.BlessingStore { return p.MockStore }
@@ -220,6 +235,12 @@
 
 func (s *mockBlessingStore) PublicKey() security.PublicKey { return s.Key }
 
+func (s *mockBlessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
+	defer s.reset()
+	m, _ := s.NextResult.(map[security.BlessingPattern]security.Blessings)
+	return m
+}
+
 func (s *mockBlessingStore) DebugString() string {
 	defer s.reset()
 	return s.NextResult.(string)
diff --git a/security/agent/client.go b/security/agent/client.go
index 6a3925f..cd26573 100644
--- a/security/agent/client.go
+++ b/security/agent/client.go
@@ -128,6 +128,33 @@
 	return c.key
 }
 
+func (c *client) BlessingsByName(pattern security.BlessingPattern) []security.Blessings {
+	var wbResults []security.WireBlessings
+	err := c.caller.call("BlessingsByName", results(&wbResults), pattern)
+	if err != nil {
+		vlog.Errorf("error calling BlessingsByName: %v", err)
+		return nil
+	}
+	blessings := make([]security.Blessings, len(wbResults))
+	for i, wb := range wbResults {
+		var err error
+		blessings[i], err = security.NewBlessings(wb)
+		if err != nil {
+			vlog.Errorf("error creating Blessing from WireBlessings: %v", err)
+		}
+	}
+	return blessings
+}
+
+func (c *client) BlessingsInfo(blessings security.Blessings) []string {
+	var names []string
+	err := c.caller.call("BlessingsInfo", results(&names), security.MarshalBlessings(blessings))
+	if err != nil {
+		vlog.Errorf("error calling BlessingsInfo: %v", err)
+		return nil
+	}
+	return names
+}
 func (c *client) BlessingStore() security.BlessingStore {
 	return &blessingStore{c.caller, c.key}
 }
@@ -192,6 +219,25 @@
 	return b.key
 }
 
+func (b *blessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
+	var wbMap map[security.BlessingPattern]security.WireBlessings
+	err := b.caller.call("BlessingStorePeerBlessings", results(&wbMap))
+	if err != nil {
+		vlog.Errorf("error calling BlessingStorePeerBlessings: %v", err)
+		return nil
+	}
+	bMap := make(map[security.BlessingPattern]security.Blessings)
+	for pattern, wb := range wbMap {
+		blessings, err := security.NewBlessings(wb)
+		if err != nil {
+			vlog.Errorf("error creating Blessing from WireBlessings: %v", err)
+			return nil
+		}
+		bMap[pattern] = blessings
+	}
+	return bMap
+}
+
 func (b *blessingStore) DebugString() (s string) {
 	err := b.caller.call("BlessingStoreDebugString", results(&s))
 	if err != nil {
diff --git a/security/agent/server/server.go b/security/agent/server/server.go
index c6ff7ea..fcf25a3 100644
--- a/security/agent/server/server.go
+++ b/security/agent/server/server.go
@@ -307,6 +307,23 @@
 	return a.principal.PublicKey().MarshalBinary()
 }
 
+func (a agentd) BlessingsByName(_ ipc.ServerContext, name security.BlessingPattern) ([]security.WireBlessings, error) {
+	blessings := a.principal.BlessingsByName(name)
+	ret := make([]security.WireBlessings, len(blessings))
+	for i, b := range blessings {
+		ret[i] = security.MarshalBlessings(b)
+	}
+	return ret, nil
+}
+
+func (a agentd) BlessingsInfo(_ ipc.ServerContext, blessings security.WireBlessings) ([]string, error) {
+	b, err := security.NewBlessings(blessings)
+	if err != nil {
+		return nil, err
+	}
+	return a.principal.BlessingsInfo(b), nil
+}
+
 func (a agentd) AddToRoots(_ ipc.ServerContext, wireBlessings security.WireBlessings) error {
 	blessings, err := security.NewBlessings(wireBlessings)
 	if err != nil {
@@ -339,6 +356,15 @@
 	return a.principal.BlessingStore().SetDefault(blessings)
 }
 
+func (a agentd) BlessingStorePeerBlessings(_ ipc.ServerContext) (map[security.BlessingPattern]security.WireBlessings, error) {
+	bMap := a.principal.BlessingStore().PeerBlessings()
+	wbMap := make(map[security.BlessingPattern]security.WireBlessings, len(bMap))
+	for p, b := range bMap {
+		wbMap[p] = security.MarshalBlessings(b)
+	}
+	return wbMap, nil
+}
+
 func (a agentd) BlessingStoreDebugString(_ ipc.ServerContext) (string, error) {
 	return a.principal.BlessingStore().DebugString(), nil
 }
diff --git a/security/agent/server/wire.vdl b/security/agent/server/wire.vdl
index dc52a7c..ee55e0b 100644
--- a/security/agent/server/wire.vdl
+++ b/security/agent/server/wire.vdl
@@ -35,12 +35,15 @@
 	Sign(message []byte) (security.Signature, error)
 	MintDischarge(tp any, caveat security.Caveat, additionalCaveats []security.Caveat) (any, error)
 	PublicKey() ([]byte, error)
+	BlessingsByName(name security.BlessingPattern) ([]security.WireBlessings, error)
+	BlessingsInfo(blessings security.WireBlessings) ([]string, error)
 	AddToRoots(blessing security.WireBlessings) error
 
 	BlessingStoreSet(blessings security.WireBlessings, forPeers security.BlessingPattern) (security.WireBlessings, error)
 	BlessingStoreForPeer(peerBlessings []string) (security.WireBlessings, error)
 	BlessingStoreSetDefault(blessings security.WireBlessings) error
 	BlessingStoreDefault() (security.WireBlessings, error)
+	BlessingStorePeerBlessings() (map[security.BlessingPattern]security.WireBlessings, error)
 	BlessingStoreDebugString() (string, error)
 
 	BlessingRootsAdd(root []byte, pattern security.BlessingPattern) error
diff --git a/security/agent/server/wire.vdl.go b/security/agent/server/wire.vdl.go
index fa5832b..3fc6f85 100644
--- a/security/agent/server/wire.vdl.go
+++ b/security/agent/server/wire.vdl.go
@@ -27,11 +27,14 @@
 	Sign(ctx __context.T, message []byte, opts ...__ipc.CallOpt) (security.Signature, error)
 	MintDischarge(ctx __context.T, tp __vdlutil.Any, caveat security.Caveat, additionalCaveats []security.Caveat, opts ...__ipc.CallOpt) (__vdlutil.Any, error)
 	PublicKey(__context.T, ...__ipc.CallOpt) ([]byte, error)
+	BlessingsByName(ctx __context.T, name security.BlessingPattern, opts ...__ipc.CallOpt) ([]security.WireBlessings, error)
+	BlessingsInfo(ctx __context.T, blessings security.WireBlessings, opts ...__ipc.CallOpt) ([]string, error)
 	AddToRoots(ctx __context.T, blessing security.WireBlessings, opts ...__ipc.CallOpt) error
 	BlessingStoreSet(ctx __context.T, blessings security.WireBlessings, forPeers security.BlessingPattern, opts ...__ipc.CallOpt) (security.WireBlessings, error)
 	BlessingStoreForPeer(ctx __context.T, peerBlessings []string, opts ...__ipc.CallOpt) (security.WireBlessings, error)
 	BlessingStoreSetDefault(ctx __context.T, blessings security.WireBlessings, opts ...__ipc.CallOpt) error
 	BlessingStoreDefault(__context.T, ...__ipc.CallOpt) (security.WireBlessings, error)
+	BlessingStorePeerBlessings(__context.T, ...__ipc.CallOpt) (map[security.BlessingPattern]security.WireBlessings, error)
 	BlessingStoreDebugString(__context.T, ...__ipc.CallOpt) (string, error)
 	BlessingRootsAdd(ctx __context.T, root []byte, pattern security.BlessingPattern, opts ...__ipc.CallOpt) error
 	BlessingRootsRecognized(ctx __context.T, root []byte, blessing string, opts ...__ipc.CallOpt) error
@@ -122,6 +125,28 @@
 	return
 }
 
+func (c implAgentClientStub) BlessingsByName(ctx __context.T, i0 security.BlessingPattern, opts ...__ipc.CallOpt) (o0 []security.WireBlessings, err error) {
+	var call __ipc.Call
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "BlessingsByName", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	if ierr := call.Finish(&o0, &err); ierr != nil {
+		err = ierr
+	}
+	return
+}
+
+func (c implAgentClientStub) BlessingsInfo(ctx __context.T, i0 security.WireBlessings, opts ...__ipc.CallOpt) (o0 []string, err error) {
+	var call __ipc.Call
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "BlessingsInfo", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	if ierr := call.Finish(&o0, &err); ierr != nil {
+		err = ierr
+	}
+	return
+}
+
 func (c implAgentClientStub) AddToRoots(ctx __context.T, i0 security.WireBlessings, opts ...__ipc.CallOpt) (err error) {
 	var call __ipc.Call
 	if call, err = c.c(ctx).StartCall(ctx, c.name, "AddToRoots", []interface{}{i0}, opts...); err != nil {
@@ -177,6 +202,17 @@
 	return
 }
 
+func (c implAgentClientStub) BlessingStorePeerBlessings(ctx __context.T, opts ...__ipc.CallOpt) (o0 map[security.BlessingPattern]security.WireBlessings, err error) {
+	var call __ipc.Call
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "BlessingStorePeerBlessings", nil, opts...); err != nil {
+		return
+	}
+	if ierr := call.Finish(&o0, &err); ierr != nil {
+		err = ierr
+	}
+	return
+}
+
 func (c implAgentClientStub) BlessingStoreDebugString(ctx __context.T, opts ...__ipc.CallOpt) (o0 string, err error) {
 	var call __ipc.Call
 	if call, err = c.c(ctx).StartCall(ctx, c.name, "BlessingStoreDebugString", nil, opts...); err != nil {
@@ -240,11 +276,14 @@
 	Sign(ctx __ipc.ServerContext, message []byte) (security.Signature, error)
 	MintDischarge(ctx __ipc.ServerContext, tp __vdlutil.Any, caveat security.Caveat, additionalCaveats []security.Caveat) (__vdlutil.Any, error)
 	PublicKey(__ipc.ServerContext) ([]byte, error)
+	BlessingsByName(ctx __ipc.ServerContext, name security.BlessingPattern) ([]security.WireBlessings, error)
+	BlessingsInfo(ctx __ipc.ServerContext, blessings security.WireBlessings) ([]string, error)
 	AddToRoots(ctx __ipc.ServerContext, blessing security.WireBlessings) error
 	BlessingStoreSet(ctx __ipc.ServerContext, blessings security.WireBlessings, forPeers security.BlessingPattern) (security.WireBlessings, error)
 	BlessingStoreForPeer(ctx __ipc.ServerContext, peerBlessings []string) (security.WireBlessings, error)
 	BlessingStoreSetDefault(ctx __ipc.ServerContext, blessings security.WireBlessings) error
 	BlessingStoreDefault(__ipc.ServerContext) (security.WireBlessings, error)
+	BlessingStorePeerBlessings(__ipc.ServerContext) (map[security.BlessingPattern]security.WireBlessings, error)
 	BlessingStoreDebugString(__ipc.ServerContext) (string, error)
 	BlessingRootsAdd(ctx __ipc.ServerContext, root []byte, pattern security.BlessingPattern) error
 	BlessingRootsRecognized(ctx __ipc.ServerContext, root []byte, blessing string) error
@@ -308,6 +347,14 @@
 	return s.impl.PublicKey(ctx)
 }
 
+func (s implAgentServerStub) BlessingsByName(ctx __ipc.ServerContext, i0 security.BlessingPattern) ([]security.WireBlessings, error) {
+	return s.impl.BlessingsByName(ctx, i0)
+}
+
+func (s implAgentServerStub) BlessingsInfo(ctx __ipc.ServerContext, i0 security.WireBlessings) ([]string, error) {
+	return s.impl.BlessingsInfo(ctx, i0)
+}
+
 func (s implAgentServerStub) AddToRoots(ctx __ipc.ServerContext, i0 security.WireBlessings) error {
 	return s.impl.AddToRoots(ctx, i0)
 }
@@ -328,6 +375,10 @@
 	return s.impl.BlessingStoreDefault(ctx)
 }
 
+func (s implAgentServerStub) BlessingStorePeerBlessings(ctx __ipc.ServerContext) (map[security.BlessingPattern]security.WireBlessings, error) {
+	return s.impl.BlessingStorePeerBlessings(ctx)
+}
+
 func (s implAgentServerStub) BlessingStoreDebugString(ctx __ipc.ServerContext) (string, error) {
 	return s.impl.BlessingStoreDebugString(ctx)
 }
@@ -415,6 +466,26 @@
 			},
 		},
 		{
+			Name: "BlessingsByName",
+			InArgs: []__ipc.ArgDesc{
+				{"name", ``}, // security.BlessingPattern
+			},
+			OutArgs: []__ipc.ArgDesc{
+				{"", ``}, // []security.WireBlessings
+				{"", ``}, // error
+			},
+		},
+		{
+			Name: "BlessingsInfo",
+			InArgs: []__ipc.ArgDesc{
+				{"blessings", ``}, // security.WireBlessings
+			},
+			OutArgs: []__ipc.ArgDesc{
+				{"", ``}, // []string
+				{"", ``}, // error
+			},
+		},
+		{
 			Name: "AddToRoots",
 			InArgs: []__ipc.ArgDesc{
 				{"blessing", ``}, // security.WireBlessings
@@ -461,6 +532,13 @@
 			},
 		},
 		{
+			Name: "BlessingStorePeerBlessings",
+			OutArgs: []__ipc.ArgDesc{
+				{"", ``}, // map[security.BlessingPattern]security.WireBlessings
+				{"", ``}, // error
+			},
+		},
+		{
 			Name: "BlessingStoreDebugString",
 			OutArgs: []__ipc.ArgDesc{
 				{"", ``}, // string
@@ -579,6 +657,13 @@
 			{Name: "", Type: 75},
 		},
 	}
+	result.Methods["BlessingStorePeerBlessings"] = __ipc.MethodSignature{
+		InArgs: []__ipc.MethodArgument{},
+		OutArgs: []__ipc.MethodArgument{
+			{Name: "", Type: 79},
+			{Name: "", Type: 75},
+		},
+	}
 	result.Methods["BlessingStoreSet"] = __ipc.MethodSignature{
 		InArgs: []__ipc.MethodArgument{
 			{Name: "blessings", Type: 74},
@@ -597,6 +682,24 @@
 			{Name: "", Type: 75},
 		},
 	}
+	result.Methods["BlessingsByName"] = __ipc.MethodSignature{
+		InArgs: []__ipc.MethodArgument{
+			{Name: "name", Type: 77},
+		},
+		OutArgs: []__ipc.MethodArgument{
+			{Name: "", Type: 78},
+			{Name: "", Type: 75},
+		},
+	}
+	result.Methods["BlessingsInfo"] = __ipc.MethodSignature{
+		InArgs: []__ipc.MethodArgument{
+			{Name: "blessings", Type: 74},
+		},
+		OutArgs: []__ipc.MethodArgument{
+			{Name: "", Type: 61},
+			{Name: "", Type: 75},
+		},
+	}
 	result.Methods["MintDischarge"] = __ipc.MethodSignature{
 		InArgs: []__ipc.MethodArgument{
 			{Name: "tp", Type: 76},
@@ -652,7 +755,7 @@
 				__wiretype.FieldType{Type: 0x49, Name: "CertificateChains"},
 			},
 			"veyron.io/veyron/veyron2/security.WireBlessings", []string(nil)},
-		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x1, Name: "anydata", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "veyron.io/veyron/veyron2/security.BlessingPattern", Tags: []string(nil)}}
+		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x1, Name: "anydata", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "veyron.io/veyron/veyron2/security.BlessingPattern", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x4a, Name: "", Tags: []string(nil)}, __wiretype.MapType{Key: 0x4d, Elem: 0x4a, Name: "", Tags: []string(nil)}}
 
 	return result, nil
 }
diff --git a/security/audit/principal.go b/security/audit/principal.go
index efd1323..c37a8d7 100644
--- a/security/audit/principal.go
+++ b/security/audit/principal.go
@@ -55,6 +55,14 @@
 	return d, nil
 }
 
+func (p *auditingPrincipal) BlessingsByName(name security.BlessingPattern) []security.Blessings {
+	return p.principal.BlessingsByName(name)
+}
+
+func (p *auditingPrincipal) BlessingsInfo(b security.Blessings) []string {
+	return p.principal.BlessingsInfo(b)
+}
+
 func (p *auditingPrincipal) PublicKey() security.PublicKey         { return p.principal.PublicKey() }
 func (p *auditingPrincipal) Roots() security.BlessingRoots         { return p.principal.Roots() }
 func (p *auditingPrincipal) BlessingStore() security.BlessingStore { return p.principal.BlessingStore() }
diff --git a/security/audit/principal_test.go b/security/audit/principal_test.go
index 487154f..00b885e 100644
--- a/security/audit/principal_test.go
+++ b/security/audit/principal_test.go
@@ -162,6 +162,14 @@
 	return d, p.NextError
 }
 
+func (p *mockPrincipal) BlessingsByName(name security.BlessingPattern) []security.Blessings {
+	return nil
+}
+
+func (p *mockPrincipal) BlessingsInfo(b security.Blessings) []string {
+	return nil
+}
+
 func (p *mockPrincipal) PublicKey() security.PublicKey         { return p.NextResult.(security.PublicKey) }
 func (p *mockPrincipal) Roots() security.BlessingRoots         { return nil }
 func (p *mockPrincipal) BlessingStore() security.BlessingStore { return nil }
diff --git a/security/blessingstore.go b/security/blessingstore.go
index be3449b..fd004e6 100644
--- a/security/blessingstore.go
+++ b/security/blessingstore.go
@@ -135,6 +135,14 @@
 	return fmt.Sprintf("{state: %v, publicKey: %v}", bs.state, bs.publicKey)
 }
 
+func (bs *blessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
+	m := make(map[security.BlessingPattern]security.Blessings)
+	for pattern, wb := range bs.state.Store {
+		m[pattern] = wb.Blessings()
+	}
+	return m
+}
+
 // DebugString return a human-readable string encoding of the store
 // in the following format
 // Default blessing : <Default blessing of the store>
diff --git a/security/blessingstore_test.go b/security/blessingstore_test.go
index fd535d8..be7824f 100644
--- a/security/blessingstore_test.go
+++ b/security/blessingstore_test.go
@@ -30,11 +30,19 @@
 		{t.forAll, "...foo", "invalid BlessingPattern"},
 		{t.forAll, "foo/.../bar", "invalid BlessingPattern"},
 	}
+	added := make(map[security.BlessingPattern]security.Blessings)
 	for _, d := range testdata {
 		_, err := s.Set(d.blessings, d.pattern)
 		if merr := matchesError(err, d.wantErr); merr != nil {
 			return fmt.Errorf("Set(%v, %q): %v", d.blessings, d.pattern, merr)
 		}
+		if err == nil {
+			added[d.pattern] = d.blessings
+		}
+	}
+	m := s.PeerBlessings()
+	if !reflect.DeepEqual(added, m) {
+		return fmt.Errorf("PeerBlessings(%v) != added(%v)", m, added)
 	}
 	return nil
 }
diff --git a/security/principal_test.go b/security/principal_test.go
index eb72f43..5f2d08c 100644
--- a/security/principal_test.go
+++ b/security/principal_test.go
@@ -7,7 +7,10 @@
 	"io/ioutil"
 	"os"
 	"path"
+	"reflect"
 	"testing"
+
+	"veyron.io/veyron/veyron2/security"
 )
 
 func TestLoadPersistentPrincipal(t *testing.T) {
@@ -116,3 +119,97 @@
 	}
 	return dir
 }
+
+func TestPrincipalBlessingsByName(t *testing.T) {
+	var p1, p2, p3 security.Principal
+	var err error
+
+	if p1, err = NewPrincipal(); err != nil {
+		t.Fatal(err)
+	}
+	if p2, err = NewPrincipal(); err != nil {
+		t.Fatal(err)
+	}
+	alice, err := p1.BlessSelf("alice")
+	if err != nil {
+		t.Fatal(err)
+	}
+	p2.AddToRoots(alice)
+	var aliceworkfriend, alicegymfriend, aliceworkboss security.Blessings
+
+	if aliceworkfriend, err = p1.Bless(p2.PublicKey(), alice, "work/friend", security.UnconstrainedUse()); err != nil {
+		t.Errorf("Bless(work/friend) failed: %v", err)
+	}
+	p2.BlessingStore().Set(aliceworkfriend, "alice/work/friend")
+	if alicegymfriend, err = p1.Bless(p2.PublicKey(), alice, "gym/friend", security.UnconstrainedUse()); err != nil {
+		t.Errorf("Bless(gym/friend) failed: %v", err)
+	}
+	p2.BlessingStore().Set(alicegymfriend, "alice/gym/friend")
+	if aliceworkboss, err = p1.Bless(p2.PublicKey(), alice, "work/boss", security.UnconstrainedUse()); err != nil {
+		t.Errorf("Bless(work/friend) failed: %v", err)
+	}
+	p2.BlessingStore().Set(aliceworkboss, "alice/work/boss")
+
+	// Blessing from an untrusted principal that should never be returned
+	if p3, err = NewPrincipal(); err != nil {
+		t.Fatal(err)
+	}
+	fake, err := p3.BlessSelf("alice")
+	if err != nil {
+		t.Fatal(err)
+	}
+	fakefriend, err := p3.Bless(p2.PublicKey(), fake, "work/friend", security.UnconstrainedUse())
+	if err != nil {
+		t.Errorf("Bless(work/friend) failed: %v", err)
+	}
+	_, err = p2.BlessingStore().Set(fakefriend, "fake/work/friend")
+
+	tests := []struct {
+		matched []security.Blessings
+		pattern security.BlessingPattern
+	}{
+		{
+			matched: []security.Blessings{aliceworkfriend, aliceworkboss},
+			pattern: "alice/work/...",
+		},
+		{
+			matched: []security.Blessings{aliceworkfriend},
+			pattern: "alice/work/friend",
+		},
+		{
+			matched: []security.Blessings{alicegymfriend},
+			pattern: "alice/gym/friend",
+		},
+		{
+			matched: []security.Blessings{aliceworkfriend, alicegymfriend, aliceworkboss},
+			pattern: "alice/...",
+		},
+		{
+			matched: []security.Blessings{aliceworkfriend, alicegymfriend, aliceworkboss},
+			pattern: "...",
+		},
+		{
+			matched: nil,
+			pattern: "alice/school/...",
+		},
+	}
+
+	for _, test := range tests {
+		matched := p2.BlessingsByName(test.pattern)
+		if len(matched) != len(test.matched) {
+			t.Errorf("BlessingsByName(%s) did not return expected number of matches wanted:%d got:%d", test.pattern, len(test.matched), len(matched))
+		}
+		for _, m := range matched {
+			found := false
+			for _, tm := range test.matched {
+				if reflect.DeepEqual(m, tm) {
+					found = true
+					break
+				}
+			}
+			if !found {
+				t.Errorf("Invalid blessing was returned as a match:%v for pattern:%s", m, test.pattern)
+			}
+		}
+	}
+}