TBR Revert "js: Use cache for blessings between go and js"

MultiPart: 2/2
This reverts commit c89f4428e02e15b368795c6ece68343ccc689339.

Change-Id: Ia333bee51a85aff744c325a558f2a8fc9fe5f88e
diff --git a/.gitignore b/.gitignore
index 5854afc..cd0b069 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,7 +14,6 @@
 go/bin
 xunit.xml
 tmp
-.idea
 
 # Vanadium
 /.v23
diff --git a/src/gen-vdl/v.io/x/ref/services/wspr/internal/app/index.js b/src/gen-vdl/v.io/x/ref/services/wspr/internal/app/index.js
index 8ff3aad..5850954 100644
--- a/src/gen-vdl/v.io/x/ref/services/wspr/internal/app/index.js
+++ b/src/gen-vdl/v.io/x/ref/services/wspr/internal/app/index.js
@@ -22,6 +22,7 @@
 
 // Types:
 var _type1 = new vdl.Type();
+var _type10 = new vdl.Type();
 var _type2 = new vdl.Type();
 var _type3 = new vdl.Type();
 var _type4 = new vdl.Type();
@@ -40,6 +41,9 @@
 _type1.kind = vdl.kind.LIST;
 _type1.name = "";
 _type1.elem = _typeRpcCallOption;
+_type10.kind = vdl.kind.LIST;
+_type10.name = "";
+_type10.elem = new principal.BlessingsHandle()._type;
 _type2.kind = vdl.kind.LIST;
 _type2.name = "";
 _type2.elem = new security.BlessingPattern()._type;
@@ -52,19 +56,19 @@
 _type5.kind = vdl.kind.LIST;
 _type5.name = "";
 _type5.elem = new security.Caveat()._type;
-_type6.kind = vdl.kind.LIST;
+_type6.kind = vdl.kind.OPTIONAL;
 _type6.name = "";
-_type6.elem = vdl.types.STRING;
-_type7.kind = vdl.kind.MAP;
+_type6.elem = new principal.JsBlessings()._type;
+_type7.kind = vdl.kind.LIST;
 _type7.name = "";
-_type7.elem = new principal.BlessingsId()._type;
-_type7.key = new security.BlessingPattern()._type;
-_type8.kind = vdl.kind.LIST;
+_type7.elem = vdl.types.STRING;
+_type8.kind = vdl.kind.MAP;
 _type8.name = "";
-_type8.elem = new signature.Interface()._type;
+_type8.elem = _type6;
+_type8.key = new security.BlessingPattern()._type;
 _type9.kind = vdl.kind.LIST;
 _type9.name = "";
-_type9.elem = new principal.BlessingsHandle()._type;
+_type9.elem = new signature.Interface()._type;
 _typeGranterHandle.kind = vdl.kind.INT32;
 _typeGranterHandle.name = "v.io/x/ref/services/wspr/internal/app.GranterHandle";
 _typeGranterRequest.kind = vdl.kind.STRUCT;
@@ -86,6 +90,7 @@
 _typeRpcServerOption.name = "v.io/x/ref/services/wspr/internal/app.RpcServerOption";
 _typeRpcServerOption.fields = [{name: "IsLeaf", type: vdl.types.BOOL}, {name: "ServesMountTable", type: vdl.types.BOOL}];
 _type1.freeze();
+_type10.freeze();
 _type2.freeze();
 _type3.freeze();
 _type4.freeze();
@@ -381,9 +386,14 @@
     },
     ],
     outArgs: [{
-      name: '',
+      name: 'publicKeyOut',
       doc: "",
-      type: new principal.BlessingsId()._type
+      type: vdl.types.STRING
+    },
+    {
+      name: 'handleOut',
+      doc: "",
+      type: new principal.BlessingsHandle()._type
     },
     ],
     inStream: null,
@@ -407,9 +417,14 @@
     },
     ],
     outArgs: [{
-      name: '',
+      name: 'publicKeyOut',
       doc: "",
-      type: new principal.BlessingsId()._type
+      type: vdl.types.STRING
+    },
+    {
+      name: 'handleOut',
+      doc: "",
+      type: new principal.BlessingsHandle()._type
     },
     ],
     inStream: null,
@@ -451,7 +466,7 @@
     outArgs: [{
       name: '',
       doc: "",
-      type: new principal.BlessingsId()._type
+      type: _type6
     },
     ],
     inStream: null,
@@ -466,13 +481,13 @@
     inArgs: [{
       name: 'peerBlessings',
       doc: "",
-      type: _type6
+      type: _type7
     },
     ],
     outArgs: [{
       name: '',
       doc: "",
-      type: new principal.BlessingsId()._type
+      type: _type6
     },
     ],
     inStream: null,
@@ -504,7 +519,7 @@
     outArgs: [{
       name: '',
       doc: "",
-      type: new principal.BlessingsId()._type
+      type: _type6
     },
     ],
     inStream: null,
@@ -536,7 +551,7 @@
     outArgs: [{
       name: '',
       doc: "",
-      type: _type7
+      type: _type8
     },
     ],
     inStream: null,
@@ -578,7 +593,7 @@
     outArgs: [{
       name: '',
       doc: "",
-      type: _type6
+      type: _type7
     },
     ],
     inStream: null,
@@ -599,7 +614,7 @@
     outArgs: [{
       name: '',
       doc: "",
-      type: _type8
+      type: _type9
     },
     ],
     inStream: null,
@@ -614,13 +629,13 @@
     inArgs: [{
       name: 'toJoin',
       doc: "",
-      type: _type9
+      type: _type10
     },
     ],
     outArgs: [{
       name: '',
       doc: "",
-      type: new principal.BlessingsId()._type
+      type: _type6
     },
     ],
     inStream: null,
diff --git a/src/gen-vdl/v.io/x/ref/services/wspr/internal/principal/index.js b/src/gen-vdl/v.io/x/ref/services/wspr/internal/principal/index.js
index f11c056..a799f10 100644
--- a/src/gen-vdl/v.io/x/ref/services/wspr/internal/principal/index.js
+++ b/src/gen-vdl/v.io/x/ref/services/wspr/internal/principal/index.js
@@ -16,39 +16,16 @@
 
 
 // Types:
-var _typeBlessingsCacheAddMessage = new vdl.Type();
-var _typeBlessingsCacheDeleteMessage = new vdl.Type();
-var _typeBlessingsCacheMessage = new vdl.Type();
 var _typeBlessingsHandle = new vdl.Type();
-var _typeBlessingsId = new vdl.Type();
 var _typeJsBlessings = new vdl.Type();
-_typeBlessingsCacheAddMessage.kind = vdl.kind.STRUCT;
-_typeBlessingsCacheAddMessage.name = "v.io/x/ref/services/wspr/internal/principal.BlessingsCacheAddMessage";
-_typeBlessingsCacheAddMessage.fields = [{name: "CacheId", type: _typeBlessingsId}, {name: "Blessings", type: _typeJsBlessings}];
-_typeBlessingsCacheDeleteMessage.kind = vdl.kind.STRUCT;
-_typeBlessingsCacheDeleteMessage.name = "v.io/x/ref/services/wspr/internal/principal.BlessingsCacheDeleteMessage";
-_typeBlessingsCacheDeleteMessage.fields = [{name: "CacheId", type: _typeBlessingsId}, {name: "DeleteAfter", type: vdl.types.UINT32}];
-_typeBlessingsCacheMessage.kind = vdl.kind.UNION;
-_typeBlessingsCacheMessage.name = "v.io/x/ref/services/wspr/internal/principal.BlessingsCacheMessage";
-_typeBlessingsCacheMessage.fields = [{name: "Add", type: _typeBlessingsCacheAddMessage}, {name: "Delete", type: _typeBlessingsCacheDeleteMessage}];
 _typeBlessingsHandle.kind = vdl.kind.INT32;
 _typeBlessingsHandle.name = "v.io/x/ref/services/wspr/internal/principal.BlessingsHandle";
-_typeBlessingsId.kind = vdl.kind.UINT32;
-_typeBlessingsId.name = "v.io/x/ref/services/wspr/internal/principal.BlessingsId";
 _typeJsBlessings.kind = vdl.kind.STRUCT;
 _typeJsBlessings.name = "v.io/x/ref/services/wspr/internal/principal.JsBlessings";
 _typeJsBlessings.fields = [{name: "Handle", type: _typeBlessingsHandle}, {name: "PublicKey", type: vdl.types.STRING}];
-_typeBlessingsCacheAddMessage.freeze();
-_typeBlessingsCacheDeleteMessage.freeze();
-_typeBlessingsCacheMessage.freeze();
 _typeBlessingsHandle.freeze();
-_typeBlessingsId.freeze();
 _typeJsBlessings.freeze();
-module.exports.BlessingsCacheAddMessage = (vdl.registry.lookupOrCreateConstructor(_typeBlessingsCacheAddMessage));
-module.exports.BlessingsCacheDeleteMessage = (vdl.registry.lookupOrCreateConstructor(_typeBlessingsCacheDeleteMessage));
-module.exports.BlessingsCacheMessage = (vdl.registry.lookupOrCreateConstructor(_typeBlessingsCacheMessage));
 module.exports.BlessingsHandle = (vdl.registry.lookupOrCreateConstructor(_typeBlessingsHandle));
-module.exports.BlessingsId = (vdl.registry.lookupOrCreateConstructor(_typeBlessingsId));
 module.exports.JsBlessings = (vdl.registry.lookupOrCreateConstructor(_typeJsBlessings));
 
 
@@ -67,8 +44,6 @@
 // Services:
 
    
-
-   
  
 
 
diff --git a/src/gen-vdl/v.io/x/ref/services/wspr/internal/rpc/server/index.js b/src/gen-vdl/v.io/x/ref/services/wspr/internal/rpc/server/index.js
index 4d2cfe6..b27766f 100644
--- a/src/gen-vdl/v.io/x/ref/services/wspr/internal/rpc/server/index.js
+++ b/src/gen-vdl/v.io/x/ref/services/wspr/internal/rpc/server/index.js
@@ -28,6 +28,7 @@
 var _type4 = new vdl.Type();
 var _type5 = new vdl.Type();
 var _type6 = new vdl.Type();
+var _type7 = new vdl.Type();
 var _typeAuthReply = new vdl.Type();
 var _typeCaveatValidationRequest = new vdl.Type();
 var _typeCaveatValidationResponse = new vdl.Type();
@@ -51,9 +52,12 @@
 _type5.kind = vdl.kind.LIST;
 _type5.name = "";
 _type5.elem = vdl.types.ERROR;
-_type6.kind = vdl.kind.LIST;
+_type6.kind = vdl.kind.OPTIONAL;
 _type6.name = "";
-_type6.elem = new signature.Interface()._type;
+_type6.elem = new principal.JsBlessings()._type;
+_type7.kind = vdl.kind.LIST;
+_type7.name = "";
+_type7.elem = new signature.Interface()._type;
 _typeAuthReply.kind = vdl.kind.STRUCT;
 _typeAuthReply.name = "v.io/x/ref/services/wspr/internal/rpc/server.AuthReply";
 _typeAuthReply.fields = [{name: "Err", type: vdl.types.ERROR}];
@@ -68,22 +72,23 @@
 _typeContext.fields = [{name: "Language", type: vdl.types.STRING}];
 _typeLookupReply.kind = vdl.kind.STRUCT;
 _typeLookupReply.name = "v.io/x/ref/services/wspr/internal/rpc/server.LookupReply";
-_typeLookupReply.fields = [{name: "Handle", type: vdl.types.INT32}, {name: "HasAuthorizer", type: vdl.types.BOOL}, {name: "HasGlobber", type: vdl.types.BOOL}, {name: "Signature", type: _type6}, {name: "Err", type: vdl.types.ERROR}];
+_typeLookupReply.fields = [{name: "Handle", type: vdl.types.INT32}, {name: "HasAuthorizer", type: vdl.types.BOOL}, {name: "HasGlobber", type: vdl.types.BOOL}, {name: "Signature", type: _type7}, {name: "Err", type: vdl.types.ERROR}];
 _typeSecurityCall.kind = vdl.kind.STRUCT;
 _typeSecurityCall.name = "v.io/x/ref/services/wspr/internal/rpc/server.SecurityCall";
-_typeSecurityCall.fields = [{name: "Method", type: vdl.types.STRING}, {name: "Suffix", type: vdl.types.STRING}, {name: "MethodTags", type: _type1}, {name: "LocalBlessings", type: new principal.BlessingsId()._type}, {name: "LocalBlessingStrings", type: _type2}, {name: "RemoteBlessings", type: new principal.BlessingsId()._type}, {name: "RemoteBlessingStrings", type: _type2}, {name: "LocalEndpoint", type: vdl.types.STRING}, {name: "RemoteEndpoint", type: vdl.types.STRING}];
+_typeSecurityCall.fields = [{name: "Method", type: vdl.types.STRING}, {name: "Suffix", type: vdl.types.STRING}, {name: "MethodTags", type: _type1}, {name: "LocalBlessings", type: new principal.JsBlessings()._type}, {name: "LocalBlessingStrings", type: _type2}, {name: "RemoteBlessings", type: new principal.JsBlessings()._type}, {name: "RemoteBlessingStrings", type: _type2}, {name: "LocalEndpoint", type: vdl.types.STRING}, {name: "RemoteEndpoint", type: vdl.types.STRING}];
 _typeServerRpcRequest.kind = vdl.kind.STRUCT;
 _typeServerRpcRequest.name = "v.io/x/ref/services/wspr/internal/rpc/server.ServerRpcRequest";
 _typeServerRpcRequest.fields = [{name: "ServerId", type: vdl.types.UINT32}, {name: "Handle", type: vdl.types.INT32}, {name: "Method", type: vdl.types.STRING}, {name: "Args", type: _type1}, {name: "Call", type: _typeServerRpcRequestCall}];
 _typeServerRpcRequestCall.kind = vdl.kind.STRUCT;
 _typeServerRpcRequestCall.name = "v.io/x/ref/services/wspr/internal/rpc/server.ServerRpcRequestCall";
-_typeServerRpcRequestCall.fields = [{name: "SecurityCall", type: _typeSecurityCall}, {name: "Deadline", type: new time.WireDeadline()._type}, {name: "Context", type: _typeContext}, {name: "TraceRequest", type: new vtrace.Request()._type}, {name: "GrantedBlessings", type: new principal.BlessingsId()._type}];
+_typeServerRpcRequestCall.fields = [{name: "SecurityCall", type: _typeSecurityCall}, {name: "Deadline", type: new time.WireDeadline()._type}, {name: "Context", type: _typeContext}, {name: "TraceRequest", type: new vtrace.Request()._type}, {name: "GrantedBlessings", type: _type6}];
 _type1.freeze();
 _type2.freeze();
 _type3.freeze();
 _type4.freeze();
 _type5.freeze();
 _type6.freeze();
+_type7.freeze();
 _typeAuthReply.freeze();
 _typeCaveatValidationRequest.freeze();
 _typeCaveatValidationResponse.freeze();
diff --git a/src/proxy/message-type.js b/src/proxy/message-type.js
index 769ae7d..04600e1 100644
--- a/src/proxy/message-type.js
+++ b/src/proxy/message-type.js
@@ -30,7 +30,6 @@
     CANCEL: 7, // A request to cancel a previously invoked JS method.
     CAVEAT_VALIDATION_REQUEST: 8, // A request to validate a set of caveats
     LOG_MESSAGE: 9,  // A request to log a message.
-    GRANTER_REQUEST: 10, // A request to call a granter
-    BLESSINGS_CACHE_MESSAGE: 11, // A request to update the blessings cache
+    GRANTER_REQUEST: 10 // A request to call a granter
   }
 };
diff --git a/src/proxy/stream-handler.js b/src/proxy/stream-handler.js
index b0df421..79b2332 100644
--- a/src/proxy/stream-handler.js
+++ b/src/proxy/stream-handler.js
@@ -6,9 +6,9 @@
 var emitStreamError = require('../lib/emit-stream-error');
 var vError = require('../gen-vdl/v.io/v23/verror');
 var SharedContextKeys = require('../runtime/shared-context-keys');
-var BlessingsId =
-  require('../gen-vdl/v.io/x/ref/services/wspr/internal/principal').BlessingsId;
-var runtimeFromContext = require('../runtime/runtime-from-context');
+var Blessings = require('../security/blessings');
+var JsBlessings =
+  require('../gen-vdl/v.io/x/ref/services/wspr/internal/principal').JsBlessings;
 var TaskSequence = require('../lib/task-sequence');
 var Promise = require('../lib/promise');
 var vom = require('../vom');
@@ -58,16 +58,12 @@
   }
   var handler = this;
   return vom.decode(data).then(function(data) {
-    if (data instanceof BlessingsId) {
-      var runtime = runtimeFromContext(handler._ctx);
-      runtime.blessingsManager.blessingsFromId(data)
-      .then(function(blessings) {
-        blessings.retain();
-        handler._stream._queueRead(blessings);
-      });
-    } else {
-      handler._stream._queueRead(data);
+    if (data instanceof JsBlessings) {
+      data = new Blessings(data.handle, data.publicKey,
+                           handler._controller);
+                           data.retain();
     }
+    handler._stream._queueRead(data);
   }, function(e) {
     emitStreamError(handler._stream,
                     new vError.InternalError(
diff --git a/src/rpc/client.js b/src/rpc/client.js
index 6246266..00975e0 100644
--- a/src/rpc/client.js
+++ b/src/rpc/client.js
@@ -39,14 +39,13 @@
 var SharedContextKeys = require('../runtime/shared-context-keys');
 var vtrace = require('../vtrace');
 var Blessings = require('../security/blessings');
-var BlessingsId =
-  require('../gen-vdl/v.io/x/ref/services/wspr/internal/principal').BlessingsId;
-var ByteStreamMessageReader = require('../vom/byte-stream-message-reader');
+var JsBlessings =
+  require('../gen-vdl/v.io/x/ref/services/wspr/internal/principal').JsBlessings;
 var ByteStreamMessageWriter = require('../vom/byte-stream-message-writer');
+var ByteStreamMessageReader = require('../vom/byte-stream-message-reader');
 var Encoder = require('../vom/encoder');
 var Decoder = require('../vom/decoder');
 var TaskSequence = require('../lib/task-sequence');
-var runtimeFromContext = require('../runtime/runtime-from-context');
 var vom = require('../vom');
 
 var OutstandingRPC = function(ctx, options, cb) {
@@ -71,34 +70,37 @@
 };
 
 // Helper function to convert an out argument to the given type.
-function convertOutArg(ctx, arg, type, controller) {
-  if (arg instanceof BlessingsId) {
-    var runtime = runtimeFromContext(ctx);
-    return runtime.blessingsManager.blessingsFromId(arg)
-    .then(function(blessings) {
-      if (blessings) {
-        blessings.retain();
-      }
-      return blessings;
-    });
+function convertOutArg(arg, type, controller) {
+  var canonOutArg = arg;
+  var unwrappedArg = unwrap(arg);
+  if (unwrappedArg instanceof JsBlessings) {
+    var res =
+      new Blessings(unwrappedArg.handle, unwrappedArg.publicKey, controller);
+    res.retain();
+    return res;
   }
 
   // There's no protection against bad out args if it's a JSValue.
   // Otherwise, convert to the out arg type to ensure type correctness.
   if (!type.equals(vdl.types.JSVALUE)) {
-    try {
-      return Promise.resolve(unwrap(vdl.canonicalize.reduce(arg, type)));
-    } catch(err) {
-      return Promise.reject(err);
-    }
+    canonOutArg = vdl.canonicalize.reduce(arg, type);
   }
 
-  return Promise.resolve(unwrap(arg));
+  return unwrap(canonOutArg);
+}
+
+// Helper function to safely convert an out argument.
+// The returned error, if any is useful for a callback.
+function convertOutArgSafe(arg, type, controller) {
+  try {
+    return [undefined, convertOutArg(arg, type, controller)];
+  } catch(err) {
+    return [err, undefined];
+  }
 }
 
 OutstandingRPC.prototype.start = function() {
   this._id = this._proxy.nextId();
-  var ctx = this._ctx;
   var self = this;
 
   var cb;
@@ -111,25 +113,25 @@
     cb = function convertToMultiArgs(err, results) { // jshint ignore:line
       // If called from a deferred, the results are undefined.
 
-      if (err) {
-        origCb(err);
-        return;
-      }
-
       // Each out argument should also be unwrapped. (results was []any)
-      results = results || [];
-      var resultPromises = results.map(function(res, i) {
-        return convertOutArg(ctx, res, outArgTypes[i], self._controller);
-      });
-      Promise.all(resultPromises)
-      .then(function(results) {
-        results.unshift(null);
-        origCb.apply(null, results);
-      }).catch(origCb);
+      results = results ? results.map(function(res, i) {
+        var errOrArg = convertOutArgSafe(res, outArgTypes[i], self._controller);
+        if (errOrArg[0] && !err) {
+          err = errOrArg[0];
+        }
+        return errOrArg[1];
+      }) : [];
+
+      // TODO(alexfandrianto): Callbacks seem to be able to get both error and
+      // results, but I think we want to limit it to one or the other.
+      var resultsCopy = results.slice();
+      resultsCopy.unshift(err);
+      origCb.apply(null, resultsCopy);
     };
   }
 
   var def = new Deferred(cb);
+  var ctx = this._ctx;
 
   if (!this._cb) {
     // If we are using a promise, strip single args out of the arg array.
@@ -140,29 +142,26 @@
           'Internal error: incorrectly formatted out args in client');
       }
 
-
       // Each out argument should also be unwrapped. (args was []any)
-      var unwrappedArgPromises = args.map(function(outArg, i) {
-        return convertOutArg(ctx, outArg, outArgTypes[i], self._controller);
+      var unwrappedArgs = args.map(function(outArg, i) {
+        return convertOutArg(outArg, outArgTypes[i], self._controller);
       });
 
-      return Promise.all(unwrappedArgPromises).then(function(unwrappedArgs) {
-        // We expect:
-        // 0 args - return; // NOT return [];
-        // 1 args - return a; // NOT return [a];
-        // 2 args - return [a, b] ;
-        //
-        // Convert the results from array style to the expected return style.
-        // undefined, a, [a, b], [a, b, c] etc
-        switch(unwrappedArgs.length) {
-          case 0:
-            return undefined;
-          case 1:
-            return unwrappedArgs[0];
-          default:
-            return unwrappedArgs;
-        }
-      });
+      // We expect:
+      // 0 args - return; // NOT return [];
+      // 1 args - return a; // NOT return [a];
+      // 2 args - return [a, b] ;
+      //
+      // Convert the results from array style to the expected return style.
+      // undefined, a, [a, b], [a, b, c] etc
+      switch(unwrappedArgs.length) {
+        case 0:
+          return undefined;
+        case 1:
+          return unwrappedArgs[0];
+        default:
+          return unwrappedArgs;
+      }
     });
   }
 
diff --git a/src/rpc/create-server-call.js b/src/rpc/create-server-call.js
deleted file mode 100644
index 616f787..0000000
--- a/src/rpc/create-server-call.js
+++ /dev/null
@@ -1,63 +0,0 @@
-// 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.
-
-var createSecurityCall = require('../security/create-security-call');
-
-module.exports = createServerCall;
-
-/**
- * Create a server call object. This exists so that we can resolve blessings
- * before the user is given the object.
- * @private
- */
-function createServerCall(request, blessingsManager) {
-  var serverCall = new ServerCall();
-  if (request instanceof ServerCall) {
-    serverCall.securityCall = request.securityCall.clone();
-    serverCall.grantedBlessings = request.grantedBlessings;
-    return Promise.resolve(serverCall);
-  } else {
-    var promises = [];
-    promises.push(createSecurityCall(request.call.securityCall,
-      blessingsManager).then(function(securityCall) {
-      serverCall.securityCall = securityCall;
-    }));
-    if (request.call.grantedBlessings) {
-      promises.push(
-        blessingsManager.blessingsFromId(request.call.grantedBlessings)
-        .then(function(grantedBlessings) {
-          serverCall.grantedBlessings = grantedBlessings;
-        })
-      );
-    }
-    return Promise.all(promises).then(function() {
-      return serverCall;
-    });
-  }
-}
-
-/**
- * @summary
- * A ServerCall is a context.Context subclass that includes additional
- * information about an ongoing server call.
- * @description
- * <p>Private Constructor, an instance of ServerCall is passed to every service
- * method as the first argument.</p>
- * @inner
- * @constructor
- *
- * @property {module:vanadium.security~SecurityCall} securityCall The
- * Security Call for the request.
- *
- * @property {module:vanadium.security~Blessings} grantedBlessings The
- * blessings optionally granted to the server from the client through a
- * granter.
- *
- * @property {*} methodTags The tags attached to the method,
- * interface specification in VDL.
- *
- * @memberof module:vanadium.rpc
- */
-function ServerCall() {
-}
diff --git a/src/rpc/granter-router.js b/src/rpc/granter-router.js
index 075d46c..dee6e7a 100644
--- a/src/rpc/granter-router.js
+++ b/src/rpc/granter-router.js
@@ -12,7 +12,7 @@
 var MessageType = require('../proxy/message-type');
 var Incoming = MessageType.Incoming;
 var Outgoing = MessageType.Outgoing;
-var createSecurityCall = require('../security/create-security-call');
+var SecurityCall = require('../security/call');
 var InspectableFunction = require('../lib/inspectable-function');
 var GranterResponse =
 require('../gen-vdl/v.io/x/ref/services/wspr/internal/app').GranterResponse;
@@ -25,14 +25,13 @@
  * grant requests.
  * @private
  */
-function GranterRouter(proxy, rootCtx, blessingsManager) {
+function GranterRouter(proxy, rootCtx) {
   proxy.addIncomingHandler(Incoming.GRANTER_REQUEST, this);
 
   this._proxy = proxy;
   this._rootCtx = rootCtx;
   this.nextGranterId = 0;
   this.activeGranters = {};
-  this._blessingsManager = blessingsManager;
 }
 
 /**
@@ -55,10 +54,9 @@
   }
 
   var router = this;
-  var granter;
   return vom.decode(request).then(function(request) {
     request = request.val;
-    granter = router.activeGranters[request.granterHandle];
+    var granter = router.activeGranters[request.granterHandle];
     if (!granter) {
       // TODO(bjornick): Pass in context here so we can generate useful error
       // messages
@@ -66,11 +64,7 @@
         new verror.NoExistError(router._rootCtx, 'unknown granter'));
     }
     delete router.activeGranters[request.granterHandle];
-    return createSecurityCall(request.call, router._blessingsManager);
-  }, function(e) {
-    return Promise.reject(
-      new verror.NoExistError(router._rootCtx, 'failed to decode message'));
-  }).then(function(securityCall) {
+    var securityCall = new SecurityCall(request.call, router._controller);
     var ctx = router._rootCtx;
     var inspectFn = new InspectableFunction(granter);
     var resolve;
@@ -87,6 +81,9 @@
                 return resolve(res);
               });
     return promise;
+  }, function(e) {
+    return Promise.reject(
+      new verror.NoExistError(router._rootCtx, 'failed to decode message'));
   }).then(function(outBlessings) {
     var result = new GranterResponse({blessings: outBlessings[0]._id});
     var data = hexVom.encode(result);
diff --git a/src/rpc/server-call.js b/src/rpc/server-call.js
new file mode 100644
index 0000000..ae9401e
--- /dev/null
+++ b/src/rpc/server-call.js
@@ -0,0 +1,46 @@
+// 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.
+
+var SecurityCall = require('../security/call');
+var Blessings = require('../security/blessings');
+
+module.exports = ServerCall;
+
+/**
+ * @summary
+ * A ServerCall is a context.Context subclass that includes additional
+ * information about an ongoing server call.
+ * @description
+ * <p>Private Constructor, an instance of ServerCall is passed to every service
+ * method as the first argument.</p>
+ * @inner
+ * @constructor
+ *
+ * @property {module:vanadium.security~SecurityCall} securityCall The
+ * Security Call for the request.
+ *
+ * @property {*} methodTags The tags attached to the method,
+ * interface specification in VDL.
+ *
+ * @memberof module:vanadium.rpc
+ */
+function ServerCall(request, controller) {
+  if (!(this instanceof ServerCall)) {
+    return new ServerCall(request, controller);
+  }
+
+  if (request instanceof ServerCall) {
+    this.securityCall = request.securityCall.clone();
+    this.grantedBlessings = request.grantedBlessings;
+  } else {
+    this.securityCall = new SecurityCall(request.call.securityCall,
+                                       controller);
+    if (request.call.grantedBlessings) {
+      this.grantedBlessings = new Blessings(
+        request.call.grantedBlessings.handle,
+        request.call.grantedBlessings.publicKey,
+        controller);
+    }
+  }
+}
diff --git a/src/rpc/server-router.js b/src/rpc/server-router.js
index 6c4155c..82ac8c4 100644
--- a/src/rpc/server-router.js
+++ b/src/rpc/server-router.js
@@ -16,8 +16,8 @@
 var vlog = require('./../lib/vlog');
 var StreamHandler = require('../proxy/stream-handler');
 var verror = require('../gen-vdl/v.io/v23/verror');
-var createSecurityCall = require('../security/create-security-call');
-var createServerCall = require('./create-server-call');
+var SecurityCall = require('../security/call');
+var ServerCall = require('./server-call');
 var vdl = require('../vdl');
 var typeUtil = require('../vdl/type-util');
 var Deferred = require('../lib/deferred');
@@ -37,8 +37,8 @@
 var lib =
   require('../gen-vdl/v.io/x/ref/services/wspr/internal/lib');
 var Blessings = require('../security/blessings');
-var BlessingsId =
-  require('../gen-vdl/v.io/x/ref/services/wspr/internal/principal').BlessingsId;
+var JsBlessings =
+  require('../gen-vdl/v.io/x/ref/services/wspr/internal/principal').JsBlessings;
 var WireBlessings =
   require('../gen-vdl/v.io/v23/security').WireBlessings;
 var SharedContextKeys = require('../runtime/shared-context-keys');
@@ -52,8 +52,7 @@
  * @constructor
  * @private
  */
-var Router = function(
-  proxy, appName, rootCtx, controller, caveatRegistry, blessingsManager) {
+var Router = function(proxy, appName, rootCtx, controller, caveatRegistry) {
   this._servers = {};
   this._proxy = proxy;
   this._streamMap = {};
@@ -63,7 +62,6 @@
   this._caveatRegistry = caveatRegistry;
   this._outstandingRequestForId = {};
   this._controller = controller;
-  this._blessingsManager = blessingsManager;
 
   proxy.addIncomingHandler(Incoming.INVOKE_REQUEST, this);
   proxy.addIncomingHandler(Incoming.LOOKUP_REQUEST, this);
@@ -119,15 +117,11 @@
   }
 
   var router = this;
-  var decodedRequest;
-  vom.decode(request).catch(function(e) {
-    return Promise.reject(new verror.InternalError(router._rootCtx,
-      'Failed to decode ', e));
-  }).then(function(req) {
-    decodedRequest = req;
+  var call;
+  vom.decode(request).then(function(request) {
     var ctx = router._rootCtx.withValue(SharedContextKeys.LANG_KEY,
-                                        decodedRequest.context.language);
-    var server = router._servers[decodedRequest.serverId];
+                                      request.context.language);
+    var server = router._servers[request.serverId];
     if (!server) {
       var authReply = new AuthReply({
         // TODO(bjornick): Use the real context
@@ -138,20 +132,22 @@
                                 null, messageId);
       return;
     }
-    return createSecurityCall(decodedRequest.call, router._blessingsManager)
-    .then(function(call) {
-      return server.handleAuthorization(decodedRequest.handle, ctx, call);
-    });
+    call = new SecurityCall(request.call, router._controller);
+
+    return server.handleAuthorization(request.handle, ctx, call);
+  }, function(e) {
+    return Promise.reject(new verror.InternalError(router._rootCtx,
+                                                   'Failed to decode ', e));
   }).then(function() {
     var authReply = new AuthReply({});
     router._proxy.sendRequest(hexVom.encode(authReply),
                               Outgoing.AUTHORIZATION_RESPONSE, null, messageId);
   }).catch(function(e) {
-    var errMsg = {
-      err: ErrorConversion.fromNativeValue(e, this._appName,
-                                           decodedRequest.call.method)
-    };
-    router._proxy.sendRequest(hexVom.encode(errMsg),
+    var authReply = new AuthReply({
+      err: ErrorConversion.fromNativeValue(e, router._appName,
+                                           call.method)
+    });
+    router._proxy.sendRequest(hexVom.encode(authReply),
                               Outgoing.AUTHORIZATION_RESPONSE, null,
                               messageId);
   });
@@ -183,24 +179,24 @@
 };
 
 Router.prototype.handleCaveatValidationRequest = function(messageId, request) {
-  var router = this;
-  createSecurityCall(request.call, this._blessingsManager)
-  .then(function(call) {
-    var ctx = router._rootCtx.withValue(SharedContextKeys.LANG_KEY,
-      request.context.language);
-    var resultPromises = request.cavs.map(function(cav) {
-      return router._validateChain(ctx, call, cav);
+  var resultPromises = new Array(request.cavs.length);
+  var call = new SecurityCall(request.call);
+  var ctx = this._rootCtx.withValue(SharedContextKeys.LANG_KEY,
+                                    request.context.language);
+  for (var i = 0; i < request.cavs.length; i++) {
+    resultPromises[i] = this._validateChain(ctx, call, request.cavs[i]);
+  }
+  var self = this;
+  Promise.all(resultPromises).then(function(results) {
+    var response = new CaveatValidationResponse({
+      results: results
     });
-    return Promise.all(resultPromises).then(function(results) {
-      var response = new CaveatValidationResponse({
-        results: results
-      });
-      var data = hexVom.encode(response);
-      router._proxy.sendRequest(data, Outgoing.CAVEAT_VALIDATION_RESPONSE, null,
-        messageId);
-    });
+    self._proxy.sendRequest(hexVom.encode(response),
+                            Outgoing.CAVEAT_VALIDATION_RESPONSE, null,
+                            messageId);
   }).catch(function(err) {
-    throw new Error('Unexpected error (all promises should resolve): ' + err);
+    vlog.logger.error(
+      new Error('Unexpected error (all promises should resolve): ' + err));
   });
 };
 
@@ -219,24 +215,24 @@
 
   var self = this;
   return server._handleLookup(request.suffix).then(function(value) {
-   var signatureList = value.invoker.signature();
-   var hasAuthorizer = (typeof value.authorizer === 'function');
-   var hasGlobber = value.invoker.hasGlobber();
-   var reply = new LookupReply({
-     handle: value._handle,
-     signature: signatureList,
-     hasAuthorizer: hasAuthorizer,
-     hasGlobber: hasGlobber
-   });
-   self._proxy.sendRequest(hexVom.encode(reply), Outgoing.LOOKUP_RESPONSE,
-                           null, messageId);
- }).catch(function(err) {
-   var reply = new LookupReply({
-     err: ErrorConversion.fromNativeValue(err, self._appName, '__Signature')
-   });
-   self._proxy.sendRequest(hexVom.encode(reply), Outgoing.LOOKUP_RESPONSE,
-                           null, messageId);
- });
+    var signatureList = value.invoker.signature();
+    var hasAuthorizer = (typeof value.authorizer === 'function');
+    var hasGlobber = value.invoker.hasGlobber();
+    var reply = new LookupReply({
+      handle: value._handle,
+      signature: signatureList,
+      hasAuthorizer: hasAuthorizer,
+      hasGlobber: hasGlobber
+    });
+    self._proxy.sendRequest(hexVom.encode(reply), Outgoing.LOOKUP_RESPONSE,
+                            null, messageId);
+  }).catch(function(err) {
+    var reply = new LookupReply({
+      err: ErrorConversion.fromNativeValue(err, self._appName, '__Signature')
+    });
+    self._proxy.sendRequest(hexVom.encode(reply), Outgoing.LOOKUP_RESPONSE,
+                            null, messageId);
+  });
 };
 
 /**
@@ -310,118 +306,111 @@
   var ctx = this.createRPCContext(request);
   var self = this;
   var stream;
-  createServerCall(request, this._blessingsManager).then(function(call) {
-    if (request.method === 'Glob__') {
-      if (!invoker.hasGlobber()) {
-        err = new Error('Glob is not implemented');
-        self.sendResult(messageId, 'Glob__', null, err);
-        return;
-      }
-      // Glob takes no streaming input and has GlobReply as output.
-      stream = new Stream(messageId, self._proxy.senderPromise, false,
-        null, naming.GlobReply.prototype._type);
-      self._streamMap[messageId] = stream;
-      self._contextMap[messageId] = ctx;
-      self._outstandingRequestForId[messageId] = 0;
-      self.incrementOutstandingRequestForId(messageId);
-      var globPattern = typeUtil.unwrap(request.args[0]);
-      self.handleGlobRequest(messageId, call.securityCall.suffix,
-                             server, new Glob(globPattern), ctx, call, invoker,
-                             completion);
+  var call = new ServerCall(request, this._controller);
+  if (request.method === 'Glob__') {
+    if (!invoker.hasGlobber()) {
+      err = new Error('Glob is not implemented');
+      self.sendResult(messageId, 'Glob__', null, err);
       return;
     }
+    // Glob takes no streaming input and has GlobReply as output.
+    stream = new Stream(messageId, this._proxy.senderPromise, false,
+      null, naming.GlobReply.prototype._type);
+    this._streamMap[messageId] = stream;
+    this._contextMap[messageId] = ctx;
+    this._outstandingRequestForId[messageId] = 0;
+    this.incrementOutstandingRequestForId(messageId);
+    var globPattern = typeUtil.unwrap(request.args[0]);
+    this.handleGlobRequest(messageId, call.securityCall.suffix,
+                           server, new Glob(globPattern), ctx, call, invoker,
+                           completion);
+    return;
+  }
 
-    function completion() {
-      // There is no results to a glob method.  Everything is sent back
-      // through the stream.
-      self.sendResult(messageId, methodName, null, undefined, 1);
-    }
+  function completion() {
+    // There is no results to a glob method.  Everything is sent back
+    // through the stream.
+    self.sendResult(messageId, methodName, null, undefined, 1);
+  }
 
-    // Find the method signature.
-    var signature = invoker.signature();
-    var methodSig;
-    signature.forEach(function(ifaceSig) {
-      ifaceSig.methods.forEach(function(method) {
-        if (method.name === methodName) {
-          methodSig = method;
-        }
-      });
-    });
-    if (methodSig === undefined) {
-      err = new verror.NoExistError(
-        call, 'Requested method', methodName, 'not found on');
-      self.sendResult(messageId, methodName, null, err);
-      return;
-    }
-
-    // Unwrap the RPC arguments sent to the JS server.
-    var unwrappedArgPromises = request.args.map(function(arg, i) {
-      // If an any type was expected, unwrapping is not needed.
-      if (methodSig.inArgs[i].type.kind === vdl.kind.ANY) {
-        return Promise.resolve(arg);
+  // Find the method signature.
+  var signature = invoker.signature();
+  var methodSig;
+  signature.forEach(function(ifaceSig) {
+    ifaceSig.methods.forEach(function(method) {
+      if (method.name === methodName) {
+        methodSig = method;
       }
-      var unwrapped = typeUtil.unwrap(arg);
-      if (unwrapped instanceof BlessingsId) {
-        return self._blessingsManager.blessingsFromId(unwrapped);
-      }
-      return Promise.resolve(unwrapped);
-    });
-
-    return Promise.all(unwrappedArgPromises).then(function(unwrappedArgs) {
-      var options = {
-        methodName: methodName,
-        args: unwrappedArgs,
-        methodSig: methodSig,
-        ctx: ctx,
-        call: call,
-      };
-
-      self._contextMap[messageId] = options.ctx;
-      if (methodIsStreaming(methodSig)) {
-        var readType = (methodSig.inStream ? methodSig.inStream.type : null);
-        var writeType = (methodSig.outStream ? methodSig.outStream.type : null);
-        stream = new Stream(messageId, self._proxy.senderPromise, false,
-          readType, writeType);
-        self._streamMap[messageId] = stream;
-        var rpc = new StreamHandler(options.ctx, stream);
-        self._proxy.addIncomingStreamHandler(messageId, rpc);
-        options.stream = stream;
-      }
-
-      // Invoke the method;
-      self.invokeMethod(invoker, options, function(err, results) {
-        if (err) {
-          var stackTrace;
-          if (err instanceof Error && err.stack !== undefined) {
-            stackTrace = err.stack;
-          }
-          vlog.logger.debug('Requested method ' + methodName +
-              ' threw an exception on invoke: ', err, stackTrace);
-
-          // The error case has no results; only send the error.
-          self.sendResult(messageId, methodName, undefined, err,
-              methodSig.outArgs.length);
-          return;
-        }
-
-        // Has results; associate the types of the outArgs.
-        var canonResults = results.map(function(result, i) {
-          var t = methodSig.outArgs[i].type;
-          if (t.equals(WireBlessings.prototype._type)) {
-            if (!(result instanceof Blessings)) {
-              vlog.logger.error(
-                'Encoding non-blessings value as wire blessings');
-                return null;
-            }
-            return result;
-          }
-          return vdl.canonicalize.fill(result, t);
-        });
-        self.sendResult(messageId, methodName, canonResults, undefined,
-                        methodSig.outArgs.length);
-      });
     });
   });
+  if (methodSig === undefined) {
+    err = new verror.NoExistError(
+      call, 'Requested method', methodName, 'not found on');
+    this.sendResult(messageId, methodName, null, err);
+    return;
+  }
+
+  // Unwrap the RPC arguments sent to the JS server.
+  var unwrappedArgs = request.args.map(function(arg, i) {
+    // If an any type was expected, unwrapping is not needed.
+    if (methodSig.inArgs[i].type.kind === vdl.kind.ANY) {
+      return arg;
+    }
+    var unwrapped = typeUtil.unwrap(arg);
+    if (unwrapped instanceof JsBlessings) {
+      return new Blessings(unwrapped.handle, unwrapped.publicKey,
+                           self._controller);
+    }
+    return unwrapped;
+  });
+  var options = {
+    methodName: methodName,
+    args: unwrappedArgs,
+    methodSig: methodSig,
+    ctx: ctx,
+    call: call,
+  };
+
+  this._contextMap[messageId] = options.ctx;
+  if (methodIsStreaming(methodSig)) {
+    var readType = (methodSig.inStream ? methodSig.inStream.type : null);
+    var writeType = (methodSig.outStream ? methodSig.outStream.type : null);
+    stream = new Stream(messageId, this._proxy.senderPromise, false, readType,
+      writeType);
+    this._streamMap[messageId] = stream;
+    var rpc = new StreamHandler(options.ctx, stream);
+    this._proxy.addIncomingStreamHandler(messageId, rpc);
+    options.stream = stream;
+  }
+
+  // Invoke the method;
+  this.invokeMethod(invoker, options, function(err, results) {
+    if (err) {
+      var stackTrace;
+      if (err instanceof Error && err.stack !== undefined) {
+        stackTrace = err.stack;
+      }
+      vlog.logger.debug('Requested method ' + methodName +
+          ' threw an exception on invoke: ', err, stackTrace);
+
+      // The error case has no results; only send the error.
+      self.sendResult(messageId, methodName, undefined, err,
+          methodSig.outArgs.length);
+      return;
+    }
+
+    // Has results; associate the types of the outArgs.
+    var canonResults = results.map(function(result, i) {
+      var t = methodSig.outArgs[i].type;
+      if (t.equals(WireBlessings.prototype._type)) {
+        return result;
+      }
+      return vdl.canonicalize.fill(result, t);
+    });
+    self.sendResult(messageId, methodName, canonResults, undefined,
+                    methodSig.outArgs.length);
+  });
+
 };
 /**
  * Handles incoming requests from the server to invoke methods on registered
@@ -561,13 +550,10 @@
 
       var suffix = namespaceUtil.join(name, child);
       self.incrementOutstandingRequestForId(messageId);
+      var subCall = new ServerCall(call);
+      subCall.securityCall.suffix = suffix;
       var nextInvoker;
-      var subCall;
-      createServerCall(call, this._blessingsManager).then(function(servCall) {
-        subCall = servCall;
-        subCall.securityCall.suffix = suffix;
-        return server._handleLookup(suffix);
-      }).then(function(value) {
+      server._handleLookup(suffix).then(function(value) {
         nextInvoker = value.invoker;
         return server.handleAuthorization(value._handle, context,
                                           subCall.securityCall);
diff --git a/src/runtime/index.js b/src/runtime/index.js
index 7c51044..8f4a379 100644
--- a/src/runtime/index.js
+++ b/src/runtime/index.js
@@ -23,8 +23,6 @@
 var vtrace = require('../vtrace');
 var Controller =
   require('../gen-vdl/v.io/x/ref/services/wspr/internal/app').Controller;
-var BlessingsManager = require('../security/blessings-manager');
-var BlessingsRouter = require('../security/blessings-router');
 
 module.exports = {
   init: init
@@ -119,9 +117,6 @@
   this._name = options.appName;
   this._language = options.language;
   this.caveatRegistry = new CaveatValidatorRegistry();
-  this.blessingsManager = new BlessingsManager(this._controller);
-  this._blessingsRouter = new BlessingsRouter(this._getProxyConnection(),
-    this.blessingsManager);
 }
 
 inherits(Runtime, EE);
@@ -254,8 +249,7 @@
       this._name,
       this.getContext(),
       this._controller,
-      this.caveatRegistry,
-      this.blessingsManager);
+      this.caveatRegistry);
   }
   return this._router;
 };
@@ -269,8 +263,7 @@
   if (!this._granterRouter) {
     this._granterRouter = new GranterRouter(
       this._getProxyConnection(),
-      this.getContext(),
-      this.blessingsManager);
+      this.getContext());
   }
   return this._granterRouter;
 };
diff --git a/src/security/access/permissions-authorizer.js b/src/security/access/permissions-authorizer.js
index 117b5db..c2a03ad 100644
--- a/src/security/access/permissions-authorizer.js
+++ b/src/security/access/permissions-authorizer.js
@@ -12,7 +12,7 @@
 var NoPermissionsError = vdlAccess.NoPermissionsError;
 var Permissions = vdlAccess.Permissions;
 
-module.exports = permissionsAuthorizer;
+module.exports = authorizer;
 var pkgPath = 'v.io/v23/security/access';
 var MultipleTagsError = makeError(
   pkgPath + '.errMultipleMethodTags',
@@ -38,7 +38,7 @@
  * @return {module:vanadium.security.Authorize} An authorizer that applies
  * the perms.
  */
-function permissionsAuthorizer(perms, type) {
+function authorizer(perms, type) {
   // Force the Permissions to have the correct Permissions format.
   var permissions = unwrap(new Permissions(perms));
 
@@ -70,4 +70,4 @@
     }
     return;
   };
-}
+}
\ No newline at end of file
diff --git a/src/security/blessings-cache.js b/src/security/blessings-cache.js
deleted file mode 100644
index e3b0444..0000000
--- a/src/security/blessings-cache.js
+++ /dev/null
@@ -1,130 +0,0 @@
-// 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.
-
-var unwrap = require('../vdl/type-util').unwrap;
-var vlog = require('../lib/vlog');
-var Deferred = require('../lib/deferred');
-
-/**
- * @fileoverview A cache of blessings, used in conjunction with the cache
- * in WSPR (principal/cache.go) to reduce the number of times blessings must
- * be sent across the wire.
- * This is kept in sync with the WSPR cache.
- * @private
- */
-
-module.exports = BlessingsCache;
-
-/**
- * @summary Cache of blessings received from WSPR.
- * @description This cache is kept in sync with WSPR to reduce the
- * number of times that blessings must be sent across the wire.
- * @constructor
- * @private
- */
-function BlessingsCache() {
- // Each entry has the following fields (which may or may not exist):
- // - deferredBlessings: a deferred object whose promise resolves to the
- // blessings
- // - refCount: number of references to the blessings
- // - deleteAfter: delete the entry after this number of blessings
- this._entries = {};
-}
-
-/**
- * @summary addBlessings adds blessings to the blessings cache.
- * @param {wspr.internal.principal.BlessingsCacheAddMessage} addMessage
- */
-BlessingsCache.prototype.addBlessings = function(addMessage) {
-  var id = this._unwrappedId(addMessage.cacheId);
-  var entry = this._getOrCreateEntry(id);
-  entry.deferredBlessings.resolve(addMessage.blessings);
-};
-
-/**
- * @summary deleteBlessings removes blessings from the blessings cache.
- * @param {wspr.internal.principal.BlessingsCacheAddMessage} addMessage
- */
-BlessingsCache.prototype.deleteBlessings = function(deleteMessage) {
-  var id = this._unwrappedId(deleteMessage.cacheId);
-  var entry = this._getOrCreateEntry(id);
-  entry.deleteAfter = deleteMessage.deleteAfter;
-
-  this._deleteIfNoLongerNeeded(id);
-};
-
-/**
- * @summary blessingsFromId looks up a blessing by id or waits for it if it
- * has not been put in the cache yet
- * @param {wspr.internal.principal.BlessingsId} blessingsId
- */
-BlessingsCache.prototype.blessingsFromId = function(blessingsId) {
-  var id = unwrap(blessingsId);
-
-  if (typeof id !== 'number') {
-    throw new Error('Expected numeric blessings id');
-  }
-  if (id === 0) {
-    // Zero is not a valid id.
-    // TODO(bprosnitz) Replace this with null once we switch to full blessings
-    // objects. It is currently a number because there are no optional numbers
-    // now in VDL.
-    return Promise.resolve(null);
-  }
-
-  var entry = this._getOrCreateEntry(id);
-  var cache = this;
-  return entry.deferredBlessings.promise.then(function(blessings) {
-    cache._increaseRefCount(id);
-    cache._deleteIfNoLongerNeeded(id);
-    return blessings;
-  });
-};
-
-BlessingsCache.prototype._increaseRefCount = function(cacheId) {
-  var entry = this._entries[cacheId];
-  if (!entry) {
-    throw new Error('Unexpectedly got id of missing entry');
-  }
-  entry.refCount++;
-};
-
-BlessingsCache.prototype._deleteIfNoLongerNeeded = function(cacheId) {
-  var entry = this._entries[cacheId];
-  if (!entry) {
-    throw new Error('Entry unexpectedly not present');
-  }
-
-  if (entry.refCount >= entry.deleteAfter) {
-    if (entry.refCount > entry.deleteAfter) {
-      vlog.logger.warn('Got more references than expected');
-    }
-    if (entry.waiting) {
-      vlog.logger.warn(
-        'There should not be anything waiting on entry to be deleted');
-    }
-    delete this._entries[cacheId];
-  }
-};
-
-BlessingsCache.prototype._getOrCreateEntry = function(cacheId) {
-  if (!this._entries[cacheId]) {
-    this._entries[cacheId] = {
-      refCount: 0,
-      deferredBlessings: new Deferred()
-    };
-  }
-  return this._entries[cacheId];
-};
-
-BlessingsCache.prototype._unwrappedId = function(cacheId) {
-  var id = unwrap(cacheId);
-  if (typeof id !== 'number') {
-    throw new Error('Got non-numeric id');
-  }
-  if (id <= 0) {
-    throw new Error('Unexpected non-positive id ' + id);
-  }
-  return id;
-};
diff --git a/src/security/blessings-manager.js b/src/security/blessings-manager.js
deleted file mode 100644
index 723b1d7..0000000
--- a/src/security/blessings-manager.js
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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.
-
-/**
- * @fileoverview Manager of cache blessings. This differs from BlessingsCache
- * because it converts JsBlessings to Blessings objects.
- * TODO(bprosnitz) Remove this after switching to performing WireBlessings to
- * Blessings conversion with native types.
- * @private
- */
-
-var BlessingsCache = require('../security/blessings-cache');
-var Blessings = require('../security/blessings');
-
-
-module.exports = BlessingsManager;
-
-/*
- * TODO(bprosnitz) Replace this with just BlessingsCache after switching
- * to using native type conversion with blessings.
- */
-/*
- * @summary Manager of blessings received from WSPR.
- * @constructor
- * @inner
- */
-function BlessingsManager(controller) {
-  this._blessingsCache = new BlessingsCache();
-  this._controller = controller;
-}
-
-BlessingsManager.prototype.blessingsFromId = function(id) {
-  var controller = this._controller;
-  return this._blessingsCache.blessingsFromId(id).then(function(jsBless) {
-    if (!jsBless) {
-      return null;
-    }
-    return new Blessings(jsBless.handle, jsBless.publicKey, controller);
-  });
-};
-
-BlessingsManager.prototype.addBlessings = function(addMessage) {
-  return this._blessingsCache.addBlessings(addMessage);
-};
-
-BlessingsManager.prototype.deleteBlessings = function(deleteMessage) {
-  return this._blessingsCache.deleteBlessings(deleteMessage);
-};
diff --git a/src/security/blessings-router.js b/src/security/blessings-router.js
deleted file mode 100644
index 4254bf9..0000000
--- a/src/security/blessings-router.js
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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.
-
-/**
- * @fileoveriew A router that handles incoming requests to update the state
- * of the blessings cache.
- * @private
- */
-
-var vlog = require('./../lib/vlog');
-var Incoming = require('../proxy/message-type').Incoming;
-
-module.exports = BlessingsRouter;
-
-/**
- * A router that handles incoming requests to update the state of the blessings
- * cache.
- * @constructor
- * @private
- */
-function BlessingsRouter(proxy, blessingsManager) {
-  this._blessingsManager = blessingsManager;
-
-  proxy.addIncomingHandler(Incoming.BLESSINGS_CACHE_MESSAGE, this);
-}
-
-BlessingsRouter.prototype.handleRequest = function(messageId, type, request) {
-  switch (type) {
-  case Incoming.BLESSINGS_CACHE_MESSAGE:
-    this.handleBlessingsCacheMessages(request);
-    return;
-  default:
-    vlog.logger.error('Unknown request type given to blessings router ' + type);
-  }
-};
-
-BlessingsRouter.prototype.handleBlessingsCacheMessages = function(messages) {
-  for (var i = 0; i < messages.length; i++) {
-    var message = messages[i];
-    if (message.hasOwnProperty('add')) {
-      this._blessingsManager.addBlessings(message.add);
-    } else if (message.hasOwnProperty('delete')) {
-      this._blessingsManager.deleteBlessings(message.delete);
-    } else {
-      vlog.logger.error('Unknown blessings cache message: ', message);
-    }
-  }
-};
diff --git a/src/security/blessingstore.js b/src/security/blessingstore.js
index ec74dd6..4ce7a31 100644
--- a/src/security/blessingstore.js
+++ b/src/security/blessingstore.js
@@ -8,7 +8,7 @@
  */
 
  var Deferred = require('../lib/deferred');
- var runtimeFromContext = require('../../src/runtime/runtime-from-context');
+ var Blessings = require('./blessings');
  var verror = require('../gen-vdl/v.io/v23/verror');
 
  module.exports = BlessingStore;
@@ -185,17 +185,14 @@
    controller.blessingStorePeerBlessings(ctx)
    .then(function(peerBlessings) {
      var outPeerBlessings = new Map();
-     var promises = [];
-     peerBlessings.forEach(function(blessId, pattern) {
-       var runtime = runtimeFromContext(ctx);
-       promises.push(runtime.blessingsManager.blessingsFromId(blessId)
-       .then(function(blessingsObj) {
-         outPeerBlessings.set(pattern, blessingsObj);
-       }));
+     peerBlessings.forEach(function(jsBlessings, pattern) {
+       var blessingObj = new Blessings(
+         jsBlessings.handle,
+         jsBlessings.publicKey,
+         controller);
+       outPeerBlessings.set(pattern, blessingObj);
      });
-     return Promise.all(promises).then(function() {
-       def.resolve(outPeerBlessings);
-     });
+     def.resolve(outPeerBlessings);
    }).catch(function(err) {
      def.reject(err);
    });
diff --git a/src/security/call.js b/src/security/call.js
new file mode 100644
index 0000000..daf095f
--- /dev/null
+++ b/src/security/call.js
@@ -0,0 +1,63 @@
+// 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.
+
+/**
+ * @fileoverview A context passed to the authorizer
+ * @private
+ */
+var Blessings = require('./blessings.js');
+module.exports = Call;
+
+/**
+ * @summary Call defines the state available for authorizing a principal.
+ * @name SecurityCall
+ * @property {string} method The method being invoked.
+ * @property {string} suffix The object name suffix of the request.
+ * @property {module:vanadium.security~Blessings} localBlessings The blessings
+ * bound to the local end.
+ * @property {string} localBlessingStrings The validated names for the local
+ * end.
+ * @property {module:vanadium.security~Blessings} remoteBlessings The blessings
+ * bound to the remote end.
+ * @property {string} remoteBlessingStrings The validated names for the remote
+ * end.
+ * @property {string} localEndpoint The endpoint string for the local end.
+ * @property {string} remoteEndpoint The endpoint string for the remote end.
+ * @inner
+ * @memberof module:vanadium.security
+ */
+function Call(call, controller) {
+  this.method = call.method;
+  this.suffix = call.suffix;
+  // TODO(bjornick): Use the enums.
+  this.methodTags = call.methodTags;
+  this.localBlessings = new Blessings(call.localBlessings.handle,
+                                      call.localBlessings.publicKey,
+                                      controller);
+  this.remoteBlessings = new Blessings(call.remoteBlessings.handle,
+                                       call.remoteBlessings.publicKey,
+                                       controller);
+  if (call.grantedBlessings) {
+    this.grantedBlessings = new Blessings(call.grantedBlessings.handle,
+                                          call.grantedBlessings.publicKey,
+                                          controller);
+  }
+  this.localBlessingStrings = call.localBlessingStrings;
+  this.remoteBlessingStrings = call.remoteBlessingStrings;
+  // TODO(bjornick): Create endpoints.
+  this.localEndpoint = call.localEndpoint;
+  this.remoteEndpoint = call.remoteEndpoint;
+}
+
+Call.prototype.clone = function() {
+  var res = Object.create(this.constructor.prototype);
+  Object.defineProperty(res, 'constructor', { value: this.constructor });
+  for (var key in this) {
+    if (!this.hasOwnProperty(key)) {
+      continue;
+    }
+    res[key] = this[key];
+  }
+  return res;
+};
diff --git a/src/security/create-security-call.js b/src/security/create-security-call.js
deleted file mode 100644
index 8cdd467..0000000
--- a/src/security/create-security-call.js
+++ /dev/null
@@ -1,74 +0,0 @@
-// 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.
-
-/**
- * @fileoverview A security information passes to authorizer and validator.
- * @private
- */
-module.exports = createSecurityCall;
-
-/**
- * Create a security call object. This exists so that we can resolve blessings
- * before the user is given the object.
- * @private
- */
-function createSecurityCall(input, blessingsManager) {
-  var call = new Call();
-  call.method = input.method;
-  call.suffix = input.suffix;
-  call.methodTags = input.methodTags;
-  call.localBlessingStrings = input.localBlessingStrings;
-  call.remoteBlessingStrings = input.remoteBlessingStrings;
-  // TODO(bjornick): Create endpoints.
-  call.localEndpoint = input.localEndpoint;
-  call.remoteEndpoint = input.remoteEndpoint;
-
-  var promises = [];
-  promises.push(blessingsManager.blessingsFromId(input.localBlessings)
-  .then(function(localBlessings) {
-    call.localBlessings = localBlessings;
-  }));
-  promises.push(blessingsManager.blessingsFromId(input.remoteBlessings)
-  .then(function(remoteBlessings) {
-    call.remoteBlessings = remoteBlessings;
-    return call;
-  }));
-
-  return Promise.all(promises).then(function() {
-    return call;
-  });
-}
-
-/**
- * @summary Call defines the state available for authorizing a principal.
- * @name SecurityCall
- * @property {string} method The method being invoked.
- * @property {string} suffix The object name suffix of the request.
- * @property {module:vanadium.security~Blessings} localBlessings The blessings
- * bound to the local end.
- * @property {string} localBlessingStrings The validated names for the local
- * end.
- * @property {module:vanadium.security~Blessings} remoteBlessings The blessings
- * bound to the remote end.
- * @property {string} remoteBlessingStrings The validated names for the remote
- * end.
- * @property {string} localEndpoint The endpoint string for the local end.
- * @property {string} remoteEndpoint The endpoint string for the remote end.
- * @inner
- * @memberof module:vanadium.security
- */
-function Call() {
-}
-
-Call.prototype.clone = function() {
-  var res = Object.create(this.constructor.prototype);
-  Object.defineProperty(res, 'constructor', { value: this.constructor });
-  for (var key in this) {
-    if (!this.hasOwnProperty(key)) {
-      continue;
-    }
-    res[key] = this[key];
-  }
-  return res;
-};
diff --git a/src/security/default-authorizer.js b/src/security/default-authorizer.js
index 6a952b4..a16958f 100644
--- a/src/security/default-authorizer.js
+++ b/src/security/default-authorizer.js
@@ -5,9 +5,9 @@
 var blessingMatches = require('./access/blessing-matching');
 var vError = require('./../gen-vdl/v.io/v23/verror');
 
-module.exports = defaultAuthorizer;
+module.exports = authorizer;
 
-function defaultAuthorizer(ctx, call, cb) {
+function authorizer(ctx, call, cb) {
   // If the remoteBlessings has a public key, and it refers to ourselves
   // (i.e a self rpc), then we always authorize.
   if (call.remoteBlessings.publicKey &&
diff --git a/src/security/principal.js b/src/security/principal.js
index afc40cc..bd69964 100644
--- a/src/security/principal.js
+++ b/src/security/principal.js
@@ -8,6 +8,7 @@
  */
 
 var Deferred = require('../lib/deferred');
+var Blessings = require('./blessings');
 var BlessingStore = require('./blessingstore');
 var verror = require('../gen-vdl/v.io/v23/verror');
 
@@ -80,9 +81,12 @@
 
   var caveats = args.slice(4);
 
+  var controller = this._controller;
   this._controller.bless(ctx, publicKey, blessings._id, extension, caveats)
-  .then(function(blessings) {
-    def.resolve(blessings);
+  .then(function(res) {
+    var publicKey = res[0];
+    var handle = res[1];
+    def.resolve(new Blessings(handle, publicKey, controller));
   }).catch(function(err) {
     def.reject(err);
   });
@@ -117,11 +121,14 @@
 
   var controller = this._controller;
   controller.blessSelf(ctx, name, caveats)
-  .then(function(blessings) {
-    def.resolve(blessings);
+  .then(function(res) {
+    var publicKey = res[0];
+    var handle = res[1];
+    def.resolve(new Blessings(handle, publicKey, controller));
   }).catch(function(err) {
     def.reject(err);
   });
+
   return def.promise;
 };
 
diff --git a/test/integration/test-authorizer.js b/test/integration/test-authorizer.js
index b8ff575..895ead4 100644
--- a/test/integration/test-authorizer.js
+++ b/test/integration/test-authorizer.js
@@ -56,9 +56,10 @@
     var ctx = res.runtime.getContext();
     client.bindTo(ctx, 'authorizerTestService/auth').then(function(service) {
       service.call(ctx, 'foo').then(function(value) {
-        assert.error(new Error('call should not have succeeded. res:' + value));
+        assert.error(new Error('call should not have succeeded' + value));
         res.end(assert);
       }).catch(function(err) {
+        // We expect to get to the error case.
         assert.ok(err);
         res.end(assert);
       });
diff --git a/test/unit/test-blessings-cache.js b/test/unit/test-blessings-cache.js
deleted file mode 100644
index 1999e3c..0000000
--- a/test/unit/test-blessings-cache.js
+++ /dev/null
@@ -1,337 +0,0 @@
-// 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.
-
-var test = require('prova');
-var BlessingsCache = require('../../src/security/blessings-cache');
-var principal =
-  require('../../src/gen-vdl/v.io/x/ref/services/wspr/internal/principal');
-
-test('Blessing cache - add before use', function(t) {
-  var blessingsA = {
-    publicKey: 'A'
-  };
-  var messages = [
-    {
-      type: 'add',
-      value: {
-        cacheId: 1,
-        blessings: blessingsA
-      }
-    },
-    {
-      type: 'blessingsFromId',
-      cacheId: 1,
-      expected: blessingsA
-    }
-  ];
-
-  testCache(t, messages);
-});
-
-test('Blessing cache - add after use', function(t) {
-  var blessingsA = {
-    publicKey: 'A'
-  };
-  var messages = [
-    {
-      type: 'blessingsFromId',
-      cacheId: 1,
-      expected: blessingsA
-    },
-    {
-      type: 'add',
-      value: {
-        cacheId: 1,
-        blessings: blessingsA
-      },
-      dontWaitPrevious: true
-    }
-  ];
-
-  testCache(t, messages);
-});
-
-test('Blessing cache - delete after add', function(t) {
-  var blessingsA = {
-    publicKey: 'A'
-  };
-  var messages = [
-    {
-      type: 'add',
-      value: {
-        cacheId: 1,
-        blessings: blessingsA
-      }
-    },
-    {
-      type: 'delete',
-      value: {
-        cacheId: 1,
-        deleteAfter: 0
-      },
-    },
-    {
-      type: 'confirmDelete',
-      cacheId: 1
-    }
-  ];
-
-  testCache(t, messages);
-});
-
-test('Blessing cache - reference counting delete', function(t) {
-  var blessingsA = {
-    publicKey: 'A'
-  };
-  var messages = [
-    {
-      type: 'add',
-      value: {
-        cacheId: 1,
-        blessings: blessingsA
-      }
-    },
-    {
-      type: 'delete',
-      value: {
-        cacheId: 1,
-        deleteAfter: 2
-      },
-    },
-    {
-      type: 'blessingsFromId',
-      cacheId: 1,
-      expected: blessingsA
-    },
-    {
-      type: 'blessingsFromId',
-      cacheId: 1,
-      expected: blessingsA
-    },
-    {
-      type: 'confirmDelete',
-      cacheId: 1
-    }
-  ];
-
-  testCache(t, messages);
-});
-
-test('Blessing cache - add after delete', function(t) {
-  var blessingsA = {
-    publicKey: 'A'
-  };
-  var messages = [
-    {
-      type: 'delete',
-      value: {
-        cacheId: 1,
-        deleteAfter: 1
-      },
-    },
-    {
-      type: 'add',
-      value: {
-        cacheId: 1,
-        blessings: blessingsA
-      }
-    },
-    {
-      type: 'blessingsFromId',
-      cacheId: 1,
-      expected: blessingsA
-    },
-    {
-      type: 'confirmDelete',
-      cacheId: 1
-    }
-  ];
-
-  testCache(t, messages);
-});
-
-test('Blessing cache - multiple entries', function(t) {
-  var blessingsA = {
-    publicKey: 'A'
-  };
-  var blessingsB = {
-    publicKey: 'B'
-  };
-  var blessingsC = {
-    publicKey: 'C'
-  };
-  var messages = [
-    {
-      type: 'add',
-      value: {
-        cacheId: 1,
-        blessings: blessingsA
-      }
-    },
-    {
-      type: 'add',
-      value: {
-        cacheId: 2,
-        blessings: blessingsB
-      }
-    },
-    {
-      type: 'blessingsFromId',
-      cacheId: 2,
-      expected: blessingsB
-    },
-    {
-      type: 'blessingsFromId',
-      cacheId: 1,
-      expected: blessingsA
-    },
-    {
-      type: 'delete',
-      value: {
-        cacheId: 1,
-        deleteAfter: 1
-      },
-    },
-    {
-      type: 'confirmDelete',
-      cacheId: 1
-    },
-    {
-      type: 'add',
-      value: {
-        cacheId: 3,
-        blessings: blessingsC
-      }
-    },
-    {
-      type: 'delete',
-      value: {
-        cacheId: 2,
-        deleteAfter: 3
-      },
-    },
-    {
-      type: 'blessingsFromId',
-      cacheId: 2,
-      expected: blessingsB
-    },
-    {
-      type: 'blessingsFromId',
-      cacheId: 3,
-      expected: blessingsC
-    },
-    {
-      type: 'delete',
-      value: {
-        cacheId: 3,
-        deleteAfter: 1
-      },
-    },
-    {
-      type: 'confirmDelete',
-      cacheId: 3
-    },
-    {
-      type: 'blessingsFromId',
-      cacheId: 2,
-      expected: blessingsB
-    },
-    {
-      type: 'confirmDelete',
-      cacheId: 2
-    }
-  ];
-
-  testCache(t, messages);
-});
-
-test('Blessing cache handles typed BlessingsId objects', function(t) {
-  var blessingsA = {
-    publicKey: 'A'
-  };
-  var messages = [
-    {
-      type: 'add',
-      value: {
-        cacheId: 1,
-        blessings: blessingsA
-      }
-    },
-    {
-      type: 'blessingsFromId',
-      cacheId: new principal.BlessingsId(1),
-      expected: blessingsA
-    }
-  ];
-
-  testCache(t, messages);
-});
-
-test('Blessing cache handles zero blessing id', function(t) {
-  var messages = [
-    {
-      type: 'blessingsFromId',
-      cacheId: new principal.BlessingsId(0),
-      expected: null
-    }
-  ];
-
-  testCache(t, messages);
-});
-
-/**
- * Tests the cache by handling a sequence of messages.
- * @private
- */
-function testCache(t, messages) {
-  var cache = new BlessingsCache();
-  var promises = [];
-  messages.forEach(function(message, index) {
-    // Wait for the previous messages to finish unless dontWaitPrevious is
-    // specified.
-    var preCondPromise = Promise.all(promises);
-    if (message.dontWaitPrevious) {
-      preCondPromise = Promise.resolve();
-    }
-
-    var result = preCondPromise.then(function() {
-      return handleCacheTestMessage(t, cache, message, index);
-    }).catch(function(err) {
-      t.fail('Error in message ' + index + ': ' + err);
-    });
-    promises.push(result);
-  });
-
-  // Wait for all promises to complete.
-  Promise.all(promises).then(function() {
-    t.end();
-  }).catch(function(err) {
-    t.end(err);
-  });
-}
-
-function handleCacheTestMessage(t, cache, message, index) {
-  if (message.type === 'add') {
-    var addMsg = new principal.BlessingsCacheAddMessage(message.value);
-    return cache.addBlessings(addMsg);
-  } else if (message.type === 'delete') {
-    var delMsg = new principal.BlessingsCacheDeleteMessage(message.value);
-    return cache.deleteBlessings(delMsg);
-  } else if (message.type === 'confirmDelete') {
-    t.ok(cache._entries, 'Entries table should exist');
-    t.notOk(message.cacheId in cache._entries,
-      'Cache entry not deleted correctly on message ' + index);
-  } else if (message.type === 'blessingsFromId') {
-    return cache.blessingsFromId(message.cacheId).then(function(blessings) {
-      var expected = null;
-      if (message.expected !== null) {
-        expected = new principal.JsBlessings(message.expected);
-      }
-      t.deepEqual(blessings, expected,
-        'Should get expected blessings on message ' + index);
-    });
-  } else {
-    throw new Error('unknown message type');
-  }
-}
diff --git a/test/unit/test-caveat-validator-registry.js b/test/unit/test-caveat-validator-registry.js
index f43a275..67fbf9d 100644
--- a/test/unit/test-caveat-validator-registry.js
+++ b/test/unit/test-caveat-validator-registry.js
@@ -6,12 +6,13 @@
 var CaveatValidatorRegistry =
   require('../../src/security/caveat-validator-registry');
 var context = require('../../src/context');
+var SecurityCall = require('../../src/security/call');
 var caveats = require('../../src/security/caveats');
 
 var testCaveats = require('../vdl-out/javascript-test/security/caveat');
 
 function getMockSecurityCall() {
-  return {
+  return new SecurityCall({
     method: '',
     suffix: '',
     methodTags: [],
@@ -27,7 +28,9 @@
     remoteBlessingStrings: [],
     localEndpoint: '',
     remoteEndpoint: ''
-  };
+  },
+  null, // controller
+  context.Context());
 }
 
 
diff --git a/test/unit/test-standard-caveat-validators.js b/test/unit/test-standard-caveat-validators.js
index 41e545e..0285090 100644
--- a/test/unit/test-standard-caveat-validators.js
+++ b/test/unit/test-standard-caveat-validators.js
@@ -8,11 +8,12 @@
 var caveats = require('../../src/security/caveats');
 var vdlSecurity = require('../../src/gen-vdl/v.io/v23/security');
 var context = require('../../src/context');
+var SecurityCall = require('../../src/security/call');
 var Time = require('../../src/gen-vdl/v.io/v23/vdlroot/time').Time;
 var vdl = require('../../src/vdl');
 
 function getMockSecurityCall() {
-  return {
+  return new SecurityCall({
     method: 'aMethod', // only field currently used
     suffix: '',
     methodTags: [],
@@ -28,7 +29,9 @@
     remoteBlessingStrings: [],
     localEndpoint: '',
     remoteEndpoint: ''
-  };
+  },
+  null, // controller
+  context.Context());
 }
 
 function assertValidation(t, cavType, val, cb) {