stellar-sdk 0.23.0.rc2 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0d8a8fa97989972efbe53dd536b329596c7f0eaa9769aff84ceb86f3f70c0f69
4
- data.tar.gz: 4d8e9eae54618c12ba827b62e8243a28cbe1c1dfe3b60e14b2e26394266a560b
3
+ metadata.gz: 14f9e7a13e44b5eb83bce5faee3918a49c03cfd9d36f00b49cdec501131702bc
4
+ data.tar.gz: cbf8145d6a546359ba66f74bc868cc1f5c6bf82a0e1c077d6073ef242f3989ef
5
5
  SHA512:
6
- metadata.gz: 4952c1aea1709d96d2933e9aeae95afd094c7708a95c450c385ab39cfa7ac96c725a78d9579c424d6cddc7ffad95260c2e75b2535504ee4e0031c41721b7235e
7
- data.tar.gz: 8d3e8c2f10c959c4c52c3e26a61f61f7580bc3a93797b4ac8a976c0951133a79b60bbc6b07e9eabd5383cac2d11b62e67066163c9eda0ecaa580417a7056d6c3
6
+ metadata.gz: a1a999329ba74c3a0448c59c4d249c4fecdc1b0961dbc82ba985f8b3fb792b993825a1eabd2df8918566ac1b7f1ca847572a381d61c0194aa8f48cc50fdea6e4
7
+ data.tar.gz: b4c7f193cd7fef55798e4788476e30898c2b8517981ad4d05da2c9ac7a1ab4758e5287700cd017b1c62cd97e995b6f645dc15ef9cff22d0cc061aeb85375dfe7
@@ -4,12 +4,34 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## [Unreleased](https://github.com/stellar/ruby-stellar-sdk/compare/v0.25.0...master)
8
+
9
+ ## [0.25.0](https://github.com/stellar/ruby-stellar-sdk/compare/v0.24.0...0.25.0)
10
+ ### Changed
11
+ - `Stellar::SEP10` is updated to comply with SEP10 v2.1.0
12
+ - `build_challenge_tx` now accepts `domain` instead of `anchor_name`, using the
13
+ old param name will now result in deprecation warning
14
+ - `read_challenge_tx` correctly validates multi-op challenge transactions
15
+ - `verify_challenge_tx_threshold` now expects simple `{'GA...' => weight, ... }` hash for `signers`
16
+ ### Removed:
17
+ - Deprecated `Stellar::SEP10.verify_challenge_tx` method is removed
18
+
19
+ ## [0.24.0](https://github.com/stellar/ruby-stellar-sdk/compare/v0.23.1...v0.24.0) - 2020-10-20
20
+ - Protocol 14 support
21
+
22
+ ## [0.23.1](https://github.com/stellar/ruby-stellar-sdk/compare/v0.23.0...v0.23.1) - 2020-06-18
23
+ - Fix SEP10, considering muxed accounts
24
+
25
+ ## [0.23.0](https://github.com/stellar/ruby-stellar-sdk/compare/v0.9.0...v0.23.0)
26
+ - No changes. We bumped this version to sync `stellar-sdk` and `stellar-base` versions
27
+
7
28
  ## [0.9.0](https://github.com/stellar/ruby-stellar-sdk/compare/v0.9.0...v0.8.0)
8
29
  ### Added
9
30
  - Stellar Protocol 13 support
10
31
  - Fee-Bump transactions ([CAP-0015](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0015.md))
11
32
  - Multiplexed accounts ([CAP-0027](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0027.md))
12
33
  - Fine-Grained control on trustline authorization ([CAP-0018](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0018.md))
34
+
13
35
  ## [0.8.0](https://github.com/stellar/ruby-stellar-sdk/compare/v0.7.0...v0.8.0)
14
36
  ### Added
15
37
  - SEP-10 Multisig Support [#69](https://github.com/stellar/ruby-stellar-sdk/pull/69)
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
- # Ruby Stellar
2
-
3
- [![Build Status](https://travis-ci.org/bloom-solutions/ruby-stellar-sdk.svg)](https://travis-ci.org/bloom-solutions/ruby-stellar-sdk)
4
- [![Code Climate](https://codeclimate.com/github/bloom-solutions/ruby-stellar-sdk/badges/gpa.svg)](https://codeclimate.com/github/bloom-solutions/ruby-stellar-sdk)
1
+ # Stellar SDK for Ruby: Horizon Integration and Higher Level Abstractions
2
+ [![stellar-sdk](https://badge.fury.io/rb/stellar-sdk.svg)](https://badge.fury.io/rb/stellar-sdk)
3
+ [![Test](https://github.com/astroband/ruby-stellar-sdk/workflows/Test/badge.svg)](https://github.com/astroband/ruby-stellar-sdk/actions?query=branch%3Amaster)
4
+ [![Maintainability](https://api.codeclimate.com/v1/badges/dadfcd9396aba493cb93/maintainability)](https://codeclimate.com/github/astroband/ruby-stellar-sdk/maintainability)
5
5
 
6
6
  This library helps you to integrate your application into the [Stellar network](http://stellar.org).
7
7
 
@@ -11,14 +11,11 @@ Add this lines to your application's Gemfile:
11
11
 
12
12
  ```ruby
13
13
  gem 'stellar-sdk'
14
- gem 'xdr', git: 'https://github.com/stellar/ruby-xdr.git', tag: 'v3.0.1'
15
14
  ```
16
15
 
17
16
  And then execute:
18
17
 
19
18
  $ bundle
20
-
21
- **Note** we need to add such explicit `xdr` dependency, because version 3.0.1 is not on RubyGems yet. When it's published, you can remove this line
22
19
 
23
20
  Also requires libsodium. Installable via `brew install libsodium` on OS X.
24
21
 
@@ -39,7 +36,7 @@ client.send_payment({
39
36
  from: account,
40
37
  to: recipient,
41
38
  amount: Stellar::Amount.new(100_000_000)
42
- })
39
+ })
43
40
  ```
44
41
 
45
42
  Be sure to set the network when submitting to the public network (more information in [stellar-base](https://www.github.com/bloom-solutions/ruby-stellar-base)):
@@ -1,5 +1,5 @@
1
1
  require "stellar-base"
2
- require_relative "./stellar/version"
2
+ require_relative "stellar/sdk/version"
3
3
 
4
4
  module Stellar
5
5
  autoload :Account
@@ -66,6 +66,10 @@ module Stellar
66
66
  def initialize(keypair)
67
67
  @keypair = keypair
68
68
  end
69
+
70
+ def to_keypair
71
+ keypair
72
+ end
69
73
  end
70
74
 
71
75
  class AccountNotFound < StandardError
@@ -78,12 +78,11 @@ module Stellar
78
78
  destination = options[:destination]
79
79
  sequence = options[:sequence] || (account_info(account).sequence.to_i + 1)
80
80
 
81
- transaction = Stellar::TransactionBuilder.new(
81
+ transaction = Stellar::TransactionBuilder.account_merge(
82
82
  source_account: destination.keypair,
83
- sequence_number: sequence
84
- ).add_operation(
85
- Stellar::Operation.account_merge(destination: destination.keypair)
86
- ).set_timeout(0).build
83
+ sequence_number: sequence,
84
+ destination: destination.keypair
85
+ )
87
86
 
88
87
  envelope = transaction.to_envelope(account.keypair)
89
88
  submit_transaction(tx_envelope: envelope)
@@ -105,17 +104,13 @@ module Stellar
105
104
  # instead of using a hard-coded default value.
106
105
  fee = options[:fee] || DEFAULT_FEE
107
106
 
108
- payment = Stellar::TransactionBuilder.new(
107
+ payment = Stellar::TransactionBuilder.create_account(
109
108
  source_account: funder.keypair,
110
109
  sequence_number: sequence,
111
- base_fee: fee
112
- ).add_operation(
113
- Stellar::Operation.create_account({
114
- destination: options[:account].keypair,
115
- starting_balance: options[:starting_balance]
116
- })
117
- ).set_timeout(0).build
118
-
110
+ base_fee: fee,
111
+ destination: options[:account].keypair,
112
+ starting_balance: options[:starting_balance]
113
+ )
119
114
  envelope = payment.to_envelope(funder.keypair)
120
115
  submit_transaction(tx_envelope: envelope)
121
116
  end
@@ -180,14 +175,18 @@ module Stellar
180
175
  )
181
176
  sequence ||= (account_info(source).sequence.to_i + 1)
182
177
 
183
- args = {
178
+ op_args = {
184
179
  account: source.keypair,
185
180
  sequence: sequence,
186
181
  line: asset
187
182
  }
188
- args[:limit] = limit unless limit.nil?
183
+ op_args[:limit] = limit unless limit.nil?
189
184
 
190
- tx = Stellar::Transaction.change_trust(args)
185
+ tx = Stellar::TransactionBuilder.change_trust(
186
+ source_account: source.keypair,
187
+ sequence_number: sequence,
188
+ **op_args
189
+ )
191
190
 
192
191
  envelope = tx.to_envelope(source.keypair)
193
192
  submit_transaction(tx_envelope: envelope)
@@ -0,0 +1,5 @@
1
+ module Stellar
2
+ module SDK
3
+ VERSION = "0.25.0"
4
+ end
5
+ end
@@ -2,22 +2,34 @@ module Stellar
2
2
  class InvalidSep10ChallengeError < StandardError; end
3
3
 
4
4
  class SEP10
5
+ include Stellar::DSL
6
+
5
7
  # Helper method to create a valid {SEP0010}[https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0010.md]
6
8
  # challenge transaction which you can use for Stellar Web Authentication.
7
9
  #
8
- # @param server [Stellar::KeyPair] Keypair for server's signing account.
9
- # @param client [Stellar::KeyPair] Keypair for the account whishing to authenticate with the server.
10
- # @param anchor_name [String] Anchor's name to be used in the manage_data key.
11
- # @param timeout [Integer] Challenge duration (default to 5 minutes).
12
- #
13
- # @return [String] A base64 encoded string of the raw TransactionEnvelope xdr struct for the transaction.
10
+ # @example
11
+ # server = Stellar::KeyPair.random # SIGNING_KEY from your stellar.toml
12
+ # user = Stellar::KeyPair.from_address('G...')
13
+ # Stellar::SEP10.build_challenge_tx(server: server, client: user, domain: 'example.com', timeout: 300)
14
14
  #
15
- # = Example
15
+ # @param server [Stellar::KeyPair] server's signing keypair (SIGNING_KEY in service's stellar.toml)
16
+ # @param client [Stellar::KeyPair] account trying to authenticate with the server
17
+ # @param domain [String] service's domain to be used in the manage_data key
18
+ # @param timeout [Integer] challenge duration (default to 5 minutes)
16
19
  #
17
- # Stellar::SEP10.build_challenge_tx(server: server, client: user, anchor_name: anchor, timeout: timeout)
20
+ # @return [String] A base64 encoded string of the raw TransactionEnvelope xdr struct for the transaction.
18
21
  #
19
22
  # @see {SEP0010: Stellar Web Authentication}[https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0010.md]
20
- def self.build_challenge_tx(server:, client:, anchor_name:, timeout: 300)
23
+ def self.build_challenge_tx(server:, client:, domain: nil, timeout: 300, **options)
24
+ if domain.blank? && options.key?(:anchor_name)
25
+ ActiveSupport::Deprecation.new("next release", "stellar-sdk").warn <<~MSG
26
+ SEP-10 v2.0.0 requires usage of service home domain instead of anchor name in the challenge transaction.
27
+ Please update your implementation to use `Stellar::SEP10.build_challenge_tx(..., home_domain: 'example.com')`.
28
+ Using `anchor_name` parameter makes your service incompatible with SEP10-2.0 clients, support for this parameter
29
+ is deprecated and will be removed in the next major release of stellar-base.
30
+ MSG
31
+ domain = options[:anchor_name]
32
+ end
21
33
  # The value must be 64 bytes long. It contains a 48 byte
22
34
  # cryptographic-quality random string encoded using base64 (for a total of
23
35
  # 64 bytes after encoding).
@@ -35,7 +47,7 @@ module Stellar
35
47
  time_bounds: time_bounds
36
48
  ).add_operation(
37
49
  Stellar::Operation.manage_data(
38
- name: "#{anchor_name} auth",
50
+ name: "#{domain} auth",
39
51
  value: value,
40
52
  source_account: client
41
53
  )
@@ -49,76 +61,68 @@ module Stellar
49
61
  # It also verifies that transaction is signed by the server.
50
62
  #
51
63
  # It does not verify that the transaction has been signed by the client or
52
- # that any signatures other than the servers on the transaction are valid. Use
53
- # one of the following functions to completely verify the transaction:
54
- # - Stellar::SEP10.verify_challenge_tx_threshold
55
- # - Stellar::SEP10.verify_challenge_tx_signers
64
+ # that any signatures other than the servers on the transaction are valid.
65
+ # Use either {.verify_challenge_tx_threshold} or {.verify_challenge_tx_signers} to completely verify
66
+ # the signed challenge
67
+ #
68
+ # @example
69
+ # sep10 = Stellar::SEP10
70
+ # server = Stellar::KeyPair.random # this should be the SIGNING_KEY from your stellar.toml
71
+ # challenge = sep10.build_challenge_tx(server: server, client: user, home_domain: domain, timeout: timeout)
72
+ # envelope, client_address = sep10.read_challenge_tx(server: server, challenge: challenge)
56
73
  #
57
74
  # @param challenge_xdr [String] SEP0010 transaction challenge in base64.
58
75
  # @param server [Stellar::KeyPair] keypair for server where the challenge was generated.
59
76
  #
60
- # @return [Stellar::TransactionEnvelope, String]
61
- #
62
- # = Example
63
- #
64
- # sep10 = Stellar::SEP10
65
- # challenge = sep10.build_challenge_tx(server: server, client: user, anchor_name: anchor, timeout: timeout)
66
- # envelope, client_address = sep10.read_challenge_tx(challenge: challenge, server: server)
67
- #
68
- def self.read_challenge_tx(challenge_xdr:, server:)
77
+ # @return [Array(Stellar::TransactionEnvelope, String)]
78
+ def self.read_challenge_tx(server:, challenge_xdr:, **options)
69
79
  envelope = Stellar::TransactionEnvelope.from_xdr(challenge_xdr, "base64")
70
80
  transaction = envelope.tx
71
81
 
72
82
  if transaction.seq_num != 0
73
- raise InvalidSep10ChallengeError.new(
74
- "The transaction sequence number should be zero"
75
- )
83
+ raise InvalidSep10ChallengeError, "The transaction sequence number should be zero"
76
84
  end
77
85
 
78
- if transaction.source_account != server.raw_public_key
79
- raise InvalidSep10ChallengeError.new(
80
- "The transaction source account is not equal to the server's account"
81
- )
86
+ if transaction.source_account != server.muxed_account
87
+ raise InvalidSep10ChallengeError, "The transaction source account is not equal to the server's account"
82
88
  end
83
89
 
84
- if transaction.operations.size != 1
85
- raise InvalidSep10ChallengeError.new(
86
- "The transaction should contain only one operation"
87
- )
90
+ if transaction.operations.size < 1
91
+ raise InvalidSep10ChallengeError, "The transaction should contain at least one operation"
88
92
  end
89
93
 
90
- operation = transaction.operations.first
91
- client_account_id = operation.source_account
94
+ auth_op, *rest_ops = transaction.operations
95
+ client_account_id = auth_op.source_account
92
96
 
93
97
  if client_account_id.nil?
94
- raise InvalidSep10ChallengeError.new(
95
- "The transaction's operation should contain a source account"
96
- )
98
+ raise InvalidSep10ChallengeError, "The transaction's operation should contain a source account"
97
99
  end
98
100
 
99
- if operation.body.arm != :manage_data_op
100
- raise InvalidSep10ChallengeError.new(
101
- "The transaction's operation should be manageData"
102
- )
101
+ if auth_op.body.arm != :manage_data_op
102
+ raise InvalidSep10ChallengeError, "The transaction's first operation should be manageData"
103
103
  end
104
104
 
105
- if operation.body.value.data_value.unpack1("m").size != 48
106
- raise InvalidSep10ChallengeError.new(
107
- "The transaction's operation value should be a 64 bytes base64 random string"
108
- )
105
+ if auth_op.body.value.data_value.unpack1("m").size != 48
106
+ raise InvalidSep10ChallengeError, "The transaction's operation value should be a 64 bytes base64 random string"
107
+ end
108
+
109
+ rest_ops.each do |op|
110
+ if op.body.arm != :manage_data_op
111
+ raise InvalidSep10ChallengeError, "The transaction has operations that are not of type 'manageData'"
112
+ elsif op.source_account != server.muxed_account
113
+ raise InvalidSep10ChallengeError, "The transaction has operations that are unrecognized"
114
+ end
109
115
  end
110
116
 
111
117
  unless verify_tx_signed_by(tx_envelope: envelope, keypair: server)
112
- raise InvalidSep10ChallengeError.new(
113
- "The transaction is not signed by the server"
114
- )
118
+ raise InvalidSep10ChallengeError, "The transaction is not signed by the server"
115
119
  end
116
120
 
117
121
  time_bounds = transaction.time_bounds
118
122
  now = Time.now.to_i
119
123
 
120
124
  if time_bounds.nil? || !now.between?(time_bounds.min_time, time_bounds.max_time)
121
- raise InvalidSep10ChallengeError.new("The transaction has expired")
125
+ raise InvalidSep10ChallengeError, "The transaction has expired"
122
126
  end
123
127
 
124
128
  # Mirror the return type of the other SDK's and return a string
@@ -127,6 +131,36 @@ module Stellar
127
131
  [envelope, client_kp.address]
128
132
  end
129
133
 
134
+ # Verifies that for a SEP 10 challenge transaction all signatures on the transaction
135
+ # are accounted for and that the signatures meet a threshold on an account. A
136
+ # transaction is verified if it is signed by the server account, and all other
137
+ # signatures match a signer that has been provided as an argument, and those
138
+ # signatures meet a threshold on the account.
139
+ #
140
+ # @param server [Stellar::KeyPair] keypair for server's account.
141
+ # @param challenge_xdr [String] SEP0010 challenge transaction in base64.
142
+ # @param signers [{String => Integer}] The signers of client account.
143
+ # @param threshold [Integer] The medThreshold on the client account.
144
+ #
145
+ # @raise InvalidSep10ChallengeError if the transaction has unrecognized signatures (only server's
146
+ # signing key and keypairs found in the `signing` argument are recognized) or total weight of
147
+ # the signers does not meet the `threshold`
148
+ #
149
+ # @return [<String>] subset of input signers who have signed `challenge_xdr`
150
+ def self.verify_challenge_tx_threshold(server:, challenge_xdr:, signers:, threshold:)
151
+ signers_found = verify_challenge_tx_signers(
152
+ server: server, challenge_xdr: challenge_xdr, signers: signers.keys
153
+ )
154
+
155
+ total_weight = signers.values_at(*signers_found).sum
156
+
157
+ if total_weight < threshold
158
+ raise InvalidSep10ChallengeError, "signers with weight #{total_weight} do not meet threshold #{threshold}."
159
+ end
160
+
161
+ signers_found
162
+ end
163
+
130
164
  # Verifies that for a SEP 10 challenge transaction all signatures on the transaction are accounted for.
131
165
  #
132
166
  # A transaction is verified if it is signed by the server account, and all other signatures match a signer
@@ -135,211 +169,82 @@ module Stellar
135
169
  #
136
170
  # If verification succeeds a list of signers that were found is returned, excluding the server account ID.
137
171
  #
172
+ # @param server [Stellar::Keypair] server's signing key
138
173
  # @param challenge_xdr [String] SEP0010 transaction challenge transaction in base64.
139
- # @param server [Stellar::Keypair] keypair for server's account.
140
- # @param signers [SetOf[String]] The signers of client account.
174
+ # @param signers [<String>] The signers of client account.
141
175
  #
142
- # @return [SetOf[String]]
176
+ # @raise InvalidSep10ChallengeError one or more signatures in the transaction are not identifiable
177
+ # as the server account or one of the signers provided in the arguments
143
178
  #
144
- # Raises a InvalidSep10ChallengeError if:
145
- # - The transaction is invalid according to Stellar::SEP10.read_challenge_tx.
146
- # - One or more signatures in the transaction are not identifiable as the server account or one of the
147
- # signers provided in the arguments.
148
- def self.verify_challenge_tx_signers(
149
- challenge_xdr:,
150
- server:,
151
- signers:
152
- )
153
- if signers.empty?
154
- raise InvalidSep10ChallengeError.new("No signers provided.")
155
- end
179
+ # @return [<String>] subset of input signers who have signed `challenge_xdr`
180
+ def self.verify_challenge_tx_signers(server:, challenge_xdr:, signers:)
181
+ raise InvalidSep10ChallengeError, "no signers provided" if signers.empty?
156
182
 
157
- te, _ = read_challenge_tx(
158
- challenge_xdr: challenge_xdr, server: server
159
- )
183
+ te, _ = read_challenge_tx(server: server, challenge_xdr: challenge_xdr)
160
184
 
161
- # deduplicate signers and ignore non-G addresses
162
- client_signers = Set.new
163
- signers.each do |signer|
164
- # ignore server kp if passed
165
- if signer == server.address
166
- next
167
- end
168
- begin
169
- Stellar::Util::StrKey.check_decode(:account_id, signer)
170
- rescue
171
- next
172
- else
173
- client_signers.add(signer)
174
- end
175
- end
176
-
177
- if client_signers.empty?
178
- raise InvalidSep10ChallengeError.new("At least one signer with a G... address must be provied")
179
- end
185
+ # ignore non-G signers and server's own address
186
+ client_signers = signers.select { |s| s =~ /G[A-Z0-9]{55}/ && s != server.address }.to_set
187
+ raise InvalidSep10ChallengeError, "at least one regular signer must be provided" if client_signers.empty?
180
188
 
181
189
  # verify all signatures in one pass
182
- all_signers = client_signers + Set[server.address]
183
- signers_found = verify_tx_signatures(
184
- tx_envelope: te, signers: all_signers
185
- )
190
+ client_signers.add(server.address)
191
+ signers_found = verify_tx_signatures(tx_envelope: te, signers: client_signers)
186
192
 
187
193
  # ensure server signed transaction and remove it
188
194
  unless signers_found.delete?(server.address)
189
- raise InvalidSep10ChallengeError.new("Transaction not signed by server: #{server.address}")
195
+ raise InvalidSep10ChallengeError, "Transaction not signed by server: #{server.address}"
190
196
  end
191
197
 
192
198
  # Confirm we matched signatures to the client signers.
193
199
  if signers_found.empty?
194
- raise InvalidSep10ChallengeError.new("Transaction not signed by any client signer.")
200
+ raise InvalidSep10ChallengeError, "Transaction not signed by any client signer."
195
201
  end
196
202
 
197
203
  # Confirm all signatures were consumed by a signer.
198
- if signers_found.length != te.signatures.length - 1
199
- raise InvalidSep10ChallengeError.new("Transaction has unrecognized signatures.")
200
- end
201
-
202
- signers_found
203
- end
204
-
205
- # Verifies that for a SEP 10 challenge transaction all signatures on the transaction
206
- # are accounted for and that the signatures meet a threshold on an account. A
207
- # transaction is verified if it is signed by the server account, and all other
208
- # signatures match a signer that has been provided as an argument, and those
209
- # signatures meet a threshold on the account.
210
- #
211
- # @param challenge_xdr [String] SEP0010 transaction challenge transaction in base64.
212
- # @param server [Stellar::KeyPair] keypair for server's account.
213
- # @param threshold [Integer] The medThreshold on the client account.
214
- # @param signers [SetOf[::Hash]]The signers of client account.
215
- #
216
- # @return [SetOf[::Hash]]
217
- #
218
- # Raises a InvalidSep10ChallengeError if:
219
- # - The transaction is invalid according to Stellar::SEP10.read_challenge_transaction.
220
- # - One or more signatures in the transaction are not identifiable as the server
221
- # account or one of the signers provided in the arguments.
222
- # - The signatures are all valid but do not meet the threshold.
223
- def self.verify_challenge_tx_threshold(
224
- challenge_xdr:,
225
- server:,
226
- threshold:,
227
- signers:
228
- )
229
- signer_str_set = signers.map { |s| s["key"] }.to_set
230
- signer_strs_found = verify_challenge_tx_signers(
231
- challenge_xdr: challenge_xdr,
232
- server: server,
233
- signers: signer_str_set
234
- )
235
-
236
- weight = 0
237
- signers_found = Set.new
238
- signers.each do |s|
239
- unless signer_strs_found.include?(s["key"])
240
- next
241
- end
242
- signer_strs_found.delete(s["key"])
243
- signers_found.add(s)
244
- weight += s["weight"]
245
- end
246
-
247
- if weight < threshold
248
- raise InvalidSep10ChallengeError.new(
249
- "signers with weight #{weight} do not meet threshold #{threshold}."
250
- )
204
+ if signers_found.size != te.signatures.length - 1
205
+ raise InvalidSep10ChallengeError, "Transaction has unrecognized signatures."
251
206
  end
252
207
 
253
208
  signers_found
254
209
  end
255
210
 
256
- # DEPRECATED: Use verify_challenge_tx_signers instead.
257
- # This function does not support multiple client signatures.
258
- #
259
- # Verifies if a transaction is a valid per SEP-10 challenge transaction, if the validation
260
- # fails, an exception will be thrown.
261
- #
262
- # This function performs the following checks:
263
- # 1. verify that transaction sequenceNumber is equal to zero;
264
- # 2. verify that transaction source account is equal to the server's signing key;
265
- # 3. verify that transaction has time bounds set, and that current time is between the minimum and maximum bounds;
266
- # 4. verify that transaction contains a single Manage Data operation and it's source account is not null;
267
- # 5. verify that transaction envelope has a correct signature by server's signing key;
268
- # 6. verify that transaction envelope has a correct signature by the operation's source account;
269
- #
270
- # @param challenge_xdr [String] SEP0010 transaction challenge transaction in base64.
271
- # @param server [Stellar::KeyPair] keypair for server's account.
272
- #
273
- # Raises a InvalidSep10ChallengeError if the validation fails
274
- def self.verify_challenge_tx(
275
- challenge_xdr: String, server: Stellar::KeyPair
276
- )
277
- transaction_envelope, client_address = read_challenge_tx(
278
- challenge_xdr: challenge_xdr, server: server
279
- )
280
- client_keypair = Stellar::KeyPair.from_address(client_address)
281
- unless verify_tx_signed_by(tx_envelope: transaction_envelope, keypair: client_keypair)
282
- raise InvalidSep10ChallengeError.new(
283
- "Transaction not signed by client: %s" % [client_keypair.address]
284
- )
285
- end
286
- end
287
-
288
211
  # Verifies every signer passed matches a signature on the transaction exactly once,
289
212
  # returning a list of unique signers that were found to have signed the transaction.
290
213
  #
291
214
  # @param tx_envelope [Stellar::TransactionEnvelope] SEP0010 transaction challenge transaction envelope.
292
- # @param signers [SetOf[String]] The signers of client account.
215
+ # @param signers [<String>] The signers of client account.
293
216
  #
294
- # @return [SetOf[String]]
295
- def self.verify_tx_signatures(
296
- tx_envelope:,
297
- signers:
298
- )
217
+ # @return [Set<Stellar::KeyPair>]
218
+ def self.verify_tx_signatures(tx_envelope:, signers:)
299
219
  signatures = tx_envelope.signatures
300
220
  if signatures.empty?
301
- raise InvalidSep10ChallengeError.new("Transaction has no signatures.")
221
+ raise InvalidSep10ChallengeError, "Transaction has no signatures."
302
222
  end
303
223
 
304
224
  tx_hash = tx_envelope.tx.hash
305
- signatures_used = Set.new
306
- signers_found = Set.new
307
- signers.each do |signer|
308
- kp = Stellar::KeyPair.from_address(signer)
309
- tx_envelope.signatures.each_with_index do |sig, i|
310
- if signatures_used.include?(i)
311
- next
312
- end
313
- if sig.hint != kp.signature_hint
314
- next
315
- end
316
- if kp.verify(sig.signature, tx_hash)
317
- signatures_used.add(i)
318
- signers_found.add(signer)
319
- end
320
- end
321
- end
225
+ to_keypair = Stellar::DSL.method(:KeyPair)
226
+ keys_by_hint = signers.map(&to_keypair).index_by(&:signature_hint)
322
227
 
323
- signers_found
228
+ tx_envelope.signatures.each.with_object(Set.new) do |sig, result|
229
+ key = keys_by_hint.delete(sig.hint)
230
+ result.add(key.address) if key&.verify(sig.signature, tx_hash)
231
+ end
324
232
  end
325
233
 
326
234
  # Verifies if a Stellar::TransactionEnvelope was signed by the given Stellar::KeyPair
327
235
  #
236
+ # @example
237
+ # Stellar::SEP10.verify_tx_signed_by(tx_envelope: envelope, keypair: keypair)
238
+ #
328
239
  # @param tx_envelope [Stellar::TransactionEnvelope]
329
240
  # @param keypair [Stellar::KeyPair]
330
241
  #
331
242
  # @return [Boolean]
332
- #
333
- # = Example
334
- #
335
- # Stellar::SEP10.verify_tx_signed_by(tx_envelope: envelope, keypair: keypair)
336
- #
337
243
  def self.verify_tx_signed_by(tx_envelope:, keypair:)
338
244
  tx_hash = tx_envelope.tx.hash
339
245
  tx_envelope.signatures.any? do |sig|
340
- if sig.hint != keypair.signature_hint
341
- next
342
- end
246
+ next if sig.hint != keypair.signature_hint
247
+
343
248
  keypair.verify(sig.signature, tx_hash)
344
249
  end
345
250
  end
metadata CHANGED
@@ -1,14 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stellar-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.23.0.rc2
4
+ version: 0.25.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Fleckenstein
8
+ - Sergey Nebolsin
9
+ - Timur Ramazanov
8
10
  autorequire:
9
- bindir: bin
11
+ bindir: exe
10
12
  cert_chain: []
11
- date: 2020-06-10 00:00:00.000000000 Z
13
+ date: 2020-10-30 00:00:00.000000000 Z
12
14
  dependencies:
13
15
  - !ruby/object:Gem::Dependency
14
16
  name: stellar-base
@@ -16,82 +18,144 @@ dependencies:
16
18
  requirements:
17
19
  - - '='
18
20
  - !ruby/object:Gem::Version
19
- version: 0.23.0.rc2
21
+ version: 0.25.0
20
22
  type: :runtime
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
23
25
  requirements:
24
26
  - - '='
25
27
  - !ruby/object:Gem::Version
26
- version: 0.23.0.rc2
28
+ version: 0.25.0
27
29
  - !ruby/object:Gem::Dependency
28
- name: hyperclient
30
+ name: activesupport
29
31
  requirement: !ruby/object:Gem::Requirement
30
32
  requirements:
31
- - - "~>"
33
+ - - ">="
32
34
  - !ruby/object:Gem::Version
33
- version: '0.7'
35
+ version: 5.0.0
36
+ - - "<"
37
+ - !ruby/object:Gem::Version
38
+ version: '7.0'
34
39
  type: :runtime
35
40
  prerelease: false
36
41
  version_requirements: !ruby/object:Gem::Requirement
37
42
  requirements:
38
- - - "~>"
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: 5.0.0
46
+ - - "<"
39
47
  - !ruby/object:Gem::Version
40
- version: '0.7'
48
+ version: '7.0'
41
49
  - !ruby/object:Gem::Dependency
42
50
  name: excon
43
51
  requirement: !ruby/object:Gem::Requirement
44
52
  requirements:
45
- - - "~>"
53
+ - - ">="
46
54
  - !ruby/object:Gem::Version
47
- version: '0.71'
55
+ version: 0.71.0
56
+ - - "<"
57
+ - !ruby/object:Gem::Version
58
+ version: '1.0'
48
59
  type: :runtime
49
60
  prerelease: false
50
61
  version_requirements: !ruby/object:Gem::Requirement
51
62
  requirements:
52
- - - "~>"
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: 0.71.0
66
+ - - "<"
53
67
  - !ruby/object:Gem::Version
54
- version: '0.71'
68
+ version: '1.0'
55
69
  - !ruby/object:Gem::Dependency
56
- name: activesupport
70
+ name: hyperclient
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - ">="
60
74
  - !ruby/object:Gem::Version
61
- version: '5.0'
75
+ version: 0.7.0
76
+ - - "<"
77
+ - !ruby/object:Gem::Version
78
+ version: '1.0'
62
79
  type: :runtime
63
80
  prerelease: false
64
81
  version_requirements: !ruby/object:Gem::Requirement
65
82
  requirements:
66
83
  - - ">="
67
84
  - !ruby/object:Gem::Version
68
- version: '5.0'
85
+ version: 0.7.0
86
+ - - "<"
87
+ - !ruby/object:Gem::Version
88
+ version: '1.0'
69
89
  - !ruby/object:Gem::Dependency
70
90
  name: toml-rb
71
91
  requirement: !ruby/object:Gem::Requirement
72
92
  requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '1.1'
76
93
  - - ">="
77
94
  - !ruby/object:Gem::Version
78
95
  version: 1.1.1
96
+ - - "<"
97
+ - !ruby/object:Gem::Version
98
+ version: '3.0'
79
99
  type: :runtime
80
100
  prerelease: false
81
101
  version_requirements: !ruby/object:Gem::Requirement
82
102
  requirements:
83
- - - "~>"
84
- - !ruby/object:Gem::Version
85
- version: '1.1'
86
103
  - - ">="
87
104
  - !ruby/object:Gem::Version
88
105
  version: 1.1.1
106
+ - - "<"
107
+ - !ruby/object:Gem::Version
108
+ version: '3.0'
109
+ - !ruby/object:Gem::Dependency
110
+ name: bundler
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '2.0'
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '2.0'
123
+ - !ruby/object:Gem::Dependency
124
+ name: rake
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '13'
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: '13'
137
+ - !ruby/object:Gem::Dependency
138
+ name: rspec
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - "~>"
142
+ - !ruby/object:Gem::Version
143
+ version: '3.9'
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - "~>"
149
+ - !ruby/object:Gem::Version
150
+ version: '3.9'
89
151
  description:
90
152
  email:
91
- - scott@stellar.org
92
153
  executables: []
93
154
  extensions: []
94
- extra_rdoc_files: []
155
+ extra_rdoc_files:
156
+ - README.md
157
+ - LICENSE
158
+ - CHANGELOG.md
95
159
  files:
96
160
  - CHANGELOG.md
97
161
  - LICENSE
@@ -101,13 +165,17 @@ files:
101
165
  - lib/stellar/amount.rb
102
166
  - lib/stellar/client.rb
103
167
  - lib/stellar/horizon/problem.rb
168
+ - lib/stellar/sdk/version.rb
104
169
  - lib/stellar/sep10.rb
105
170
  - lib/stellar/transaction_page.rb
106
- - lib/stellar/version.rb
107
- homepage: http://github.com/stellar/ruby-stellar-sdk
171
+ homepage: https://github.com/stellar/ruby-stellar-sdk/tree/master/sdk
108
172
  licenses:
109
173
  - Apache-2.0
110
- metadata: {}
174
+ metadata:
175
+ github_repo: ssh://github.com/astroband/ruby-stellar-sdk
176
+ documentation_uri: https://rubydoc.info/gems/stellar-sdk/0.25.0/
177
+ changelog_uri: https://github.com/astroband/ruby-stellar-sdk/blob/v0.25.0/sdk/CHANGELOG.md
178
+ source_code_uri: https://github.com/astroband/ruby-stellar-sdk/tree/v0.25.0/sdk
111
179
  post_install_message:
112
180
  rdoc_options: []
113
181
  require_paths:
@@ -116,14 +184,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
116
184
  requirements:
117
185
  - - ">="
118
186
  - !ruby/object:Gem::Version
119
- version: '0'
187
+ version: 2.5.0
120
188
  required_rubygems_version: !ruby/object:Gem::Requirement
121
189
  requirements:
122
- - - ">"
190
+ - - ">="
123
191
  - !ruby/object:Gem::Version
124
- version: 1.3.1
192
+ version: '0'
125
193
  requirements: []
126
- rubygems_version: 3.1.4
194
+ rubygems_version: 3.2.0.rc.2
127
195
  signing_key:
128
196
  specification_version: 4
129
197
  summary: Stellar client library
@@ -1,3 +0,0 @@
1
- module Stellar
2
- VERSION = "0.23.0.rc2"
3
- end