Request handling¶
To handler requests sent by client, the node has a several managers:
write_manager
read_manager
action_manager
All of this managers have a 2 type of handlers:request handlers
(WriteRequestHandler
,ReadRequestHandler
andActionRequestHandler
)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.
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_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.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.
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
ClientMessageValidator
andstatic_validation
from 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. AREQNACK
might be sent if the query is not correctly constructed.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.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.If it has already processed the request, then it sends the corresponding
Reply
to the clientIf the
Request
is already in process, then it sends an acknowledgement to the client as aREQACK
If the node has not seen the
Request
before it broadcasts theRequest
to all nodes in aPROPAGATE
.Once a node receives sufficient (
Quorums.propagate
)PROPAGATE
s 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_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.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 aPREPARE
otherwise they reject thePRE-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.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.The node also tracks the request’s
identifier
andreqId
in a key value database inupdateSeqNoMap
.
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