"x/ref": VDL types for BlessingRoot and BlessingStore

This CL adds VDL types defining the wire formats
for BlessingStore and BlessingRoots.

Additionally, it changes that semantics of BlessingStore.Default()
according to CL: https://vanadium-review.googlesource.com/#/c/9846/

Closes veyron/release-issues#1232

Change-Id: I98545f13f2db695ce4fdeaef99fc40f12ff03d41
diff --git a/lib/security/blessingroots.go b/lib/security/blessingroots.go
index 6ecd0ba..43417b2 100644
--- a/lib/security/blessingroots.go
+++ b/lib/security/blessingroots.go
@@ -20,10 +20,10 @@
 	persistedData SerializerReaderWriter
 	signer        serialization.Signer
 	mu            sync.RWMutex
-	store         map[string][]security.BlessingPattern // GUARDED_BY(mu)
+	state         blessingRootsState // GUARDED_BY(mu)
 }
 
-func storeMapKey(root security.PublicKey) (string, error) {
+func stateMapKey(root security.PublicKey) (string, error) {
 	rootBytes, err := root.MarshalBinary()
 	if err != nil {
 		return "", err
@@ -32,37 +32,37 @@
 }
 
 func (br *blessingRoots) Add(root security.PublicKey, pattern security.BlessingPattern) error {
-	key, err := storeMapKey(root)
+	key, err := stateMapKey(root)
 	if err != nil {
 		return err
 	}
 
 	br.mu.Lock()
 	defer br.mu.Unlock()
-	patterns := br.store[key]
+	patterns := br.state[key]
 	for _, p := range patterns {
 		if p == pattern {
 			return nil
 		}
 	}
-	br.store[key] = append(patterns, pattern)
+	br.state[key] = append(patterns, pattern)
 
 	if err := br.save(); err != nil {
-		br.store[key] = patterns[:len(patterns)-1]
+		br.state[key] = patterns[:len(patterns)-1]
 		return err
 	}
 	return nil
 }
 
 func (br *blessingRoots) Recognized(root security.PublicKey, blessing string) error {
-	key, err := storeMapKey(root)
+	key, err := stateMapKey(root)
 	if err != nil {
 		return err
 	}
 
 	br.mu.RLock()
 	defer br.mu.RUnlock()
-	for _, p := range br.store[key] {
+	for _, p := range br.state[key] {
 		if p.MatchedBy(blessing) {
 			return nil
 		}
@@ -82,7 +82,7 @@
 	const format = "%-47s   %s\n"
 	b := bytes.NewBufferString(fmt.Sprintf(format, "Public key", "Pattern"))
 	var s rootSorter
-	for keyBytes, patterns := range br.store {
+	for keyBytes, patterns := range br.state {
 		key, err := security.UnmarshalPublicKey([]byte(keyBytes))
 		if err != nil {
 			return fmt.Sprintf("failed to decode public key: %v", err)
@@ -115,7 +115,7 @@
 	if err != nil {
 		return err
 	}
-	return encodeAndStore(br.store, data, signature, br.signer)
+	return encodeAndStore(br.state, data, signature, br.signer)
 }
 
 // newInMemoryBlessingRoots returns an in-memory security.BlessingRoots.
@@ -123,7 +123,7 @@
 // The returned BlessingRoots is initialized with an empty set of keys.
 func newInMemoryBlessingRoots() security.BlessingRoots {
 	return &blessingRoots{
-		store: make(map[string][]security.BlessingPattern),
+		state: make(blessingRootsState),
 	}
 }
 
@@ -135,7 +135,7 @@
 		return nil, verror.New(errDataOrSignerUnspecified, nil)
 	}
 	br := &blessingRoots{
-		store:         make(map[string][]security.BlessingPattern),
+		state:         make(blessingRootsState),
 		persistedData: persistedData,
 		signer:        signer,
 	}
@@ -144,7 +144,7 @@
 		return nil, err
 	}
 	if (data != nil) && (signature != nil) {
-		if err := decodeFromStorage(&br.store, data, signature, br.signer.PublicKey()); err != nil {
+		if err := decodeFromStorage(&br.state, data, signature, br.signer.PublicKey()); err != nil {
 			return nil, err
 		}
 	}
diff --git a/lib/security/blessingstore.go b/lib/security/blessingstore.go
index 381ec87..8397294 100644
--- a/lib/security/blessingstore.go
+++ b/lib/security/blessingstore.go
@@ -27,24 +27,14 @@
 	errDataOrSignerUnspecified = verror.Register(pkgPath+".errDataOrSignerUnspecified", verror.NoRetry, "{1:}{2:} persisted data or signer is not specified{:_}")
 )
 
-// TODO(ashankar,ataly): The only reason that Value is encapsulated in a struct
-// is for backward compatibility.  We should probably restore "oldState" and
-// get rid of this.
+// TODO(ataly, ashankar): Get rid of this struct once we have switched all
+// credentials directories to the new serialization format.
 type blessings struct {
 	Value security.Blessings
 }
 
-func (w *blessings) Blessings() security.Blessings {
-	if w == nil {
-		return security.Blessings{}
-	}
-	return w.Value
-}
-
-func newWireBlessings(b security.Blessings) *blessings {
-	return &blessings{Value: b}
-}
-
+// TODO(ataly, ashankar): Get rid of this struct once we have switched all
+// credentials directories to the new serialization format.
 type state struct {
 	// Store maps BlessingPatterns to the Blessings object that is to be shared
 	// with peers which present blessings of their own that match the pattern.
@@ -62,7 +52,7 @@
 	serializer SerializerReaderWriter
 	signer     serialization.Signer
 	mu         sync.RWMutex
-	state      state // GUARDED_BY(mu)
+	state      blessingStoreState // GUARDED_BY(mu)
 }
 
 func (bs *blessingStore) Set(blessings security.Blessings, forPeers security.BlessingPattern) (security.Blessings, error) {
@@ -74,21 +64,21 @@
 	}
 	bs.mu.Lock()
 	defer bs.mu.Unlock()
-	old, hadold := bs.state.Store[forPeers]
+	old, hadold := bs.state.PeerBlessings[forPeers]
 	if !blessings.IsZero() {
-		bs.state.Store[forPeers] = newWireBlessings(blessings)
+		bs.state.PeerBlessings[forPeers] = blessings
 	} else {
-		delete(bs.state.Store, forPeers)
+		delete(bs.state.PeerBlessings, forPeers)
 	}
 	if err := bs.save(); err != nil {
 		if hadold {
-			bs.state.Store[forPeers] = old
+			bs.state.PeerBlessings[forPeers] = old
 		} else {
-			delete(bs.state.Store, forPeers)
+			delete(bs.state.PeerBlessings, forPeers)
 		}
 		return security.Blessings{}, err
 	}
-	return old.Blessings(), nil
+	return old, nil
 }
 
 func (bs *blessingStore) ForPeer(peerBlessings ...string) security.Blessings {
@@ -96,9 +86,8 @@
 	defer bs.mu.RUnlock()
 
 	var ret security.Blessings
-	for pattern, wb := range bs.state.Store {
+	for pattern, b := range bs.state.PeerBlessings {
 		if pattern.MatchedBy(peerBlessings...) {
-			b := wb.Blessings()
 			if union, err := security.UnionOfBlessings(ret, b); err != nil {
 				vlog.Errorf("UnionOfBlessings(%v, %v) failed: %v, dropping the latter from BlessingStore.ForPeers(%v)", ret, b, err, peerBlessings)
 			} else {
@@ -112,10 +101,7 @@
 func (bs *blessingStore) Default() security.Blessings {
 	bs.mu.RLock()
 	defer bs.mu.RUnlock()
-	if bs.state.Default != nil {
-		return bs.state.Default.Blessings()
-	}
-	return bs.ForPeer()
+	return bs.state.DefaultBlessings
 }
 
 func (bs *blessingStore) SetDefault(blessings security.Blessings) error {
@@ -124,10 +110,11 @@
 	if !blessings.IsZero() && !reflect.DeepEqual(blessings.PublicKey(), bs.publicKey) {
 		return verror.New(errStoreAddMismatch, nil)
 	}
-	oldDefault := bs.state.Default
-	bs.state.Default = newWireBlessings(blessings)
+	oldDefault := bs.state.DefaultBlessings
+	bs.state.DefaultBlessings = blessings
 	if err := bs.save(); err != nil {
-		bs.state.Default = oldDefault
+		bs.state.DefaultBlessings = oldDefault
+		return err
 	}
 	return nil
 }
@@ -142,8 +129,8 @@
 
 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()
+	for pattern, b := range bs.state.PeerBlessings {
+		m[pattern] = b
 	}
 	return m
 }
@@ -157,20 +144,19 @@
 // <pattern>      <blessings>
 func (bs *blessingStore) DebugString() string {
 	const format = "%-30s   %s\n"
-	b := bytes.NewBufferString(fmt.Sprintf(format, "Default Blessings", bs.state.Default.Blessings()))
+	buff := bytes.NewBufferString(fmt.Sprintf(format, "Default Blessings", bs.state.DefaultBlessings))
 
-	b.WriteString(fmt.Sprintf(format, "Peer pattern", "Blessings"))
+	buff.WriteString(fmt.Sprintf(format, "Peer pattern", "Blessings"))
 
-	sorted := make([]string, 0, len(bs.state.Store))
-	for k, _ := range bs.state.Store {
+	sorted := make([]string, 0, len(bs.state.PeerBlessings))
+	for k, _ := range bs.state.PeerBlessings {
 		sorted = append(sorted, string(k))
 	}
 	sort.Strings(sorted)
 	for _, pattern := range sorted {
-		wb := bs.state.Store[security.BlessingPattern(pattern)]
-		b.WriteString(fmt.Sprintf(format, pattern, wb.Blessings()))
+		buff.WriteString(fmt.Sprintf(format, pattern, bs.state.PeerBlessings[security.BlessingPattern(pattern)]))
 	}
-	return b.String()
+	return buff.String()
 }
 
 func (bs *blessingStore) save() error {
@@ -191,50 +177,18 @@
 func newInMemoryBlessingStore(publicKey security.PublicKey) security.BlessingStore {
 	return &blessingStore{
 		publicKey: publicKey,
-		state:     state{Store: make(map[security.BlessingPattern]*blessings)},
+		state:     blessingStoreState{PeerBlessings: make(map[security.BlessingPattern]security.Blessings)},
 	}
 }
 
-// TODO(ataly, ashankar): Get rid of this struct once we have switched all
-// credentials directories to the new serialization format. Or maybe we should
-// restore this and get rid of "type state". Probably should define the
-// serialization format in VDL!
-type oldState struct {
-	Store   map[security.BlessingPattern]security.Blessings
-	Default security.Blessings
-}
-
-// TODO(ataly, ashankar): Get rid of this method once we have switched all
-// credentials directories to the new serialization format.
-func (bs *blessingStore) tryOldFormat() bool {
-	var empty security.Blessings
-	if len(bs.state.Store) == 0 {
-		return bs.state.Default.Value.IsZero() || reflect.DeepEqual(bs.state.Default.Value, empty)
-	}
-	for _, wb := range bs.state.Store {
-		if wb.Value.IsZero() {
-			return true
-		}
-	}
-	return false
-}
-
 func (bs *blessingStore) verifyState() error {
-	verifyBlessings := func(wb *blessings, key security.PublicKey) error {
-		if b := wb.Blessings(); !reflect.DeepEqual(b.PublicKey(), key) {
-			return verror.New(errBlessingsNotForKey, nil, b, key)
-		}
-		return nil
-	}
-	for _, wb := range bs.state.Store {
-		if err := verifyBlessings(wb, bs.publicKey); err != nil {
-			return err
+	for _, b := range bs.state.PeerBlessings {
+		if !reflect.DeepEqual(b.PublicKey(), bs.publicKey) {
+			return verror.New(errBlessingsNotForKey, nil, b, bs.publicKey)
 		}
 	}
-	if bs.state.Default != nil {
-		if err := verifyBlessings(bs.state.Default, bs.publicKey); err != nil {
-			return err
-		}
+	if !bs.state.DefaultBlessings.IsZero() && !reflect.DeepEqual(bs.state.DefaultBlessings.PublicKey(), bs.publicKey) {
+		return verror.New(errBlessingsNotForKey, nil, bs.state.DefaultBlessings, bs.publicKey)
 	}
 	return nil
 }
@@ -249,24 +203,32 @@
 	if data == nil && signature == nil {
 		return nil
 	}
-	var old oldState
+
+	var old state
 	if err := decodeFromStorage(&old, data, signature, bs.signer.PublicKey()); err != nil {
 		return err
 	}
-	for p, wire := range old.Store {
-		bs.state.Store[p] = &blessings{Value: wire}
+
+	for p, wb := range old.Store {
+		if wb != nil {
+			bs.state.PeerBlessings[p] = wb.Value
+		}
 	}
-	bs.state.Default = &blessings{Value: old.Default}
+	if old.Default != nil {
+		bs.state.DefaultBlessings = old.Default.Value
+	}
 
 	if err := bs.verifyState(); err != nil {
 		return err
 	}
+
 	// Save the blessingstore in the new serialization format. This will ensure
 	// that all credentials directories in the old format will switch to the new
 	// format.
 	if err := bs.save(); err != nil {
 		return err
 	}
+
 	return nil
 }
 
@@ -278,13 +240,10 @@
 	if data == nil && signature == nil {
 		return nil
 	}
-	if err := decodeFromStorage(&bs.state, data, signature, bs.signer.PublicKey()); err == nil && !bs.tryOldFormat() {
-		return bs.verifyState()
+	if err := decodeFromStorage(&bs.state, data, signature, bs.signer.PublicKey()); err != nil {
+		return bs.deserializeOld()
 	}
-	if err := bs.deserializeOld(); err != nil {
-		return err
-	}
-	return nil
+	return bs.verifyState()
 }
 
 // newPersistingBlessingStore returns a security.BlessingStore for a principal
@@ -296,7 +255,7 @@
 	}
 	bs := &blessingStore{
 		publicKey:  signer.PublicKey(),
-		state:      state{Store: make(map[security.BlessingPattern]*blessings)},
+		state:      blessingStoreState{PeerBlessings: make(map[security.BlessingPattern]security.Blessings)},
 		serializer: serializer,
 		signer:     signer,
 	}
diff --git a/lib/security/blessingstore_test.go b/lib/security/blessingstore_test.go
index cd86c37..8177624 100644
--- a/lib/security/blessingstore_test.go
+++ b/lib/security/blessingstore_test.go
@@ -50,10 +50,7 @@
 	return nil
 }
 
-func (t *storeTester) testSetDefault(s security.BlessingStore, currentDefault security.Blessings) error {
-	if got := s.Default(); !reflect.DeepEqual(got, currentDefault) {
-		return fmt.Errorf("Default(): got: %v, want: %v", got, currentDefault)
-	}
+func (t *storeTester) testSetDefault(s security.BlessingStore) error {
 	if err := s.SetDefault(security.Blessings{}); err != nil {
 		return fmt.Errorf("SetDefault({}): %v", err)
 	}
@@ -140,7 +137,7 @@
 	if err := tester.testForPeer(s); err != nil {
 		t.Error(err)
 	}
-	if err := tester.testSetDefault(s, tester.forAll); err != nil {
+	if err := tester.testSetDefault(s); err != nil {
 		t.Error(err)
 	}
 }
@@ -164,7 +161,7 @@
 	if err := tester.testForPeer(s); err != nil {
 		t.Error(err)
 	}
-	if err := tester.testSetDefault(s, tester.forAll); err != nil {
+	if err := tester.testSetDefault(s); err != nil {
 		t.Error(err)
 	}
 
diff --git a/lib/security/type.vdl b/lib/security/type.vdl
new file mode 100644
index 0000000..9d65571
--- /dev/null
+++ b/lib/security/type.vdl
@@ -0,0 +1,21 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package security
+
+import "v.io/v23/security"
+
+type blessingRootsState map[string][]security.BlessingPattern
+
+type blessingStoreState struct {
+	// PeerBlessings maps BlessingPatterns to the Blessings object that is to
+	// be shared with peers which present blessings of their own that match the
+	// pattern.
+	//
+	// All blessings bind to the same public key.
+	PeerBlessings map[security.BlessingPattern]security.WireBlessings
+	// DefaultBlessings is the default Blessings to be shared with peers for which
+	// no other information is available to select blessings.
+	DefaultBlessings security.WireBlessings
+}
diff --git a/lib/security/type.vdl.go b/lib/security/type.vdl.go
new file mode 100644
index 0000000..127698b
--- /dev/null
+++ b/lib/security/type.vdl.go
@@ -0,0 +1,45 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file was auto-generated by the vanadium vdl tool.
+// Source: type.vdl
+
+package security
+
+import (
+	// VDL system imports
+	"v.io/v23/vdl"
+
+	// VDL user imports
+	"v.io/v23/security"
+)
+
+type blessingRootsState map[string][]security.BlessingPattern
+
+func (blessingRootsState) __VDLReflect(struct {
+	Name string "v.io/x/ref/lib/security.blessingRootsState"
+}) {
+}
+
+type blessingStoreState struct {
+	// PeerBlessings maps BlessingPatterns to the Blessings object that is to
+	// be shared with peers which present blessings of their own that match the
+	// pattern.
+	//
+	// All blessings bind to the same public key.
+	PeerBlessings map[security.BlessingPattern]security.Blessings
+	// DefaultBlessings is the default Blessings to be shared with peers for which
+	// no other information is available to select blessings.
+	DefaultBlessings security.Blessings
+}
+
+func (blessingStoreState) __VDLReflect(struct {
+	Name string "v.io/x/ref/lib/security.blessingStoreState"
+}) {
+}
+
+func init() {
+	vdl.Register((*blessingRootsState)(nil))
+	vdl.Register((*blessingStoreState)(nil))
+}