iota-ruby 1.1.7 → 1.1.8
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 +5 -5
- data/.travis.yml +14 -0
- data/CHANGELOG.md +8 -2
- data/README.md +12 -0
- data/Rakefile +23 -11
- data/ext/ccurl/ccurl.c +17 -9
- data/ext/jcurl/JCurl.java +126 -0
- data/ext/jcurl/JCurlService.java +36 -0
- data/iota-ruby.gemspec +18 -10
- data/lib/iota.rb +1 -2
- data/lib/iota/crypto/converter.rb +4 -1
- data/lib/iota/crypto/curl.rb +4 -4
- data/lib/iota/crypto/curl_c.rb +4 -2
- data/lib/iota/crypto/curl_java.rb +18 -0
- data/lib/iota/crypto/kerl.rb +7 -3
- data/lib/iota/crypto/sha3_ruby.rb +122 -0
- data/lib/iota/multisig/multisig.rb +1 -1
- data/lib/iota/version.rb +1 -1
- data/lib/patch.rb +17 -0
- data/test/curl_c_test.rb +2 -2
- data/test/curl_java_test.rb +31 -0
- data/test/kerl_test.rb +0 -12
- data/test/sha3_test.rb +71 -0
- data/test/utils_test.rb +6 -0
- metadata +22 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0eddb950ffbc3bf0e3da4e220391718183273cb590bd721edc759fb76b0fd7bf
|
4
|
+
data.tar.gz: 53e845e6eacd344ae3237b2547320565cd8323b6fee7d0aa872668f1cb47c507
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6873ed591a86864e6ff9ed57179d34bf2f0046dd059eb6849478ffd5ed1209dbc61920c466fae17e0b896a2507b47073ae28ee4b98557d7cd4575db279fdcf4
|
7
|
+
data.tar.gz: d13783668a13b9bbf76df9afee95a7a0ef04a081bfaffaaacb4f03b76f3a805f8798727cc0e454dd8b724ebeac64e05171d4d9f92dfaffbedde88005322dac16
|
data/.travis.yml
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
sudo: false
|
2
2
|
language: ruby
|
3
|
+
dist: trusty
|
4
|
+
osx_image: xcode9.3
|
3
5
|
os:
|
4
6
|
- linux
|
5
7
|
- osx
|
@@ -7,4 +9,16 @@ rvm:
|
|
7
9
|
- ruby-head
|
8
10
|
- 2.5.1
|
9
11
|
- 2.4.1
|
12
|
+
- jruby-head
|
13
|
+
- jruby-18mode
|
14
|
+
- jruby-19mode
|
15
|
+
- rbx-3
|
16
|
+
matrix:
|
17
|
+
exclude:
|
18
|
+
- os: osx
|
19
|
+
rvm: rbx-3
|
20
|
+
- os: osx
|
21
|
+
rvm: ruby-head
|
22
|
+
- os: osx
|
23
|
+
rvm: jruby-head
|
10
24
|
before_install: gem install bundler -v 1.15.0
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## [1.1.8] - 2019-07-15
|
2
|
+
- minor fixes in IOTA::Crypto::Converter.trytes
|
3
|
+
- Fixing some stuff in c extenstion to make it compatible with MRI ruby and Rubinius
|
4
|
+
- adding support for Rubinius
|
5
|
+
- adding support for JRuby platforms with native curl function in Java
|
6
|
+
|
1
7
|
## [1.1.7] - 2018-12-02
|
2
8
|
- adding `user` & `password` options to client
|
3
9
|
- [Local PoW Support](https://github.com/vivekmarakana/iota.lib.rb#local-pow-support)
|
@@ -8,5 +14,5 @@
|
|
8
14
|
- Inbuilt batching for following apis: `getTrytes`, `getBalances`, `wereAddressesSpentFrom`, `getInclusionStates` & `findTransactions`
|
9
15
|
- adding changelog file to keep track of future changes
|
10
16
|
|
11
|
-
###
|
12
|
-
- Only returning balance array as reponse for `getBalances` api call
|
17
|
+
### Old major changes
|
18
|
+
- Only returning balance array as reponse for `getBalances` api call
|
data/README.md
CHANGED
@@ -107,3 +107,15 @@ client = IOTA::Client.new(provider: 'https://node.iota-tangle.io:14265')
|
|
107
107
|
client = IOTA::Client.new(provider: 'https://node.iota-tangle.io:14265', local_pow: true)
|
108
108
|
# Now you can use `client.api.attachToTangle` api, which will do the proof-of-work on transaction and return the trytes that needs to be broadcasted
|
109
109
|
```
|
110
|
+
|
111
|
+
## Compatibility
|
112
|
+
|
113
|
+
Tested on [Travis CI](https://travis-ci.org/vivekmarakana/iota.lib.rb) on following environment [configurations](https://github.com/vivekmarakana/iota.lib.rb/blob/master/.travis.yml):
|
114
|
+
|
115
|
+
- ruby-head (Linux)
|
116
|
+
- 2.5.1 (Linux & Mac)
|
117
|
+
- 2.4.1 (Linux & Mac)
|
118
|
+
- jruby-head (OpenJDK8/Linux)
|
119
|
+
- jruby-19mode (OpenJDK8/Linux & OpenJDK8/OSX)
|
120
|
+
- jruby-18mode (OpenJDK8/Linux & OpenJDK8/OSX)
|
121
|
+
- rbx-3 (Linux)
|
data/Rakefile
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rake/testtask"
|
3
|
-
require "rake/extensiontask"
|
4
3
|
|
5
4
|
Rake::TestTask.new(:test) do |t|
|
6
5
|
t.libs << "test"
|
@@ -8,17 +7,30 @@ Rake::TestTask.new(:test) do |t|
|
|
8
7
|
t.test_files = FileList["test/**/*_test.rb"]
|
9
8
|
end
|
10
9
|
|
11
|
-
|
12
|
-
ext.lib_dir = "lib"
|
13
|
-
end
|
10
|
+
tasks = []
|
14
11
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
12
|
+
if RUBY_PLATFORM =~ /java/
|
13
|
+
if ENV['TRAVIS'].to_s.empty?
|
14
|
+
puts "Will build JAVA extension"
|
15
|
+
|
16
|
+
require 'rake/javaextensiontask'
|
17
|
+
Rake::JavaExtensionTask.new "jcurl" do |ext|
|
18
|
+
ext.lib_dir = "lib"
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
-
|
21
|
+
tasks << :compile
|
22
|
+
else
|
23
|
+
puts "Not building jar for travis"
|
24
|
+
end
|
22
25
|
else
|
23
|
-
|
26
|
+
puts "Will build C extension"
|
27
|
+
|
28
|
+
require 'rake/extensiontask'
|
29
|
+
Rake::ExtensionTask.new "ccurl" do |ext|
|
30
|
+
ext.lib_dir = "lib"
|
31
|
+
end
|
32
|
+
|
33
|
+
tasks << :compile
|
24
34
|
end
|
35
|
+
|
36
|
+
task :default => tasks + [:test]
|
data/ext/ccurl/ccurl.c
CHANGED
@@ -5,6 +5,10 @@
|
|
5
5
|
#define NUMBER_OF_ROUNDS 81
|
6
6
|
#define STATE_LENGTH 3 * HASH_LENGTH
|
7
7
|
|
8
|
+
#ifndef RARRAY_LEN
|
9
|
+
# define RARRAY_LEN(x) return (long)NUM2INT(rb_funcall(x, rb_intern("length"), 0));
|
10
|
+
#endif
|
11
|
+
|
8
12
|
typedef int64_t trit_t;
|
9
13
|
|
10
14
|
#define __TRUTH_TABLE 1, 0, -1, 1, -1, 0, -1, 1, 0
|
@@ -43,7 +47,7 @@ static VALUE ccurl_absorb(VALUE self, VALUE data) {
|
|
43
47
|
trit_t *trits;
|
44
48
|
int offset = 0;
|
45
49
|
int i;
|
46
|
-
int length =
|
50
|
+
int length = (int)RARRAY_LEN(data);
|
47
51
|
|
48
52
|
Curl *ctx;
|
49
53
|
Data_Get_Struct(self, Curl, ctx);
|
@@ -66,21 +70,25 @@ static VALUE ccurl_absorb(VALUE self, VALUE data) {
|
|
66
70
|
}
|
67
71
|
|
68
72
|
static VALUE ccurl_squeeze(VALUE self, VALUE data) {
|
69
|
-
int
|
73
|
+
int offset = 0;
|
70
74
|
int i;
|
75
|
+
int length = (int)RARRAY_LEN(data);
|
71
76
|
|
72
77
|
Curl *ctx;
|
73
78
|
Data_Get_Struct(self, Curl, ctx);
|
74
79
|
|
75
|
-
|
76
|
-
|
77
|
-
|
80
|
+
do {
|
81
|
+
for(; length < HASH_LENGTH; length++) {
|
82
|
+
rb_ary_push(data, LONG2NUM(0));
|
83
|
+
}
|
78
84
|
|
79
|
-
|
80
|
-
|
81
|
-
|
85
|
+
for (i = 0; i < HASH_LENGTH; i++) {
|
86
|
+
rb_ary_store(data, i, LONG2NUM(ctx->state[i]));
|
87
|
+
}
|
82
88
|
|
83
|
-
|
89
|
+
ccurl_transform(self);
|
90
|
+
offset += HASH_LENGTH;
|
91
|
+
} while ((length -= HASH_LENGTH) > 0);
|
84
92
|
|
85
93
|
return Qnil;
|
86
94
|
}
|
@@ -0,0 +1,126 @@
|
|
1
|
+
package com.vmarakana;
|
2
|
+
|
3
|
+
import java.util.Arrays;
|
4
|
+
|
5
|
+
import org.jruby.Ruby;
|
6
|
+
import org.jruby.RubyArray;
|
7
|
+
import org.jruby.RubyClass;
|
8
|
+
import org.jruby.RubyInteger;
|
9
|
+
import org.jruby.RubyNil;
|
10
|
+
import org.jruby.RubyObject;
|
11
|
+
import org.jruby.anno.JRubyMethod;
|
12
|
+
import org.jruby.runtime.ThreadContext;
|
13
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
14
|
+
|
15
|
+
public class JCurl extends RubyObject {
|
16
|
+
/**
|
17
|
+
* The hash length.
|
18
|
+
*/
|
19
|
+
public static final int HASH_LENGTH = 243;
|
20
|
+
private static final int STATE_LENGTH = 3 * HASH_LENGTH;
|
21
|
+
|
22
|
+
public static final int NUMBER_OF_ROUNDS = 81;
|
23
|
+
private int numberOfRounds;
|
24
|
+
|
25
|
+
private static final int[] TRUTH_TABLE = {1, 0, -1, 2, 1, -1, 0, 2, -1, 1, 0};
|
26
|
+
private final int[] scratchpad = new int[STATE_LENGTH];
|
27
|
+
private int[] state;
|
28
|
+
|
29
|
+
/**
|
30
|
+
* Java constructor
|
31
|
+
* @param ruby Ruby
|
32
|
+
* @param metaclass RubyClass
|
33
|
+
*/
|
34
|
+
public JCurl(Ruby ruby, RubyClass rubyClass) {
|
35
|
+
super(ruby, rubyClass);
|
36
|
+
}
|
37
|
+
|
38
|
+
/**
|
39
|
+
*
|
40
|
+
* @param context ThreadContext
|
41
|
+
* @param klass IRubyObject
|
42
|
+
* @param args optional (no args rounds = NUMBER_OF_ROUNDS)
|
43
|
+
* @return new Vec3 object (ruby)
|
44
|
+
*/
|
45
|
+
@JRubyMethod(name = "new", meta = true, rest = true)
|
46
|
+
public static IRubyObject rbNew(ThreadContext context, IRubyObject klass, IRubyObject... args) {
|
47
|
+
JCurl jcurl = (JCurl) ((RubyClass) klass).allocate();
|
48
|
+
jcurl.init(context, args);
|
49
|
+
return jcurl;
|
50
|
+
}
|
51
|
+
|
52
|
+
// This method is internal and not exposed
|
53
|
+
private IRubyObject init(ThreadContext context, IRubyObject... args) {
|
54
|
+
state = new int[STATE_LENGTH];
|
55
|
+
|
56
|
+
// Set rounds
|
57
|
+
if (args.length > 0 && args[0] instanceof RubyInteger) {
|
58
|
+
numberOfRounds = ((RubyInteger) args[0]).getIntValue();
|
59
|
+
} else {
|
60
|
+
numberOfRounds = NUMBER_OF_ROUNDS;
|
61
|
+
}
|
62
|
+
|
63
|
+
return new RubyNil(context.runtime);
|
64
|
+
}
|
65
|
+
|
66
|
+
@JRubyMethod
|
67
|
+
public IRubyObject transform(ThreadContext context) {
|
68
|
+
int scratchpadIndex = 0;
|
69
|
+
int prev_scratchpadIndex = 0;
|
70
|
+
for (int round = 0; round < numberOfRounds; round++) {
|
71
|
+
System.arraycopy(state, 0, scratchpad, 0, STATE_LENGTH);
|
72
|
+
for (int stateIndex = 0; stateIndex < STATE_LENGTH; stateIndex++) {
|
73
|
+
prev_scratchpadIndex = scratchpadIndex;
|
74
|
+
if (scratchpadIndex < 365) {
|
75
|
+
scratchpadIndex += 364;
|
76
|
+
} else {
|
77
|
+
scratchpadIndex += -365;
|
78
|
+
}
|
79
|
+
state[stateIndex] = TRUTH_TABLE[scratchpad[prev_scratchpadIndex] + (scratchpad[scratchpadIndex] << 2) + 5];
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
return new RubyNil(context.runtime);
|
84
|
+
}
|
85
|
+
|
86
|
+
@JRubyMethod
|
87
|
+
public IRubyObject absorb(ThreadContext context, final IRubyObject trits) {
|
88
|
+
int offset = 0;
|
89
|
+
int length = ((RubyArray) trits).getLength();
|
90
|
+
|
91
|
+
do {
|
92
|
+
System.arraycopy(trits.toJava(int[].class), offset, state, 0, length < HASH_LENGTH ? length : HASH_LENGTH);
|
93
|
+
transform(context);
|
94
|
+
offset += HASH_LENGTH;
|
95
|
+
} while ((length -= HASH_LENGTH) > 0);
|
96
|
+
|
97
|
+
return new RubyNil(context.runtime);
|
98
|
+
}
|
99
|
+
|
100
|
+
@JRubyMethod
|
101
|
+
public RubyNil squeeze(ThreadContext context, final IRubyObject trits) {
|
102
|
+
int offset = 0;
|
103
|
+
int length = ((RubyArray) trits).getLength();
|
104
|
+
|
105
|
+
do {
|
106
|
+
for(; length < HASH_LENGTH; length++) {
|
107
|
+
((RubyArray) trits).append(context.runtime.newFixnum(0));
|
108
|
+
}
|
109
|
+
|
110
|
+
for (int i = 0; i < HASH_LENGTH; i++) {
|
111
|
+
((RubyArray) trits).store(i, context.runtime.newFixnum(state[i]));
|
112
|
+
}
|
113
|
+
|
114
|
+
transform(context);
|
115
|
+
offset += HASH_LENGTH;
|
116
|
+
} while ((length -= HASH_LENGTH) > 0);
|
117
|
+
|
118
|
+
return new RubyNil(context.runtime);
|
119
|
+
}
|
120
|
+
|
121
|
+
@JRubyMethod
|
122
|
+
public IRubyObject reset(ThreadContext context) {
|
123
|
+
Arrays.fill(state, 0);
|
124
|
+
return new RubyNil(context.runtime);
|
125
|
+
}
|
126
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
package com.vmarakana;
|
2
|
+
|
3
|
+
import java.io.IOException;
|
4
|
+
|
5
|
+
import org.jruby.Ruby;
|
6
|
+
import org.jruby.RubyClass;
|
7
|
+
import org.jruby.RubyModule;
|
8
|
+
import org.jruby.runtime.ObjectAllocator;
|
9
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
10
|
+
import org.jruby.runtime.load.BasicLibraryService;
|
11
|
+
|
12
|
+
public class JCurlService implements BasicLibraryService {
|
13
|
+
private Ruby runtime;
|
14
|
+
|
15
|
+
/**
|
16
|
+
* Basic load method of the BasicLibraryService, this method is
|
17
|
+
* invoked when the ruby code does the related require call.
|
18
|
+
* @param ruby An instance of the JRuby runtime.
|
19
|
+
* @return boolean True if everything was successful, false otherwise.
|
20
|
+
* @throws IOException is required to match the BasicLibraryService signature
|
21
|
+
*/
|
22
|
+
|
23
|
+
@Override
|
24
|
+
public boolean basicLoad(final Ruby ruby) throws IOException {
|
25
|
+
RubyModule iota = ruby.defineModule("IOTA");
|
26
|
+
RubyModule crypto = iota.defineModuleUnder("Crypto");
|
27
|
+
RubyClass jcurl = crypto.defineClassUnder("JCurl", ruby.getObject(), new ObjectAllocator() {
|
28
|
+
public IRubyObject allocate(Ruby ruby1, RubyClass rubyClass) {
|
29
|
+
return new JCurl(ruby1, rubyClass);
|
30
|
+
}
|
31
|
+
});
|
32
|
+
|
33
|
+
jcurl.defineAnnotatedMethods(JCurl.class);
|
34
|
+
return true;
|
35
|
+
}
|
36
|
+
}
|
data/iota-ruby.gemspec
CHANGED
@@ -13,17 +13,25 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.description = "Ruby gem for the IOTA core"
|
14
14
|
spec.homepage = "https://github.com/vivekmarakana/iota.lib.rb"
|
15
15
|
|
16
|
-
spec.files = `git ls-files`.split("\n")
|
16
|
+
spec.files = `git ls-files`.split("\n") - [ "lib/jcurl.jar"]
|
17
17
|
spec.test_files = `git ls-files -- test/*`.split("\n")
|
18
|
-
spec.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
19
18
|
spec.require_paths = ["lib"]
|
20
|
-
spec.extensions = ["ext/ccurl/extconf.rb"]
|
21
19
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
20
|
+
if RUBY_PLATFORM =~ /java/
|
21
|
+
spec.platform = "java"
|
22
|
+
spec.files << "lib/jcurl.jar"
|
23
|
+
else
|
24
|
+
spec.extensions = ["ext/ccurl/extconf.rb"]
|
25
|
+
end
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", ">= 1.15"
|
28
|
+
spec.add_development_dependency "rake", ">= 10.0"
|
29
|
+
spec.add_development_dependency "minitest", ">= 5.0"
|
30
|
+
spec.add_development_dependency "rake-compiler", ">= 1.0.4"
|
31
|
+
|
32
|
+
unless RUBY_PLATFORM =~ /java/
|
33
|
+
spec.add_runtime_dependency "digest-sha3", "~> 1.1"
|
34
|
+
end
|
35
|
+
|
36
|
+
spec.add_runtime_dependency "ffi", "~> 1.9.25"
|
29
37
|
end
|
data/lib/iota.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "patch"
|
1
2
|
require "iota/version"
|
2
3
|
|
3
4
|
require "iota/utils/input_validator"
|
@@ -40,8 +41,6 @@ module IOTA
|
|
40
41
|
@utils = IOTA::Utils::Utils.new
|
41
42
|
@validator = @utils.validator
|
42
43
|
@multisig = IOTA::Multisig::Multisig.new(self)
|
43
|
-
# TODO: Implement MAM
|
44
|
-
# TODO: Implement Flash Channel
|
45
44
|
end
|
46
45
|
|
47
46
|
def changeNode(settings = {})
|
data/lib/iota/crypto/curl.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
if
|
1
|
+
if RUBY_PLATFORM =~ /java/
|
2
|
+
require "iota/crypto/curl_java"
|
3
|
+
BaseCurl = IOTA::Crypto::JCurl
|
4
|
+
else
|
2
5
|
require "iota/crypto/curl_c"
|
3
6
|
BaseCurl = IOTA::Crypto::CCurl
|
4
|
-
else
|
5
|
-
require "iota/crypto/curl_ruby"
|
6
|
-
BaseCurl = IOTA::Crypto::RubyCurl
|
7
7
|
end
|
8
8
|
|
9
9
|
module IOTA
|
data/lib/iota/crypto/curl_c.rb
CHANGED
@@ -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
|
data/lib/iota/crypto/kerl.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'digest/sha3'
|
2
|
-
|
3
1
|
module IOTA
|
4
2
|
module Crypto
|
5
3
|
class Kerl
|
@@ -11,7 +9,13 @@ module IOTA
|
|
11
9
|
end
|
12
10
|
|
13
11
|
def reset
|
14
|
-
|
12
|
+
unless RUBY_PLATFORM =~ /java/
|
13
|
+
require 'digest/sha3'
|
14
|
+
@hasher = Digest::SHA3.new(BIT_HASH_LENGTH)
|
15
|
+
else
|
16
|
+
require "iota/crypto/sha3_ruby"
|
17
|
+
@hasher = Digest::RubySHA3.new(BIT_HASH_LENGTH)
|
18
|
+
end
|
15
19
|
end
|
16
20
|
|
17
21
|
def absorb(trits, offset = 0, length = nil)
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
3
|
+
module Digest
|
4
|
+
class RubySHA3 < Digest::Class
|
5
|
+
PILN = [10, 7, 11, 17, 18, 3, 5, 16,
|
6
|
+
8, 21, 24, 4, 15, 23, 19, 13,
|
7
|
+
12, 2, 20, 14, 22, 9, 6, 1]
|
8
|
+
|
9
|
+
ROTC = [ 1, 3, 6, 10, 15, 21, 28, 36,
|
10
|
+
45, 55, 2, 14, 27, 41, 56, 8,
|
11
|
+
25, 43, 62, 18, 39, 61, 20, 44]
|
12
|
+
|
13
|
+
RNDC = [0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
|
14
|
+
0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
|
15
|
+
0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
|
16
|
+
0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
|
17
|
+
0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
|
18
|
+
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
|
19
|
+
0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
|
20
|
+
0x8000000000008080, 0x0000000080000001, 0x8000000080008008]
|
21
|
+
|
22
|
+
def initialize hash_size = 512
|
23
|
+
@size = hash_size / 8
|
24
|
+
@buffer = ''
|
25
|
+
end
|
26
|
+
|
27
|
+
def << s
|
28
|
+
@buffer << s.unpack('C*').pack('C*')
|
29
|
+
self
|
30
|
+
end
|
31
|
+
alias update <<
|
32
|
+
|
33
|
+
def reset
|
34
|
+
# @buffer.clear # CHANGE: DO NOT CLEAR BUFFER AS WE NEED
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def digest(data = nil)
|
39
|
+
if data
|
40
|
+
update(data)
|
41
|
+
value = finish
|
42
|
+
else
|
43
|
+
cloned = dup
|
44
|
+
value = cloned.finish
|
45
|
+
end
|
46
|
+
value
|
47
|
+
end
|
48
|
+
|
49
|
+
def hexdigest(data = nil)
|
50
|
+
value = digest(data)
|
51
|
+
value.unpack("H*").first
|
52
|
+
end
|
53
|
+
|
54
|
+
def inspect
|
55
|
+
"#<#{self.class}: #{hexdigest}>"
|
56
|
+
end
|
57
|
+
|
58
|
+
def finish
|
59
|
+
s = Array.new 25, 0
|
60
|
+
width = 200 - @size * 2
|
61
|
+
|
62
|
+
buffer_dup = @buffer.dup
|
63
|
+
buffer_dup << "\x01" << "\0" * (width - buffer_dup.size % width)
|
64
|
+
buffer_dup[-1] = (buffer_dup[-1].ord | 0x80).chr.unpack('C*').pack('C*')
|
65
|
+
|
66
|
+
0.step buffer_dup.size - 1, width do |j|
|
67
|
+
quads = buffer_dup[j, width].unpack 'Q*'
|
68
|
+
(width / 8).times do |i|
|
69
|
+
s[i] ^= quads[i]
|
70
|
+
end
|
71
|
+
|
72
|
+
keccak s
|
73
|
+
end
|
74
|
+
|
75
|
+
s.pack('Q*')[0, @size]
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
def keccak s
|
80
|
+
24.times.each_with_object [] do |round, a|
|
81
|
+
# Theta
|
82
|
+
5.times do |i|
|
83
|
+
a[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20]
|
84
|
+
end
|
85
|
+
|
86
|
+
5.times do |i|
|
87
|
+
t = a[(i + 4) % 5] ^ rotate(a[(i + 1) % 5], 1)
|
88
|
+
0.step 24, 5 do |j|
|
89
|
+
s[j + i] ^= t
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Rho Pi
|
94
|
+
t = s[1]
|
95
|
+
24.times do |i|
|
96
|
+
j = PILN[i]
|
97
|
+
a[0] = s[j]
|
98
|
+
s[j] = rotate t, ROTC[i]
|
99
|
+
t = a[0]
|
100
|
+
end
|
101
|
+
|
102
|
+
# Chi
|
103
|
+
0.step 24, 5 do |j|
|
104
|
+
5.times do |i|
|
105
|
+
a[i] = s[j + i]
|
106
|
+
end
|
107
|
+
|
108
|
+
5.times do |i|
|
109
|
+
s[j + i] ^= ~a[(i + 1) % 5] & a[(i + 2) % 5]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Iota
|
114
|
+
s[0] ^= RNDC[round]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def rotate x, y
|
119
|
+
(x << y | x >> 64 - y) & (1 << 64) - 1
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -57,7 +57,7 @@ module IOTA
|
|
57
57
|
# validate remainder address
|
58
58
|
raise StandardError, "Invalid remainder address provided" if remainderAddress && !@validator.isAddress(remainderAddress)
|
59
59
|
|
60
|
-
remainderAddress = @utils.noChecksum(remainderAddress) if remainderAddress.length == 90
|
60
|
+
remainderAddress = @utils.noChecksum(remainderAddress) if remainderAddress && remainderAddress.length == 90
|
61
61
|
|
62
62
|
# Create a new bundle
|
63
63
|
bundle = IOTA::Crypto::Bundle.new
|
data/lib/iota/version.rb
CHANGED
data/lib/patch.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Patching Array#sum method for older rubies, jruby and rubinbius
|
2
|
+
if !Array.instance_methods.include?(:sum)
|
3
|
+
class Array
|
4
|
+
def sum
|
5
|
+
inject(0) {|sum, val| sum + val}
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# Patching Regexp#match? method for older rubies, jruby and rubinbius
|
11
|
+
if !Regexp.instance_methods.include?(:match?)
|
12
|
+
class Regexp
|
13
|
+
def match?(a)
|
14
|
+
!match(a).nil?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/test/curl_c_test.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require "test_helper"
|
2
|
-
|
2
|
+
unless RUBY_PLATFORM =~ /java/
|
3
3
|
require "iota/crypto/curl_c"
|
4
4
|
|
5
|
-
class
|
5
|
+
class CCurlTest < Minitest::Test
|
6
6
|
def setup
|
7
7
|
@converter = IOTA::Crypto::Converter
|
8
8
|
@curl = IOTA::Crypto::CCurl.new(81)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
if RUBY_PLATFORM =~ /java/
|
3
|
+
require "iota/crypto/curl_java"
|
4
|
+
|
5
|
+
class JavaCurlTest < Minitest::Test
|
6
|
+
def setup
|
7
|
+
@converter = IOTA::Crypto::Converter
|
8
|
+
@curl = IOTA::Crypto::JCurl.new(81)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_that_hash_works
|
12
|
+
trytes = "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999G9AIBZPUUIXPRDTUJNGAUSWPJMLJOCSJSPVGP9KDCABPQIWXYOAXJVMDYSCPAAIJNWOHUIUNKKOVJJASCHJYTXA999999999999999999999FOINFALCON99999999999999999RJFYLXD99999999999D99999999WCKBQGFJRFIYVJAZDYLNQZIUQGG9EKZKNUOBEEASPPJXUGCTAGHGWLQSWJKC9DRVEKKHDOUJLNEQCGYK9HKFPGUUIXFOZBXZIJAFPWBYUTIAZMYHGAC9QMRDJCGOW9VXVLVQKTKRLQFITNLDHPDXHDWIVRZQGZ9999OEMEOVATRLZWXXDXIX9AVNDCHRLC9WHB9IAUUYKHUGIFBKCCYN9LRGTTQISBQYPDHTXRTOYVZTLU99999COINFALCON99999999999999999Z9PSAGQJE999999999L99999999IQXMVTRNAQVADDX9ET9IAMVJDZV"
|
13
|
+
expected_hash = "QLMNETEZDOYSBQLRPRJIZNRRDZ9EKY9LCOLNIDQEZNUFWOVYR9SJLBCVIJWIOKGNPMPGWYTNFMOW99999"
|
14
|
+
|
15
|
+
transactionTrits = @converter.trits(trytes)
|
16
|
+
hash = []
|
17
|
+
|
18
|
+
start = Time.now
|
19
|
+
# generate the correct transaction hash
|
20
|
+
@curl.reset
|
21
|
+
@curl.absorb(transactionTrits)
|
22
|
+
@curl.squeeze(hash)
|
23
|
+
hash = @converter.trytes(hash)
|
24
|
+
puts "Java Curl time: #{(Time.now - start) * 1000.0}ms"
|
25
|
+
|
26
|
+
assert expected_hash == hash
|
27
|
+
end
|
28
|
+
end
|
29
|
+
else
|
30
|
+
puts "Java extension is not available. Skipping tests for it."
|
31
|
+
end
|
data/test/kerl_test.rb
CHANGED
@@ -6,18 +6,6 @@ class KerlTest < Minitest::Test
|
|
6
6
|
@kerl = IOTA::Crypto::Kerl.new
|
7
7
|
end
|
8
8
|
|
9
|
-
def test_that_sha3_works
|
10
|
-
digest = "\xe0\xef\x02\xd2FD\xa7\xb2\x8b<\x1b\x01\xc4\xfe\x13zI\x86M[\xdefV\xfa\xf49\xe1\xeb\xa6X\x06M\x9e\xcf\x842U\xba\x90=\x1c\xeb\xdcf\xff/\x16\xce".unpack('C*')
|
11
|
-
hexdigest = "e0ef02d24644a7b28b3c1b01c4fe137a49864d5bde6656faf439e1eba658064d9ecf843255ba903d1cebdc66ff2f16ce"
|
12
|
-
|
13
|
-
a = Digest::SHA3.new(384)
|
14
|
-
a.update("GYOMKVTSNHVJNCNFBBAH9AAMXLPLLLROQY99QN9DLSJUHDPBLCFFAIQXZA9BKMBJCYSFHFPXAHDWZFEIZ")
|
15
|
-
|
16
|
-
assert a.digest_length == 48
|
17
|
-
assert a.digest.bytes == digest
|
18
|
-
assert a.hexdigest == hexdigest
|
19
|
-
end
|
20
|
-
|
21
9
|
def test_that_absorb_squeeze_works
|
22
10
|
input = "GYOMKVTSNHVJNCNFBBAH9AAMXLPLLLROQY99QN9DLSJUHDPBLCFFAIQXZA9BKMBJCYSFHFPXAHDWZFEIZ"
|
23
11
|
expected = "OXJCNFHUNAHWDLKKPELTBFUCVW9KLXKOGWERKTJXQMXTKFKNWNNXYD9DMJJABSEIONOSJTTEVKVDQEWTW"
|
data/test/sha3_test.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
require "iota/crypto/sha3_ruby"
|
4
|
+
|
5
|
+
class Sha3Test < Minitest::Test
|
6
|
+
def setup
|
7
|
+
@ruby_sha3_class = Digest::RubySHA3
|
8
|
+
unless RUBY_PLATFORM =~ /java/
|
9
|
+
require 'digest/sha3'
|
10
|
+
@c_sha3_class = Digest::SHA3
|
11
|
+
else
|
12
|
+
@c_sha3_class = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
@str = "GYOMKVTSNHVJNCNFBBAH9AAMXLPLLLROQY99QN9DLSJUHDPBLCFFAIQXZA9BKMBJCYSFHFPXAHDWZFEIZ"
|
16
|
+
@result = "e0ef02d24644a7b28b3c1b01c4fe137a49864d5bde6656faf439e1eba658064d9ecf843255ba903d1cebdc66ff2f16ce"
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_that_c_sha3_update_works
|
20
|
+
if @c_sha3_class
|
21
|
+
start = Time.now
|
22
|
+
a = @c_sha3_class.new(IOTA::Crypto::Kerl::BIT_HASH_LENGTH)
|
23
|
+
a.update(@str)
|
24
|
+
puts "C SHA3 Update time: #{(Time.now - start) * 1000.0}ms"
|
25
|
+
|
26
|
+
assert a.digest_length == 48
|
27
|
+
assert a.hexdigest == @result
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_that_c_sha3_digest_works
|
32
|
+
if @c_sha3_class
|
33
|
+
start = Time.now
|
34
|
+
a = @c_sha3_class.new(IOTA::Crypto::Kerl::BIT_HASH_LENGTH)
|
35
|
+
assert a.hexdigest(@str) == @result
|
36
|
+
puts "C SHA3 Digest time: #{(Time.now - start) * 1000.0}ms"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_that_ruby_sha3_update_works
|
41
|
+
if @ruby_sha3_class
|
42
|
+
start = Time.now
|
43
|
+
a = @ruby_sha3_class.new(IOTA::Crypto::Kerl::BIT_HASH_LENGTH)
|
44
|
+
a.update(@str)
|
45
|
+
puts "Ruby SHA3 Update time: #{(Time.now - start) * 1000.0}ms"
|
46
|
+
assert a.digest_length == 48
|
47
|
+
assert a.hexdigest == @result
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_that_ruby_sha3_digest_works
|
52
|
+
if @ruby_sha3_class
|
53
|
+
start = Time.now
|
54
|
+
a = @ruby_sha3_class.new(IOTA::Crypto::Kerl::BIT_HASH_LENGTH)
|
55
|
+
assert a.hexdigest(@str) == @result
|
56
|
+
puts "Ruby SHA3 Digest time: #{(Time.now - start) * 1000.0}ms"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_that_c_sha3_and_ruby_sha3_give_same_results
|
61
|
+
if @ruby_sha3_class && @c_sha3_class
|
62
|
+
a = @ruby_sha3_class.new(IOTA::Crypto::Kerl::BIT_HASH_LENGTH)
|
63
|
+
b = @c_sha3_class.new(IOTA::Crypto::Kerl::BIT_HASH_LENGTH)
|
64
|
+
assert a.hexdigest(@str) == b.hexdigest(@str)
|
65
|
+
|
66
|
+
a = @ruby_sha3_class.new(IOTA::Crypto::Kerl::BIT_HASH_LENGTH)
|
67
|
+
b = @c_sha3_class.new(IOTA::Crypto::Kerl::BIT_HASH_LENGTH)
|
68
|
+
assert a.update(@str).hexdigest == b.update(@str).hexdigest
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/test/utils_test.rb
CHANGED
@@ -5,6 +5,12 @@ class UtilsTest < Minitest::Test
|
|
5
5
|
@utils = IOTA::Utils::Utils.new
|
6
6
|
end
|
7
7
|
|
8
|
+
def test_add_checksum
|
9
|
+
addressWithoutChecksum = "UYEEERFQYTPFAHIPXDQAQYWYMSMCLMGBTYAXLWFRFFWPYFOICOVLK9A9VYNCKK9TQUNBTARCEQXJHD9VY"
|
10
|
+
addressWithChecksum = "UYEEERFQYTPFAHIPXDQAQYWYMSMCLMGBTYAXLWFRFFWPYFOICOVLK9A9VYNCKK9TQUNBTARCEQXJHD9VYXOEDEOMRC"
|
11
|
+
assert_equal @utils.addChecksum(addressWithoutChecksum), addressWithChecksum
|
12
|
+
end
|
13
|
+
|
8
14
|
def test_checksum_validation
|
9
15
|
addressWithChecksum = "UYEEERFQYTPFAHIPXDQAQYWYMSMCLMGBTYAXLWFRFFWPYFOICOVLK9A9VYNCKK9TQUNBTARCEQXJHD9VYXOEDEOMRC"
|
10
16
|
assert_equal @utils.isValidChecksum(addressWithChecksum), true
|
metadata
CHANGED
@@ -1,69 +1,69 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: iota-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vivek Marakana
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-07-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.15'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.15'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '10.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: minitest
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '5.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '5.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake-compiler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: 1.0.4
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 1.0.4
|
69
69
|
- !ruby/object:Gem::Dependency
|
@@ -97,8 +97,7 @@ dependencies:
|
|
97
97
|
description: Ruby gem for the IOTA core
|
98
98
|
email:
|
99
99
|
- vivek.marakana@gmail.com
|
100
|
-
executables:
|
101
|
-
- iota-console
|
100
|
+
executables: []
|
102
101
|
extensions:
|
103
102
|
- ext/ccurl/extconf.rb
|
104
103
|
extra_rdoc_files: []
|
@@ -116,6 +115,8 @@ files:
|
|
116
115
|
- examples/multisig.rb
|
117
116
|
- ext/ccurl/ccurl.c
|
118
117
|
- ext/ccurl/extconf.rb
|
118
|
+
- ext/jcurl/JCurl.java
|
119
|
+
- ext/jcurl/JCurlService.java
|
119
120
|
- ext/pow/ccurl-0.3.0.dll
|
120
121
|
- ext/pow/libccurl-0.3.0.dylib
|
121
122
|
- ext/pow/libccurl-0.3.0.so
|
@@ -129,11 +130,13 @@ files:
|
|
129
130
|
- lib/iota/crypto/converter.rb
|
130
131
|
- lib/iota/crypto/curl.rb
|
131
132
|
- lib/iota/crypto/curl_c.rb
|
133
|
+
- lib/iota/crypto/curl_java.rb
|
132
134
|
- lib/iota/crypto/curl_ruby.rb
|
133
135
|
- lib/iota/crypto/hmac.rb
|
134
136
|
- lib/iota/crypto/kerl.rb
|
135
137
|
- lib/iota/crypto/pow_provider.rb
|
136
138
|
- lib/iota/crypto/private_key.rb
|
139
|
+
- lib/iota/crypto/sha3_ruby.rb
|
137
140
|
- lib/iota/crypto/signing.rb
|
138
141
|
- lib/iota/models/account.rb
|
139
142
|
- lib/iota/models/base.rb
|
@@ -150,11 +153,14 @@ files:
|
|
150
153
|
- lib/iota/utils/object_validator.rb
|
151
154
|
- lib/iota/utils/utils.rb
|
152
155
|
- lib/iota/version.rb
|
156
|
+
- lib/patch.rb
|
153
157
|
- test/ascii_test.rb
|
154
158
|
- test/curl_c_test.rb
|
159
|
+
- test/curl_java_test.rb
|
155
160
|
- test/curl_ruby_test.rb
|
156
161
|
- test/kerl_test.rb
|
157
162
|
- test/pow_provider_test.rb
|
163
|
+
- test/sha3_test.rb
|
158
164
|
- test/test_helper.rb
|
159
165
|
- test/utils_test.rb
|
160
166
|
homepage: https://github.com/vivekmarakana/iota.lib.rb
|
@@ -168,23 +174,24 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
168
174
|
requirements:
|
169
175
|
- - ">="
|
170
176
|
- !ruby/object:Gem::Version
|
171
|
-
version:
|
177
|
+
version: '0'
|
172
178
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
179
|
requirements:
|
174
180
|
- - ">="
|
175
181
|
- !ruby/object:Gem::Version
|
176
182
|
version: '0'
|
177
183
|
requirements: []
|
178
|
-
|
179
|
-
rubygems_version: 2.6.14
|
184
|
+
rubygems_version: 3.0.4
|
180
185
|
signing_key:
|
181
186
|
specification_version: 4
|
182
187
|
summary: IOTA API wrapper for Ruby
|
183
188
|
test_files:
|
184
189
|
- test/ascii_test.rb
|
185
190
|
- test/curl_c_test.rb
|
191
|
+
- test/curl_java_test.rb
|
186
192
|
- test/curl_ruby_test.rb
|
187
193
|
- test/kerl_test.rb
|
188
194
|
- test/pow_provider_test.rb
|
195
|
+
- test/sha3_test.rb
|
189
196
|
- test/test_helper.rb
|
190
197
|
- test/utils_test.rb
|