iota-ruby 1.1.8-java

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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +8 -0
  3. data/.gitignore +15 -0
  4. data/.travis.yml +24 -0
  5. data/.yardopts +7 -0
  6. data/CHANGELOG.md +18 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +21 -0
  9. data/README.md +121 -0
  10. data/Rakefile +36 -0
  11. data/bin/iota-console +15 -0
  12. data/examples/multisig.rb +69 -0
  13. data/ext/ccurl/ccurl.c +134 -0
  14. data/ext/ccurl/extconf.rb +22 -0
  15. data/ext/jcurl/JCurl.java +126 -0
  16. data/ext/jcurl/JCurlService.java +36 -0
  17. data/ext/pow/ccurl-0.3.0.dll +0 -0
  18. data/ext/pow/libccurl-0.3.0.dylib +0 -0
  19. data/ext/pow/libccurl-0.3.0.so +0 -0
  20. data/iota-ruby.gemspec +37 -0
  21. data/lib/iota.rb +76 -0
  22. data/lib/iota/api/api.rb +251 -0
  23. data/lib/iota/api/commands.rb +113 -0
  24. data/lib/iota/api/transport.rb +43 -0
  25. data/lib/iota/api/wrappers.rb +429 -0
  26. data/lib/iota/crypto/bundle.rb +163 -0
  27. data/lib/iota/crypto/converter.rb +244 -0
  28. data/lib/iota/crypto/curl.rb +18 -0
  29. data/lib/iota/crypto/curl_c.rb +17 -0
  30. data/lib/iota/crypto/curl_java.rb +18 -0
  31. data/lib/iota/crypto/curl_ruby.rb +70 -0
  32. data/lib/iota/crypto/hmac.rb +27 -0
  33. data/lib/iota/crypto/kerl.rb +82 -0
  34. data/lib/iota/crypto/pow_provider.rb +27 -0
  35. data/lib/iota/crypto/private_key.rb +80 -0
  36. data/lib/iota/crypto/sha3_ruby.rb +122 -0
  37. data/lib/iota/crypto/signing.rb +97 -0
  38. data/lib/iota/models/account.rb +489 -0
  39. data/lib/iota/models/base.rb +13 -0
  40. data/lib/iota/models/bundle.rb +87 -0
  41. data/lib/iota/models/input.rb +38 -0
  42. data/lib/iota/models/seed.rb +33 -0
  43. data/lib/iota/models/transaction.rb +52 -0
  44. data/lib/iota/models/transfer.rb +44 -0
  45. data/lib/iota/multisig/address.rb +41 -0
  46. data/lib/iota/multisig/multisig.rb +244 -0
  47. data/lib/iota/utils/ascii.rb +50 -0
  48. data/lib/iota/utils/broker.rb +124 -0
  49. data/lib/iota/utils/input_validator.rb +149 -0
  50. data/lib/iota/utils/object_validator.rb +34 -0
  51. data/lib/iota/utils/utils.rb +324 -0
  52. data/lib/iota/version.rb +3 -0
  53. data/lib/jcurl.jar +0 -0
  54. data/lib/patch.rb +17 -0
  55. data/test/ascii_test.rb +114 -0
  56. data/test/curl_c_test.rb +31 -0
  57. data/test/curl_java_test.rb +31 -0
  58. data/test/curl_ruby_test.rb +27 -0
  59. data/test/kerl_test.rb +52 -0
  60. data/test/pow_provider_test.rb +36 -0
  61. data/test/sha3_test.rb +71 -0
  62. data/test/test_helper.rb +4 -0
  63. data/test/utils_test.rb +179 -0
  64. metadata +183 -0
@@ -0,0 +1,163 @@
1
+ module IOTA
2
+ module Crypto
3
+ class Bundle
4
+ attr_reader :bundle
5
+
6
+ def initialize(bundle = [])
7
+ bundle = bundle.map do |b|
8
+ if b.class != IOTA::Models::Transaction
9
+ IOTA::Models::Transaction.new(b)
10
+ else
11
+ b
12
+ end
13
+ end
14
+
15
+ @bundle = bundle
16
+ end
17
+
18
+ def addEntry(signatureMessageLength, address, value, tag, timestamp)
19
+ (0...signatureMessageLength).step(1) do |i|
20
+ transactionObject = IOTA::Models::Transaction.new(
21
+ address: address,
22
+ value: i==0 ? value : 0,
23
+ obsoleteTag: tag,
24
+ tag: tag,
25
+ timestamp: timestamp
26
+ )
27
+
28
+ @bundle << transactionObject
29
+ end
30
+ end
31
+
32
+ def addTrytes(signatureFragments)
33
+ emptySignatureFragment = ''
34
+ emptyHash = '9' * 81
35
+ emptyTag = '9' * 27
36
+ emptyTimestamp = '9' * 9
37
+
38
+ while emptySignatureFragment.length < 2187
39
+ emptySignatureFragment += '9'
40
+ end
41
+
42
+ (0...@bundle.length).step(1) do |i|
43
+ # Fill empty signatureMessageFragment
44
+ @bundle[i].signatureMessageFragment = signatureFragments[i] ? signatureFragments[i] : emptySignatureFragment
45
+
46
+ # Fill empty trunkTransaction
47
+ @bundle[i].trunkTransaction = emptyHash
48
+
49
+ # Fill empty branchTransaction
50
+ @bundle[i].branchTransaction = emptyHash
51
+
52
+ @bundle[i].attachmentTimestamp = emptyTimestamp
53
+ @bundle[i].attachmentTimestampLowerBound = emptyTimestamp
54
+ @bundle[i].attachmentTimestampUpperBound = emptyTimestamp
55
+
56
+ # Fill empty nonce
57
+ @bundle[i].nonce = emptyTag
58
+ end
59
+ end
60
+
61
+ def finalize
62
+ validBundle = false
63
+
64
+ while !validBundle
65
+
66
+ kerl = Kerl.new
67
+
68
+ (0...@bundle.length).step(1) do |i|
69
+ valueTrits = Converter.trits(@bundle[i].value)
70
+ while valueTrits.length < 81
71
+ valueTrits << 0
72
+ end
73
+
74
+ timestampTrits = Converter.trits(@bundle[i].timestamp)
75
+ while timestampTrits.length < 27
76
+ timestampTrits << 0
77
+ end
78
+
79
+ @bundle[i].currentIndex = i
80
+ currentIndexTrits = Converter.trits(@bundle[i].currentIndex)
81
+ while currentIndexTrits.length < 27
82
+ currentIndexTrits << 0
83
+ end
84
+
85
+ @bundle[i].lastIndex = @bundle.length - 1
86
+ lastIndexTrits = Converter.trits(@bundle[i].lastIndex)
87
+ while lastIndexTrits.length < 27
88
+ lastIndexTrits << 0
89
+ end
90
+
91
+ bundleEssence = Converter.trits(@bundle[i].address + Converter.trytes(valueTrits) + @bundle[i].obsoleteTag + Converter.trytes(timestampTrits) + Converter.trytes(currentIndexTrits) + Converter.trytes(lastIndexTrits))
92
+ kerl.absorb(bundleEssence, 0, bundleEssence.length)
93
+ end
94
+
95
+ hash = []
96
+ kerl.squeeze(hash, 0, Kerl::HASH_LENGTH)
97
+ hash = Converter.trytes(hash)
98
+
99
+ (0...@bundle.length).step(1) do |i|
100
+ @bundle[i].bundle = hash
101
+ end
102
+
103
+ normalizedHash = normalizedBundle(hash)
104
+ if !normalizedHash.index(13).nil?
105
+ # Insecure bundle. Increment Tag and recompute bundle hash.
106
+ increasedTagTrits = Converter.trits(@bundle[0].obsoleteTag)
107
+
108
+ # Adder implementation with 1 round
109
+ (0...increasedTagTrits.length).step(1) do |j|
110
+ increasedTagTrits[j] += 1
111
+
112
+ if increasedTagTrits[j] > 1
113
+ increasedTagTrits[j] = -1
114
+ else
115
+ break
116
+ end
117
+ end
118
+
119
+ @bundle[0].obsoleteTag = Converter.trytes(increasedTagTrits)
120
+ else
121
+ validBundle = true
122
+ end
123
+ end
124
+ end
125
+
126
+ def normalizedBundle(bundleHash)
127
+ normalizedBundleArr = []
128
+
129
+ (0...3).step(1) do |i|
130
+ sum = 0
131
+ (0...27).step(1) do |j|
132
+ normalizedBundleArr[i * 27 + j] = Converter.value(Converter.trits(bundleHash[i * 27 + j]))
133
+ sum += normalizedBundleArr[i * 27 + j]
134
+ end
135
+
136
+ if sum >= 0
137
+ while sum > 0
138
+ sum -= 1
139
+ (0...27).step(1) do |j|
140
+ if normalizedBundleArr[i * 27 + j] > -13
141
+ normalizedBundleArr[i * 27 + j] -= 1
142
+ break
143
+ end
144
+ end
145
+ end
146
+ else
147
+ while sum < 0
148
+ sum += 1
149
+ (0...27).step(1) do |j|
150
+ if normalizedBundleArr[i * 27 + j] < 13
151
+ normalizedBundleArr[i * 27 + j] += 1
152
+ break
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
158
+
159
+ normalizedBundleArr
160
+ end
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,244 @@
1
+ module IOTA
2
+ module Crypto
3
+ class Converter
4
+ RADIX = 3
5
+ RADIX_BYTES = 256
6
+ MAX_TRIT_VALUE = 1
7
+ MIN_TRIT_VALUE = -1
8
+ BYTE_HASH_LENGTH = 48
9
+ HASH_LENGTH = Curl::HASH_LENGTH
10
+
11
+ # All possible tryte values
12
+ TRYTES_ALPHABET = "9ABCDEFGHIJKLMNOPQRSTUVWXYZ"
13
+
14
+ TRYTE_TRITS = [
15
+ [ 0, 0, 0],
16
+ [ 1, 0, 0],
17
+ [-1, 1, 0],
18
+ [ 0, 1, 0],
19
+ [ 1, 1, 0],
20
+ [-1, -1, 1],
21
+ [ 0, -1, 1],
22
+ [ 1, -1, 1],
23
+ [-1, 0, 1],
24
+ [ 0, 0, 1],
25
+ [ 1, 0, 1],
26
+ [-1, 1, 1],
27
+ [ 0, 1, 1],
28
+ [ 1, 1, 1],
29
+ [-1, -1, -1],
30
+ [ 0, -1, -1],
31
+ [ 1, -1, -1],
32
+ [-1, 0, -1],
33
+ [ 0, 0, -1],
34
+ [ 1, 0, -1],
35
+ [-1, 1, -1],
36
+ [ 0, 1, -1],
37
+ [ 1, 1, -1],
38
+ [-1, -1, 0],
39
+ [ 0, -1, 0],
40
+ [ 1, -1, 0],
41
+ [-1, 0, 0]
42
+ ]
43
+
44
+ class << self
45
+ def trits(input, state = [])
46
+ trits = state
47
+
48
+ if input.is_a? Integer
49
+ absoluteValue = input < 0 ? -input : input
50
+
51
+ while absoluteValue > 0
52
+ remainder = absoluteValue % 3
53
+ absoluteValue = (absoluteValue / 3).floor
54
+
55
+ if remainder > 1
56
+ remainder = -1
57
+ absoluteValue += 1
58
+ end
59
+
60
+ trits[trits.length] = remainder
61
+ end
62
+
63
+ if input < 0
64
+ (0... trits.length).step(1) do |i|
65
+ trits[i] = -trits[i]
66
+ end
67
+ end
68
+ else
69
+ (0... input.length).step(1) do |i|
70
+ index = TRYTES_ALPHABET.index(input[i])
71
+ tmp = i * 3
72
+ trits[tmp...tmp+3] = TRYTE_TRITS[index]
73
+ end
74
+ end
75
+
76
+ trits
77
+ end
78
+
79
+ def trytes(trits)
80
+ trytes = ""
81
+
82
+ (0...trits.length).step(3) do |i|
83
+ chunk = trits[i...i+3]
84
+ index = TRYTE_TRITS.index(chunk)
85
+ if !index.nil?
86
+ trytes += TRYTES_ALPHABET[index]
87
+ end
88
+ end
89
+
90
+ trytes
91
+ end
92
+
93
+ def value(trits)
94
+ returnValue = 0
95
+
96
+ range = (trits.length..0)
97
+
98
+ range.first.downto(range.last).each do |i|
99
+ returnValue = returnValue * 3 + trits[i].to_i
100
+ end
101
+
102
+ returnValue
103
+ end
104
+
105
+ def fromValue(value)
106
+ destination = []
107
+ absoluteValue = value < 0 ? -value : value
108
+ i = 0
109
+
110
+ while absoluteValue > 0
111
+ remainder = absoluteValue % RADIX
112
+ absoluteValue = (absoluteValue / RADIX).floor
113
+
114
+ if remainder > MAX_TRIT_VALUE
115
+ remainder = MIN_TRIT_VALUE
116
+ absoluteValue += 1
117
+ end
118
+ destination[i] = remainder
119
+ i += 1
120
+ end
121
+
122
+ if value < 0
123
+ (0...destination.length).step(1) do |j|
124
+ # switch values
125
+ destination[j] = destination[j] == 0 ? 0 : -destination[j]
126
+ end
127
+ end
128
+
129
+ destination
130
+ end
131
+
132
+ ### ADOPTED FROM PYTHON LIBRARY
133
+ # Word to tryte & trytes to words conversion
134
+ def convertToBytes(trits)
135
+ bigInt = convertBaseToBigInt(trits, 3)
136
+ bytes_k = convertBigIntToBytes(bigInt)
137
+ bytes_k
138
+ end
139
+
140
+ def convertToTrits(bytes)
141
+ bigInt = convertBytesToBigInt(bytes)
142
+ trits = convertBigIntToBase(bigInt, 3, HASH_LENGTH)
143
+ trits
144
+ end
145
+
146
+ # Convert between signed and unsigned bytes
147
+ def convertSign(byte)
148
+ if byte < 0
149
+ return 256 + byte
150
+ elsif byte > 127
151
+ return -256 + byte
152
+ end
153
+ byte
154
+ end
155
+
156
+ def convertBaseToBigInt(array, base)
157
+ bigint = 0
158
+ (0...array.length).step(1) do |i|
159
+ bigint += array[i] * (base ** i)
160
+ end
161
+ bigint
162
+ end
163
+
164
+ def convertBigIntToBase(bigInt, base, length)
165
+ result = []
166
+
167
+ isNegative = bigInt < 0
168
+ quotient = bigInt.abs
169
+
170
+ max, _ = (isNegative ? base : base-1).divmod(2)
171
+
172
+ length.times do
173
+ quotient, remainder = quotient.divmod(base)
174
+
175
+ if remainder > max
176
+ # Lend 1 to the next place so we can make this digit negative.
177
+ quotient += 1
178
+ remainder -= base
179
+ end
180
+
181
+ remainder = -remainder if isNegative
182
+
183
+ result << remainder
184
+ end
185
+
186
+ result
187
+ end
188
+
189
+ def convertBigIntToBytes(big)
190
+ bytesArrayTemp = []
191
+
192
+ (0...48).step(1) do |pos|
193
+ bytesArrayTemp << (big.abs >> pos * 8) % (1 << 8)
194
+ end
195
+
196
+ # big endian and balanced
197
+ bytesArray = bytesArrayTemp.reverse.map { |x| x <= 0x7F ? x : x - 0x100 }
198
+
199
+ if big < 0
200
+ # 1-compliment
201
+ bytesArray = bytesArray.map { |x| ~x }
202
+
203
+ # add1
204
+ (0...bytesArray.length).reverse_each do |pos|
205
+ add = (bytesArray[pos] & 0xFF) + 1
206
+ bytesArray[pos] = add <= 0x7F ? add : add - 0x100
207
+ break if bytesArray[pos] != 0
208
+ end
209
+ end
210
+
211
+ bytesArray
212
+ end
213
+
214
+ def convertBytesToBigInt(array)
215
+ # copy of array
216
+ bytesArray = array.map { |x| x }
217
+
218
+ # number sign in MSB
219
+ signum = bytesArray[0] >= 0 ? 1 : -1
220
+
221
+ if signum == -1
222
+ # sub1
223
+ (0...bytesArray.length).reverse_each do |pos|
224
+ sub = (bytesArray[pos] & 0xFF) - 1
225
+ bytesArray[pos] = sub <= 0x7F ? sub : sub - 0x100
226
+ break if bytesArray[pos] != -1
227
+ end
228
+
229
+ # 1-compliment
230
+ bytesArray = bytesArray.map { |x| ~x }
231
+ end
232
+
233
+ # sum magnitudes and set sign
234
+ sum = 0
235
+ bytesArray.reverse.each_with_index do |v, pos|
236
+ sum += (v & 0xFF) << pos * 8
237
+ end
238
+
239
+ sum * signum
240
+ end
241
+ end
242
+ end
243
+ end
244
+ end
@@ -0,0 +1,18 @@
1
+ if RUBY_PLATFORM =~ /java/
2
+ require "iota/crypto/curl_java"
3
+ BaseCurl = IOTA::Crypto::JCurl
4
+ else
5
+ require "iota/crypto/curl_c"
6
+ BaseCurl = IOTA::Crypto::CCurl
7
+ end
8
+
9
+ module IOTA
10
+ module Crypto
11
+ class Curl < BaseCurl
12
+ def initialize(rounds = nil)
13
+ rounds ||= NUMBER_OF_ROUNDS
14
+ super(rounds)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ module IOTA
2
+ module Crypto
3
+ class CCurl
4
+ NUMBER_OF_ROUNDS = 81
5
+ HASH_LENGTH = 243
6
+ STATE_LENGTH = 3 * HASH_LENGTH
7
+
8
+ unless RUBY_PLATFORM =~ /java/
9
+ require "ccurl"
10
+ end
11
+
12
+ def version
13
+ "C"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ module IOTA
2
+ module Crypto
3
+ class JCurl
4
+ NUMBER_OF_ROUNDS = 81
5
+ HASH_LENGTH = 243
6
+ STATE_LENGTH = 3 * HASH_LENGTH
7
+
8
+ if RUBY_PLATFORM =~ /java/
9
+ require 'jcurl'
10
+ com.vmarakana.JCurlService.new.basicLoad(JRuby.runtime)
11
+ end
12
+
13
+ def version
14
+ "Java"
15
+ end
16
+ end
17
+ end
18
+ end