@@ -18,32 +18,123 @@ syntax = "proto3";
18
18
19
19
package protos ;
20
20
21
- import "fabric_transaction_header.proto" ;
21
+ /*
22
+ The flow to get a generic transaction approved goes as follows:
23
+
24
+ 1. client sends proposal to endorser
25
+ ====================================
26
+
27
+ The proposal is basically a request to do something that will result on some
28
+ action with impact on the ledger; a proposal contains a header (with some
29
+ metadata describing it, such as the type, the identity of the invoker, the
30
+ time, the ID of the chain, a cryptographic nonce..) and an opaque payload that
31
+ depends on the type specified in the header. A proposal contains the following
32
+ messages:
33
+
34
+ SignedProposal
35
+ |\_ Signature (signature on the Proposal message by the creator specified in the header)
36
+ \_ Proposal
37
+ |\_ Header (the header for this proposal)
38
+ \_ Payload (the payload for this proposal)
39
+
40
+ 2. endorser sends proposal response back to client
41
+ ==================================================
42
+
43
+ The proposal response contains an endorser's response to a client's proposal. A
44
+ proposal response contains a success/error code, a response payload and a
45
+ signature (also referred to as endorsement) over the response payload. The
46
+ response payload contains a hash of the proposal (to securely link this
47
+ response to the corresponding proposal) and an opaque extension field that
48
+ depends on the type specified in the header of the corresponding proposal. A
49
+ proposal response contains the following messages:
50
+
51
+ ProposalResponse
52
+ |\_ Endorsement (the endorser's signature over the whole response payload)
53
+ \_ ProposalResponsePayload (the payload of the proposal response)
22
54
23
- // This structure is necessary to sign over the proposal which contains
24
- // the header and the payload. Without this structure, we would have to
25
- // concatenate the header and the payload to verify the signature, which
26
- // could be expensive with large payload
55
+ 3. client assembles endorsements into a transaction
56
+ ===================================================
57
+
58
+ A transaction message assembles one or more proposals and corresponding
59
+ responses into a message to be sent to orderers. After ordering, (batches of)
60
+ transactions are delivered to committing peers for validation and final
61
+ delivery into the ledger. A transaction contains one or more actions. Each of
62
+ them contains a header (same as that of the proposal that requested it) and an
63
+ opaque payload that depends on the type specified in the header.
64
+
65
+ SignedTransaction
66
+ |\_ Signature (signature on the Transaction message by the creator specified in the header)
67
+ \_ Transaction
68
+ \_ TransactionAction (1...n)
69
+ |\_ Header (1) (the header of the proposal that requested this action)
70
+ \_ Payload (1) (the payload for this action)
71
+ */
72
+
73
+ // This structure is necessary to sign the proposal which contains the header
74
+ // and the payload. Without this structure, we would have to concatenate the
75
+ // header and the payload to verify the signature, which could be expensive
76
+ // with large payload
77
+ //
78
+ // When an endorser receives a SignedProposal message, it should verify the
79
+ // signature over the proposal bytes. This verification requires the following
80
+ // steps:
81
+ // 1. Verification of the validity of the certificate that was used to produce
82
+ // the signature. The certificate will be available once proposalBytes has
83
+ // been unmarshalled to a Proposal message, and Proposal.header has been
84
+ // unmarshalled to a Header message. While this unmarshalling-before-verifying
85
+ // might not be ideal, it is unavoidable because i) the signature needs to also
86
+ // protect the signing certificate; ii) it is desirable that Header is created
87
+ // once by the client and never changed (for the sake of accountability and
88
+ // non-repudiation). Note also that it is actually impossible to conclusively
89
+ // verify the validity of the certificate included in a Proposal, because the
90
+ // proposal needs to first be endorsed and ordered with respect to certificate
91
+ // expiration transactions. Still, it is useful to pre-filter expired
92
+ // certificates at this stage.
93
+ // 2. Verification that the certificate is trusted (signed by a trusted CA) and
94
+ // that it is allowed to transact with us (with respect to some ACLs);
95
+ // 3. Verification that the signature on proposalBytes is valid;
96
+ // 4. Detect replay attacks;
27
97
message SignedProposal {
98
+
28
99
// The bytes of Proposal
29
- // Allow ProposalResponse to easily hash over the bytes
30
100
bytes proposalBytes = 1 ;
31
101
32
- // Signaure over proposalBytes
102
+ // Signaure over proposalBytes; this signature is to be verified against
103
+ // the creator identity contained in the header of the Proposal message
104
+ // marshaled as proposalBytes
33
105
bytes signature = 2 ;
34
106
}
35
107
36
- // A Proposal is sent to an endorser for endorsement.
37
- // The proposal contains:
38
- // 1. A header which has fields common to all proposals and specifies
39
- // a type field for customization
108
+ // A Proposal is sent to an endorser for endorsement. The proposal contains:
109
+ // 1. A header which should be unmarshaled to a Header message. Note that
110
+ // Header is both the header of a Proposal and of a Transaction, in that i)
111
+ // both headers should be unmarshaled to this message; and ii) it is used to
112
+ // compute cryptographic hashes and signatures. The header has fields common
113
+ // to all proposals/transactions. In addition it has a type field for
114
+ // additional customization. An example of this is the ChaincodeHeaderExtension
115
+ // message used to extend the Header for type CHAINCODE.
40
116
// 2. A payload whose type depends on the header's type field.
117
+ // 3. An extension whose type depends on the header's type field.
118
+ //
119
+ // Let us see an example. For type CHAINCODE (see the Header message),
120
+ // we have the following:
121
+ // 1. The header is a Header message whose extensions field is a
122
+ // ChaincodeHeaderExtension message.
123
+ // 2. The payload is a ChaincodeProposalPayload message.
124
+ // 3. The extension is a ChaincodeAction that might be used to ask the
125
+ // endorsers to endorse a specific ChaincodeAction, thus emulating the
126
+ // submitting peer model.
41
127
message Proposal {
42
128
43
- // The header of the proposal
44
- TransactionHeader header = 1 ;
129
+ // The header of the proposal. It is the bytes of the Header
130
+ bytes header = 1 ;
45
131
46
132
// The payload of the proposal as defined by the type in the proposal
47
- // header. For chaincode, it's bytes of ChaincodeProposalPayload
133
+ // header.
48
134
bytes payload = 2 ;
49
- }
135
+
136
+ // Optional extensions to the proposal. Its content depends on the Header's
137
+ // type field. For the type CHAINCODE, it might be the bytes of a
138
+ // ChaincodeAction message.
139
+ bytes extension = 3 ;
140
+ }
0 commit comments