文章目录
当peer收到leader发来的block后,需要进行VSCC、MVCC、commit三步操作。下面我们从peer收到block开始,分析VSCC这个过程的代码(HLF v1.3)。
收到block
- 在
gossip/state/state.go
的listen
函数中收到payload(其中有block和private data),通过queueNewMessage
将其放入payloads
中等待后续处理。 - 然后在
deliverPayloads
函数中开始处理payloads
中的payload,得到block和pvtData后,做了一些简单的检查,之后调用commitBlock
函数。 - 在
commitBblock
中,调用了gossip/privdata/coordinator.go
中的StoreBlock
函数和UpdateLedgerHeight函数(TODO)。
VSCC
-
在
StoreBlock
中,首先调用了core/committer/txvalidator/validator.go
中的Validate
对该block做VSCC。 -
在
Validate
中,对block中的每一个tx都启动一个gorouting调用validateTx
,验证结果通过result
传回进行处理(存储了VSCC的结果供后续使用)。 -
在
validateTx
中,调用core/common/validation/msgvalidation.go
中的ValidateTransaction
,对该TX的envelop的格式进行了检查,并在checkSignatureFromCreator
中验证该tx的创建这者身份的有效性&检查签名的有效性,然后根据TX的类型(normal transaction 或者config transaction)分别调用了对应的函数(validateEndorserTransaction
或者validateConfigTransaction
),再检查tx所属的channel是否存在。a. (在调用之前先检查了txID的正确性
protos/utils/proputils.go:CheckProposalTxID
)。在validateEndorserTransaction
中,获取该TX的action
(TODO),并验证action的签名header(确保有nounce),然后重新计算了该TX的proposal的hash并与proposal中带有的hash进行了比较。b. 在
validateConfigTransaction
中,什么也没做:There is no need to do this validation here, the configtx.Validator handles this. -
然后根据TX类型做不同的处理:
- 对于normal tranasaction(也就是代码里的
HeaderType_ENDORSER_TRANSACTION
):
a. 检查该txID在账本中是否已经存在
b. 调用core/committer/txvalidator/vscc_validator.go
中的VSCCValidateTx
做VSCC (TODO) - 对于config trnasaction(也就是代码里的
HeaderType_CONFIG
):
a. 调用Apply
(TODO)
- 对于normal tranasaction(也就是代码里的
-
在
core/committer/txvalidator/vscc_validator.go
的VSCCValidateTx
中,先对该tx的chaincode的名字和版本做了检查,然后会根据chaincode类型做不同处理
a. 对于
application chaincode
: 对于每一个namespace,
调用VSCCValidateTxForCC
=》core/committer/txvalidator/plugin_validator.go:ValidateWithPlugin
=》core/handlers/validation/builtin/default_validation.go:Validate
=》core/handlers/validation/builtin/v13/validation_logic.go:Validate
…
…
=>core/committer/txvalidator/plugin_validator.go:Evaluate
=>common/cauthdsl/policy.go: Evaluate
进行验证(TODO)b. 对于
system chaincode
: