nis-ruby 0.0.13 → 0.0.14

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