Request handling
July 5, 2019 ยท View on GitHub
To handler requests sent by client, the node has a several managers:
write_managerread_manageraction_managerAll of this managers have a 2 type of handlers:request handlers(WriteRequestHandler,ReadRequestHandlerandActionRequestHandler)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_batchandreject_batch. All of managers have an API method for registering request and batch handlers, that's calledregister_req_handlerandregister_batch_handlercorrespondingly. 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.
There are 3 types of requests a client can send:
- Query:
Here the client is requesting transactions or some state variables from the node(s). The client can either send a
GET_TXNto get any transaction with a sequence number from any ledger. Or it can send specificGET_*transactions for queries.read_managerwill be used for this request type. - 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_managerwill be used for this request type.
Request handling
Below is a description of how a request is processed.
A node on receiving a client request in validateClientMsg:
- The node performs static validation checks (validation that does not require any state, like mandatory fields are present, etc), it uses
ClientMessageValidatorandstatic_validationfrom associated manager. - 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. - 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. AREQNACKmight be sent if the query is not correctly constructed. - Checks if it's a specific query, then corresponded
request_handlerfromread_managerreturn a result. AREQNACKmight be sent if the query is not correctly constructed. - If it is a write, then node checks if it has already processed the request before by checking the uniqueness of
identifierandreqIdfields of the Request.- If it has already processed the request, then it sends the corresponding
Replyto the client - If the
Requestis already in process, then it sends an acknowledgement to the client as aREQACK - If the node has not seen the
Requestbefore it broadcasts theRequestto all nodes in aPROPAGATE. - Once a node receives sufficient (
Quorums.propagate)PROPAGATEs for a request, it forwards the request to its 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_validationofwrite_managerwhich choose a specific request handlers. If the validation succeeds thenapply_requestmethod ofwrite_manageris called which optimistically applies the changes to ledger and state. If the validation fails, the primary sends aREJECTto the client. Then the primary sends aPRE-PREPAREto other nodes which contains the merkle roots and some other information for all such requests. - The non-primary replicas on receiving the
PRE-PREPAREperforms 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 aPREPAREotherwise they reject thePRE-PREPARE - Once the consensus protocol is successfully executed on the request, the replicas send
ORDEREDmessage to its node and the node updates the monitor. - If the
ORDEREDmessage 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_batchmethod ofwrite_managerand send aReplyback to client. - The node also tracks the request's
identifierandreqIdin a key value database inupdateSeqNoMap.
- If it has already processed the request, then it sends the corresponding
Signature verification
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 atleast 1 authenticator called CoreAuthNr whose authenticate method is called over the serialised request data to verify signature.
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