give resolution time in minutes for the given user story, only provide the number of minutes in the output without any other text

User story: This was discussed with many people including [~<USER>, [~<USER>, [~<USER>.    h1. 1. Motivation    Application chaincodes are required to authenticate the means by which the chaincode has been invoked, as authorised or not, to access (read/write) parts of its state or its services (e.g., connect to some third party to retrieve confidential info). An application chaincode invocation may be triggered either directly by a proposal referring to that chaincode, or by another chaincode’s invocation. One could thus, identify two paths a chaincode may decide to move to “authorise” the invocation:   # By directly assessing the rights of the invoker. An application chaincode’s invocation (even if the invocation is called by another chaincode) is ultimately triggered by a user’s proposal; given this, a chaincode may want to choose to directly evaluate the access rights of the creator of the proposal who led to this chaincode’s execution.   # By assessing the rights of the chaincode that invoked it. Two or more chaincodes may belong to the same application, and therefore may trust each other. That is, a chaincode may trust the access control checks performed inside the logic of another chaincode and therefore it is fine to be invokable by the latter. This, in some cases could optimise performance as access authorisation can be deduplicated. Recall that checks on the invoking chaincode are usually faster than evaluation of signature-based policies.    A couple of options to pursue for either of the above mechanisms. This draft will elaborate on how RAPI could be leveraged to do this.    *Background on RAPI.* Resources peer API (formerly called Resource system chaincode) is initialised with a set of policies at the time when a peer is requested to join a channel. These policies govern access control of system APIs (or system chaincodes).    As discussed in FAB-6042, each channel maintains a resources tree, which among other things, contains information on each chaincode. In particular, at chaincode deploy time, a subtree is created in the resources tree under /Resources/Chaincodes to include information on the freshly created chaincode:  {code:java}   <Resources>      <Chaincodes>          <Chaincode1>              (ID) : {                  CodeHash                  InstalledVersion              }              (EndorsementPolicy) : {                  PolicyReference              }          ...          <ChaincodeN>      <GlobalPolicies>          |Policy1|          ...          |PolicyN|   {code}  Where {{<xxx>}} indicates a group of name {{xxx}}, {{|xxx|}} indicates a policy of name {{xxx}}, and {{(xxx)}} indicates a value of name {{xxx}}.    More specifically, each chaincode is configured at deployment time with information to compose its identifier, i.e., hash of the code to be executed in it, and its running version, as well as its endorsement policy. Implicitly an admin policy for that chaincode is also defined. This is because when defining the chaincode sub-tree itself, a mod-policy for each item in the tree needs to be specified.    Ultimately as specified here, the per-chaincode information specified at chaincode deployment time aims to be include more components, e.g.,  a list of policies that chaincode function could identify, and/or list of collections and their interfaces.    {code:java}              <Functions>                  (Function1) : {                      InvocationPolicyReference                      EndorsementPolicyReference                  }                  ...                  (FunctionN) : {                      InvocationPolicyReference                      EndorsementPolicyReference                  }              <Collections>                  (Collection1) : {                      ReadPolicyReference                      EndorsementPolicyReference                  }                  ...                  (CollectionN) : {                      ReadPolicyReference                      EndorsementPolicyReference                  }  {code}    The functions subtree aims to represent access policies of each chaincode function.    h1. 2. Invoker-based access control enforcement    The resources tree can be extended to maintain access policies associated to a given application chaincode and its functions and/or help that these policies are evaluated. This implies two capabilities specified in a “Resources API” (RAPI or RSCC) that can work in a complementary fashion.    h2. 2.1 Bind Application Chaincode (functions) to specific policies    At instantiation time, chaincode instantiator can provide a set of policies that could be used for that chaincode’s purposes. That is, these policies can be namespaced with this chaincode’s identifier, and the chaincode can call RAPI to evaluate one of these policies on the chaincode’s behalf via chaincode to system chaincode query.     h3. 2.1.1 Policy specification    Specification of these policies can take place during chaincode instantiation, where the configuration transaction that signifies the instantiation of a chaincode (config_update for a chaincode deploy) is enhanced with a list of chaincode policies, e.g.,       {code:java}              <CCPolicies>                  (Policy1) : {                      Policy1Reference                  }                  (Policy2) : {                      Policy2Reference                  }  {code}    More specifically, at chaincode deploy time the chaincode’s configuration tree would include a list of policy references, and their modification policies. Modification policies would essentially define authorisation to modify chaincode policies.     At validation of chaincode deployment, committing peers, in addition to the other checks they do, would need to check that policy references match an existing policy.    Note: For chaincode upgrade similar remarks would apply.     h3. 2.1.2 Evaluation of an application chaincode policy     After being instantiated, and during its execution, the chaincode may wish to evaluate one or more of the policies it specified in its instantiation. For this the chaincode could invoke the following function available to the peer in the form of RAPI.       {code:java}          Func evaluatePolicy(policyRef string, idinfo interface{}) error  {code}      Where, PolicyRef would represent the path of the policy to be evaluated in the resources tree, e.g., /ChannelID/Application/Readers, or /ChannelID/Chaincodes/ChaincodeA/mypolicy.    Peer would leverage for RAPI calls the the respective channel resource tree and MSP capabilities. The RAPI will be exposed to the peer in the form of a system chaincode, e.g., RSCC.    h3. 2.1.3 Update of a policy of an application chaincode    Let now an application chaincode instantiated on a channel, and a few RSCC policies. Each policy, as described above would be namespaced under the channel identifier, and an identifier for the chaincode that owns it (identifier or name).  Now assume that a change in these policies is required. A change could include:  * Addition of a new policy under the same namespace  * Change of an existing policy under the chaincode’s namespace  * Removal of an existing policy under the chaincode’s namespace - can be accompanied by chaincode upgrade    Recall that updates to the chaincode subtree of Resources would be triggered via transactions that have the form of config_updates. That is, a (properly authorised) client or set of clients would need to submit a config_update to the channel referencing the item to be upgraded, and content of the  new version of its.     Validation of modification of CCPolicies content, i.e., of the list of policies residing under a chaincode in resources tree, will quest for signatures/approvals from a list of entities that satisfy the CCPolicies modification policy. Similarly modification of the content of an existing policy under CCPolicies, would require approvals from the list of entities that would satisfy that policy’s modification policy in the Resources tree.    h2. 2.2 Arbitrary policy evaluation for a chaincode via RSCC    In 2.1 policy specification, it is required that all the policies a specific chaincode is to leverage are created up front. It is also required that policies are publicly visible, since they constitute part of the Resources channel-specific state. However, there may be cases of chaincodes who wish to keep confidential policies that they may apply (notice that installation is a process that takes place locally on the peer side), and that may nevertheless wish to leverage channel MSPs (and respective MSP management mechanisms) to evaluate such policies.     Such requirements can be dealt with in the following ways:  # By extending RAPI or introducing a new chaincode that would perform policy evaluation using the channel’s msp manager  # By introducing RSCC/p whose operation is similar to the RSCC/c but only private    In case (1), required extensions would include the following functions  * {noformat}func (rscc *Rscc) EvaluatePolicy( policy []byte, signedData SignedData ) error{noformat}  *   {noformat}  func (rscc *Rscc) ValidateIdentity( serIdentity []byte ) error   {noformat}    *   {noformat}  func (rscc *Rscc) Verify( serIdentity []byte, signature []byte, message[]byte, opts SigOpts) error  {noformat}    *   {noformat}  func (rscc *Rscc) Sign( serIdentity []byte, secret[]byte, signature []byte, message[]byte, opts SigOpts ) signature []byte   {noformat}    *   {noformat}  func (rscc *Rscc) SatisfiesPrincipal( serIdentity []byte, principal MSPPrincipal ) error []byte   {noformat}    h3. 2.2.1 Invocation by client, RAPI as a system chaincode    This function is called when RSCC is invoked by something other than another chaincode.  In practice, this would be a client that sends a proposal that has been signed by one or more members of the channel.      {code:java}    core/scc/rscc/rscc.go:      //Invoke - update policies      func (rscc *Rscc) Invoke(stub shim.ChaincodeStubInterface) pb.Response {          return shim.Error("--TBD---")      }  {code}      The above Rscc Invoke() function would be similar to the Invoke function in CSCC:      {code:java}    core/scc/cscc/configure.go:      func (e *PeerConfiger) Invoke(stub shim.ChaincodeStubInterface)          pb.Response {        ...      }  {code}      The PeerConfiger.Invoke() function contains a large switch statement that decides the function to execute based on the arguments in the ChaincodeStubInterface that is passed to the Invoke() function.      {code:java}    core/chaincode/shim/interfaces_stable.go:      type ChaincodeStubInterface interface {        ...      }  {code}      In the above PeerConfiger.Invoke() function, we call a policy checker to see if the policy has been fulfilled:    {code:java}    core/policy/policy.go:      type PolicyChecker interface {        CheckPolicy(channelID, policyName string, signedProp *pb.SignedProposal)          error        CheckPolicyBySignedData(channelID, policyName string,          sd []*common.SignedData) error        CheckPolicyNoChannel(policyName string, signedProp *pb.SignedProposal)          error      }  {code}      For the to-be-implemented Rscc Invoke() function, we need something similar to check the MSP memberships.  Using information obtained from the shim.ChaincodeStubInterface argument, as well as the policy/policies we can do the following in Rscc.Invoke():    * Get the channel ID (stub.GetChannelID())  * Get the MSP ID    ** The MSP ID is stored in the SerializedIdentity    ** Call stub.GetSignedProposal() to get the signed proposal bytes    ** Get the actual proposal utils.GetProposal(signedProp.ProposalBytes)    ** Get the header from the actual proposal utils.GetHeader(proposal.Header)    ** Get the signature header utils.GetSignatureHeader(header.SignatureHeader)    ** Deserialize the proposal's creator with the local MSP p.localMSP.DeserializeIdentity(shdr.Creator)    ** Or maybe we can call the MSPManager instead of the local MSP (do we know which MSP to ask?)      *** MSPManager.DeserializeIdentity(serializedID []byte) and get an Identity, which will have the MSP ID  * Get the MSP (MSPManager.GetMSPs()[mspID])  * Call msp.Validate() to validate the identity from the proposal    ** Or other MSP functions?  * Once the identity has been validated, we can check the ACL of the function: Rscc.CheckACL()    The above would be used together with one or more other arguments (at least the function name) from the request that is being Invoke():d to determine whether or not Rscc will actually invoke the function or not.    After retrieving the corresponding MSP, we can also implement the functions defined in Section 2.2 (EvaluatePolicy(), ValidateIdentity(), etc.).    We would need to provide the MSP as a parameter to the function.    h3. 2.2.2 Invocation by client, introduction of RSCC/p    Same as in 2.2.1, but the peer would, in addition to public (per channel) policies, use some locally configured (private) policies (e.g., per organization policies) for ACL. The private policies would be applied within the chaincode, and their use would not impact the general interface.    h1. 3. Chaincode-based access policies    Chaincodes may trust other chaincodes to invoke them. For this reason, we can allow that at instantiation time chaincodes define the list of other chaincodes that are allowed to invoke them via a CC2CC invocation.    To do this chaincode instantiation can be extended to include a list of chaincode identifiers.     When the Rscc chaincode is invoked by another chaincode, it is called through the following function:      {code:java}    core/chaincode/shim/interfaces_stable.go:      func (stub *ChaincodeStub) InvokeChaincode(chaincodeName string,          args [][]byte, channel string) pb.Response {        ...      }  {code}      The function is defined in interfaces_stable.go, and implemented in core/chaincode/shim/chaincode.go.    Here, we assume that the calling chaincode performs the ACL and policy checks before calling InvokeChaincode. For the calling chaincode, the following function is executed to send the invocation:      {code:java}    core/chaincode/shim/handler.go:      func (handler *Handler) handleInvokeChaincode(chaincodeName string,          args [][]byte, channelId string, txid string) pb.Response {        ...      }  {code}      The receiving chaincode gets the message in this function:      {code:java}    core/chaincode/shim/chaincode.go:      func chatWithPeer(chaincodename string, stream PeerChaincodeStream,          cc Chaincode) error {        ...      }  {code}      The message is then processed here:      {code:java}    core/chaincode/shim/handler.go:      func (handler *Handler) handleMessage(msg *pb.ChaincodeMessage) error {        ...        err := handler.FSM.Event(msg.Type.String(), msg)        ...      }  {code}      While handling the event, the following function will be called (for valid transactions):      {code:java}    core/chaincode/shim/handler.go:      func (handler *Handler) beforeTransaction(e *fsm.Event) {        ...        handler.handleTransaction(msg)        ...      }  {code}      The handling will eventually be done in a function that implements the following interface call:      {code:java}    core/chaincode/shim/interfaces_stable.go:      Chaincode.Invoke(stub ChaincodeStubInterface) pb.Response  {code}    
Answer: 1100675.0