hyperledger-fabric-sdk 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/lib/fabric/block_decoder.rb +299 -0
  3. data/lib/fabric/chaincode_response.rb +47 -0
  4. data/lib/fabric/channel.rb +55 -34
  5. data/lib/fabric/client.rb +107 -25
  6. data/lib/fabric/configuration.rb +12 -4
  7. data/lib/fabric/constants.rb +1 -1
  8. data/lib/fabric/crypto_suite.rb +145 -0
  9. data/lib/fabric/enumerator_queue.rb +26 -0
  10. data/lib/fabric/error.rb +52 -0
  11. data/lib/fabric/event_hub.rb +81 -0
  12. data/lib/fabric/helper.rb +31 -0
  13. data/lib/fabric/identity.rb +25 -19
  14. data/lib/fabric/logger.rb +37 -0
  15. data/lib/fabric/orderer.rb +18 -2
  16. data/lib/fabric/peer.rb +15 -36
  17. data/lib/fabric/proposal.rb +100 -0
  18. data/lib/{protos → fabric/protos}/common/collection_pb.rb +14 -14
  19. data/lib/{protos → fabric/protos}/common/common_pb.rb +37 -36
  20. data/lib/fabric/protos/common/configtx_pb.rb +71 -0
  21. data/lib/{protos → fabric/protos}/common/configuration_pb.rb +13 -13
  22. data/lib/{protos → fabric/protos}/common/ledger_pb.rb +2 -2
  23. data/lib/{protos → fabric/protos}/common/policies_pb.rb +19 -19
  24. data/lib/fabric/protos/discovery/protocol_pb.rb +120 -0
  25. data/lib/{protos → fabric/protos}/discovery/protocol_services_pb.rb +0 -1
  26. data/lib/fabric/protos/gossip/message_pb.rb +233 -0
  27. data/lib/{protos → fabric/protos}/gossip/message_services_pb.rb +0 -1
  28. data/lib/{protos → fabric/protos}/idemix/idemix_pb.rb +37 -37
  29. data/lib/{protos → fabric/protos}/ledger/queryresult/kv_query_result_pb.rb +5 -5
  30. data/lib/fabric/protos/ledger/rwset/kvrwset/kv_rwset_pb.rb +85 -0
  31. data/lib/fabric/protos/ledger/rwset/rwset_pb.rb +46 -0
  32. data/lib/{protos → fabric/protos}/msp/identities_pb.rb +4 -4
  33. data/lib/{protos → fabric/protos}/msp/msp_config_pb.rb +27 -27
  34. data/lib/{protos → fabric/protos}/msp/msp_principal_pb.rb +20 -20
  35. data/lib/fabric/protos/orderer/ab_pb.rb +52 -0
  36. data/lib/{protos → fabric/protos}/orderer/ab_services_pb.rb +0 -1
  37. data/lib/fabric/protos/orderer/cluster_pb.rb +31 -0
  38. data/lib/fabric/protos/orderer/cluster_services_pb.rb +31 -0
  39. data/lib/{protos → fabric/protos}/orderer/configuration_pb.rb +11 -10
  40. data/lib/fabric/protos/orderer/etcdraft/configuration_pb.rb +21 -0
  41. data/lib/{protos → fabric/protos}/orderer/kafka_pb.rb +16 -16
  42. data/lib/{protos → fabric/protos}/peer/admin_pb.rb +12 -12
  43. data/lib/{protos → fabric/protos}/peer/admin_services_pb.rb +0 -1
  44. data/lib/{protos → fabric/protos}/peer/chaincode_event_pb.rb +2 -2
  45. data/lib/fabric/protos/peer/chaincode_pb.rb +60 -0
  46. data/lib/fabric/protos/peer/chaincode_shim_pb.rb +129 -0
  47. data/lib/{protos → fabric/protos}/peer/chaincode_shim_services_pb.rb +0 -1
  48. data/lib/{protos → fabric/protos}/peer/configuration_pb.rb +10 -10
  49. data/lib/fabric/protos/peer/events_pb.rb +45 -0
  50. data/lib/fabric/protos/peer/events_services_pb.rb +34 -0
  51. data/lib/{protos → fabric/protos}/peer/peer_pb.rb +5 -5
  52. data/lib/{protos → fabric/protos}/peer/peer_services_pb.rb +0 -1
  53. data/lib/{protos → fabric/protos}/peer/proposal_pb.rb +13 -13
  54. data/lib/{protos → fabric/protos}/peer/proposal_response_pb.rb +11 -11
  55. data/lib/{protos → fabric/protos}/peer/query_pb.rb +10 -10
  56. data/lib/{protos → fabric/protos}/peer/resources_pb.rb +12 -12
  57. data/lib/{protos → fabric/protos}/peer/signed_cc_dep_spec_pb.rb +3 -3
  58. data/lib/{protos → fabric/protos}/peer/transaction_pb.rb +22 -18
  59. data/lib/fabric/protos/token/prover_pb.rb +66 -0
  60. data/lib/fabric/protos/token/prover_services_pb.rb +33 -0
  61. data/lib/fabric/protos/token/transaction_pb.rb +41 -0
  62. data/lib/{protos → fabric/protos}/transientstore/transientstore_pb.rb +4 -4
  63. data/lib/fabric/queue.rb +26 -0
  64. data/lib/fabric/transaction.rb +51 -0
  65. data/lib/fabric/transaction_info.rb +20 -0
  66. data/lib/fabric/version.rb +1 -1
  67. data/lib/fabric.rb +74 -0
  68. data/lib/fabric_ca/attribute.rb +7 -0
  69. data/lib/fabric_ca/client.rb +11 -19
  70. data/lib/fabric_ca/configuration.rb +4 -2
  71. data/lib/fabric_ca/connection.rb +22 -20
  72. data/lib/fabric_ca/error.rb +3 -2
  73. data/lib/fabric_ca/faraday_middleware/basic_auth.rb +3 -3
  74. data/lib/fabric_ca/faraday_middleware/raise_http_exception.rb +13 -13
  75. data/lib/fabric_ca/faraday_middleware/token_auth.rb +10 -12
  76. data/lib/fabric_ca/request.rb +13 -24
  77. data/lib/fabric_ca/version.rb +1 -1
  78. data/lib/fabric_ca.rb +16 -0
  79. data/lib/hyperledger-fabric-sdk.rb +2 -47
  80. metadata +161 -61
  81. data/lib/crypto_suite/ecdsa_aes.rb +0 -86
  82. data/lib/fabric/peer_endorser.rb +0 -85
  83. data/lib/fabric/transaction_id.rb +0 -11
  84. data/lib/fabric/user.rb +0 -24
  85. data/lib/fabric_ca/tools.rb +0 -35
  86. data/lib/protos/common/configtx_pb.rb +0 -71
  87. data/lib/protos/discovery/protocol_pb.rb +0 -119
  88. data/lib/protos/gossip/message_pb.rb +0 -233
  89. data/lib/protos/ledger/rwset/kvrwset/kv_rwset_pb.rb +0 -85
  90. data/lib/protos/ledger/rwset/rwset_pb.rb +0 -46
  91. data/lib/protos/orderer/ab_pb.rb +0 -52
  92. data/lib/protos/peer/chaincode_pb.rb +0 -60
  93. data/lib/protos/peer/chaincode_shim_pb.rb +0 -94
  94. data/lib/protos/peer/events_pb.rb +0 -98
  95. data/lib/protos/peer/events_services_pb.rb +0 -59
@@ -0,0 +1,145 @@
1
+ require 'openssl'
2
+
3
+ module Fabric
4
+ class CryptoSuite
5
+ DEFAULT_KEY_SIZE = 256
6
+ DEFAULT_DIGEST_ALGORITHM = 'SHA256'.freeze
7
+ DEFAULT_AES_KEY_SIZE = 128
8
+
9
+ EC_CURVES = { 256 => 'prime256v1', 384 => 'secp384r1' }.freeze
10
+
11
+ CIPHER = 'aes-256-cbc'.freeze
12
+
13
+ attr_reader :key_size, :digest_algorithm, :digest, :curve, :cipher
14
+
15
+ def initialize(opts = {})
16
+ @key_size = opts[:key_size] || DEFAULT_KEY_SIZE
17
+ @digest_algorithm = opts[:digest_algorithm] || DEFAULT_DIGEST_ALGORITHM
18
+ @digest = OpenSSL::Digest.new digest_algorithm
19
+ @curve = EC_CURVES[key_size]
20
+ @cipher = opts[:cipher] || CIPHER
21
+ end
22
+
23
+ def sign(private_key, message)
24
+ digest = digest message
25
+ key = pkey_from_private_key private_key
26
+ signature = key.dsa_sign_asn1 digest
27
+ sequence = OpenSSL::ASN1.decode signature
28
+ sequence = prevent_malleability sequence, key.group.order
29
+
30
+ sequence.to_der
31
+ end
32
+
33
+ def generate_private_key
34
+ key = OpenSSL::PKey::EC.new curve
35
+ key.generate_key!
36
+
37
+ key.private_key.to_i.to_s(16).downcase
38
+ end
39
+
40
+ def generate_csr(private_key, attrs = [])
41
+ key = pkey_from_private_key private_key
42
+
43
+ req = OpenSSL::X509::Request.new
44
+ req.public_key = key
45
+ req.subject = OpenSSL::X509::Name.new attrs
46
+ req.sign key, @digest
47
+
48
+ req
49
+ end
50
+
51
+ def generate_nonce(length = 24)
52
+ OpenSSL::Random.random_bytes length
53
+ end
54
+
55
+ def hexdigest(message)
56
+ @digest.hexdigest message
57
+ end
58
+
59
+ def digest(message)
60
+ @digest.digest message
61
+ end
62
+
63
+ def encode_hex(bytes)
64
+ bytes.unpack('H*').first
65
+ end
66
+
67
+ def decode_hex(string)
68
+ [string].pack('H*')
69
+ end
70
+
71
+ def keccak256(bytes)
72
+ Digest::SHA3.new(256).digest bytes
73
+ end
74
+
75
+ def restore_public_key(private_key)
76
+ private_bn = OpenSSL::BN.new private_key, 16
77
+ group = OpenSSL::PKey::EC::Group.new curve
78
+ public_bn = group.generator.mul(private_bn).to_bn
79
+ public_bn = OpenSSL::PKey::EC::Point.new(group, public_bn).to_bn
80
+
81
+ public_bn.to_s(16).downcase
82
+ end
83
+
84
+ def address_from_public_key(public_key)
85
+ bytes = decode_hex public_key
86
+ address_bytes = keccak256(bytes[1..-1])[-20..-1]
87
+
88
+ encode_hex address_bytes
89
+ end
90
+
91
+ def build_shared_key(private_key, public_key)
92
+ pkey = pkey_from_private_key private_key
93
+ public_bn = OpenSSL::BN.new public_key, 16
94
+ group = OpenSSL::PKey::EC::Group.new curve
95
+ public_point = OpenSSL::PKey::EC::Point.new group, public_bn
96
+
97
+ encode_hex pkey.dh_compute_key(public_point)
98
+ end
99
+
100
+ def encrypt(secret, data)
101
+ aes = OpenSSL::Cipher.new cipher
102
+ aes.encrypt
103
+ aes.key = decode_hex(secret)
104
+ iv = aes.random_iv
105
+ aes.iv = iv
106
+
107
+ Base64.strict_encode64(iv + aes.update(data) + aes.final)
108
+ end
109
+
110
+ def decrypt(secret, data)
111
+ return unless data
112
+
113
+ encrypted_data = Base64.strict_decode64 data
114
+ aes = OpenSSL::Cipher.new cipher
115
+ aes.decrypt
116
+ aes.key = decode_hex(secret)
117
+ aes.iv = encrypted_data[0..15]
118
+ encrypted_data = encrypted_data[16..-1]
119
+
120
+ aes.update(encrypted_data) + aes.final
121
+ end
122
+
123
+ private
124
+
125
+ def pkey_from_private_key(private_key)
126
+ public_key = restore_public_key private_key
127
+ key = OpenSSL::PKey::EC.new curve
128
+ key.private_key = OpenSSL::BN.new private_key, 16
129
+ key.public_key = OpenSSL::PKey::EC::Point.new key.group,
130
+ OpenSSL::BN.new(public_key, 16)
131
+
132
+ key
133
+ end
134
+
135
+ def prevent_malleability(sequence, order)
136
+ half_order = order >> 1
137
+
138
+ if (half_key = sequence.value[1].value) > half_order
139
+ sequence.value[1].value = order - half_key
140
+ end
141
+
142
+ sequence
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,26 @@
1
+ module Fabric
2
+ class EnumeratorQueue
3
+ extend Forwardable
4
+ def_delegators :@q, :push
5
+ def_delegators :@q, :size
6
+
7
+ def initialize(sentinel)
8
+ @q = Queue.new
9
+ @sentinel = sentinel
10
+ end
11
+
12
+ def each
13
+ return enum_for(:each) unless block_given?
14
+
15
+ loop do
16
+ r = @q.pop
17
+
18
+ break if r.equal?(@sentinel)
19
+
20
+ raise r if r.is_a? Exception
21
+
22
+ yield r
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,52 @@
1
+ module Fabric
2
+ class ErrorFactory
3
+ CHAINCODE_ERROR_MESSAGE_PREFIX = 'transaction returned with failure:'.freeze
4
+
5
+ def self.create(message)
6
+ if message.start_with? CHAINCODE_ERROR_MESSAGE_PREFIX
7
+ ChaincodeError.new message.gsub(CHAINCODE_ERROR_MESSAGE_PREFIX, '')
8
+ else
9
+ UnknownError.new message
10
+ end
11
+ end
12
+ end
13
+
14
+ class Error < StandardError
15
+ attr_reader :code, :errors
16
+
17
+ def initialize(message, code = 0, errors = {})
18
+ super message
19
+
20
+ @code = code
21
+ @errors = errors
22
+ end
23
+
24
+ def response
25
+ Hashie::Mash.new success: false,
26
+ code: code,
27
+ result: {},
28
+ message: message,
29
+ errors: errors
30
+ end
31
+ end
32
+
33
+ class ChaincodeError < Fabric::Error
34
+ def initialize(message)
35
+ response = Hashie::Mash.new JSON.parse(message)
36
+
37
+ super response.message, response.code, response.errors
38
+ end
39
+ end
40
+
41
+ class OrdererError < Fabric::Error; end
42
+
43
+ class TransactionError < Fabric::Error
44
+ def initialize(status)
45
+ super "Transaction failed (#{status})", "TX_STATUS_#{status}"
46
+ end
47
+ end
48
+
49
+ class NetworkOfflineError < Fabric::Error; end
50
+
51
+ class UnknownError < Fabric::Error; end
52
+ end
@@ -0,0 +1,81 @@
1
+ module Fabric
2
+ class EventHub
3
+ attr_reader :url, :identity, :logger, :crypto_suite, :channel_id
4
+ attr_reader :channel, :connection, :queue
5
+
6
+ MAX_BLOCK_NUMBER = 1_000_000_000
7
+
8
+ def initialize(opts = {})
9
+ @url = opts[:url]
10
+ @identity = opts[:identity]
11
+ @crypto_suite = opts[:crypto_suite]
12
+ @logger = opts[:logger]
13
+ @channel_id = opts[:channel_id]
14
+
15
+ @channel = ::Protos::Deliver::Stub.new url, :this_channel_is_insecure
16
+ @queue = Fabric::EnumeratorQueue.new channel
17
+ @connection = channel.deliver(queue.each).each
18
+ end
19
+
20
+ def observe(start_block = :newest, stop_block = MAX_BLOCK_NUMBER)
21
+ tx_info = Fabric::TransactionInfo.new crypto_suite, identity
22
+ seek_header = build_seek_header tx_info
23
+ seek_info = build_seek_info start_block, stop_block
24
+ envelope = build_envelope tx_info, seek_header, seek_info
25
+
26
+ loop do
27
+ queue.push envelope
28
+
29
+ event = connection.next
30
+
31
+ block = Fabric::BlockDecoder.decode_block(event.block)
32
+
33
+ yield block if block_given?
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def build_envelope(tx_info, seek_header, seek_info)
40
+ seek_payload = ::Common::Payload.new(
41
+ header: seek_header,
42
+ data: seek_info.to_proto
43
+ )
44
+
45
+ ::Common::Envelope.new signature: tx_info.identity.sign(seek_payload.to_proto),
46
+ payload: seek_payload.to_proto
47
+ end
48
+
49
+ def build_seek_header(tx_info)
50
+ seek_info_header = Fabric::Helper.build_channel_header(
51
+ type: ::Common::HeaderType::DELIVER_SEEK_INFO,
52
+ channel_id: channel_id,
53
+ tx_id: tx_info.tx_id
54
+ )
55
+
56
+ ::Common::Header.new(
57
+ channel_header: seek_info_header.to_proto,
58
+ signature_header: tx_info.signature_header.to_proto
59
+ )
60
+ end
61
+
62
+ def build_seek_info(start_block, stop_block)
63
+ ::Orderer::SeekInfo.new(
64
+ start: build_seek_position(start_block),
65
+ stop: build_seek_position(stop_block),
66
+ behavior: ::Orderer::SeekInfo::SeekBehavior::BLOCK_UNTIL_READY
67
+ )
68
+ end
69
+
70
+ def build_seek_position(block_number)
71
+ case block_number
72
+ when :newest then ::Orderer::SeekPosition.new(newest: ::Orderer::SeekNewest.new)
73
+ when :oldest then ::Orderer::SeekPosition.new(oldest: ::Orderer::SeekOldest.new)
74
+ else
75
+ ::Orderer::SeekPosition.new(
76
+ specified: ::Orderer::SeekSpecified.new(number: block_number)
77
+ )
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,31 @@
1
+ module Fabric
2
+ module Helper
3
+ def self.build_channel_header(opts)
4
+ header = Common::ChannelHeader.new type: opts[:type],
5
+ channel_id: opts[:channel_id],
6
+ tx_id: opts[:tx_id],
7
+ timestamp: opts[:timestamp] || build_timestamp,
8
+ version: 1
9
+
10
+ header.extension = build_channel_header_extension(opts) if opts[:chaincode_id]
11
+
12
+ header
13
+ end
14
+
15
+ def self.build_channel_header_extension(opts)
16
+ id = Protos::ChaincodeID.new name: opts[:chaincode_id]
17
+
18
+ Protos::ChaincodeHeaderExtension.new chaincode_id: id
19
+ end
20
+
21
+ def self.build_timestamp
22
+ now = Time.current
23
+
24
+ Google::Protobuf::Timestamp.new seconds: now.to_i, nanos: now.nsec
25
+ end
26
+
27
+ def self.timestamp_to_time(timestamp)
28
+ (timestamp.seconds * 1000 + timestamp.nanos / 10**6).to_i
29
+ end
30
+ end
31
+ end
@@ -2,35 +2,41 @@ require 'msp/identities_pb'
2
2
 
3
3
  module Fabric
4
4
  class Identity
5
- attr_reader :certificate, :public_key, :private_key, :msp_id, :crypto_suite,
6
- :key, :iv
7
-
8
- def initialize(args)
9
- @certificate = args[:certificate]
10
- @public_key = args[:public_key]
11
- @private_key = args[:private_key]
12
- @msp_id = args[:msp_id]
13
- @crypto_suite = args[:crypto_suite]
14
- @key = args[:key].to_s
15
- @iv = args[:iv].to_s
5
+ attr_reader :private_key,
6
+ :public_key,
7
+ :address
8
+
9
+ attr_accessor :certificate, :mspid
10
+
11
+ def initialize(crypto_suite, opts = {})
12
+ @crypto_suite = crypto_suite
13
+
14
+ @private_key = opts[:private_key] || @crypto_suite.generate_private_key
15
+ @public_key = opts[:public_key] || @crypto_suite.restore_public_key(private_key)
16
+ @certificate = opts[:certificate]
17
+ @mspid = opts[:mspid]
18
+
19
+ @address = @crypto_suite.address_from_public_key public_key
16
20
  end
17
21
 
18
- def serialize
19
- Msp::SerializedIdentity.new(mspid: msp_id, id_bytes: certificate).to_proto
22
+ def generate_csr(attrs = [])
23
+ @crypto_suite.generate_csr private_key, attrs
20
24
  end
21
25
 
22
26
  def sign(message)
23
- digest = crypto_suite.digest message
27
+ @crypto_suite.sign(private_key, message)
28
+ end
24
29
 
25
- crypto_suite.sign private_key, digest
30
+ def shared_secret_by(public_key)
31
+ @crypto_suite.build_shared_key private_key, public_key
26
32
  end
27
33
 
28
- def encrypt(message)
29
- crypto_suite.encrypt key, iv, message
34
+ def decoded_certificate
35
+ Base64.strict_decode64 certificate
30
36
  end
31
37
 
32
- def decrypt(message)
33
- crypto_suite.decrypt key, iv, message
38
+ def serialize
39
+ Msp::SerializedIdentity.new(mspid: mspid, id_bytes: decoded_certificate).to_proto
34
40
  end
35
41
  end
36
42
  end
@@ -0,0 +1,37 @@
1
+ module Fabric
2
+ class Logger
3
+ LOGGER_TAG = 'HYPERLEDGER FABRIC'.colorize(:green).freeze
4
+ FILTERED_MASK = '[FILTERED]'.freeze
5
+
6
+ attr_reader :logger, :filters
7
+
8
+ def initialize(logger, filters = [])
9
+ @logger = logger
10
+ @filters = [filters]
11
+ end
12
+
13
+ def error(*args)
14
+ return unless logger
15
+
16
+ logger.tagged(LOGGER_TAG) { |logger| logger.error filter_message(args.join('|')) }
17
+ end
18
+
19
+ def info(*args)
20
+ return unless logger
21
+
22
+ logger.tagged(LOGGER_TAG) { |logger| logger.info filter_message(args.join('|')) }
23
+ end
24
+
25
+ def debug(*args)
26
+ return unless logger
27
+
28
+ logger.tagged(LOGGER_TAG) { |logger| logger.debug filter_message(args.join('|')) }
29
+ end
30
+
31
+ private
32
+
33
+ def filter_message(message)
34
+ filters.inject(message) { |msg, filter| msg.gsub(filter, FILTERED_MASK) }
35
+ end
36
+ end
37
+ end
@@ -2,18 +2,34 @@ require 'orderer/ab_services_pb.rb'
2
2
 
3
3
  module Fabric
4
4
  class Orderer
5
- attr_reader :url, :opts, :client
5
+ attr_reader :url, :opts, :client, :logger
6
6
 
7
7
  def initialize(args)
8
8
  @url = args[:url]
9
9
  @opts = args[:opts]
10
+ @logger = args[:logger]
11
+
10
12
  @client = ::Orderer::AtomicBroadcast::Stub.new url, :this_channel_is_insecure
11
13
  end
12
14
 
13
15
  def send_broadcast(envelope)
14
- client.broadcast([envelope]) do |response|
16
+ logging :send_broadcast_request, envelope.to_h
17
+
18
+ client.broadcast([envelope]).each do |response|
19
+ logging :send_broadcast_response, response.to_h
20
+
21
+ raise OrdererError response.message unless response.status == :SUCCESS
22
+
15
23
  yield response if block_given?
16
24
  end
17
25
  end
26
+
27
+ private
28
+
29
+ def logging(section, message)
30
+ logger.debug section.to_s.upcase.colorize(:yellow),
31
+ url.colorize(:red),
32
+ message.to_s.colorize(:blue)
33
+ end
18
34
  end
19
35
  end
data/lib/fabric/peer.rb CHANGED
@@ -1,58 +1,37 @@
1
- require 'peer/query_pb'
1
+ require 'peer/peer_services_pb'
2
2
 
3
3
  module Fabric
4
4
  class Peer
5
- attr_reader :url, :opts, :identity_context, :client
5
+ attr_reader :url, :opts, :client, :logger
6
6
 
7
7
  def initialize(args)
8
8
  @url = args[:url]
9
9
  @opts = args[:opts]
10
- @identity_context = args[:identity_context]
10
+ @logger = args[:logger]
11
+
11
12
  @client = Protos::Endorser::Stub.new url, :this_channel_is_insecure
12
13
  end
13
14
 
14
15
  def send_process_proposal(proposal)
15
- client.process_proposal proposal
16
- end
16
+ logging :send_process_proposal_request, proposal.to_h
17
17
 
18
- def query_channels
19
- request = {
20
- targets: [self],
21
- chaincode_id: Constants::CSCC,
22
- transaction: TransactionID.new(identity_context),
23
- function: Constants::FUNC_GET_CHANNELS,
24
- args: []
25
- }
18
+ response = client.process_proposal proposal
26
19
 
27
- responses = PeerEndorser.send_transaction_proposal request, '', identity_context
28
- response = responses.first
20
+ logging :send_process_proposal_response, response.to_h
29
21
 
30
- Protos::ChannelQueryResponse.decode response.response.payload
22
+ response
31
23
  end
32
24
 
33
- def query_config_block(channel_id)
34
- request = {
35
- targets: [self],
36
- chaincode_id: Constants::CSCC,
37
- transaction: TransactionID.new(identity_context),
38
- function: Constants::FUNC_GET_CONFIG_BLOCK,
39
- args: [channel_id]
40
- }
41
-
42
- responses = PeerEndorser.send_transaction_proposal request, '', identity_context
43
- proposal_response = responses.first
44
-
45
- extract_config_enveloper proposal_response
25
+ def create_event_hub
26
+ EventHub.new url: url, opts: opts, logger: logger
46
27
  end
47
28
 
48
29
  private
49
30
 
50
- def extract_config_enveloper(proposal_response)
51
- block = Common::Block.decode proposal_response.response.payload
52
- envelope = Common::Envelope.decode block.data.data.first
53
- payload = Common::Payload.decode envelope.payload
54
-
55
- Common::ConfigEnvelope.decode payload.data
56
- end
31
+ def logging(section, message)
32
+ logger.debug section.to_s.upcase.colorize(:yellow),
33
+ url.colorize(:red),
34
+ message.to_s.colorize(:blue)
35
+ end
57
36
  end
58
37
  end
@@ -0,0 +1,100 @@
1
+ module Fabric
2
+ class Proposal
3
+ attr_reader :crypto_suite, :identity, :request
4
+
5
+ def initialize(crypto_suite, identity, request = {})
6
+ @crypto_suite = crypto_suite
7
+ @identity = identity
8
+ @request = request
9
+
10
+ assign_tx request[:transaction_info] if request[:transaction_info]
11
+ end
12
+
13
+ def nonce
14
+ @nonce ||= crypto_suite.generate_nonce
15
+ end
16
+
17
+ def channel_id
18
+ request[:channel_id]
19
+ end
20
+
21
+ def chaincode_id
22
+ request[:chaincode_id]
23
+ end
24
+
25
+ def args
26
+ request[:args].compact.map &:to_s
27
+ end
28
+
29
+ def transient
30
+ request[:transient] || {}
31
+ end
32
+
33
+ def transaction_id
34
+ request[:transaction_id]
35
+ end
36
+
37
+ def tx_id
38
+ @tx_id ||= crypto_suite.hexdigest(nonce + identity.serialize)
39
+ end
40
+
41
+ def proposal
42
+ @proposal ||= Protos::Proposal.new header: header.to_proto,
43
+ payload: chaincode_proposal.to_proto
44
+ end
45
+
46
+ def signed_proposal
47
+ proposal_bytes = proposal.to_proto
48
+ signature = identity.sign proposal_bytes
49
+
50
+ Protos::SignedProposal.new proposal_bytes: proposal_bytes, signature: signature
51
+ end
52
+
53
+ def header
54
+ Common::Header.new channel_header: channel_header.to_proto,
55
+ signature_header: signature_header.to_proto
56
+ end
57
+
58
+ def channel_header
59
+ Common::ChannelHeader.new type: Common::HeaderType::ENDORSER_TRANSACTION,
60
+ channel_id: channel_id, tx_id: tx_id,
61
+ extension: channel_header_extension.to_proto,
62
+ timestamp: tx_timestamp,
63
+ version: Constants::CHANNEL_HEADER_VERSION
64
+ end
65
+
66
+ def channel_header_extension
67
+ id = Protos::ChaincodeID.new name: chaincode_id
68
+
69
+ Protos::ChaincodeHeaderExtension.new chaincode_id: id
70
+ end
71
+
72
+ def tx_timestamp
73
+ now = Time.current
74
+
75
+ @tx_timestamp ||= Google::Protobuf::Timestamp.new seconds: now.to_i, nanos: now.nsec
76
+ end
77
+
78
+ def signature_header
79
+ Common::SignatureHeader.new creator: identity.serialize, nonce: nonce
80
+ end
81
+
82
+ def chaincode_proposal
83
+ id = Protos::ChaincodeID.new name: chaincode_id
84
+ chaincode_input = Protos::ChaincodeInput.new args: args
85
+ chaincode_spec = Protos::ChaincodeSpec.new type: Protos::ChaincodeSpec::Type::NODE,
86
+ chaincode_id: id,
87
+ input: chaincode_input
88
+ input = Protos::ChaincodeInvocationSpec.new chaincode_spec: chaincode_spec
89
+
90
+ Protos::ChaincodeProposalPayload.new input: input.to_proto, TransientMap: transient
91
+ end
92
+
93
+ private
94
+
95
+ def assign_tx(transaction_info)
96
+ @tx_id = transaction_info[:tx_id]
97
+ @nonce = crypto_suite.decode_hex transaction_info[:nonce_hex]
98
+ end
99
+ end
100
+ end