nis-ruby 0.0.13 → 0.0.14

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
2
  SHA1:
3
- metadata.gz: 90a209933bc58268e827373213bbd8246aeb5147
4
- data.tar.gz: 2842c5967a6dfab98aea4fdf1e659b967528071e
3
+ metadata.gz: 681592f0869e7c2ff1956e2b04ad32ffcd07f002
4
+ data.tar.gz: d3f7c8660d39d09d9186c3df607e5b00682ca5d1
5
5
  SHA512:
6
- metadata.gz: 4d7bbc7b84d6495f60484c7cd3927ca47643f0659dd9948ebaa5be823b741ab1caa052772a8156d78328faf210a57cfa90f348b3b64ae9a6ca5577443b142a8f
7
- data.tar.gz: 7a275ef7fda5a0cfb0e34c01db7ba7c92c18feb7036285dd6fe2d50944c74ff9f2307174b7acb93f42b1dfa79be155c4c69ec4bd2b682c3ac39ea4baa5c8b546
6
+ metadata.gz: f7c4b08efb1324125b792de4df01fa6dc7aaacc355358a65e10ce337dbad2dce308a830103aa23bebb954488b673cd00ab086036c41cef5dfbdc9522bd6aa5ee
7
+ data.tar.gz: 05e7ed7f141eb73a948b3690376dc5d5b4a43ebdd343d6a68942470d46f6d5dd089b396026567f6fcf579d996332e6c9ec28bc5d62593fb4893c68a247f66bdd
data/README.md CHANGED
@@ -5,9 +5,9 @@
5
5
  [![Code Climate](https://codeclimate.com/github/44uk/nis-ruby/badges/gpa.svg)](https://codeclimate.com/github/44uk/nis-ruby)
6
6
  [![Join the chat at https://gitter.im/44uk/nis-ruby](https://badges.gitter.im/44uk/nis-ruby.svg)](https://gitter.im/44uk/nis-ruby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
7
7
 
8
- <img src="https://cloud.githubusercontent.com/assets/370508/24320282/a332d238-1175-11e7-96dc-75bc30e562d2.png" width="320" height="320" alt="NEM" align="right" />
8
+ <img src="https://cloud.githubusercontent.com/assets/370508/24320282/a332d238-1175-11e7-96dc-75bc30e562d2.png" width="280" height="280" alt="nem" align="right" />
9
9
 
10
- Ruby client library for the NEM Infrastructure Server API
10
+ Ruby client library for the NEM Infrastructure Server(NIS) API.
11
11
 
12
12
  - [NEM \- Distributed Ledger Technology \(Blockchain\)](https://www.nem.io/)
13
13
  - [NEM NIS API Documentation](https://nemproject.github.io/)
@@ -15,6 +15,9 @@ Ruby client library for the NEM Infrastructure Server API
15
15
 
16
16
  *The gem is under development. Incompatible changes can be made.*
17
17
 
18
+ *Do a thorough test on testnet before you use this gem on production.*
19
+
20
+ - [NEM Testnet Faucet \- You can get Testnet XEM for development / testing.](http://test-nem-faucet.44uk.net/)
18
21
 
19
22
  ## Installation
20
23
 
@@ -30,6 +33,8 @@ gem 'nis-ruby'
30
33
 
31
34
  ## Usage
32
35
 
36
+ ### Examples
37
+
33
38
  More specific example codes are in **examples/** directory.
34
39
 
35
40
  ### Methods
@@ -79,7 +84,6 @@ nis.request(:post, '/account/unlock',
79
84
  # See https://nemproject.github.io/#locking-and-unlocking-accounts
80
85
  ```
81
86
 
82
-
83
87
  ## Commandline
84
88
 
85
89
  ```bash
@@ -96,11 +100,9 @@ $ nis request get account/harvests --params=address:TALICELCD3XPH4FFI5STGGNSNSWP
96
100
  # => [Array <HervestInfo structure>]
97
101
  ```
98
102
 
99
-
100
103
  ## Connection
101
104
 
102
- You can find nodes here.
103
- - [NEM Node Rewards](https://supernodes.nem.io/)
105
+ You can find nodes here. [NEM Node Rewards](https://supernodes.nem.io/)
104
106
 
105
107
  ### Hash
106
108
 
@@ -121,26 +123,29 @@ $ nis heartbeat # => {"code":1,"type":2,"message":"ok"}
121
123
 
122
124
  Environment variable used as default value.
123
125
 
126
+ ## For More Information
127
+
128
+ * [Documentation for nis-ruby - rubydoc.info](http://www.rubydoc.info/gems/nis-ruby)
124
129
 
125
130
  ## TODO
126
131
 
127
132
  * Do more improvements
128
- * Mosaic transferring
129
133
  * Encryption message
134
+ * Failover connection
130
135
  * Be more easy to use
131
136
 
137
+ ## Contact
132
138
 
133
- ## Documentation
134
-
135
- Available at [rubydoc.info](http://www.rubydoc.info/gems/nis-ruby).
139
+ Feel free to ask me if you have any questions.
136
140
 
141
+ * [@44uk_i3 - Twitter](https://twitter.com/44uk_i3)
142
+ * [44uk/nis-ruby - gitter](https://gitter.im/44uk/nis-ruby)
137
143
 
138
144
  ## Contributing
139
145
 
140
146
  Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/nis-ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
141
147
 
142
-
143
148
  ## License
144
149
 
145
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
150
+ The gem is available as open source under the terms of the [MIT License](LICENSE).
146
151
 
data/Rakefile CHANGED
@@ -1,6 +1,9 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rspec/core/rake_task'
3
+ require 'yard'
3
4
 
4
5
  RSpec::Core::RakeTask.new(:spec)
5
6
 
7
+ YARD::Rake::YardocTask.new
8
+
6
9
  task default: :spec
@@ -0,0 +1,48 @@
1
+ require 'nis'
2
+ require 'pp'
3
+
4
+ # sender
5
+ A_PRIVATE_KEY = '260206d683962350532408e8774fd14870a173b7fba17f6b504da3dbc5f1cc9f'
6
+
7
+ # receiver
8
+ B_ADDRESS = 'TAWKJTUP4DWKLDKKS534TYP6G324CBNMXKBA4X7B'
9
+
10
+ kp = Nis::Keypair.new(A_PRIVATE_KEY)
11
+
12
+ # fetch mosaic information
13
+ nis = Nis.new(host: '104.128.226.60')
14
+ mo_dmdps = nis.namespace_mosaic_definition_page(namespace: 'sushi')
15
+ mo_def = mo_dmdps.first.mosaic
16
+
17
+ # require 'pry'; binding.pry
18
+
19
+ # mosaic_id = Nis::Struct::MosaicId.new(
20
+ # namespaceId: 'sushi',
21
+ # name: 'anago'
22
+ # )
23
+
24
+ # properties = Nis::Struct::MosaicProperties.new(
25
+ # divisibility: 0,
26
+ # initialSupply: 10_000,
27
+ # supplyMutable: true,
28
+ # transferable: true
29
+ # )
30
+
31
+ # mo_def = Nis::Struct::MosaicDefinition.new(
32
+ # id: mosaic_id,
33
+ # properties: properties,
34
+ # )
35
+
36
+ tx = Nis::Transaction::Transfer.new(B_ADDRESS, 1_000_000, 'Good luck!')
37
+ tx.mosaics << Nis::Struct::MosaicAttachment.new(mo_def, 1_000_000)
38
+
39
+ # pp tx.to_hash
40
+
41
+ nis = Nis.new
42
+ req = Nis::Request::PrepareAnnounce.new(tx, kp)
43
+ pp req.to_hash
44
+ # res = nis.transaction_prepare_announce(req)
45
+
46
+ #
47
+ # puts "Message: #{res.message}"
48
+ # puts "TransactionHash: #{res.transaction_hash}"
@@ -6,7 +6,7 @@ class Nis::Fee
6
6
 
7
7
  # @return [Integer] fee in micro XEM
8
8
  def value
9
- testnet? ? 0.15 * 1_000_000 : 6_000_000
9
+ 0.15 * 1_000_000
10
10
  end
11
11
 
12
12
  # @return [Integer] fee in micro XEM
@@ -6,7 +6,7 @@ class Nis::Fee
6
6
 
7
7
  # @return [Integer] fee in micro XEM
8
8
  def value
9
- (testnet? ? 10 : 500) * 1_000_000
9
+ 10 * 1_000_000
10
10
  end
11
11
 
12
12
  # @return [Integer] fee in micro XEM
@@ -6,7 +6,7 @@ class Nis::Fee
6
6
 
7
7
  # @return [Integer] fee in micro XEM
8
8
  def value
9
- testnet? ? 0.15 * 1_000_000 : 20 * 1_000_000
9
+ 0.15 * 1_000_000
10
10
  end
11
11
 
12
12
  # @return [Integer] fee in micro XEM
@@ -6,7 +6,7 @@ class Nis::Fee
6
6
 
7
7
  # @return [Integer] fee in micro XEM
8
8
  def value
9
- testnet? ? 0.15 * 1_000_000 : 6_000_000
9
+ 0.15 * 1_000_000
10
10
  end
11
11
 
12
12
  # @return [Integer] fee in micro XEM
@@ -7,13 +7,9 @@ class Nis::Fee
7
7
  # @return [Integer] fee in micro XEM
8
8
  def value
9
9
  if @transaction.minCosignatories == 0
10
- testnet? ?
11
- 0.5 * 1_000_000 :
12
- (10 + 6 * @transaction.modifications.length) * 1_000_000
10
+ 0.5 * 1_000_000
13
11
  else
14
- testnet? ?
15
- 0.5 * 1_000_000 :
16
- (10 + 6 * @transaction.modifications.length + 6) * 1_000_000
12
+ 0.5 * 1_000_000
17
13
  end
18
14
  end
19
15
 
@@ -22,11 +22,11 @@ class Nis::Fee
22
22
  private
23
23
 
24
24
  def root_fee
25
- (testnet? ? 100 : 5_000) * 1_000_000
25
+ 100 * 1_000_000
26
26
  end
27
27
 
28
28
  def sub_fee
29
- (testnet? ? 10 : 200) * 1_000_000
29
+ 10 * 1_000_000
30
30
  end
31
31
  end
32
32
  end
@@ -1,23 +1,19 @@
1
1
  class Nis::Fee
2
2
  class Transfer
3
+ FEE_FACTOR = 0.05
4
+
3
5
  def initialize(transaction)
4
6
  @transaction = transaction
5
7
  end
6
8
 
7
9
  # @return [Integer] fee in micro XEM
8
10
  def value
9
- tmp = 0
10
-
11
- if @transaction.mosaics.empty?
12
- tmp += min_fee
11
+ tmp = if @transaction.has_mosaics?
12
+ mosaics_fee
13
13
  else
14
- tmp += mosaics_fee
15
- end
16
-
17
- if @transaction.message.bytesize > 0
18
- tmp += message_fee
14
+ FEE_FACTOR * minimum_fee(@transaction.amount / 1_000_000)
19
15
  end
20
-
16
+ tmp += message_fee if @transaction.has_message?
21
17
  tmp * 1_000_000
22
18
  end
23
19
 
@@ -33,19 +29,40 @@ class Nis::Fee
33
29
 
34
30
  private
35
31
 
36
- def min_fee
37
- tmp = [1, @transaction.amount / 1_000_000 / 10_000].max
38
- tmp = (tmp > 25 ? 25 : tmp)
39
- testnet? ? 0.05 * tmp : tmp
32
+ def minimum_fee(base)
33
+ tmp = [1, base / 10_000].max
34
+ tmp > 25 ? 25 : tmp
40
35
  end
41
36
 
42
37
  def message_fee
43
- tmp = [1, (@transaction.message.bytesize / 2 / 32) + 1].max
44
- testnet? ? 0.05 * tmp : tmp
38
+ FEE_FACTOR * [1, (@transaction.message.bytesize / 2 / 32) + 1].max
45
39
  end
46
40
 
47
41
  def mosaics_fee
48
- raise NotImplementedError, 'not implemented calculation mosaics fee.'
42
+ FEE_FACTOR * @transaction.mosaics.inject(0) do |sum, mo_attachment|
43
+ mo = mo_attachment.mosaic_definition
44
+ quantity = mo_attachment.quantity
45
+ tmp_fee = 0
46
+ if mo.divisibility == 0 && mo.initial_supply <= 10_000
47
+ # It is called *Small Business Mosaic Fee*
48
+ supply_related_adjustment = 0
49
+ tmp_fee = 1
50
+ else
51
+ # custom mosaic fee, Max is 1.25.
52
+ max_mosaic_quantity = 9_000_000_000_000_000
53
+ total_mosaic_quantity = mo.initial_supply * (10**mo.divisibility)
54
+ supply_related_adjustment = (0.8 * (Math.log(max_mosaic_quantity / total_mosaic_quantity))).floor
55
+
56
+ num_nem = if mo.initial_supply == 0
57
+ 0
58
+ else
59
+ 8_999_999_999.to_f * quantity * 1_000_000 / mo.initial_supply / (10**(mo.divisibility + 6))
60
+ end
61
+ tmp_fee = minimum_fee(num_nem.ceil)
62
+ end
63
+
64
+ sum + [1, tmp_fee - supply_related_adjustment].max
65
+ end
49
66
  end
50
67
  end
51
68
  end
data/lib/nis/keypair.rb CHANGED
@@ -2,11 +2,15 @@ class Nis
2
2
  class Keypair
3
3
  attr_reader :private, :public
4
4
 
5
+ # @param [String] Private Key
6
+ # @option options [Strung] :public_key Public Key
5
7
  def initialize(private_key, public_key: nil)
6
8
  @private = private_key
7
9
  @public = public_key || calc_public_key
8
10
  end
9
11
 
12
+ # @param [String] Hex string
13
+ # @return [String] Signed hex string
10
14
  def sign(data)
11
15
  bin_data = data.scan(/../).map(&:hex).pack('C*')
12
16
  bin_signed = Nis::Util::Ed25519.signature_hash_unsafe(bin_data, @bin_secret, @bin_public)
@@ -14,6 +14,7 @@ class Nis::Request
14
14
  @transaction = transaction
15
15
  end
16
16
 
17
+ # @return [Hash] Attribute and value pairs
17
18
  def to_hash
18
19
  if @transaction.respond_to?(:other_trans)
19
20
  other_trans(@transaction)
@@ -22,7 +23,7 @@ class Nis::Request
22
23
  @transaction.tap do |tx|
23
24
  tx.timeStamp = Nis::Util.timestamp
24
25
  tx.deadline = Nis::Util.deadline(DEADLINE)
25
- tx.version = Nis::Util.parse_version(tx.network, 1)
26
+ tx.version = Nis::Util.parse_version(tx.network, version(tx))
26
27
  tx.signer = @keypair.public
27
28
  end
28
29
 
@@ -47,9 +48,13 @@ class Nis::Request
47
48
  transaction.other_trans.tap do |tx|
48
49
  tx.timeStamp = Nis::Util.timestamp
49
50
  tx.deadline = Nis::Util.deadline(DEADLINE)
50
- tx.version = Nis::Util.parse_version(tx.network, 1)
51
+ tx.version = Nis::Util.parse_version(tx.network, version(tx))
51
52
  tx.signer = transaction.signer
52
53
  end
53
54
  end
55
+
56
+ def version(transaction)
57
+ transaction.respond_to?(:has_mosaics?) && transaction.has_mosaics? ? 2 : 1
58
+ end
54
59
  end
55
60
  end
@@ -14,6 +14,7 @@ class Nis::Request
14
14
  @transaction = transaction
15
15
  end
16
16
 
17
+ # @return [Hash] Attribute and value pairs
17
18
  def to_hash
18
19
  if @transaction.respond_to?(:other_trans)
19
20
  other_trans(@transaction)
@@ -22,7 +23,7 @@ class Nis::Request
22
23
  @transaction.tap do |tx|
23
24
  tx.timeStamp = Nis::Util.timestamp
24
25
  tx.deadline = Nis::Util.deadline(DEADLINE)
25
- tx.version = Nis::Util.parse_version(tx.network, 1)
26
+ tx.version = Nis::Util.parse_version(tx.network, version(tx))
26
27
  tx.signer = @keypair.public
27
28
  end
28
29
 
@@ -36,13 +37,15 @@ class Nis::Request
36
37
  transaction.other_trans.tap do |tx|
37
38
  tx.timeStamp = Nis::Util.timestamp
38
39
  tx.deadline = Nis::Util.deadline(DEADLINE)
39
- tx.version = Nis::Util.parse_version(tx.network, 1)
40
-
41
- # tx.signer = @keypair.public
40
+ tx.version = Nis::Util.parse_version(tx.network, version(tx))
42
41
 
43
42
  # multisig transfer
44
43
  tx.signer = transaction.signer
45
44
  end
46
45
  end
46
+
47
+ def version(transaction)
48
+ transaction.respond_to?(:has_mosaics?) && transaction.has_mosaics? ? 2 : 1
49
+ end
47
50
  end
48
51
  end
@@ -0,0 +1,21 @@
1
+ class Nis::Struct
2
+ # @attr [String] fqn ex) nem.xem
3
+ # @attr [Integer] quantity
4
+ # @see https://nemproject.github.io/#version-2-transfer-transactions
5
+ class MosaicAttachment
6
+ extend Forwardable
7
+ def_delegators :@mosaic_definition, :initial_supply, :divisibility
8
+
9
+ attr_reader :mosaic_definition, :quantity
10
+
11
+ def initialize(mo_def, quantity)
12
+ @mosaic_definition = mo_def
13
+ @quantity = quantity
14
+ end
15
+
16
+ def to_hash
17
+ { mosaicId: @mosaic_definition.id.to_hash,
18
+ quantity: @quantity }
19
+ end
20
+ end
21
+ end
@@ -9,9 +9,13 @@ class Nis::Struct
9
9
  include Nis::Util::Assignable
10
10
  attr_accessor :creator, :id, :description, :properties, :levy
11
11
 
12
+ extend Forwardable
13
+ def_delegators :@properties, :divisibility, :initialSupply, :supplyMutable, :transferable,
14
+ :initial_supply, :supply_mutable
15
+
12
16
  def self.build(attrs)
13
17
  attrs[:id] = MosaicId.build(attrs[:id])
14
- attrs[:properties] = attrs[:properties].map { |p| MosaicProperties.build(p) }
18
+ attrs[:properties] = MosaicProperties.build(attrs[:properties])
15
19
  attrs[:levy] = MosaicLevy.build(attrs[:levy]) if attrs[:levy]
16
20
  new(attrs)
17
21
  end
@@ -13,7 +13,17 @@ class Nis::Struct
13
13
  alias supply_mutable supplyMutable
14
14
  alias supply_mutable= supplyMutable=
15
15
 
16
- def self.build(attrs)
16
+ def self.build(props)
17
+ attrs = props.inject({}) do |hash, prop|
18
+ hash[prop[:name]] = case prop[:name]
19
+ when 'divisibility' then prop[:value].to_i
20
+ when 'initialSupply' then prop[:value].to_i
21
+ when 'supplyMutable' then prop[:value] == 'true' ? true : false
22
+ when 'transferable' then prop[:value] == 'true' ? true : false
23
+ else prop[:value]
24
+ end
25
+ hash
26
+ end
17
27
  new(attrs)
18
28
  end
19
29
 
@@ -47,7 +47,7 @@ class Nis::Transaction
47
47
  fee: 20 * 1_000_000 }
48
48
  else
49
49
  { sink: 'NBMOSAICOD4F54EE5CDMR23CCBGOAM2XSIUX6TRS',
50
- fee: 500 * 1_000_000 }
50
+ fee: 20 * 1_000_000 }
51
51
  end
52
52
  end
53
53
  end
@@ -64,10 +64,10 @@ class Nis::Transaction
64
64
  end
65
65
  else
66
66
  if root?
67
- { fee: 5_000 * 1_000_000 ,
67
+ { fee: 100 * 1_000_000 ,
68
68
  sink: 'NAMESPACEWH4MKFMBCVFERDPOOP4FK7MTBXDPZZA' }
69
69
  else
70
- { fee: 200 * 1_000_000 ,
70
+ { fee: 10 * 1_000_000 ,
71
71
  sink: 'NAMESPACEWH4MKFMBCVFERDPOOP4FK7MTBXDPZZA' }
72
72
  end
73
73
  end
@@ -20,13 +20,14 @@ class Nis::Transaction
20
20
  attr_reader :type, :fee
21
21
  attr_accessor :recipient, :amount, :message,
22
22
  :deadline, :timeStamp, :version, :signer,
23
- :network
23
+ :network,
24
+ :mosaics
24
25
 
25
26
  alias timestamp timeStamp
26
27
 
27
28
  TYPE = 0x0101 # 257 (transfer transaction)
28
29
 
29
- def initialize(recipient, amount, message = '', network: :testnet)
30
+ def initialize(recipient, amount, message = '', mosaics: [], network: :testnet)
30
31
  @type = TYPE
31
32
  @network = network
32
33
 
@@ -34,11 +35,15 @@ class Nis::Transaction
34
35
  @amount = amount
35
36
  @message = Nis::Struct::Message.new(message)
36
37
  @fee = Nis::Fee::Transfer.new(self)
38
+ @mosaics = mosaics
37
39
  end
38
40
 
39
- def mosaics
40
- # TODO: to be implemented...
41
- []
41
+ def has_message?
42
+ @message.bytesize > 0
43
+ end
44
+
45
+ def has_mosaics?
46
+ @mosaics.size > 0
42
47
  end
43
48
  end
44
49
  end
@@ -48,7 +48,7 @@ module Nis::Unit
48
48
  ripe = OpenSSL::Digest::RIPEMD160.digest(public_key_hash)
49
49
 
50
50
  if network == :testnet
51
- version = "\x98".force_encoding("ASCII-8BIT") + ripe
51
+ version = "\x98".force_encoding('ASCII-8BIT') + ripe
52
52
  else
53
53
  version = "\x68" + ripe
54
54
  end
data/lib/nis/util.rb CHANGED
@@ -29,6 +29,10 @@ module Nis::Util
29
29
  end
30
30
  end
31
31
 
32
+ def self.parse_nemtime(nemtime)
33
+ NEM_EPOCH + nemtime
34
+ end
35
+
32
36
  def self.deadline(seconds = 3600)
33
37
  timestamp + seconds
34
38
  end
@@ -0,0 +1,46 @@
1
+ module Nis::Util
2
+ module Deserializer
3
+ # Deserialize a transaction object
4
+ # @param [String] serialized
5
+ # @return [Hash]
6
+ def self.deserialize_transaction(serialized)
7
+ s = Nis::Util::Convert.hex2ua(serialized)
8
+ tx = {}
9
+ tx[:type] = deserialize_int(s[0, 4])
10
+ tx[:version] = deserialize_int(s[4, 4])
11
+ tx[:timeStamp] = deserialize_int(s[8, 4])
12
+ # s[12,4] # length of public key
13
+ tx[:signer] = deserialize_hex(s[16, 32])
14
+ tx[:fee] = deserialize_int(s[48, 8])
15
+ tx[:deadline] = deserialize_int(s[56, 4])
16
+ # s[60,4] # length of address
17
+ tx[:recipient] = deserialize_a(s[64, 40])
18
+ tx[:amount] = deserialize_int(s[104, 8])
19
+
20
+ tx[:message] = {}
21
+ message_len = deserialize_int(s[112, 4])
22
+ if message_len > 0
23
+ tx[:message][:type] = deserialize_int(s[116, 4])
24
+ # s[120, 4] # length of payload
25
+ tx[:message][:payload] = deserialize_hex(s[124, s.size])
26
+ else
27
+ tx[:message] = { type: 1, payload: '' }
28
+ end
29
+ tx
30
+ end
31
+
32
+ private
33
+
34
+ def self.deserialize_int(ua)
35
+ Nis::Util::Convert.ua2hex(ua.reverse).to_i(16)
36
+ end
37
+
38
+ def self.deserialize_hex(ua)
39
+ Nis::Util::Convert.ua2hex(ua)
40
+ end
41
+
42
+ def self.deserialize_a(ua)
43
+ Nis::Util::Convert.hex2a(deserialize_hex(ua))
44
+ end
45
+ end
46
+ end
@@ -14,7 +14,7 @@ module Nis::Util
14
14
  end
15
15
 
16
16
  def intlist2bytes(l)
17
- l.map {|c| c.chr }.join
17
+ l.map { |c| c.chr }.join
18
18
  end
19
19
 
20
20
  # standard implement
@@ -27,36 +27,34 @@ module Nis::Util
27
27
  end
28
28
 
29
29
  def pow2(x, p)
30
- # """== pow(x, 2**p, q)"""
31
30
  while p > 0 do
32
- x = x * x % $q
31
+ x = x * x % @@q
33
32
  p -= 1
34
33
  end
35
34
  x
36
35
  end
37
36
 
38
37
  def inv(z)
39
- # """$= z^{-1} \mod q$, for z != 0"""
40
38
  # Adapted from curve25519_athlon.c in djb's Curve25519.
41
- z2 = z * z % $q # 2
42
- z9 = pow2(z2, 2) * z % $q # 9
43
- z11 = z9 * z2 % $q # 11
44
- z2_5_0 = (z11 * z11) % $q * z9 % $q # 31 == 2^5 - 2^0
45
- z2_10_0 = pow2(z2_5_0, 5) * z2_5_0 % $q # 2^10 - 2^0
46
- z2_20_0 = pow2(z2_10_0, 10) * z2_10_0 % $q # ...
47
- z2_40_0 = pow2(z2_20_0, 20) * z2_20_0 % $q
48
- z2_50_0 = pow2(z2_40_0, 10) * z2_10_0 % $q
49
- z2_100_0 = pow2(z2_50_0, 50) * z2_50_0 % $q
50
- z2_200_0 = pow2(z2_100_0, 100) * z2_100_0 % $q
51
- z2_250_0 = pow2(z2_200_0, 50) * z2_50_0 % $q # 2^250 - 2^0
52
- pow2(z2_250_0, 5) * z11 % $q # 2^255 - 2^5 + 11 = q - 2
39
+ z2 = z * z % @@q # 2
40
+ z9 = pow2(z2, 2) * z % @@q # 9
41
+ z11 = z9 * z2 % @@q # 11
42
+ z2_5_0 = (z11 * z11) % @@q * z9 % @@q # 31 == 2^5 - 2^0
43
+ z2_10_0 = pow2(z2_5_0, 5) * z2_5_0 % @@q # 2^10 - 2^0
44
+ z2_20_0 = pow2(z2_10_0, 10) * z2_10_0 % @@q # ...
45
+ z2_40_0 = pow2(z2_20_0, 20) * z2_20_0 % @@q
46
+ z2_50_0 = pow2(z2_40_0, 10) * z2_10_0 % @@q
47
+ z2_100_0 = pow2(z2_50_0, 50) * z2_50_0 % @@q
48
+ z2_200_0 = pow2(z2_100_0, 100) * z2_100_0 % @@q
49
+ z2_250_0 = pow2(z2_200_0, 50) * z2_50_0 % @@q # 2^250 - 2^0
50
+ pow2(z2_250_0, 5) * z11 % @@q # 2^255 - 2^5 + 11 = q - 2
53
51
  end
54
52
 
55
53
  def xrecover(y)
56
- xx = (y * y - 1) * inv($d * y * y + 1)
57
- x = xx.to_bn.mod_exp(($q + 3) / 8, $q)
58
- x = (x * $I) % $q if (x * x - xx) % $q != 0
59
- x = $q - x if x % 2 != 0
54
+ xx = (y * y - 1) * inv(@@d * y * y + 1)
55
+ x = xx.to_bn.mod_exp((@@q + 3) / 8, @@q)
56
+ x = (x * @@I) % @@q if (x * x - xx) % @@q != 0
57
+ x = @@q - x if x % 2 != 0
60
58
  x
61
59
  end
62
60
 
@@ -66,10 +64,10 @@ module Nis::Util
66
64
  x1, y1, z1, t1 = _P
67
65
  x2, y2, z2, t2 = _Q
68
66
 
69
- a = (y1 - x1) * (y2 - x2) % $q
70
- b = (y1 + x1) * (y2 + x2) % $q
71
- c = t1 * 2 * $d * t2 % $q
72
- dd = z1 * 2 * z2 % $q
67
+ a = (y1 - x1) * (y2 - x2) % @@q
68
+ b = (y1 + x1) * (y2 + x2) % @@q
69
+ c = t1 * 2 * @@d * t2 % @@q
70
+ dd = z1 * 2 * z2 % @@q
73
71
  e = b - a
74
72
  f = dd - c
75
73
  g = dd + c
@@ -79,7 +77,7 @@ module Nis::Util
79
77
  t3 = e * h
80
78
  z3 = f * g
81
79
 
82
- [x3 % $q, y3 % $q, z3 % $q, t3 % $q]
80
+ [x3 % @@q, y3 % @@q, z3 % @@q, t3 % @@q]
83
81
  end
84
82
 
85
83
  def edwards_double(_P)
@@ -87,11 +85,11 @@ module Nis::Util
87
85
  # http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
88
86
  x1, y1, z1, _t1 = _P
89
87
 
90
- a = x1 * x1 % $q
91
- b = y1 * y1 % $q
92
- c = 2 * z1 * z1 % $q
88
+ a = x1 * x1 % @@q
89
+ b = y1 * y1 % @@q
90
+ c = 2 * z1 * z1 % @@q
93
91
  # dd = -a
94
- e = ((x1 + y1) * (x1 + y1) - a - b) % $q
92
+ e = ((x1 + y1) * (x1 + y1) - a - b) % @@q
95
93
  g = -a + b # dd + b
96
94
  f = g - c
97
95
  h = -a - b # dd - b
@@ -100,11 +98,11 @@ module Nis::Util
100
98
  t3 = e * h
101
99
  z3 = f * g
102
100
 
103
- return x3 % $q, y3 % $q, z3 % $q, t3 % $q
101
+ [x3 % @@q, y3 % @@q, z3 % @@q, t3 % @@q]
104
102
  end
105
103
 
106
104
  def scalarmult(_P, e)
107
- return $ident if e == 0
105
+ @@ident if e == 0
108
106
  _Q = scalarmult(_P, e / 2)
109
107
  _Q = edwards_double(_Q)
110
108
  _Q = edwards_add(_Q, _P) if e & 1
@@ -112,9 +110,9 @@ module Nis::Util
112
110
  end
113
111
 
114
112
  def make_Bpow
115
- _P = $B
113
+ _P = @@B
116
114
  (0...253).each do |_|
117
- $Bpow << _P
115
+ @@Bpow << _P
118
116
  _P = edwards_double(_P)
119
117
  end
120
118
  end
@@ -122,27 +120,27 @@ module Nis::Util
122
120
  # Implements scalarmult(B, e) more efficiently.
123
121
  def scalarmult_B(e)
124
122
  # scalarmult(B, l) is the identity
125
- e = e % $l
126
- _P = $ident
123
+ e = e % @@l
124
+ _P = @@ident
127
125
  (0...253).each do |i|
128
- _P = edwards_add(_P, $Bpow[i]) if e & 1 == 1
126
+ _P = edwards_add(_P, @@Bpow[i]) if e & 1 == 1
129
127
  e = e / 2
130
128
  end
131
129
  _P
132
130
  end
133
131
 
134
132
  def encodeint(y)
135
- bits = (0...$b).map {|i| (y >> i) & 1}
136
- (0...$b/8).map {|i| int2byte((0...8).inject(0) {|sum, j| sum + (bits[i * 8 + j] << j) }) }.join
133
+ bits = (0...@@b).map { |i| (y >> i) & 1 }
134
+ (0...@@b / 8).map { |i| int2byte((0...8).inject(0) { |sum, j| sum + (bits[i * 8 + j] << j) }) }.join
137
135
  end
138
136
 
139
137
  def encodepoint(_P)
140
138
  x, y, z, _t = _P
141
139
  zi = inv(z)
142
- x = (x * zi) % $q
143
- y = (y * zi) % $q
144
- bits = (0...$b-1).map {|i| (y >> i) & 1} + [x & 1]
145
- (0...$b/8).map {|i| int2byte((0...8).inject(0) {|sum, j| sum + (bits[i * 8 + j] << j) }) }.join
140
+ x = (x * zi) % @@q
141
+ y = (y * zi) % @@q
142
+ bits = (0...@@b - 1).map { |i| (y >> i) & 1 } + [x & 1]
143
+ (0...@@b / 8).map { |i| int2byte((0...8).inject(0) { |sum, j| sum + (bits[i * 8 + j] << j) }) }.join
146
144
  end
147
145
 
148
146
  def bit(h, i)
@@ -151,70 +149,69 @@ module Nis::Util
151
149
 
152
150
  def publickey_unsafe(sk)
153
151
  h = H(sk)
154
- a = 2 ** ($b-2) + (3...$b-2).inject(0) {|sum, i| sum + 2 ** i * bit(h, i) }
152
+ a = 2**(@@b - 2) + (3...@@b - 2).inject(0) { |sum, i| sum + 2**i * bit(h, i) }
155
153
  _A = scalarmult_B(a)
156
- return encodepoint(_A)
154
+ codepoint(_A)
157
155
  end
158
156
 
159
157
  def publickey_hash_unsafe(sk)
160
158
  h = HH(sk)
161
- a = 2 ** ($b-2) + (3...$b-2).inject(0) {|sum, i| sum + 2 ** i * bit(h, i) }
159
+ a = 2**(@@b - 2) + (3...@@b - 2).inject(0) { |sum, i| sum + 2**i * bit(h, i) }
162
160
  _A = scalarmult_B(a)
163
- return encodepoint(_A)
161
+ encodepoint(_A)
164
162
  end
165
163
 
166
164
  def Hint(m)
167
165
  h = H(m)
168
- (0...2*$b).inject(0) {|sum, i| sum + 2 ** i * bit(h, i) }
166
+ (0...2 * @@b).inject(0) { |sum, i| sum + 2**i * bit(h, i) }
169
167
  end
170
168
 
171
169
  def Hint_hash(m)
172
170
  h = HH(m)
173
- (0...2*$b).inject(0) {|sum, i| sum + 2 ** i * bit(h, i) }
171
+ (0...2 * @@b).inject(0) { |sum, i| sum + 2**i * bit(h, i) }
174
172
  end
175
173
 
176
174
  def signature_unsafe(m, sk, pk)
177
175
  h = H(sk)
178
- a = 2 ** ($b-2) + (3...$b-2).inject(0) {|sum, i| sum + 2 ** i * bit(h, i) }
176
+ a = 2**(@@b - 2) + (3...@@b - 2).inject(0) { |sum, i| sum + 2**i * bit(h, i) }
179
177
  r = Hint(
180
- intlist2bytes(($b/8...$b/4).map {|j| indexbytes(h, j) }) + m
178
+ intlist2bytes((@@b / 8...@@b / 4).map { |j| indexbytes(h, j) }) + m
181
179
  )
182
180
  _R = scalarmult_B(r)
183
- _S = (r + Hint(encodepoint(_R) + pk + m) * a) % $l
181
+ _S = (r + Hint(encodepoint(_R) + pk + m) * a) % @@l
184
182
  encodepoint(_R) + encodeint(_S)
185
183
  end
186
184
 
187
185
  # Not safe to use with secret keys or secret data.
188
- #
189
- # See module docstring. This function should be used for testing only.
186
+ # This function should be used for testing only.
190
187
  def signature_hash_unsafe(m, sk, pk)
191
188
  h = HH(sk)
192
- a = 2 ** ($b-2) + (3...$b-2).inject(0) {|sum, i| sum + 2 ** i * bit(h, i) }
189
+ a = 2**(@@b - 2) + (3...@@b - 2).inject(0) { |sum, i| sum + 2**i * bit(h, i) }
193
190
  r = Hint_hash(
194
- intlist2bytes(($b/8...$b/4).map {|j| indexbytes(h, j) }) + m
191
+ intlist2bytes((@@b / 8...@@b / 4).map { |j| indexbytes(h, j) }) + m
195
192
  )
196
193
  _R = scalarmult_B(r)
197
- _S = (r + Hint_hash(encodepoint(_R) + pk + m) * a) % $l
194
+ _S = (r + Hint_hash(encodepoint(_R) + pk + m) * a) % @@l
198
195
  encodepoint(_R) + encodeint(_S)
199
196
  end
200
197
 
201
198
  def isoncurve(_P)
202
199
  x, y, z, t = _P
203
- (z % $q != 0 and
204
- x * y % $q == z * t % $q and
205
- (y * y - x * x - z * z - $d * t * t) % $q == 0)
200
+ (z % @@q != (0) &&
201
+ x * y % @@q == (z * t % @@q) &&
202
+ (y * y - x * x - z * z - @@d * t * t) % @@q == (0))
206
203
  end
207
204
 
208
205
  def decodeint(s)
209
- (0...$b).inject(0) {|sum, i| sum + 2 ** i * bit(s, i) }
206
+ (0...@@b).inject(0) { |sum, i| sum + 2**i * bit(s, i) }
210
207
  end
211
208
 
212
209
  def decodepoint(s)
213
- y = (0...$b-1).inject(0) {|sum, i| 2 ** i * bit(s, i) }
210
+ y = (0...@@b - 1).inject(0) { |sum, i| 2**i * bit(s, i) }
214
211
  x = xrecover(y)
215
- x = $q - x if x & 1 != bit(s, $b - 1)
216
- _P = [x, y, 1, (x * y) % $q]
217
- raise "decoding point that is not on curve" unless isoncurve(_P)
212
+ x = @@q - x if x & 1 != bit(s, @@b - 1)
213
+ _P = [x, y, 1, (x * y) % @@q]
214
+ raise 'decoding point that is not on curve' unless isoncurve(_P)
218
215
  _P
219
216
  end
220
217
 
@@ -222,42 +219,39 @@ module Nis::Util
222
219
  end
223
220
 
224
221
  # Not safe to use when any argument is secret.
225
- #
226
- # See module docstring. This function should be used only for
222
+ # This function should be used only for
227
223
  # verifying public signatures of public messages.
228
224
  def checkvalid(s, m, pk)
229
- raise "signature length is wrong" if s.size != $b / 4
230
- raise "public-key length is wrong" if pk.size != $b / 8
225
+ raise 'signature length is wrong' if s.size != @@b / 4
226
+ raise 'public-key length is wrong' if pk.size != @@b / 8
231
227
 
232
- # _R = decodepoint(s[:b // 8])
233
- _R = decodepoint(s[0...$b/8])
228
+ _R = decodepoint(s[0...@@b / 8])
234
229
  _A = decodepoint(pk)
235
- _S = decodeint(s[$b/8...$b/4])
230
+ _S = decodeint(s[@@b / 8...@@b / 4])
236
231
  h = Hint(encodepoint(_R) + pk + m)
237
232
 
238
233
  x1, y1, z1, _t1 = _P = scalarmult_B(_S)
239
234
  x2, y2, z2, _t2 = _Q = edwards_add(_R, scalarmult(_A, h))
240
235
 
241
236
  if (!isoncurve(_P) || !isoncurve(_Q) || (x1 * z2 - x2 * z1) % q != 0 || (y1 * z2 - y2 * z1) % q != 0)
242
- raise SignatureMismatch("signature does not pass verification")
237
+ raise SignatureMismatch('signature does not pass verification')
243
238
  end
244
239
  end
245
240
  end
246
241
 
247
- $b = 256
248
- $q = 2 ** 255 - 19
249
- $l = 2 ** 252 + 27742317777372353535851937790883648493
242
+ @@b = 256
243
+ @@q = 2**255 - 19
244
+ @@l = 2**252 + 27742317777372353535851937790883648493
250
245
 
251
- $d = -121665 * self.inv(121666) % $q
252
- $I = 2.to_bn.mod_exp(($q - 1) / 4, $q)
246
+ @@d = -121665 * self.inv(121666) % @@q
247
+ @@I = 2.to_bn.mod_exp((@@q - 1) / 4, @@q)
253
248
 
254
- $By = 4 * self.inv(5)
255
- $Bx = self.xrecover($By)
256
- $B = [$Bx % $q, $By % $q, 1, ($Bx * $By) % $q]
257
- $ident = [0, 1, 1, 0]
249
+ @@By = 4 * self.inv(5)
250
+ @@Bx = self.xrecover(@@By)
251
+ @@B = [@@Bx % @@q, @@By % @@q, 1, (@@Bx * @@By) % @@q]
252
+ @@ident = [0, 1, 1, 0]
258
253
 
259
- # Bpow[i] == scalarmult(B, 2**i)
260
- $Bpow = []
254
+ @@Bpow = []
261
255
  self.make_Bpow
262
256
  end
263
257
  end
@@ -5,8 +5,8 @@ module Nis::Util
5
5
  # @return [Array]
6
6
  def self.serialize_transaction(entity)
7
7
  method = case entity[:type]
8
- when 257 then method(:serialize_transfer)
9
- when 4100 then method(:serialize_multisig_transfer)
8
+ when 257 then method(:serialize_transfer)
9
+ when 4100 then method(:serialize_multisig_transfer)
10
10
  else raise "Not implemented entity type: #{entity[:type]}"
11
11
  end
12
12
  method.call(entity)
@@ -54,7 +54,7 @@ module Nis::Util
54
54
 
55
55
  temp = hex2ua(entity[:message][:payload])
56
56
  if temp.size == 0
57
- a += [0,0,0,0]
57
+ a += [0, 0, 0, 0]
58
58
  else
59
59
  a += serialize_int(temp.size + 8)
60
60
  a += serialize_int(entity[:message][:type])
data/lib/nis/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Nis
2
- VERSION = '0.0.13'.freeze
2
+ VERSION = '0.0.14'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nis-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.13
4
+ version: 0.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yoshiyuki Ieyama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-26 00:00:00.000000000 Z
11
+ date: 2017-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -213,6 +213,7 @@ files:
213
213
  - examples/transactions/multisig_signature.rb
214
214
  - examples/transactions/provision_namespace.rb
215
215
  - examples/transactions/transfer.rb
216
+ - examples/transactions/transfer_mosaic.rb
216
217
  - examples/transactions/transfer_remote.rb
217
218
  - lib/nis.rb
218
219
  - lib/nis/client.rb
@@ -295,6 +296,7 @@ files:
295
296
  - lib/nis/struct/key_pair_view_model.rb
296
297
  - lib/nis/struct/message.rb
297
298
  - lib/nis/struct/mosaic.rb
299
+ - lib/nis/struct/mosaic_attachment.rb
298
300
  - lib/nis/struct/mosaic_definition.rb
299
301
  - lib/nis/struct/mosaic_definition_meta_data.rb
300
302
  - lib/nis/struct/mosaic_definition_meta_data_pair.rb
@@ -340,6 +342,7 @@ files:
340
342
  - lib/nis/util.rb
341
343
  - lib/nis/util/assignable.rb
342
344
  - lib/nis/util/convert.rb
345
+ - lib/nis/util/deserializer.rb
343
346
  - lib/nis/util/ed25519.rb
344
347
  - lib/nis/util/serializer.rb
345
348
  - lib/nis/version.rb