hyperledger-fabric-sdk 0.1.0

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 (65) hide show
  1. checksums.yaml +7 -0
  2. data/lib/crypto_suite/ecdsa_aes.rb +86 -0
  3. data/lib/fabric/channel.rb +54 -0
  4. data/lib/fabric/client.rb +45 -0
  5. data/lib/fabric/configuration.rb +25 -0
  6. data/lib/fabric/constants.rb +18 -0
  7. data/lib/fabric/identity.rb +36 -0
  8. data/lib/fabric/orderer.rb +19 -0
  9. data/lib/fabric/peer.rb +58 -0
  10. data/lib/fabric/peer_endorser.rb +85 -0
  11. data/lib/fabric/transaction_id.rb +11 -0
  12. data/lib/fabric/user.rb +24 -0
  13. data/lib/fabric/version.rb +3 -0
  14. data/lib/fabric_ca/client.rb +51 -0
  15. data/lib/fabric_ca/configuration.rb +25 -0
  16. data/lib/fabric_ca/connection.rb +32 -0
  17. data/lib/fabric_ca/error.rb +11 -0
  18. data/lib/fabric_ca/faraday_middleware/basic_auth.rb +33 -0
  19. data/lib/fabric_ca/faraday_middleware/raise_http_exception.rb +47 -0
  20. data/lib/fabric_ca/faraday_middleware/token_auth.rb +38 -0
  21. data/lib/fabric_ca/request.rb +50 -0
  22. data/lib/fabric_ca/response.rb +10 -0
  23. data/lib/fabric_ca/tools.rb +35 -0
  24. data/lib/fabric_ca/version.rb +3 -0
  25. data/lib/hyperledger-fabric-sdk.rb +47 -0
  26. data/lib/protos/common/collection_pb.rb +42 -0
  27. data/lib/protos/common/common_pb.rb +106 -0
  28. data/lib/protos/common/configtx_pb.rb +71 -0
  29. data/lib/protos/common/configuration_pb.rb +33 -0
  30. data/lib/protos/common/ledger_pb.rb +16 -0
  31. data/lib/protos/common/policies_pb.rb +52 -0
  32. data/lib/protos/discovery/protocol_pb.rb +119 -0
  33. data/lib/protos/discovery/protocol_services_pb.rb +30 -0
  34. data/lib/protos/gossip/message_pb.rb +233 -0
  35. data/lib/protos/gossip/message_services_pb.rb +31 -0
  36. data/lib/protos/idemix/idemix_pb.rb +93 -0
  37. data/lib/protos/ledger/queryresult/kv_query_result_pb.rb +24 -0
  38. data/lib/protos/ledger/rwset/kvrwset/kv_rwset_pb.rb +85 -0
  39. data/lib/protos/ledger/rwset/rwset_pb.rb +46 -0
  40. data/lib/protos/msp/identities_pb.rb +23 -0
  41. data/lib/protos/msp/msp_config_pb.rb +72 -0
  42. data/lib/protos/msp/msp_principal_pb.rb +54 -0
  43. data/lib/protos/orderer/ab_pb.rb +52 -0
  44. data/lib/protos/orderer/ab_services_pb.rb +41 -0
  45. data/lib/protos/orderer/configuration_pb.rb +32 -0
  46. data/lib/protos/orderer/kafka_pb.rb +45 -0
  47. data/lib/protos/peer/admin_pb.rb +41 -0
  48. data/lib/protos/peer/admin_services_pb.rb +33 -0
  49. data/lib/protos/peer/chaincode_event_pb.rb +17 -0
  50. data/lib/protos/peer/chaincode_pb.rb +60 -0
  51. data/lib/protos/peer/chaincode_shim_pb.rb +94 -0
  52. data/lib/protos/peer/chaincode_shim_services_pb.rb +30 -0
  53. data/lib/protos/peer/configuration_pb.rb +27 -0
  54. data/lib/protos/peer/events_pb.rb +98 -0
  55. data/lib/protos/peer/events_services_pb.rb +59 -0
  56. data/lib/protos/peer/peer_pb.rb +21 -0
  57. data/lib/protos/peer/peer_services_pb.rb +37 -0
  58. data/lib/protos/peer/proposal_pb.rb +40 -0
  59. data/lib/protos/peer/proposal_response_pb.rb +35 -0
  60. data/lib/protos/peer/query_pb.rb +32 -0
  61. data/lib/protos/peer/resources_pb.rb +34 -0
  62. data/lib/protos/peer/signed_cc_dep_spec_pb.rb +17 -0
  63. data/lib/protos/peer/transaction_pb.rb +72 -0
  64. data/lib/protos/transientstore/transientstore_pb.rb +18 -0
  65. metadata +123 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8868d76ed70adc4cedf983ad30718b1964bdd4a4a06291bc336d7381bc152a74
4
+ data.tar.gz: 97809db15dee6a3f8ac534a63eb3933895e8f0fa0ebd255b10569124e5ff06c4
5
+ SHA512:
6
+ metadata.gz: e4c1c49bdc093de69d552136954eacf30f0e92128222f5e878d760e71dd94ac08720ad832e8172014fb2363ce507963fe1099f1c7589878875c412704063de8f
7
+ data.tar.gz: e91abaeeee3053694b18362ab2fff01132267782ae6fdc0e01ed8bcc04540ff565fa70ae6bd5e4931068664f8ae51230008792e3a9cf1592c23ba5284bead9e0
@@ -0,0 +1,86 @@
1
+ require 'openssl'
2
+
3
+ module CryptoSuite
4
+ class ECDSA_AES
5
+ DEFAULT_KEY_SIZE = 256.freeze
6
+ DEFAULT_NONCE_LENGTH = 24.freeze
7
+ DEFAULT_DIGEST_ALGORITHM = 'SHA256'.freeze
8
+ DEFAULT_AES_KEY_SIZE = 128.freeze
9
+
10
+ EC_CURVES = { 256 => 'prime256v1', 384 => 'secp384r1' }.freeze
11
+
12
+ attr_reader :key_size, :nonce_length, :digest_algorithm, :digest, :cipher
13
+
14
+ def initialize(opts = {})
15
+ @key_size = opts[:key_size] || DEFAULT_KEY_SIZE
16
+ @nonce_length = opts[:nonce_length] || DEFAULT_NONCE_LENGTH
17
+ @digest_algorithm = opts[:digest_algorithm] || DEFAULT_DIGEST_ALGORITHM
18
+ @digest = OpenSSL::Digest.new(digest_algorithm)
19
+ @cipher = OpenSSL::Cipher::AES.new(opts[:aes_key_size] || DEFAULT_AES_KEY_SIZE, :CBC)
20
+ end
21
+
22
+ def generate_nonce
23
+ OpenSSL::Random.random_bytes nonce_length
24
+ end
25
+
26
+ def hexdigest(message)
27
+ @digest.hexdigest message
28
+ end
29
+
30
+ def digest(message)
31
+ @digest.digest message
32
+ end
33
+
34
+ def sign(private_key, msg)
35
+ key = OpenSSL::PKey::EC.new private_key
36
+ signature = key.dsa_sign_asn1 msg
37
+ sequence = OpenSSL::ASN1.decode signature
38
+ sequence = prevent_malleability sequence, key.group.order
39
+
40
+ sequence.to_der
41
+ end
42
+
43
+ def generate_private_key
44
+ key = OpenSSL::PKey::EC.new EC_CURVES[key_size]
45
+ key.generate_key!
46
+
47
+ key.to_pem
48
+ end
49
+
50
+ def generate_csr(private_key, options = [])
51
+ key = OpenSSL::PKey::EC.new private_key
52
+ req = OpenSSL::X509::Request.new
53
+ req.public_key = key
54
+ req.subject = OpenSSL::X509::Name.new(options)
55
+ req.sign key, @digest
56
+
57
+ req
58
+ end
59
+
60
+ def encrypt(key, iv, message)
61
+ cipher.encrypt key, iv
62
+
63
+ Base64.strict_encode64(cipher.update(message) + cipher.final)
64
+ end
65
+
66
+ def decrypt(key, iv, message)
67
+ cipher.decrypt key, iv
68
+
69
+ cipher.update(Base64.strict_decode64(message)) + cipher.final
70
+ rescue OpenSSL::Cipher::CipherError
71
+ nil
72
+ end
73
+
74
+ private
75
+
76
+ def prevent_malleability(sequence, order)
77
+ half_order = order >> 1
78
+
79
+ if (half_key = sequence.value[1].value) > half_order
80
+ sequence.value[1].value = order - half_key
81
+ end
82
+
83
+ sequence
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,54 @@
1
+ require 'peer/transaction_pb'
2
+
3
+ module Fabric
4
+ class Channel
5
+ attr_reader :identity_context, :name, :peers, :orderers
6
+
7
+ def initialize(args)
8
+ @identity_context = args[:identity_context]
9
+ @name = args[:name]
10
+ @peers = args[:peers] || []
11
+ @orderers = args[:orderers] || []
12
+ end
13
+
14
+ def query_by_chaincode(request)
15
+ request[:targets] ||= peers
16
+ request[:transaction] = TransactionID.new identity_context
17
+
18
+ PeerEndorser.send_transaction_proposal request, name, identity_context
19
+ end
20
+
21
+ def send_transaction(request, &block)
22
+ header = Common::Header.decode request[:proposal].header
23
+ chaincode_action_payload = build_chaincode_action request
24
+
25
+ transaction_action = Protos::TransactionAction.new header: header.signature_header,
26
+ payload: chaincode_action_payload.to_proto
27
+ transaction = Protos::Transaction.new actions: [transaction_action]
28
+
29
+ payload = Common::Payload.new header: header,
30
+ data: transaction.to_proto
31
+
32
+ envelope = Common::Envelope.new signature: identity_context.identity.sign(payload.to_proto),
33
+ payload: payload.to_proto
34
+
35
+ orderers.first.send_broadcast envelope, &block
36
+ end
37
+
38
+ private
39
+
40
+ def build_chaincode_action(request)
41
+ responses = request[:responses].select { |response| response.response.status == 200 }
42
+ endorsements = responses.map { |response| response.endorsement }
43
+ chaincode_endorser_action =
44
+ Protos::ChaincodeEndorsedAction.new proposal_response_payload: responses.first.payload,
45
+ endorsements: endorsements
46
+
47
+ payload = Protos::ChaincodeProposalPayload.decode request[:proposal].payload
48
+ payload_no_trans = Protos::ChaincodeProposalPayload.new input: payload.input
49
+
50
+ Protos::ChaincodeActionPayload.new action: chaincode_endorser_action,
51
+ chaincode_proposal_payload: payload_no_trans.to_proto
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,45 @@
1
+ module Fabric
2
+ class Client
3
+ attr_reader :identity_context, :orderers, :peers, :channels
4
+
5
+ def initialize(options = {})
6
+ options = Fabric.options.merge(options)
7
+
8
+ @identity_context = options[:identity_context]
9
+ @orderers = {}
10
+ @channels = {}
11
+ @peers = {}
12
+ end
13
+
14
+ def config
15
+ conf = {}
16
+ Configuration::VALID_OPTIONS_KEYS.each do |key|
17
+ conf[key] = public_send key
18
+ end
19
+
20
+ conf
21
+ end
22
+
23
+ def new_channel(name)
24
+ channels[name] ||= Channel.new name: name,
25
+ orderers: orderers.values , peers: peers.values,
26
+ identity_context: identity_context
27
+
28
+ channels[name]
29
+ end
30
+
31
+ def new_peer(url, opts = {})
32
+ peers[url] ||= Peer.new url: url, opts: opts,
33
+ identity_context: identity_context
34
+
35
+ peers[url]
36
+ end
37
+
38
+ def new_orderer(url, opts = {})
39
+ orderers[url] ||= Orderer.new url: url, opts: opts,
40
+ identity_context: identity_context
41
+
42
+ orderers[url]
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,25 @@
1
+ module Fabric
2
+ module Configuration
3
+ VALID_OPTIONS_KEYS = [:identity_context, :orderers, :peers]
4
+
5
+ attr_accessor *VALID_OPTIONS_KEYS
6
+
7
+ def self.extended(base)
8
+ base.reset
9
+ end
10
+
11
+ def configure
12
+ yield self
13
+ end
14
+
15
+ def options
16
+ VALID_OPTIONS_KEYS.inject({}) do |option, key|
17
+ option.merge!(key => send(key))
18
+ end
19
+ end
20
+
21
+ def reset
22
+ VALID_OPTIONS_KEYS.each {|key| send("#{key}=", nil)}
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,18 @@
1
+ module Fabric
2
+ module Constants
3
+ ## System Chaincodes
4
+ LSCC = 'lscc'.freeze
5
+ QSCC = 'qscc'.freeze
6
+ CSCC = 'cscc'.freeze
7
+
8
+ ## System Channels
9
+ SYSTEM_CHANNEL_NAME = 'testchainid'.freeze
10
+
11
+ ## System Functions
12
+ FUNC_GET_CHANNELS = 'GetChannels'.freeze
13
+ FUNC_GET_CONFIG_BLOCK = 'GetConfigBlock'.freeze
14
+
15
+ ## Variables
16
+ CHANNEL_HEADER_VERSION = 1.freeze
17
+ end
18
+ end
@@ -0,0 +1,36 @@
1
+ require 'msp/identities_pb'
2
+
3
+ module Fabric
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
16
+ end
17
+
18
+ def serialize
19
+ Msp::SerializedIdentity.new(mspid: msp_id, id_bytes: certificate).to_proto
20
+ end
21
+
22
+ def sign(message)
23
+ digest = crypto_suite.digest message
24
+
25
+ crypto_suite.sign private_key, digest
26
+ end
27
+
28
+ def encrypt(message)
29
+ crypto_suite.encrypt key, iv, message
30
+ end
31
+
32
+ def decrypt(message)
33
+ crypto_suite.decrypt key, iv, message
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,19 @@
1
+ require 'orderer/ab_services_pb.rb'
2
+
3
+ module Fabric
4
+ class Orderer
5
+ attr_reader :url, :opts, :client
6
+
7
+ def initialize(args)
8
+ @url = args[:url]
9
+ @opts = args[:opts]
10
+ @client = ::Orderer::AtomicBroadcast::Stub.new url, :this_channel_is_insecure
11
+ end
12
+
13
+ def send_broadcast(envelope)
14
+ client.broadcast([envelope]) do |response|
15
+ yield response if block_given?
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,58 @@
1
+ require 'peer/query_pb'
2
+
3
+ module Fabric
4
+ class Peer
5
+ attr_reader :url, :opts, :identity_context, :client
6
+
7
+ def initialize(args)
8
+ @url = args[:url]
9
+ @opts = args[:opts]
10
+ @identity_context = args[:identity_context]
11
+ @client = Protos::Endorser::Stub.new url, :this_channel_is_insecure
12
+ end
13
+
14
+ def send_process_proposal(proposal)
15
+ client.process_proposal proposal
16
+ end
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
+ }
26
+
27
+ responses = PeerEndorser.send_transaction_proposal request, '', identity_context
28
+ response = responses.first
29
+
30
+ Protos::ChannelQueryResponse.decode response.response.payload
31
+ end
32
+
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
46
+ end
47
+
48
+ private
49
+
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
57
+ end
58
+ end
@@ -0,0 +1,85 @@
1
+ require 'peer/peer_services_pb'
2
+
3
+ module Fabric
4
+ class PeerEndorser
5
+ def self.send_transaction_proposal(request, channel_id, identity_context)
6
+ args = request[:args].unshift request[:function]
7
+
8
+ transaction = request[:transaction]
9
+
10
+ channel_header = build_channel_header Common::HeaderType::ENDORSER_TRANSACTION,
11
+ channel_id, transaction.id, request[:chaincode_id]
12
+ header = build_header channel_header, identity_context.identity, transaction.nonce
13
+ proposal = build_proposal header, request[:chaincode_id], args
14
+ signed_proposal = sign_proposal identity_context.identity, proposal
15
+
16
+ responses = send_peers_process_proposal request[:targets], signed_proposal
17
+
18
+ { responses: responses, proposal: proposal, header: header }
19
+ end
20
+
21
+ private
22
+
23
+ def self.build_header(channel_header, identity, nonce)
24
+ signature_header = Common::SignatureHeader.new creator: identity.serialize,
25
+ nonce: nonce
26
+
27
+ Common::Header.new channel_header: channel_header.to_proto,
28
+ signature_header: signature_header.to_proto
29
+ end
30
+
31
+ def self.build_channel_header(type, channel_id, tx_id, chaincode_id)
32
+ attrs = { type: type, channel_id: channel_id, tx_id: tx_id }
33
+ attrs[:extension] = build_channel_header_extension(chaincode_id).to_proto if chaincode_id
34
+ attrs[:timestamp] = build_current_timestamp
35
+ attrs[:version] = Constants::CHANNEL_HEADER_VERSION
36
+
37
+ Common::ChannelHeader.new attrs
38
+ end
39
+
40
+ def self.build_channel_header_extension(chaincode_id)
41
+ id = Protos::ChaincodeID.new name: chaincode_id
42
+
43
+ Protos::ChaincodeHeaderExtension.new chaincode_id: id
44
+ end
45
+
46
+ def self.build_current_timestamp
47
+ now = Time.current
48
+
49
+ Google::Protobuf::Timestamp.new seconds: now.to_i, nanos: now.sec
50
+ end
51
+
52
+ def self.build_proposal(header, chaincode_id, args)
53
+ chaincode_proposal = build_chaincode_proposal chaincode_id, args
54
+
55
+ Protos::Proposal.new header: header.to_proto,
56
+ payload: chaincode_proposal.to_proto
57
+ end
58
+
59
+ def self.build_chaincode_proposal(chaincode_id, args)
60
+ id = Protos::ChaincodeID.new name: chaincode_id
61
+ chaincode_input = Protos::ChaincodeInput.new args: args
62
+ chaincode_spec = Protos::ChaincodeSpec.new type: Protos::ChaincodeSpec::Type::GOLANG,
63
+ chaincode_id: id,
64
+ input: chaincode_input
65
+ chaincode_invocation_spec =
66
+ Protos::ChaincodeInvocationSpec.new chaincode_spec: chaincode_spec
67
+
68
+ Protos::ChaincodeProposalPayload.new input: chaincode_invocation_spec.to_proto
69
+ end
70
+
71
+ def self.sign_proposal(identity, proposal)
72
+ proposal_bytes = proposal.to_proto
73
+ signature = identity.sign(proposal_bytes)
74
+
75
+ Protos::SignedProposal.new proposal_bytes: proposal_bytes,
76
+ signature: signature
77
+ end
78
+
79
+ def self.send_peers_process_proposal(peers, proposal)
80
+ peers.map do |peer|
81
+ peer.send_process_proposal(proposal)
82
+ end
83
+ end
84
+ end
85
+ end