stellar-sdk 0.24.0 → 0.25.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -4
- data/README.md +5 -5
- data/lib/stellar/sdk/version.rb +1 -1
- data/lib/stellar/sep10.rb +116 -211
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 14f9e7a13e44b5eb83bce5faee3918a49c03cfd9d36f00b49cdec501131702bc
|
4
|
+
data.tar.gz: cbf8145d6a546359ba66f74bc868cc1f5c6bf82a0e1c077d6073ef242f3989ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1a999329ba74c3a0448c59c4d249c4fecdc1b0961dbc82ba985f8b3fb792b993825a1eabd2df8918566ac1b7f1ca847572a381d61c0194aa8f48cc50fdea6e4
|
7
|
+
data.tar.gz: b4c7f193cd7fef55798e4788476e30898c2b8517981ad4d05da2c9ac7a1ab4758e5287700cd017b1c62cd97e995b6f645dc15ef9cff22d0cc061aeb85375dfe7
|
data/CHANGELOG.md
CHANGED
@@ -4,12 +4,25 @@ 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]
|
7
|
+
## [Unreleased](https://github.com/stellar/ruby-stellar-sdk/compare/v0.25.0...master)
|
8
8
|
|
9
|
-
## [0.
|
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
|
10
23
|
- Fix SEP10, considering muxed accounts
|
11
24
|
|
12
|
-
## [0.23.0](https://github.com/stellar/ruby-stellar-sdk/compare/v0.
|
25
|
+
## [0.23.0](https://github.com/stellar/ruby-stellar-sdk/compare/v0.9.0...v0.23.0)
|
13
26
|
- No changes. We bumped this version to sync `stellar-sdk` and `stellar-base` versions
|
14
27
|
|
15
28
|
## [0.9.0](https://github.com/stellar/ruby-stellar-sdk/compare/v0.9.0...v0.8.0)
|
@@ -18,7 +31,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|
18
31
|
- Fee-Bump transactions ([CAP-0015](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0015.md))
|
19
32
|
- Multiplexed accounts ([CAP-0027](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0027.md))
|
20
33
|
- Fine-Grained control on trustline authorization ([CAP-0018](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0018.md))
|
21
|
-
|
34
|
+
|
22
35
|
## [0.8.0](https://github.com/stellar/ruby-stellar-sdk/compare/v0.7.0...v0.8.0)
|
23
36
|
### Added
|
24
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
|
2
|
-
|
3
|
-
[](https://badge.fury.io/rb/stellar-sdk)
|
3
|
+
[](https://github.com/astroband/ruby-stellar-sdk/actions?query=branch%3Amaster)
|
4
|
+
[](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
|
|
@@ -36,7 +36,7 @@ client.send_payment({
|
|
36
36
|
from: account,
|
37
37
|
to: recipient,
|
38
38
|
amount: Stellar::Amount.new(100_000_000)
|
39
|
-
})
|
39
|
+
})
|
40
40
|
```
|
41
41
|
|
42
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)):
|
data/lib/stellar/sdk/version.rb
CHANGED
data/lib/stellar/sep10.rb
CHANGED
@@ -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
|
-
# @
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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:,
|
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: "#{
|
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.
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
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
|
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
86
|
if transaction.source_account != server.muxed_account
|
79
|
-
raise InvalidSep10ChallengeError
|
80
|
-
"The transaction source account is not equal to the server's account"
|
81
|
-
)
|
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
|
85
|
-
raise InvalidSep10ChallengeError
|
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
|
-
|
91
|
-
client_account_id =
|
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
|
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
|
100
|
-
raise InvalidSep10ChallengeError
|
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
|
106
|
-
raise InvalidSep10ChallengeError
|
107
|
-
|
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
|
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
|
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
|
140
|
-
# @param signers [SetOf[String]] The signers of client account.
|
174
|
+
# @param signers [<String>] The signers of client account.
|
141
175
|
#
|
142
|
-
# @
|
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
|
-
#
|
145
|
-
|
146
|
-
|
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
|
-
#
|
162
|
-
client_signers =
|
163
|
-
|
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
|
-
|
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
|
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
|
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.
|
199
|
-
raise InvalidSep10ChallengeError
|
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 [
|
215
|
+
# @param signers [<String>] The signers of client account.
|
293
216
|
#
|
294
|
-
# @return [
|
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
|
221
|
+
raise InvalidSep10ChallengeError, "Transaction has no signatures."
|
302
222
|
end
|
303
223
|
|
304
224
|
tx_hash = tx_envelope.tx.hash
|
305
|
-
|
306
|
-
|
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
|
-
|
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
|
-
|
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,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stellar-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.25.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Fleckenstein
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2020-10-
|
13
|
+
date: 2020-10-30 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: stellar-base
|
@@ -18,14 +18,14 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - '='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.
|
21
|
+
version: 0.25.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
26
|
- - '='
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version: 0.
|
28
|
+
version: 0.25.0
|
29
29
|
- !ruby/object:Gem::Dependency
|
30
30
|
name: activesupport
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
@@ -172,9 +172,10 @@ homepage: https://github.com/stellar/ruby-stellar-sdk/tree/master/sdk
|
|
172
172
|
licenses:
|
173
173
|
- Apache-2.0
|
174
174
|
metadata:
|
175
|
-
|
176
|
-
|
177
|
-
|
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
|
178
179
|
post_install_message:
|
179
180
|
rdoc_options: []
|
180
181
|
require_paths:
|