neb 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/README.md +9 -1
- data/example/account_example.rb +25 -0
- data/example/api_example.rb +20 -0
- data/example/transaction_example.rb +65 -0
- data/lib/neb.rb +1 -0
- data/lib/neb/client/admin.rb +9 -10
- data/lib/neb/configuration.rb +2 -1
- data/lib/neb/secp256k1.rb +12 -33
- data/lib/neb/transaction.rb +11 -2
- data/lib/neb/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f216057e4c5de7893b728db7501ba49c2a5c3596617c549c343b5e9d5b2276b
|
4
|
+
data.tar.gz: 7b2a8448465159794dd6e5f80849e80d3cd8daf2937ab286fa89ee2ea30f748d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25f05d7ef55a37b153021ef253f310d6ae4ddbe6e38b7bb60bd6bfee9e9764962ce4d418cd212c13ff896cf367270b44ff9950e1f813a21fb4438078ba44b529
|
7
|
+
data.tar.gz: c7804b0ae81e804b924fddebc28cc845db063f77ccbf2dede49b861e3e999ae18716e0ec6aed6df096d612655df3a3daeb45aa7f2c4627d5288d1d0a957d8808
|
data/.gitignore
CHANGED
@@ -13,7 +13,6 @@
|
|
13
13
|
/test/tmp/
|
14
14
|
/test/version_tmp/
|
15
15
|
# /tmp/
|
16
|
-
/log
|
17
16
|
|
18
17
|
# Used by dotenv library to load environment variables.
|
19
18
|
# .env
|
@@ -56,6 +55,7 @@ build-iPhoneSimulator/
|
|
56
55
|
.tags*
|
57
56
|
|
58
57
|
tmp/*.json
|
58
|
+
log/*.log
|
59
59
|
# End of https://www.gitignore.io/api/ruby
|
60
60
|
|
61
61
|
.ruby-version
|
data/README.md
CHANGED
@@ -11,7 +11,7 @@ https://github.com/cryptape/ruby-bitcoin-secp256k1
|
|
11
11
|
Add this line to your application's Gemfile:
|
12
12
|
|
13
13
|
```ruby
|
14
|
-
gem 'neb', '0.1.
|
14
|
+
gem 'neb', '0.1.3'
|
15
15
|
```
|
16
16
|
|
17
17
|
And then execute:
|
@@ -115,6 +115,14 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
115
115
|
|
116
116
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
117
117
|
|
118
|
+
## Test
|
119
|
+
|
120
|
+
1. Install [ruby-bitcoin-secp256k1](https://github.com/cryptape/ruby-bitcoin-secp256k1)
|
121
|
+
2. Start [go-nebulas](https://github.com/nebulasio/go-nebulas) at localhost, `./neb -c conf/default/config.conf`, `./neb -c conf/example/miner.conf`
|
122
|
+
3. Install dependency, `cd ~/neb.rb` and `bundle install`
|
123
|
+
4. Run test, `rake test` or `rake test test/account_test.rb`
|
124
|
+
5. Also you can use [guard](https://github.com/guard/guard) to autotest
|
125
|
+
|
118
126
|
## Contributing
|
119
127
|
|
120
128
|
Bug reports and pull requests are welcome on GitHub at https://github.com/NaixSpirit/neb.rb. 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.
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'neb'
|
2
|
+
|
3
|
+
# Create a new account with random private_key
|
4
|
+
account = Neb::Account.create
|
5
|
+
account = Neb::Account.create(password: "passphrase")
|
6
|
+
|
7
|
+
puts "new account info: \n"
|
8
|
+
puts account.private_key # => "b5e53a1582a48d243ebd478a7722d1bfea4805ff7c1da4cc7084043e8263c5a8"
|
9
|
+
puts account.public_key # => "35a80ac8a27e2bf072ae84b2cb019e3af0c06547ad939fab1c6d12f713d26ae178d1fd6677aef3e6e94bc7cc1a39f4ca80fc2409a5ef59f97ee55dbd6efc7714"
|
10
|
+
puts account.address # => "n1NfnKqgXBixjiDkJZDSVwqf7ps5roGwFyJ"
|
11
|
+
puts account.password = "123456" # or account.set_password("123456")
|
12
|
+
puts account.to_key # => {:version=>4, :id=>"becde267-902e-4f23-ac01-53a4ba6edac7", :address=>"n1VYLxkZoehWEWPHxi351HgZ2R8Hfn2DGpa" ....}
|
13
|
+
|
14
|
+
account.to_key_file(file_path: "../tmp/example_keyjson.json")
|
15
|
+
|
16
|
+
# Create a new account from exist private_key
|
17
|
+
account = Neb::Account.new(private_key: account.private_key)
|
18
|
+
account = Neb::Account.new(private_key: account.private_key, password: "passphrase")
|
19
|
+
|
20
|
+
# Restore account from key
|
21
|
+
account = Neb::Account.from_key(key: account.to_key, password: "passphrase")
|
22
|
+
|
23
|
+
# Restore account from a key file
|
24
|
+
account = Neb::Account.from_key_file(key_file: "../tmp/example_keyjson.json", password: "passphrase")
|
25
|
+
puts "imported account: #{account.address}"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'neb'
|
2
|
+
|
3
|
+
#Neb.configure(host: 'https://testnet.nebulas.io')
|
4
|
+
Neb.configure(host: 'http://127.0.0.1:8685') #local node
|
5
|
+
client = Neb::Client.new
|
6
|
+
|
7
|
+
resp = client.api.get_neb_state
|
8
|
+
puts resp.code # => 200
|
9
|
+
puts resp.success? # => true
|
10
|
+
puts resp.result # => {:chain_id=>100, :tail=>"xxxx", :lib=>"xxxx", :height=>"1085", :protocol_version=>"/neb/1.0.0", :synchronized=>false, :version=>"1.0.1"}
|
11
|
+
|
12
|
+
client.api.subscribe(
|
13
|
+
topics: ["chain.pendingTransaction"],
|
14
|
+
on_download_progress: ->(c) { puts c }
|
15
|
+
)
|
16
|
+
|
17
|
+
resp = client.admin.accounts
|
18
|
+
resp.code # => 200
|
19
|
+
resp.success? # => true
|
20
|
+
resp.result # => {:addresses=>["n1FF1nz6tarkDVwWQkMnnwFPuPKUaQTdptE", "n1FNj5aZhKFeFJ8cQ26Lvsr84NDvNSVRu67"]}
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'neb'
|
2
|
+
|
3
|
+
Neb.configure(host: 'http://127.0.0.1:8685') # local node
|
4
|
+
|
5
|
+
client = Neb::Client.new
|
6
|
+
account = Neb::Account.create
|
7
|
+
|
8
|
+
tx = Neb::Transaction.new(
|
9
|
+
chain_id: 100,
|
10
|
+
from_account: account,
|
11
|
+
to_address: 'n1SAeQRVn33bamxN4ehWUT7JGdxipwn8b17',
|
12
|
+
value: 10,
|
13
|
+
nonce: 1,
|
14
|
+
gas_price: 1000000,
|
15
|
+
gas_limit: 2000000
|
16
|
+
)
|
17
|
+
|
18
|
+
tx.sign_hash
|
19
|
+
|
20
|
+
resp = client.api.send_raw_transaction(data: tx.to_proto_str)
|
21
|
+
puts resp.code # => 200
|
22
|
+
if resp.success?
|
23
|
+
puts resp.result # => {:txhash=>"8524384dce7e122bfd007e0ba465e597d821e22db6d563b87dfc55d703fb008c", :contract_address=>""}
|
24
|
+
else
|
25
|
+
puts resp.error
|
26
|
+
end
|
27
|
+
|
28
|
+
resp = client.api.get_transaction_receipt(hash: "8524384dce7e122bfd007e0ba465e597d821e22db6d563b87dfc55d703fb008c")
|
29
|
+
if resp.success?
|
30
|
+
puts resp.result[:status] # => 0,1,2
|
31
|
+
else
|
32
|
+
puts resp.error
|
33
|
+
end
|
34
|
+
|
35
|
+
client.api.get_account_state(address: 'n1SAeQRVn33bamxN4ehWUT7JGdxipwn8b17').result # => {:balance=>"10", :nonce=>"0", :type=>87}
|
36
|
+
|
37
|
+
#
|
38
|
+
# call type transaction example, using a contract on the testnet
|
39
|
+
#
|
40
|
+
Neb.configure(host: 'https://testnet.nebulas.io')
|
41
|
+
|
42
|
+
client = Neb::Client.new
|
43
|
+
key_json = '{"version":4,"id":"72dd1261-96dc-4463-ad97-dd212795e1a0","address":"n1H2Yb5Q6ZfKvs61htVSV4b1U2gr2GA9vo6","crypto":{"ciphertext":"40352b32f39392b38022c2a778cf8424ab823b2288c85a25f6097c1455837b74","cipherparams":{"iv":"0f0fb4b21e0727c16aabf339540b80f8"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"dklen":32,"salt":"405dfabee17917c4f4f7b818e387200fc83452d57b00d9ea329a5687d07aca01","n":4096,"r":8,"p":1},"mac":"59d9d7a36726ce3da1bf2d20d7469800376b0975e7110afbd578cf3401666557","machash":"sha3256"}}'
|
44
|
+
account = Neb::Account.from_key(key: key_json, password:'passphrase')
|
45
|
+
|
46
|
+
tx = Neb::Transaction.new(
|
47
|
+
chain_id: 1001,
|
48
|
+
from_account: account,
|
49
|
+
to_address: 'n1oXdmwuo5jJRExnZR5rbceMEyzRsPeALgm',
|
50
|
+
value: 10,
|
51
|
+
nonce: 41,
|
52
|
+
gas_price: 1000000,
|
53
|
+
gas_limit: 2000000,
|
54
|
+
contract: { function: 'get', args: '["nebulas"]' }
|
55
|
+
)
|
56
|
+
|
57
|
+
tx.sign_hash
|
58
|
+
|
59
|
+
resp = client.api.send_raw_transaction(data: tx.to_proto_str)
|
60
|
+
puts resp.code # => 200
|
61
|
+
if resp.success?
|
62
|
+
puts resp.result # => {:txhash=>"8524384dce7e122bfd007e0ba465e597d821e22db6d563b87dfc55d703fb008c", :contract_address=>""}
|
63
|
+
else
|
64
|
+
puts resp.error
|
65
|
+
end
|
data/lib/neb.rb
CHANGED
data/lib/neb/client/admin.rb
CHANGED
@@ -44,10 +44,10 @@ module Neb
|
|
44
44
|
params = {
|
45
45
|
from: from,
|
46
46
|
to: to,
|
47
|
-
value: value.to_i,
|
48
|
-
nonce: nonce.to_i,
|
49
|
-
gas_price: gas_price.to_i,
|
50
|
-
gas_limit: gas_limit.to_i
|
47
|
+
value: value.to_i.to_s,
|
48
|
+
nonce: nonce.to_i.to_s,
|
49
|
+
gas_price: gas_price.to_i.to_s,
|
50
|
+
gas_limit: gas_limit.to_i.to_s
|
51
51
|
}
|
52
52
|
send_request(:post, "/transaction", params)
|
53
53
|
end
|
@@ -57,16 +57,15 @@ module Neb
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def sign_transaction_with_passphrase(from:, to:, value:, nonce:, gas_price: 1_000_000, gas_limit: 20_000,
|
60
|
-
|
60
|
+
contract: nil, binary: nil, passphrase:)
|
61
61
|
params = {
|
62
62
|
transaction: {
|
63
63
|
from: from,
|
64
64
|
to: to,
|
65
|
-
value: value.to_i,
|
66
|
-
nonce: nonce.to_i,
|
67
|
-
gas_price: gas_price.to_i,
|
68
|
-
gas_limit: gas_limit.to_i,
|
69
|
-
type: type,
|
65
|
+
value: value.to_i.to_s,
|
66
|
+
nonce: nonce.to_i.to_s,
|
67
|
+
gas_price: gas_price.to_i.to_s,
|
68
|
+
gas_limit: gas_limit.to_i.to_s,
|
70
69
|
contract: contract,
|
71
70
|
binary: binary
|
72
71
|
},
|
data/lib/neb/configuration.rb
CHANGED
data/lib/neb/secp256k1.rb
CHANGED
@@ -13,17 +13,25 @@ module Neb
|
|
13
13
|
Gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424
|
14
14
|
G = [Gx, Gy].freeze
|
15
15
|
|
16
|
-
SECP256K1 = 1
|
16
|
+
SECP256K1 = 1;
|
17
17
|
|
18
18
|
class InvalidPrivateKey < StandardError; end
|
19
19
|
|
20
|
-
class << self
|
20
|
+
class << self
|
21
21
|
|
22
22
|
def sign(msg, priv)
|
23
23
|
priv = PrivateKey.new(priv)
|
24
24
|
privkey = ::Secp256k1::PrivateKey.new(privkey: priv.encode(:bin), raw: true)
|
25
|
-
|
26
|
-
|
25
|
+
signature = privkey.ecdsa_recoverable_serialize(
|
26
|
+
privkey.ecdsa_sign_recoverable(msg, raw: true)
|
27
|
+
)
|
28
|
+
|
29
|
+
# v = signature[1]
|
30
|
+
# r = Utils.bin_to_hex(signature[0][0,32])
|
31
|
+
# s = Utils.bin_to_hex(signature[0][32,32])
|
32
|
+
# puts v, r, s
|
33
|
+
|
34
|
+
signature[0] << signature[1]
|
27
35
|
end
|
28
36
|
|
29
37
|
def priv_to_pub(priv)
|
@@ -32,35 +40,6 @@ module Neb
|
|
32
40
|
pubkey = privkey.pubkey
|
33
41
|
PublicKey.new(pubkey.serialize).encode(priv.format)
|
34
42
|
end
|
35
|
-
|
36
|
-
def recoverable_sign(msg, privkey)
|
37
|
-
pk = ::Secp256k1::PrivateKey.new(privkey: privkey, raw: true)
|
38
|
-
signature = pk.ecdsa_recoverable_serialize(pk.ecdsa_sign_recoverable(msg, raw: true))
|
39
|
-
|
40
|
-
v = signature[1]
|
41
|
-
r = Utils.big_endian_to_int signature[0][0,32]
|
42
|
-
s = Utils.big_endian_to_int signature[0][32,32]
|
43
|
-
|
44
|
-
[v,r,s]
|
45
|
-
end
|
46
|
-
|
47
|
-
def signature_verify(msg, vrs, pubkey)
|
48
|
-
pk = ::Secp256k1::PublicKey.new(pubkey: pubkey)
|
49
|
-
raw_sig = Utils.zpad_int(vrs[1]) + Utils.zpad_int(vrs[2])
|
50
|
-
|
51
|
-
sig = ::Secp256k1::C::ECDSASignature.new
|
52
|
-
sig[:data].to_ptr.write_bytes(raw_sig)
|
53
|
-
|
54
|
-
pk.ecdsa_verify(msg, sig)
|
55
|
-
end
|
56
|
-
|
57
|
-
def recover_pubkey(msg, vrs, compressed: false)
|
58
|
-
pk = ::Secp256k1::PublicKey.new(flags: ::Secp256k1::ALL_FLAGS)
|
59
|
-
sig = Utils.zpad_int(vrs[1]) + Utils.zpad_int(vrs[2])
|
60
|
-
recsig = pk.ecdsa_recoverable_deserialize(sig, vrs[0])
|
61
|
-
pk.public_key = pk.ecdsa_recover msg, recsig, raw: true
|
62
|
-
pk.serialize compressed: compressed
|
63
|
-
end
|
64
43
|
end
|
65
44
|
end
|
66
45
|
end
|
data/lib/neb/transaction.rb
CHANGED
@@ -30,10 +30,12 @@ module Neb
|
|
30
30
|
@to_address = Address.new(to_address)
|
31
31
|
@value = value
|
32
32
|
@nonce = nonce
|
33
|
-
@gas_price = gas_price
|
34
|
-
@gas_limit = gas_limit
|
33
|
+
@gas_price = gas_price >= 0 ? gas_price : GAS_PRICE
|
34
|
+
@gas_limit = gas_limit >= 0 ? gas_limit : GAS_LIMIT
|
35
35
|
@data = parse_contract(contract)
|
36
36
|
@timestamp = Time.now.to_i
|
37
|
+
|
38
|
+
validate_args!
|
37
39
|
end
|
38
40
|
|
39
41
|
def parse_contract(contract)
|
@@ -116,5 +118,12 @@ module Neb
|
|
116
118
|
@sign = Secp256k1.sign(@hash, from_account.private_key)
|
117
119
|
end
|
118
120
|
|
121
|
+
private
|
122
|
+
|
123
|
+
def validate_args!
|
124
|
+
if !CHAIN_ID_LIST.keys.include?(chain_id) || value < 0 || nonce < 0
|
125
|
+
raise InvalidTransaction
|
126
|
+
end
|
127
|
+
end
|
119
128
|
end
|
120
129
|
end
|
data/lib/neb/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: neb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Spirit
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-07-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -237,6 +237,9 @@ files:
|
|
237
237
|
- Rakefile
|
238
238
|
- bin/console
|
239
239
|
- bin/setup
|
240
|
+
- example/account_example.rb
|
241
|
+
- example/api_example.rb
|
242
|
+
- example/transaction_example.rb
|
240
243
|
- lib/neb.rb
|
241
244
|
- lib/neb/account.rb
|
242
245
|
- lib/neb/address.rb
|