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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1e5423f9645a1fceef2e926f77101b6d28a2e837
4
- data.tar.gz: 55d897d2dec4177927a57e90f7e5570c79d95604
2
+ SHA256:
3
+ metadata.gz: 0eddb950ffbc3bf0e3da4e220391718183273cb590bd721edc759fb76b0fd7bf
4
+ data.tar.gz: 53e845e6eacd344ae3237b2547320565cd8323b6fee7d0aa872668f1cb47c507
5
5
  SHA512:
6
- metadata.gz: 16ccbc15b79c844294c81ab21146e6fb848dd1db5d2e3e6b8b56b8096f3aed43d117a607f046b3b7ddd4fcb2e7770284662df7246ea5649c94498f03ceb5e3d9
7
- data.tar.gz: 077a3b55befc66196a5bfa9e2ceab5074d5d42afd856a245a90c4c15d701b7b4f6446973e604c53c748acc1263d549dca8f48df232c826a0b1c42b681c6ba2f1
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
- ### Changed
12
- - Only returning balance array as reponse for `getBalances` api call (Major)
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
- Rake::ExtensionTask.new "ccurl" do |ext|
12
- ext.lib_dir = "lib"
13
- end
10
+ tasks = []
14
11
 
15
- def can_compile_extensions
16
- return false if RUBY_DESCRIPTION =~ /jruby/
17
- return true
18
- end
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
- if can_compile_extensions
21
- task :default => [:compile, :test]
21
+ tasks << :compile
22
+ else
23
+ puts "Not building jar for travis"
24
+ end
22
25
  else
23
- task :default => [:test]
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 = NUM2INT(rb_funcall(data, rb_intern("length"), 0, 0));
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 length = NUM2INT(rb_funcall(data, rb_intern("length"), 0, 0));
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
- for(; length < HASH_LENGTH; length++) {
76
- rb_ary_push(data, LONG2NUM(0));
77
- }
80
+ do {
81
+ for(; length < HASH_LENGTH; length++) {
82
+ rb_ary_push(data, LONG2NUM(0));
83
+ }
78
84
 
79
- for (i = 0; i < HASH_LENGTH; i++) {
80
- rb_ary_store(data, i, LONG2NUM(ctx->state[i]));
81
- }
85
+ for (i = 0; i < HASH_LENGTH; i++) {
86
+ rb_ary_store(data, i, LONG2NUM(ctx->state[i]));
87
+ }
82
88
 
83
- ccurl_transform(self);
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
- spec.required_ruby_version = '>= 2.4.0'
23
- spec.add_development_dependency "bundler", "~> 1.15"
24
- spec.add_development_dependency "rake", "~> 10.0"
25
- spec.add_development_dependency "minitest", "~> 5.0"
26
- spec.add_development_dependency "rake-compiler", "~> 1.0.4"
27
- spec.add_dependency "digest-sha3", "~> 1.1"
28
- spec.add_dependency "ffi", "~> 1.9.25"
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 = {})
@@ -81,7 +81,10 @@ module IOTA
81
81
 
82
82
  (0...trits.length).step(3) do |i|
83
83
  chunk = trits[i...i+3]
84
- trytes += TRYTES_ALPHABET[TRYTE_TRITS.index(chunk)]
84
+ index = TRYTE_TRITS.index(chunk)
85
+ if !index.nil?
86
+ trytes += TRYTES_ALPHABET[index]
87
+ end
85
88
  end
86
89
 
87
90
  trytes
@@ -1,9 +1,9 @@
1
- if !Dir.glob(File.join(File.dirname(__FILE__), '../../ccurl.*')).empty?
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
@@ -5,11 +5,13 @@ module IOTA
5
5
  HASH_LENGTH = 243
6
6
  STATE_LENGTH = 3 * HASH_LENGTH
7
7
 
8
+ unless RUBY_PLATFORM =~ /java/
9
+ require "ccurl"
10
+ end
11
+
8
12
  def version
9
13
  "C"
10
14
  end
11
15
  end
12
16
  end
13
17
  end
14
-
15
- require "ccurl"
@@ -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
@@ -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
- @hasher = Digest::SHA3.new(BIT_HASH_LENGTH)
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
@@ -1,3 +1,3 @@
1
1
  module IOTA
2
- VERSION = "1.1.7"
2
+ VERSION = "1.1.8"
3
3
  end
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
- if !Dir.glob(File.join(File.dirname(__FILE__), '../lib/ccurl.*')).empty?
2
+ unless RUBY_PLATFORM =~ /java/
3
3
  require "iota/crypto/curl_c"
4
4
 
5
- class CcurlTest < Minitest::Test
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.7
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: 2018-12-02 00:00:00.000000000 Z
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: 2.4.0
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
- rubyforge_project:
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