原文地址:https://hyperledger-indy.readthedocs.io/projects/plenum/en/latest/request_handling.html
To handler requests sent by client, the node has a several managers:
节点有不同的 managers 来处理由客户端发送的请求:
write_manager
read_manager
action_manager
All of this managers have a 2 type of handlers:
所有的这个 managers 都有 2 种类型的 handlers:- request handlers (WriteRequestHandler, ReadRequestHandler and ActionRequestHandler)
batch handlers
(Pool/Domain/Config/Audit BatchHandler
) Request handler needs to making static and dynamic validation and updating state. Batch handlers perform a batch-related functions, likeapply_batch
,commit_batch
andreject_batch
. All of managers have an API method for registering request and batch handlers, that’s calledregister_req_handler
andregister_batch_handler
correspondingly. During static or dynamic validation all of handlers which associated with required transaction type will be called and performed. It means, that we can divide some specific validations into different request handlers. Also, this logic is suitable for batch’s handlers too.
batch handlers
(Pool/Domain/Config/Audit BatchHandler
) 请求 handler 需要进行静态地以及动态的校验并且更新 state。Batch handlers 执行的是 batch 相关的功能,比如apply_batch
,commit_batch
andreject_batch
。所有的 managers 都有一个 API 方法来注册请求以及 batch handlers,方法名字分别是register_req_handler
andregister_batch_handler
。在进行静态或者动态的校验过程中,所有跟请求的交易类型相关联的 handlers 会被调用和执行。这意味着,我们可以将一些特定的验证拆分到不同的 request handlers 来处理。这个逻辑对于 batch 的 handlers 也是适用的。
There are 3 types of requests a client can send:
客户端可以发送 3 种类型的请求:
- Query: Here the client is requesting transactions or some state variables from the node(s). The client can either send a
GET_TXN
to get any transaction with a sequence number from any ledger. Or it can send specificGET_*
transactions for queries.read_manager
will be used for this request type.
Query:客户端在请求从节点获取交易信息或者一些 state 变量。客户端可以发送一个GET_TXN
从账本上获得带有一个顺序编号的任何一个交易信息。或者它也可以发送指定的GET_*
来查询交易。read_manager
会用来处理这种类型的请求。 - Write: Here the client is asking the nodes to write a new transaction to the ledger and change some state variable. This requires the nodes to run a consensus protocol (currently RBFT). If the protocol run is successful, then the client’s proposed changes are written.
write_manager
will be used for this request type.
Write:客户端会请求节点向账本种写入一个新的交易并且改变一些 state 变量值。这个需要节点运行一个共识协议 (当前是 RBFT)。如果节点运行成功,那么客户端提出的这个改动就会被写入。write_manager
会用来处理这种类型的请求。
请求处理的流程
Below is a description of how a request is processed. A node on receiving a client request in validateClientMsg
:
下边描述了一个请求是如何被处理的。当节点在 validateClientMsg
中接收到了一个客户端的请求的时候:
- The node performs static validation checks (validation that does not require any state, like mandatory fields are present, etc), it uses
ClientMessageValidator
andstatic_validation
from associated manager.
节点会进行静态校验 (静态校验不需要任何的 state,比如一些展示的必填的字段,等等),它会使用来自于相应的 manager 的ClientMessageValidator
和static_validation
。 - If the static validation passes, it checks if the signature check is required (not required for queries) and does that if needed in
verifySignature
. More on this later.
如果静态验证通过的话,它会检查是否需要验证签名 (这个对所有查询不是必须的),如果需要的话,它会在verifySignature
中来验证签名。稍后会详细说明。 - Checks if it’s a generic transaction query (
GET_TXN
). If it is then query the ledger for that particular sequence number and return the result. AREQNACK
might be sent if the query is not correctly constructed.
检查这个是不是一个通用的交易查询 (GET_TXN
)。如果是的话,那么就从账本上查询那个指定的顺序编号然后返回结果。如果查询没有被正确的构建的话,一个REQNACK
可能会被发送。 - Checks if it’s a specific query, then corresponded
request_handler
fromread_manager
return a result. AREQNACK
might be sent if the query is not correctly constructed.
如果是一个特定的查询,那么来自于read_manager
的对应的request_handler
会返回结果。如果查询没有被正确的构建的话,一个REQNACK
可能会被发送。 - If it is a write, then node checks if it has already processed the request before by checking the uniqueness of
identifier
andreqId
fields of the Request.
如果是一个写入请求的话,节点会通过检查请求的identifier
以及reqId
字段的唯一性来检查这个请求之前是已经被处理了。- If it has already processed the request, then it sends the corresponding
Reply
to the client
如果请求已经被处理过了,那么就会将对应的Reply
发送给客户端 - If the
Request
is already in process, then it sends an acknowledgement to the client as aREQACK
如果Request
已经在处理,它会向客户端发送一个REQACK
作为一个确认。 - If the node has not seen the
Request
before it broadcasts theRequest
to all nodes in aPROPAGATE
.
如果节点以前没有见过这个Request
,它会使用一个PROPAGATE
将这个Request
广播给所有节点。 - Once a node receives sufficient (
Quorums.propagate
)PROPAGATE
s for a request, it forwards the request to its replicas.
对于一个请求,当一个节点接收到足够多的 (Quorums.propagate
)PROPAGATE
的时候,它会将这个请求转发给它的副本 replicas。 - A primary replica on receiving a forwarded request does dynamic validation (requiring state, like if violating some unique constraint or doing an unauthorised action) on the request calling
dynamic_validation
ofwrite_manager
which choose a specific request handlers. If the validation succeeds thenapply_request
method ofwrite_manager
is called which optimistically applies the changes to ledger and state. If the validation fails, the primary sends aREJECT
to the client. Then the primary sends aPRE-PREPARE
to other nodes which contains the merkle roots and some other information for all such requests.
当一个 primary 副本接受到一个被转发过来的请求的时候,它会通过调用write_manager
的dynamic_validation
,选择一个指定的请求 handler,对请求进行静态校验 (请求 state,比如判断是否违反了一些唯一性约束或者是否在进行一个没有被授权的动作)。如果校验通过,write_manager
的apply_request
方法会被调用,这会很好地将这些改动更新到账本和 state。如果校验失败了,primary 副本会向客户端发送一个REJECT
。然后这个 primary 副本会向其他的节点发送一个PRE-PREPARE
,其中包含了 merkle 根以及一些这种类型的请求的其他信息。 - The non-primary replicas on receiving the PRE-PREPARE performs the same dynamic validation that the primary performed on each request. It also checks if the merkle roots match. If all checks pass the replicas send a
PREPARE
otherwise they reject thePRE-PREPARE
当非 primary 的副本接收到PRE-PREPARE
的时候,会对每个请求跟 primary 副本执行相同的静态校验。它也会检查 merkle 根是否匹配。如果所有的检查都通过了,那么这个副本就会发送一个PREPARE
,否则它们会拒绝这个PRE-PREPARE
。 - Once the consensus protocol is successfully executed on the request, the replicas send
ORDERED
message to its node and the node updates the monitor.
当对于这个请求的共识协议成功执行之后,副本们会向它的节点发送ORDERD
消息,然后节点会更新 monitor。 - If the
ORDERED
message above was sent by the master replica then the node executes the request; meaning they commit any changes made to the ledger and state by that request by callingcommit_batch
method ofwrite_manager
and send aReply
back to client.
如果上边的这个ORDER
消息由 master 副本发送出来的话,那么节点会执行这个请求,也就是说它们会通过调用write_manager
的commit_batch
方法将该请求的所有的改动更新到账本和 state,然后发送一个Reply
给客户端。 - The node also tracks the request’s
identifier
andreqId
in a key value database inupdateSeqNoMap
.
节点也会跟踪存储在updateSeqNoMap
中的一个 key value 数据库里的,关于请求的identifier
和reqId
。
- If it has already processed the request, then it sends the corresponding
签名校验
Each node has a ReqAuthenticator
object which allows to register ClientAuthNr
objects using register_authenticator
method. During signature verification, a node runs each registered authenticator over the request and if any authenticator results in an exception then signature verification is considered failed. A node has at least 1 authenticator called CoreAuthNr
whose authenticate
method is called over the serialised request data to verify signature.
每个节点都有个 ReqAuthenticator
对象,它允许使用 register_authenticator
方法注册 ClientAuthNr
对象。在签名校验的过程中,一个节点会针对这个请求运行每个注册的 authenticator,如果任何 authenticator 的结果有问题的话,那么签名的校验就被认为是失败的。一个节点至少有一个名为 CorAuthNr
的 authenticator,它的 authenticate
方法会针对序列化的请求数据来调用,用来验证签名。
Relevant code:
相关的代码:
- Node:
plenum/server/node.py
- Replica:
plenum/server/replica.py
- Propagator:
plenum/server/propagator.py
- Request:
plenum/common/request.py
- Request structure validation:
plenum/common/messages/client_request.py
- WriteRequestManager:
plenum/server/request_managers/write_request_manager.py
- ReadRequestManager:
plenum/server/request_managers/read_request_manager.py
- ActionRequestManager:
plenum/server/request_managers/action_request_manager.py
- WriteRequestHandler:
plenum/server/request_handlers/handler_interfaces/write_request_handler.py
- ReadRequestHandler:
plenum/server/request_handlers/handler_interfaces/read_request_handler.py
- ActionRequestHandler:
plenum/server/request_handlers/handler_interfaces/action_request_handler.py
- Base RequestHandlers:
plenum/server/request_handlers/
- Request Authenticator:
plenum/server/req_authenticator.py
- Core Authenticator:
plenum/server/client_authn.py
- Quorums:
plenum/server/quorums.py