fabric-gateway 0.2.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,247 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fabric
4
+ #
5
+ # Represents an endorsed transaction that can be submitted to the orderer for commit to the ledger,
6
+ # query the transaction results and its commit status.
7
+ #
8
+ class Transaction
9
+ attr_reader :network
10
+
11
+ include Fabric::Accessors::Network
12
+
13
+ # @return [Gateway::PreparedTransaction] Prepared Transaction
14
+ attr_reader :prepared_transaction
15
+
16
+ # @return [Fabric::Envelope]
17
+ attr_reader :envelope
18
+
19
+ #
20
+ # Creates a new Transaction instance.
21
+ #
22
+ # @param [Fabric::Network] network
23
+ # @param [Gateway::PreparedTransaction] prepared_transaction
24
+ #
25
+ def initialize(network, prepared_transaction)
26
+ @network = network
27
+ @prepared_transaction = prepared_transaction
28
+ @envelope = Envelope.new(prepared_transaction.envelope)
29
+ end
30
+
31
+ #
32
+ # Get the transaction result. This is obtained during the endorsement process when the transaction proposal is
33
+ # run on endorsing peers.
34
+ #
35
+ # @param [boolean] check_status set to true to raise exception if transaction has not yet been committed
36
+ #
37
+ # @return [String] Raw transaction result
38
+ #
39
+ def result(check_status: true)
40
+ raise Fabric::CommitError, status if check_status && !status.successful
41
+
42
+ envelope.result
43
+ end
44
+
45
+ #
46
+ # Returns the transaction ID from the prepared transaction.
47
+ #
48
+ # @return [String] transaction_id
49
+ #
50
+ def transaction_id
51
+ prepared_transaction.transaction_id
52
+ end
53
+
54
+ #
55
+ # Submit the transaction to the orderer to be committed to the ledger.
56
+ #
57
+ # @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:request_response
58
+ #
59
+ # @param [Hash] options gRPC call options
60
+ #
61
+ # @return [Fabric::Transaction] self
62
+ def submit(options = {})
63
+ sign_submit_request
64
+
65
+ client.submit(new_submit_request, options)
66
+
67
+ self
68
+ end
69
+
70
+ #
71
+ # Sign the transaction envelope.
72
+ #
73
+ # @return [void]
74
+ def sign_submit_request
75
+ return if submit_request_signed?
76
+
77
+ signature = signer.sign(envelope.payload_bytes)
78
+ self.submit_request_signature = signature
79
+ end
80
+
81
+ #
82
+ # Returns true if the transaction envelope has been signed.
83
+ #
84
+ # @return [Boolean] true if signed; false otherwise
85
+ #
86
+ def submit_request_signed?
87
+ @envelope.signed?
88
+ end
89
+
90
+ #
91
+ # Digest to be signed to support offline signing of the submit request
92
+ #
93
+ # @return [String] digest of the submit request
94
+ #
95
+ def submit_request_digest
96
+ envelope.payload_digest
97
+ end
98
+
99
+ #
100
+ # Sets the submit request signature. This is used to support offline signing of the submit request.
101
+ #
102
+ # @param [String] signature
103
+ #
104
+ # @return [void]
105
+ #
106
+ def submit_request_signature=(signature)
107
+ envelope.signature = signature
108
+ end
109
+
110
+ #
111
+ # Get status of the committed transaction. If the transaction has not yet committed, this method blocks until the
112
+ # commit occurs. If status is already queried, this returns status from cache and does not make additional queries.
113
+ #
114
+ # @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:request_response
115
+ #
116
+ # @param [Hash] options gRPC call options
117
+ #
118
+ # @return [Fabric::Status] status of the committed transaction
119
+ #
120
+ def status(options = {})
121
+ @status ||= query_status(options)
122
+ end
123
+
124
+ #
125
+ # Digest to be signed to support offline signing of the commit status request
126
+ #
127
+ # @return [String] digest of the commit status request
128
+ #
129
+ def status_request_digest
130
+ Fabric.crypto_suite.digest(signed_commit_status_request.request)
131
+ end
132
+
133
+ #
134
+ # Sets the status request signature. This is used to support offline signing of the commit status request.
135
+ #
136
+ # @param [String] signature
137
+ #
138
+ # @return [void]
139
+ #
140
+ def status_request_signature=(signature)
141
+ signed_commit_status_request.signature = signature
142
+ end
143
+
144
+ #
145
+ # Returns true if the signed commit status request has been signed.
146
+ #
147
+ # @return [Boolean] true if signed; false otherwise
148
+ #
149
+ def status_request_signed?
150
+ !signed_commit_status_request.signature.empty?
151
+ end
152
+
153
+ #
154
+ # Sign the signed commit status request
155
+ #
156
+ # @return [Fabric::Transaction] self
157
+ #
158
+ def sign_status_request
159
+ return if status_request_signed?
160
+
161
+ signature = signer.sign(signed_commit_status_request.request)
162
+ signed_commit_status_request.signature = signature
163
+
164
+ self
165
+ end
166
+
167
+ #
168
+ # Returns the current instance of the signed commit status request. Necessary so we can keep the state of the
169
+ # signature in the transaction object.
170
+ #
171
+ # @return [Gateway::SignedCommitStatusRequest] signed commit status request
172
+ #
173
+ def signed_commit_status_request
174
+ @signed_commit_status_request ||= new_signed_commit_status_request
175
+ end
176
+
177
+ private
178
+
179
+ #
180
+ # Actual status query call used by status method.
181
+ #
182
+ # @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:request_response
183
+ #
184
+ # @param [Hash] options gRPC call options
185
+ #
186
+ # @return [Fabric::Status] status of the committed transaction
187
+ #
188
+ def query_status(options = {})
189
+ sign_status_request
190
+
191
+ commit_status_response = client.commit_status(signed_commit_status_request, options)
192
+ new_status(commit_status_response)
193
+ end
194
+
195
+ #
196
+ # Generates a new signed commit status request
197
+ #
198
+ # @return [Gateway::SignedCommitStatusRequest] signed commit status request protobuf message
199
+ #
200
+ def new_signed_commit_status_request
201
+ ::Gateway::SignedCommitStatusRequest.new(
202
+ request: new_commit_status_request.to_proto
203
+ )
204
+ end
205
+
206
+ #
207
+ # Generates a new commit status request
208
+ #
209
+ # @return [Gateway::CommitStatusRequest] commit status request protobuf message
210
+ #
211
+ def new_commit_status_request
212
+ ::Gateway::CommitStatusRequest.new(
213
+ channel_id: network_name,
214
+ transaction_id: transaction_id,
215
+ identity: signer.to_proto
216
+ )
217
+ end
218
+
219
+ #
220
+ # Generates a new submit request.
221
+ #
222
+ # @return [Gateway::SubmitRequest] submit request protobuf message
223
+ #
224
+ def new_submit_request
225
+ ::Gateway::SubmitRequest.new(
226
+ transaction_id: transaction_id,
227
+ channel_id: network_name,
228
+ prepared_transaction: envelope.envelope
229
+ )
230
+ end
231
+
232
+ #
233
+ # New Status from CommitStatusResponse
234
+ #
235
+ # @param [Gateway::CommitStatusResponse] response commit status response
236
+ #
237
+ # @return [Fabric::Status] transaction status
238
+ #
239
+ def new_status(response)
240
+ Fabric::Status.new(
241
+ transaction_id,
242
+ response.block_number,
243
+ Fabric::Status::TRANSACTION_STATUSES[response.result]
244
+ )
245
+ end
246
+ end
247
+ end
@@ -11,19 +11,14 @@ module Fabric
11
11
  class Network
12
12
  attr_reader :gateway, :name
13
13
 
14
+ # @!parse include Fabric::Accessors::Gateway
15
+ include Fabric::Accessors::Gateway
16
+
14
17
  def initialize(gateway, name)
15
18
  @gateway = gateway
16
19
  @name = name
17
20
  end
18
21
 
19
- def client
20
- gateway.client
21
- end
22
-
23
- def signer
24
- gateway.signer
25
- end
26
-
27
22
  #
28
23
  # Creates a new contract instance
29
24
  #
@@ -37,25 +32,39 @@ module Fabric
37
32
  end
38
33
 
39
34
  #
40
- # @TODO: original SDK has getChaincodeEvents and newChaincodeEventsRequest methods
41
- # @see https://github.com/hyperledger/fabric-gateway/blob/08118cf0a792898925d0b2710b0a9e7c5ec23228/node/src/network.ts
42
- # @see https://github.com/hyperledger/fabric-gateway/blob/main/pkg/client/network.go
35
+ # Get chaincode events emitted by transaction functions of a specific chaincode.
36
+ #
37
+ # @see Fabric::Client#chaincode_events Fabric::Client#chaincode_events - explanation of the different return types
38
+ # and example usage.
39
+ # @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:server_streamer Call options for options parameter
43
40
  #
44
- # @return [?] ?
41
+ # @param [Fabric::Contract] contract the chaincode to listen for events on
42
+ # @param [Integer] start_block Block number at which to start reading chaincode events.
43
+ # @param [Hash] call_options gRPC call options (merged with default_call_options from initializer)
44
+ # @yield [chaincode_event] loops through the chaincode events
45
+ # @yieldparam chaincode_event [Gateway::ChaincodeEventsResponse] the chaincode event
45
46
  #
46
- def new_chaincode_events
47
- raise NotYetImplemented
47
+ # @return [Enumerator|GRPC::ActiveCall::Operation|nil] Dependent on parameters passed;
48
+ # please see Fabric::Client#get_chaincode_events
49
+ #
50
+ def chaincode_events(contract, start_block: nil, call_options: {}, &block)
51
+ new_chaincode_events_request(contract, start_block: start_block).get_events(call_options, &block)
48
52
  end
49
53
 
50
54
  #
51
- # @TODO: original SDK has getChaincodeEvents and newChaincodeEventsRequest methods
52
- # @see https://github.com/hyperledger/fabric-gateway/blob/08118cf0a792898925d0b2710b0a9e7c5ec23228/node/src/network.ts
53
- # @see https://github.com/hyperledger/fabric-gateway/blob/main/pkg/client/network.go
55
+ # Create a request to receive chaincode events emitted by transaction functions of a specific chaincode. Supports
56
+ # off-line signing flow.
57
+ #
58
+ # @note I'm lying. I just copy and pasted the description from the node SDK. Offline signing should work, but it has
59
+ # not been explicitly tested.
60
+ # @todo Test off-line signing flow.
54
61
  #
55
- # @return [?] ?
62
+ # @param [Fabric::Contract] contract the chaincode to listen for events on
63
+ # @param [Integer] start_block Block number at which to start reading chaincode events.
64
+ # @return [Fabric::ChaincodeEventsRequest] Encapsulated ChaincodeEventsRequest
56
65
  #
57
- def new_chaincode_events_request
58
- raise NotImplementedError
66
+ def new_chaincode_events_request(contract, start_block: nil)
67
+ ChaincodeEventsRequest.new(contract, start_block: start_block)
59
68
  end
60
69
  end
61
70
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fabric
4
- VERSION = '0.2.0'
4
+ VERSION = '0.4.1'
5
5
  end
data/lib/fabric.rb CHANGED
@@ -1,19 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'gateway/gateway_pb'
4
+ require 'gateway/gateway_services_pb'
5
+
6
+ require 'fabric/accessors/gateway'
7
+ require 'fabric/accessors/network'
8
+ require 'fabric/accessors/contract'
9
+
10
+ require 'fabric/entities/envelope'
11
+ require 'fabric/entities/identity'
12
+ require 'fabric/entities/proposal'
13
+ require 'fabric/entities/proposed_transaction'
14
+ require 'fabric/entities/status'
15
+ require 'fabric/entities/transaction'
16
+ require 'fabric/entities/chaincode_events_requests'
17
+
3
18
  require 'fabric/constants'
4
19
  require 'fabric/contract'
5
20
  require 'fabric/client'
6
21
  require 'fabric/ec_crypto_suite'
7
22
  require 'fabric/gateway'
8
- require 'fabric/identity'
9
23
  require 'fabric/network'
10
- require 'fabric/proposal'
11
- require 'fabric/proposed_transaction'
12
24
  require 'fabric/version'
13
25
 
14
- require 'gateway/gateway_pb'
15
- require 'gateway/gateway_services_pb'
16
-
17
26
  #
18
27
  # Hyperledger Fabric Gateway SDK
19
28
  #
@@ -25,14 +34,20 @@ module Fabric
25
34
  #
26
35
  # CommitError
27
36
  #
28
- # @TODO: TEST ME!
37
+ # TODO: Add RSpec Tests for CommitError
38
+ # @todo TEST ME!
29
39
  #
30
40
  class CommitError < Error
31
41
  attr_reader :code, :transaction_id
32
42
 
43
+ #
44
+ # Creates a transaction commit error from the status
45
+ #
46
+ # @param [Fabric::Status] status transaction status
47
+ #
33
48
  def initialize(status)
34
- super("Transaction #{status.transaction_id} failed to commit with status code #{status.code} -" +
35
- Protos::TxValidationCode.lookup(status.code).to_s)
49
+ super("Transaction #{status.transaction_id} failed to commit with status code #{status.code} - " +
50
+ Status::TRANSACTION_STATUSES.key(status.code).to_s)
36
51
  @code = code
37
52
  @transaction_id = status.transaction_id
38
53
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fabric-gateway
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Chan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-12-29 00:00:00.000000000 Z
11
+ date: 2022-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-protobuf
@@ -72,14 +72,28 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '1.42'
75
+ version: 1.46.2
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '1.42'
82
+ version: 1.46.2
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake-notes
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.2.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.2.0
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: rubocop
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -136,8 +150,21 @@ dependencies:
136
150
  - - "~>"
137
151
  - !ruby/object:Gem::Version
138
152
  version: 0.9.4
139
- description: 'Hyperledger Fabric Gateway gRPC SDK generated directly from protos found
140
- at: https://github.com/hyperledger/fabric-protos.'
153
+ - !ruby/object:Gem::Dependency
154
+ name: yard
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: 0.9.27
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: 0.9.27
167
+ description: Ruby port of the Hyperledger Fabric Gateway SDK
141
168
  email:
142
169
  - jonathan.chan@ethicalidentity.com
143
170
  executables: []
@@ -145,8 +172,11 @@ extensions: []
145
172
  extra_rdoc_files: []
146
173
  files:
147
174
  - ".editorconfig"
175
+ - ".github/workflows/codeql-analysis.yml"
148
176
  - ".github/workflows/rspec.yml"
149
177
  - ".github/workflows/rubocop.yml"
178
+ - ".github/workflows/todo.yml"
179
+ - ".github/workflows/yardoc.yml"
150
180
  - ".gitignore"
151
181
  - ".gitmodules"
152
182
  - ".rspec"
@@ -154,6 +184,7 @@ files:
154
184
  - ".ruby-version"
155
185
  - ".travis.yml"
156
186
  - ".vscode/settings.json"
187
+ - ".yardopts"
157
188
  - CHANGELOG.md
158
189
  - CODE_OF_CONDUCT.md
159
190
  - Gemfile
@@ -171,15 +202,22 @@ files:
171
202
  - lib/common/policies_pb.rb
172
203
  - lib/fabric.rb
173
204
  - lib/fabric/.DS_Store
205
+ - lib/fabric/accessors/contract.rb
206
+ - lib/fabric/accessors/gateway.rb
207
+ - lib/fabric/accessors/network.rb
174
208
  - lib/fabric/client.rb
175
209
  - lib/fabric/constants.rb
176
210
  - lib/fabric/contract.rb
177
211
  - lib/fabric/ec_crypto_suite.rb
212
+ - lib/fabric/entities/chaincode_events_requests.rb
213
+ - lib/fabric/entities/envelope.rb
214
+ - lib/fabric/entities/identity.rb
215
+ - lib/fabric/entities/proposal.rb
216
+ - lib/fabric/entities/proposed_transaction.rb
217
+ - lib/fabric/entities/status.rb
218
+ - lib/fabric/entities/transaction.rb
178
219
  - lib/fabric/gateway.rb
179
- - lib/fabric/identity.rb
180
220
  - lib/fabric/network.rb
181
- - lib/fabric/proposal.rb
182
- - lib/fabric/proposed_transaction.rb
183
221
  - lib/fabric/version.rb
184
222
  - lib/gateway/gateway_pb.rb
185
223
  - lib/gateway/gateway_services_pb.rb
@@ -217,5 +255,5 @@ requirements: []
217
255
  rubygems_version: 3.1.6
218
256
  signing_key:
219
257
  specification_version: 4
220
- summary: Hyperledger Fabric Gateway gRPC SDK
258
+ summary: Hyperledger Fabric Gateway SDK
221
259
  test_files: []