appchain.rb 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -3
- data/Gemfile.lock +2 -2
- data/README.md +15 -2
- data/lib/appchain/contract.rb +2 -2
- data/lib/appchain/protos/blockchain_pb.rb +7 -5
- data/lib/appchain/rpc.rb +8 -2
- data/lib/appchain/transaction.rb +16 -6
- data/lib/appchain/transaction_signer.rb +69 -11
- data/lib/appchain/utils.rb +13 -1
- data/lib/appchain/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd176c97f662397947072cd9b6b08cb967cbc1ea171b44e5e2c9d4b348cd5e4a
|
4
|
+
data.tar.gz: 354f3c9e6dbad28a6d7e8a4c9053b942d11c889615e60903145d03daa879e1bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57c287fc34a72b7b0fa5d51a859a11dcb37a69fa81455a659b75327ec42e0a0e5eebcddce7a90c9b256eaf7f29f3cf0fe9417d04013fccbb042296adb7c390df
|
7
|
+
data.tar.gz: 78cd56fc25a1ed429be686b1db3ae2b958b585e8aa3207b2ee40b95bf81b5fb4a679082c98dc4b8b0a4fa740450db7151a1d2f3d8a8363f892dbeba99416c2c3
|
data/.travis.yml
CHANGED
@@ -3,9 +3,9 @@ sudo: false
|
|
3
3
|
language: ruby
|
4
4
|
cache: bundler
|
5
5
|
rvm:
|
6
|
-
- 2.4.
|
7
|
-
- 2.5.
|
8
|
-
before_install: gem install bundler -v 1.16.
|
6
|
+
- 2.4.5
|
7
|
+
- 2.5.3
|
8
|
+
before_install: gem install bundler -v 1.16.6
|
9
9
|
install:
|
10
10
|
- cd secp256k1 && ./autogen.sh && ./configure --enable-module-recovery --enable-experimental --enable-module-ecdh && make && sudo make install && cd ..
|
11
11
|
- bundle install
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
appchain.rb (0.
|
4
|
+
appchain.rb (0.2.0)
|
5
5
|
activesupport (~> 5.2.1)
|
6
6
|
ciri-crypto (= 0.1.1)
|
7
7
|
faraday (~> 0.15.3)
|
@@ -33,7 +33,7 @@ GEM
|
|
33
33
|
multipart-post (>= 1.2, < 3)
|
34
34
|
ffi (1.9.25)
|
35
35
|
google-protobuf (3.6.1-universal-darwin)
|
36
|
-
i18n (1.1.
|
36
|
+
i18n (1.1.1)
|
37
37
|
concurrent-ruby (~> 1.0)
|
38
38
|
jaro_winkler (1.5.1)
|
39
39
|
method_source (0.9.0)
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# AppChain.rb
|
2
2
|
|
3
3
|
[![Build Status](https://travis-ci.org/cryptape/appchain.rb.svg?branch=master)](https://travis-ci.org/cryptape/appchain.rb)
|
4
|
+
[![Documentation](http://img.shields.io/badge/docs-rdoc.info-blue.svg)](https://www.rubydoc.info/github/cryptape/appchain.rb/master)
|
4
5
|
|
5
6
|
Nervos AppChain Ruby SDK
|
6
7
|
|
@@ -44,8 +45,8 @@ transaction = AppChain::Transaction.new(
|
|
44
45
|
valid_until_block: 1882078,
|
45
46
|
data: "",
|
46
47
|
value: "0x3e8",
|
47
|
-
chain_id: 1,
|
48
|
-
version:
|
48
|
+
chain_id: "1",
|
49
|
+
version: 1
|
49
50
|
)
|
50
51
|
|
51
52
|
# sign transaction with your private key
|
@@ -74,6 +75,18 @@ response = contract.call_func(method: :symbol)
|
|
74
75
|
response = contract.send_func(tx: tx, private_key: private_key, method: :transfer, params: [address, tokens])
|
75
76
|
```
|
76
77
|
|
78
|
+
## CHANGELOG
|
79
|
+
|
80
|
+
### v0.1
|
81
|
+
|
82
|
+
* supports CITA 0.19
|
83
|
+
|
84
|
+
### 0.2
|
85
|
+
|
86
|
+
* supports CITA 0.20 and 0.19
|
87
|
+
* set default transaction version to 1
|
88
|
+
* update TransactionSinger.decode output type to hash with symbol keys
|
89
|
+
* parse TransactionSinger.decode hash value to hex string if it's bytes.
|
77
90
|
|
78
91
|
## Contributing
|
79
92
|
|
data/lib/appchain/contract.rb
CHANGED
@@ -40,7 +40,7 @@ module AppChain
|
|
40
40
|
# @param tx [Hash] see rpc `call` doc for more info
|
41
41
|
#
|
42
42
|
# @return [any]
|
43
|
-
def call_func(method:, params: [], tx: {})
|
43
|
+
def call_func(method:, params: [], tx: {}) # rubocop:disable Naming/UncommunicativeMethodParamName
|
44
44
|
data, output_types = function_data_with_ot(method, *params)
|
45
45
|
resp = @rpc.call_rpc(:call, params: [tx.merge(data: data, to: address), "latest"])
|
46
46
|
result = resp["result"]
|
@@ -60,7 +60,7 @@ module AppChain
|
|
60
60
|
# @param *params [Array] your params
|
61
61
|
#
|
62
62
|
# @return [nil | Hash] {hash: "", status: ""}, sendRawTransactionResult
|
63
|
-
def send_func(tx:, private_key:, method:, params: [])
|
63
|
+
def send_func(tx:, private_key:, method:, params: []) # rubocop:disable Naming/UncommunicativeMethodParamName
|
64
64
|
data, _output_types = function_data_with_ot(method, *params)
|
65
65
|
transaction = if tx.is_a?(Hash)
|
66
66
|
Transaction.from_hash(tx)
|
@@ -15,8 +15,8 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
15
15
|
optional :state_root, :bytes, 4
|
16
16
|
optional :transactions_root, :bytes, 5
|
17
17
|
optional :receipts_root, :bytes, 6
|
18
|
-
optional :
|
19
|
-
optional :
|
18
|
+
optional :quota_used, :uint64, 7
|
19
|
+
optional :quota_limit, :uint64, 8
|
20
20
|
optional :proof, :message, 9, "Proof"
|
21
21
|
optional :proposer, :bytes, 10
|
22
22
|
end
|
@@ -25,8 +25,8 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
25
25
|
optional :height, :uint64, 2
|
26
26
|
end
|
27
27
|
add_message "AccountGasLimit" do
|
28
|
-
optional :
|
29
|
-
map :
|
28
|
+
optional :common_quota_limit, :uint64, 1
|
29
|
+
map :specific_quota_limit, :string, :uint64, 2
|
30
30
|
end
|
31
31
|
add_message "RichStatus" do
|
32
32
|
optional :hash, :bytes, 1
|
@@ -34,6 +34,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
34
34
|
repeated :nodes, :bytes, 3
|
35
35
|
optional :interval, :uint64, 4
|
36
36
|
optional :version, :uint32, 5
|
37
|
+
repeated :validators, :bytes, 6
|
37
38
|
end
|
38
39
|
add_message "Transaction" do
|
39
40
|
optional :to, :string, 1
|
@@ -44,6 +45,8 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
44
45
|
optional :value, :bytes, 6
|
45
46
|
optional :chain_id, :uint32, 7
|
46
47
|
optional :version, :uint32, 8
|
48
|
+
optional :to_v1, :bytes, 9
|
49
|
+
optional :chain_id_v1, :bytes, 10
|
47
50
|
end
|
48
51
|
add_message "UnverifiedTransaction" do
|
49
52
|
optional :transaction, :message, 1, "Transaction"
|
@@ -107,4 +110,3 @@ module AppChain::Protos
|
|
107
110
|
ProofType = Google::Protobuf::DescriptorPool.generated_pool.lookup("ProofType").enummodule
|
108
111
|
Crypto = Google::Protobuf::DescriptorPool.generated_pool.lookup("Crypto").enummodule
|
109
112
|
end
|
110
|
-
|
data/lib/appchain/rpc.rb
CHANGED
@@ -70,8 +70,14 @@ module AppChain
|
|
70
70
|
# @return [Hash]
|
71
71
|
def transfer(to:, private_key:, value:, quota: 30_000)
|
72
72
|
valid_until_block = block_number["result"].hex + 88
|
73
|
-
|
74
|
-
|
73
|
+
meta_data = get_meta_data("latest")["result"]
|
74
|
+
version = meta_data["version"]
|
75
|
+
chain_id = if version.zero?
|
76
|
+
meta_data["chainId"]
|
77
|
+
elsif version == 1
|
78
|
+
meta_data["chainIdV1"]
|
79
|
+
end
|
80
|
+
transaction = Transaction.new(nonce: Utils.nonce, valid_until_block: valid_until_block, chain_id: chain_id, to: to, value: value, quota: quota, version: version)
|
75
81
|
send_transaction(transaction, private_key)
|
76
82
|
end
|
77
83
|
end
|
data/lib/appchain/transaction.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require "active_support/core_ext/string"
|
2
3
|
|
3
4
|
module AppChain
|
4
5
|
class Transaction
|
6
|
+
class VersionError < StandardError
|
7
|
+
end
|
8
|
+
|
5
9
|
attr_accessor :to, :nonce, :quota, :valid_until_block, :data, :value, :chain_id, :version
|
6
10
|
|
7
|
-
# @param nonce [String]
|
11
|
+
# @param nonce [String] default is SecureRandom.hex; if you provide with nil or empty string, it will be assigned a random string.
|
8
12
|
# @param valid_until_block [Integer]
|
9
|
-
# @param chain_id [Integer]
|
13
|
+
# @param chain_id [Integer | String] hex string if version == 1
|
10
14
|
# @param version [Integer]
|
11
15
|
# @param to [String]
|
12
16
|
# @param data [String]
|
@@ -14,13 +18,19 @@ module AppChain
|
|
14
18
|
# @param quota [Integer]
|
15
19
|
#
|
16
20
|
# @return [void]
|
17
|
-
def initialize(
|
21
|
+
def initialize(valid_until_block:, chain_id:, nonce: nil, version: 1, to: nil, data: nil, value: "0", quota: 1_000_000) # rubocop:disable Metrics/ParameterLists
|
22
|
+
raise VersionError, "transaction version error, expected 0 or 1, got #{version}" unless [0, 1].include?(version)
|
23
|
+
|
18
24
|
@to = to
|
19
|
-
@nonce = nonce
|
25
|
+
@nonce = nonce.blank? ? SecureRandom.hex : nonce
|
20
26
|
@quota = quota
|
21
27
|
@valid_until_block = valid_until_block
|
22
28
|
@data = data
|
23
|
-
@chain_id = chain_id
|
29
|
+
@chain_id = if chain_id.is_a?(String)
|
30
|
+
chain_id.delete("-")
|
31
|
+
else
|
32
|
+
chain_id
|
33
|
+
end
|
24
34
|
@version = version
|
25
35
|
@value = if value.is_a?(Integer)
|
26
36
|
Utils.to_hex(value)
|
@@ -38,7 +48,7 @@ module AppChain
|
|
38
48
|
chain_id: h[:chain_id],
|
39
49
|
to: h[:to],
|
40
50
|
data: h[:data],
|
41
|
-
version: h[:version] ||
|
51
|
+
version: h[:version] || 1,
|
42
52
|
value: h[:value] || "0",
|
43
53
|
quota: h[:quota] || 1_000_000
|
44
54
|
)
|
@@ -13,16 +13,23 @@ module AppChain
|
|
13
13
|
def encode(transaction, private_key)
|
14
14
|
tx = AppChain::Protos::Transaction.new
|
15
15
|
|
16
|
-
tx.nonce = transaction.nonce
|
17
16
|
to = AppChain::Utils.remove_hex_prefix(transaction.to)&.downcase
|
18
|
-
|
17
|
+
|
18
|
+
tx.nonce = transaction.nonce
|
19
19
|
tx.quota = transaction.quota
|
20
20
|
tx.data = AppChain::Utils.to_bytes(transaction.data)
|
21
|
+
tx.value = hex_to_bytes(transaction.value)
|
21
22
|
tx.version = transaction.version
|
22
|
-
tx.value = process_value(transaction.value)
|
23
|
-
tx.chain_id = transaction.chain_id
|
24
23
|
tx.valid_until_block = transaction.valid_until_block
|
25
24
|
|
25
|
+
if transaction.version.zero?
|
26
|
+
tx.to = to unless to.nil?
|
27
|
+
tx.chain_id = transaction.chain_id
|
28
|
+
elsif transaction.version == 1
|
29
|
+
tx.to_v1 = Utils.to_bytes(to) unless to.nil?
|
30
|
+
tx.chain_id_v1 = hex_to_bytes(transaction.chain_id)
|
31
|
+
end
|
32
|
+
|
26
33
|
encoded_tx = Protos::Transaction.encode(tx)
|
27
34
|
|
28
35
|
private_key_bytes = AppChain::Utils.to_bytes(private_key)
|
@@ -41,7 +48,7 @@ module AppChain
|
|
41
48
|
# unsign transaction
|
42
49
|
#
|
43
50
|
# @param tx_content [String] hex string
|
44
|
-
def
|
51
|
+
def simple_decode(tx_content)
|
45
52
|
content_bytes = AppChain::Utils.to_bytes(tx_content)
|
46
53
|
unverified_transaction = Protos::UnverifiedTransaction.decode(content_bytes)
|
47
54
|
|
@@ -57,22 +64,73 @@ module AppChain
|
|
57
64
|
from_address_hex = Utils.from_bytes(from_address)
|
58
65
|
|
59
66
|
sender = {
|
60
|
-
|
61
|
-
|
67
|
+
address: from_address_hex,
|
68
|
+
public_key: pubkey_hex
|
62
69
|
}
|
63
70
|
|
64
71
|
{
|
65
|
-
|
66
|
-
|
72
|
+
unverified_transaction: unverified_transaction.to_h,
|
73
|
+
sender: sender
|
67
74
|
}
|
68
75
|
end
|
69
76
|
|
77
|
+
# decode and support forks
|
78
|
+
#
|
79
|
+
# @param tx_content [String] hex string
|
80
|
+
# @return [Hash]
|
81
|
+
def original_decode(tx_content)
|
82
|
+
data = simple_decode(tx_content)
|
83
|
+
utx = data[:unverified_transaction]
|
84
|
+
tx = utx[:transaction]
|
85
|
+
version = tx[:version]
|
86
|
+
|
87
|
+
if version == 0 # rubocop:disable Style/NumericPredicate
|
88
|
+
tx.delete(:to_v1)
|
89
|
+
tx.delete(:chain_id_v1)
|
90
|
+
elsif version == 1
|
91
|
+
tx[:to] = tx.delete(:to_v1)
|
92
|
+
tx[:chain_id] = tx.delete(:chain_id_v1)
|
93
|
+
else
|
94
|
+
raise Transaction::VersionError, "transaction version error, expected 0 or 1, got #{version}"
|
95
|
+
end
|
96
|
+
|
97
|
+
data
|
98
|
+
end
|
99
|
+
|
100
|
+
# decode and parse bytes to hex string
|
101
|
+
#
|
102
|
+
# @param tx_content [String] hex string
|
103
|
+
# @return [Hash]
|
104
|
+
def decode(tx_content)
|
105
|
+
data = original_decode(tx_content)
|
106
|
+
utx = data[:unverified_transaction]
|
107
|
+
tx = utx[:transaction]
|
108
|
+
version = tx[:version]
|
109
|
+
|
110
|
+
tx[:value] = Utils.from_bytes(tx[:value])
|
111
|
+
tx[:data] = Utils.from_bytes(tx[:data])
|
112
|
+
tx[:nonce] = Utils.add_prefix_for_not_blank(tx[:nonce])
|
113
|
+
utx[:signature] = Utils.from_bytes(utx[:signature])
|
114
|
+
|
115
|
+
if version == 0 # rubocop:disable Style/NumericPredicate
|
116
|
+
tx.delete(:to_v1)
|
117
|
+
tx.delete(:chain_id_v1)
|
118
|
+
tx[:to] = Utils.add_prefix_for_not_blank(tx[:to])
|
119
|
+
elsif version == 1
|
120
|
+
tx[:to] = Utils.from_bytes(tx[:to])
|
121
|
+
tx[:chain_id] = Utils.from_bytes(tx[:chain_id])
|
122
|
+
end
|
123
|
+
|
124
|
+
data
|
125
|
+
end
|
126
|
+
|
70
127
|
private
|
71
128
|
|
72
129
|
# @param value [String] hex string with or without `0x` prefix
|
130
|
+
# @param length [Integer] length, default is 64
|
73
131
|
# @return [String] byte code string
|
74
|
-
def
|
75
|
-
AppChain::Utils.to_bytes(AppChain::Utils.remove_hex_prefix(value).rjust(
|
132
|
+
def hex_to_bytes(value, length = 64)
|
133
|
+
AppChain::Utils.to_bytes(AppChain::Utils.remove_hex_prefix(value).rjust(length, "0"))
|
76
134
|
end
|
77
135
|
end
|
78
136
|
end
|
data/lib/appchain/utils.rb
CHANGED
@@ -15,6 +15,15 @@ module AppChain
|
|
15
15
|
HEX_PREFIX + hex
|
16
16
|
end
|
17
17
|
|
18
|
+
# add `0x` prefix to not blank hex string
|
19
|
+
#
|
20
|
+
# @param hex [String]
|
21
|
+
def add_prefix_for_not_blank(hex)
|
22
|
+
return add_hex_prefix(hex) unless hex.blank?
|
23
|
+
|
24
|
+
hex
|
25
|
+
end
|
26
|
+
|
18
27
|
# remove `0x` prefix from hex string
|
19
28
|
#
|
20
29
|
# @param hex [String]
|
@@ -55,7 +64,10 @@ module AppChain
|
|
55
64
|
# @param bytes_str [String] byte code string
|
56
65
|
# @return [String] normal string
|
57
66
|
def from_bytes(bytes_str)
|
58
|
-
|
67
|
+
hex = bytes_str.unpack1("H*")
|
68
|
+
return AppChain::Utils.add_hex_prefix(hex) unless hex.blank?
|
69
|
+
|
70
|
+
hex
|
59
71
|
end
|
60
72
|
|
61
73
|
# keccak 256 hash
|
data/lib/appchain/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: appchain.rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- classicalliu
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-11-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -219,7 +219,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
219
219
|
version: '0'
|
220
220
|
requirements: []
|
221
221
|
rubyforge_project:
|
222
|
-
rubygems_version: 2.7.
|
222
|
+
rubygems_version: 2.7.7
|
223
223
|
signing_key:
|
224
224
|
specification_version: 4
|
225
225
|
summary: Ruby Nervos AppChain SDK
|