iota-ruby 1.1.7 → 1.1.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|