sigma_rb 0.1.3 → 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/README.md +68 -6
- data/lib/sigma/address.rb +64 -2
- data/lib/sigma/block_header.rb +49 -1
- data/lib/sigma/box_selection.rb +29 -0
- data/lib/sigma/byte_array.rb +22 -0
- data/lib/sigma/constant.rb +43 -14
- data/lib/sigma/context_extension.rb +10 -0
- data/lib/sigma/contract.rb +21 -2
- data/lib/sigma/data_input.rb +24 -0
- data/lib/sigma/enums.rb +8 -0
- data/lib/sigma/ergo_box.rb +175 -2
- data/lib/sigma/ergo_box_candidate_builder.rb +45 -1
- data/lib/sigma/ergo_state_context.rb +8 -0
- data/lib/sigma/ergo_tree.rb +38 -2
- data/lib/sigma/input.rb +57 -1
- data/lib/sigma/merkle_proof.rb +7 -1
- data/lib/sigma/nipopow.rb +29 -0
- data/lib/sigma/pre_header.rb +7 -0
- data/lib/sigma/reduced_transaction.rb +25 -0
- data/lib/sigma/secret_key.rb +29 -1
- data/lib/sigma/structs.rb +10 -0
- data/lib/sigma/token.rb +61 -1
- data/lib/sigma/transaction.rb +105 -0
- data/lib/sigma/tx_builder.rb +32 -0
- data/lib/sigma/wallet.rb +39 -0
- data/lib/sigma.rb +1 -1
- data/sigma.gemspec +3 -2
- data/tests/sigma/ergo_tree_test.rb +3 -1
- data/tests/sigma/merkle_proof_test.rb +1 -1
- data/tests/sigma/nipopow_test.rb +1 -0
- data/tests/sigma/token_test.rb +6 -4
- data/tests/test_seeds.rb +1 -0
- metadata +16 -2
data/lib/sigma/contract.rb
CHANGED
@@ -3,6 +3,7 @@ require_relative './util.rb'
|
|
3
3
|
require 'ffi-compiler/loader'
|
4
4
|
|
5
5
|
module Sigma
|
6
|
+
# Defines the contract (script) that will be guarding box contents
|
6
7
|
class Contract
|
7
8
|
extend FFI::Library
|
8
9
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -16,10 +17,17 @@ module Sigma
|
|
16
17
|
|
17
18
|
attr_accessor :pointer
|
18
19
|
|
20
|
+
# Takes ownership of an existing Contract Pointer.
|
21
|
+
# @note A user of sigma_rb generally does not need to call this function
|
22
|
+
# @param pointer [FFI::MemoryPointer]
|
23
|
+
# @return [Contract]
|
19
24
|
def self.with_raw_pointer(contract_pointer)
|
20
25
|
init(contract_pointer)
|
21
26
|
end
|
22
27
|
|
28
|
+
# Create a new contract from an ErgoTree
|
29
|
+
# @param ergo_tree [ErgoTree]
|
30
|
+
# @return [Contract]
|
23
31
|
def self.from_ergo_tree(ergo_tree)
|
24
32
|
pointer = FFI::MemoryPointer.new(:pointer)
|
25
33
|
ergo_lib_contract_new(ergo_tree.pointer, pointer)
|
@@ -27,14 +35,20 @@ module Sigma
|
|
27
35
|
init(pointer)
|
28
36
|
end
|
29
37
|
|
30
|
-
|
38
|
+
# Compiles a contract from ErgoScript source code
|
39
|
+
# @param source [String]
|
40
|
+
# @return [Contract]
|
41
|
+
def self.compile_from_string(source)
|
31
42
|
pointer = FFI::MemoryPointer.new(:pointer)
|
32
|
-
error = ergo_lib_contract_compile(
|
43
|
+
error = ergo_lib_contract_compile(source, pointer)
|
33
44
|
Util.check_error!(error)
|
34
45
|
|
35
46
|
init(pointer)
|
36
47
|
end
|
37
48
|
|
49
|
+
# Create new contract that allow spending of the guarded box by a given recipient (Address)
|
50
|
+
# @param address [Address]
|
51
|
+
# @return [Contract]
|
38
52
|
def self.pay_to_address(address)
|
39
53
|
pointer = FFI::MemoryPointer.new(:pointer)
|
40
54
|
error = ergo_lib_contract_pay_to_address(address.pointer, pointer)
|
@@ -43,12 +57,17 @@ module Sigma
|
|
43
57
|
init(pointer)
|
44
58
|
end
|
45
59
|
|
60
|
+
# Get the ErgoTree of the contract
|
61
|
+
# @return [ErgoTree]
|
46
62
|
def get_ergo_tree
|
47
63
|
pointer = FFI::MemoryPointer.new(:pointer)
|
48
64
|
ergo_lib_contract_ergo_tree(self.pointer, pointer)
|
49
65
|
Sigma::ErgoTree.with_raw_pointer(pointer)
|
50
66
|
end
|
51
67
|
|
68
|
+
# Equality check for two Contracts
|
69
|
+
# @param contract_two [Contract]
|
70
|
+
# @return [bool]
|
52
71
|
def ==(contract_two)
|
53
72
|
ergo_lib_contract_eq(self.pointer, contract_two.pointer)
|
54
73
|
end
|
data/lib/sigma/data_input.rb
CHANGED
@@ -3,6 +3,7 @@ require_relative './util.rb'
|
|
3
3
|
require 'ffi-compiler/loader'
|
4
4
|
|
5
5
|
module Sigma
|
6
|
+
# Inputs, that are used to enrich script context, but won't be spent by the transaction
|
6
7
|
class DataInput
|
7
8
|
extend FFI::Library
|
8
9
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -12,16 +13,25 @@ module Sigma
|
|
12
13
|
attach_function :ergo_lib_data_input_delete, [:pointer], :void
|
13
14
|
attr_accessor :pointer
|
14
15
|
|
16
|
+
# Parse BoxId and create DataInput
|
17
|
+
# @param box_id [BoxId]
|
18
|
+
# @return [DataInput]
|
15
19
|
def self.with_box_id(box_id)
|
16
20
|
pointer = FFI::MemoryPointer.new(:pointer)
|
17
21
|
ergo_lib_data_input_new(box_id.pointer, pointer)
|
18
22
|
init(pointer)
|
19
23
|
end
|
20
24
|
|
25
|
+
# Takes ownership of an existing DataInput Pointer.
|
26
|
+
# @note A user of sigma_rb generally does not need to call this function
|
27
|
+
# @param pointer [FFI::MemoryPointer]
|
28
|
+
# @return [DataInput]
|
21
29
|
def self.with_raw_pointer(pointer)
|
22
30
|
init(pointer)
|
23
31
|
end
|
24
32
|
|
33
|
+
# Get BoxId
|
34
|
+
# @return [BoxId]
|
25
35
|
def get_box_id
|
26
36
|
pointer = FFI::MemoryPointer.new(:pointer)
|
27
37
|
ergo_lib_data_input_new(self.pointer, pointer)
|
@@ -43,6 +53,7 @@ module Sigma
|
|
43
53
|
|
44
54
|
end
|
45
55
|
|
56
|
+
# An ordered collection of DataInput
|
46
57
|
class DataInputs
|
47
58
|
extend FFI::Library
|
48
59
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -54,10 +65,16 @@ module Sigma
|
|
54
65
|
attach_function :ergo_lib_data_inputs_get, [:pointer, :uint8, :pointer], ReturnOption.by_value
|
55
66
|
attr_accessor :pointer
|
56
67
|
|
68
|
+
# Takes ownership of an existing DataInputs Pointer.
|
69
|
+
# @note A user of sigma_rb generally does not need to call this function
|
70
|
+
# @param pointer [FFI::MemoryPointer]
|
71
|
+
# @return [DataInputs]
|
57
72
|
def self.with_raw_pointer(unread_pointer)
|
58
73
|
init(unread_pointer)
|
59
74
|
end
|
60
75
|
|
76
|
+
# Create an empty collection
|
77
|
+
# @return [DataInputs]
|
61
78
|
def self.create
|
62
79
|
pointer = FFI::MemoryPointer.new(:pointer)
|
63
80
|
ergo_lib_data_inputs_new(pointer)
|
@@ -65,14 +82,21 @@ module Sigma
|
|
65
82
|
init(pointer)
|
66
83
|
end
|
67
84
|
|
85
|
+
# Get length of DataInputs
|
86
|
+
# @return [Integer]
|
68
87
|
def len
|
69
88
|
ergo_lib_data_inputs_len(self.pointer)
|
70
89
|
end
|
71
90
|
|
91
|
+
# Add a DataInput
|
92
|
+
# @param data_input [DataInput]
|
72
93
|
def add(data_input)
|
73
94
|
ergo_lib_data_inputs_add(data_input.pointer, self.pointer)
|
74
95
|
end
|
75
96
|
|
97
|
+
# Get item at specified index or return nil if no item exists
|
98
|
+
# @params index [Integer]
|
99
|
+
# @return [DataInput, nil]
|
76
100
|
def get(index)
|
77
101
|
pointer = FFI::MemoryPointer.new(:pointer)
|
78
102
|
res = ergo_lib_data_inputs_get(self.pointer, index, pointer)
|
data/lib/sigma/enums.rb
CHANGED
@@ -4,6 +4,8 @@ module Sigma
|
|
4
4
|
extend FFI::Library
|
5
5
|
typedef :pointer, :error_pointer
|
6
6
|
|
7
|
+
# Address type prefix
|
8
|
+
# @see https://github.com/ffi/ffi/wiki/Enums FFI Enum Documentation
|
7
9
|
ADDRESS_TYPE_PREFIX_ENUM = enum :address_type_prefix,
|
8
10
|
[
|
9
11
|
:p2pk, 1,
|
@@ -11,12 +13,16 @@ module Sigma
|
|
11
13
|
:pay2s
|
12
14
|
]
|
13
15
|
|
16
|
+
# Network prefix
|
17
|
+
# @see https://github.com/ffi/ffi/wiki/Enums FFI Enum Documentation
|
14
18
|
NETWORK_PREFIX_ENUM = enum :network_prefix,
|
15
19
|
[
|
16
20
|
:mainnet, 0,
|
17
21
|
:testnet, 16,
|
18
22
|
]
|
19
23
|
|
24
|
+
# Register id
|
25
|
+
# @see https://github.com/ffi/ffi/wiki/Enums FFI Enum Documentation
|
20
26
|
REGISTER_ID_ENUM = enum :non_mandatory_register_id,
|
21
27
|
[
|
22
28
|
:r4, 4,
|
@@ -27,6 +33,8 @@ module Sigma
|
|
27
33
|
:r9
|
28
34
|
]
|
29
35
|
|
36
|
+
# Represents which side the node is on in the merkle tree
|
37
|
+
# @see https://github.com/ffi/ffi/wiki/Enums FFI Enum Documentation
|
30
38
|
NODE_SIDE_ENUM = enum :node_side,
|
31
39
|
[
|
32
40
|
:left, 0,
|
data/lib/sigma/ergo_box.rb
CHANGED
@@ -4,6 +4,7 @@ require 'ffi-compiler/loader'
|
|
4
4
|
require 'json'
|
5
5
|
|
6
6
|
module Sigma
|
7
|
+
# BoxId (32-byte digest)
|
7
8
|
class BoxId
|
8
9
|
extend FFI::Library
|
9
10
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -16,10 +17,17 @@ module Sigma
|
|
16
17
|
|
17
18
|
attr_accessor :pointer
|
18
19
|
|
20
|
+
# Takes ownership of an existing BoxId Pointer.
|
21
|
+
# @note A user of sigma_rb generally does not need to call this function
|
22
|
+
# @param pointer [FFI::MemoryPointer]
|
23
|
+
# @return [BoxId]
|
19
24
|
def self.with_raw_pointer(bid_ptr)
|
20
25
|
init(bid_ptr)
|
21
26
|
end
|
22
27
|
|
28
|
+
# Parse box id (32 byte digest) from base16-encoded string
|
29
|
+
# @param str [String]
|
30
|
+
# @return [BoxId]
|
23
31
|
def self.with_string(str)
|
24
32
|
bid_ptr = FFI::MemoryPointer.new(:pointer)
|
25
33
|
error = ergo_lib_box_id_from_str(str, bid_ptr)
|
@@ -28,12 +36,16 @@ module Sigma
|
|
28
36
|
init(bid_ptr)
|
29
37
|
end
|
30
38
|
|
39
|
+
# Returns byte array (32-bytes) representation
|
40
|
+
# @return [Array<uint8, 32>]
|
31
41
|
def to_bytes
|
32
42
|
b_ptr = FFI::MemoryPointer.new(:uint8, 32)
|
33
43
|
ergo_lib_box_id_to_bytes(self.pointer, b_ptr)
|
34
44
|
b_ptr.get_array_of_uint8(0, 32)
|
35
45
|
end
|
36
46
|
|
47
|
+
# Returns base16 encoded string representation
|
48
|
+
# @return [String]
|
37
49
|
def to_s
|
38
50
|
s_ptr = FFI::MemoryPointer.new(:pointer, 1)
|
39
51
|
ergo_lib_box_id_to_str(self.pointer, s_ptr)
|
@@ -43,6 +55,9 @@ module Sigma
|
|
43
55
|
str
|
44
56
|
end
|
45
57
|
|
58
|
+
# Equality check of two BoxId
|
59
|
+
# @param box_id_two [BoxId]
|
60
|
+
# @return [bool]
|
46
61
|
def ==(box_id_two)
|
47
62
|
ergo_lib_box_id_eq(self.pointer, box_id_two.pointer)
|
48
63
|
end
|
@@ -61,6 +76,7 @@ module Sigma
|
|
61
76
|
end
|
62
77
|
end
|
63
78
|
|
79
|
+
# Box value in nanoERGs with bound checks
|
64
80
|
class BoxValue
|
65
81
|
extend FFI::Library
|
66
82
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -75,21 +91,28 @@ module Sigma
|
|
75
91
|
|
76
92
|
attr_accessor :pointer
|
77
93
|
|
94
|
+
# Takes ownership of an existing BoxValue Pointer.
|
95
|
+
# @note A user of sigma_rb generally does not need to call this function
|
96
|
+
# @param pointer [FFI::MemoryPointer]
|
97
|
+
# @return [BoxValue]
|
78
98
|
def self.with_raw_pointer(bv_pointer)
|
79
99
|
init(bv_pointer)
|
80
100
|
end
|
81
101
|
|
102
|
+
# Number of units inside one ERGO (i.e. one ERG using nano ERG representation)
|
82
103
|
def self.units_per_ergo
|
83
104
|
ergo_lib_box_value_units_per_ergo
|
84
105
|
end
|
85
106
|
|
107
|
+
# Recommended (safe) minimal box value to use in case box size estimation is unavailable.
|
108
|
+
# Allows box size upto 2777 bytes with current min box value per byte of 360 nanoERGs
|
86
109
|
def self.safe_user_min
|
87
110
|
bv_ptr = FFI::MemoryPointer.new(:pointer)
|
88
111
|
ergo_lib_box_value_safe_user_min(bv_ptr)
|
89
112
|
|
90
113
|
init(bv_ptr)
|
91
114
|
end
|
92
|
-
|
115
|
+
# Create a new box value which is the sum of the arguments, throwing error if value is out of bounds.
|
93
116
|
def self.sum_of(bv_one, bv_two)
|
94
117
|
bv_ptr = FFI::MemoryPointer.new(:pointer)
|
95
118
|
error = ergo_lib_box_value_sum_of(bv_one.pointer, bv_two.pointer, bv_ptr)
|
@@ -98,6 +121,9 @@ module Sigma
|
|
98
121
|
init(bv_ptr)
|
99
122
|
end
|
100
123
|
|
124
|
+
# Create BoxValue from 64-bit integer
|
125
|
+
# @param int [Integer]
|
126
|
+
# @return [BoxValue]
|
101
127
|
def self.from_i64(int)
|
102
128
|
bv_ptr = FFI::MemoryPointer.new(:pointer)
|
103
129
|
error = ergo_lib_box_value_from_i64(int, bv_ptr)
|
@@ -106,10 +132,15 @@ module Sigma
|
|
106
132
|
init(bv_ptr)
|
107
133
|
end
|
108
134
|
|
135
|
+
# Get value as 64-bit integer
|
136
|
+
# @return [Integer]
|
109
137
|
def to_i64
|
110
138
|
ergo_lib_box_value_as_i64(self.pointer)
|
111
139
|
end
|
112
140
|
|
141
|
+
# Equality check for two BoxValues
|
142
|
+
# @param box_value_two [BoxValue]
|
143
|
+
# @return [bool]
|
113
144
|
def ==(box_value_two)
|
114
145
|
ergo_lib_box_value_eq(self.pointer, box_value_two.pointer)
|
115
146
|
end
|
@@ -128,6 +159,8 @@ module Sigma
|
|
128
159
|
end
|
129
160
|
end
|
130
161
|
|
162
|
+
# Contains the same fields as ``ErgoBox``, except for transaction id and index, that will be
|
163
|
+
# calculated after full transaction formation. Use ``ErgoBoxCandidateBuilder`` to create an instance
|
131
164
|
class ErgoBoxCandidate
|
132
165
|
extend FFI::Library
|
133
166
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -142,10 +175,18 @@ module Sigma
|
|
142
175
|
|
143
176
|
attr_accessor :pointer
|
144
177
|
|
178
|
+
# Takes ownership of an existing ErgoBoxCandidate Pointer.
|
179
|
+
# @note A user of sigma_rb generally does not need to call this function
|
180
|
+
# @param pointer [FFI::MemoryPointer]
|
181
|
+
# @return [ErgoBoxCandidate]
|
145
182
|
def self.with_raw_pointer(pointer)
|
146
183
|
init(pointer)
|
147
184
|
end
|
148
185
|
|
186
|
+
# Returns value (ErgoTree constant) stored in the register or `nil` if the register is empty
|
187
|
+
# @param register_id [Integer]
|
188
|
+
# @return [Constant, nil]
|
189
|
+
# @see REGISTER_ID_ENUM
|
149
190
|
def get_register_value(register_id)
|
150
191
|
constant_ptr = FFI::MemoryPointer.new(:pointer)
|
151
192
|
res = ergo_lib_ergo_box_candidate_register_value(self.pointer, register_id, constant_ptr)
|
@@ -157,28 +198,39 @@ module Sigma
|
|
157
198
|
end
|
158
199
|
end
|
159
200
|
|
201
|
+
# Get box creation height
|
202
|
+
# @return [Integer]
|
160
203
|
def get_creation_height
|
161
204
|
ergo_lib_ergo_box_candidate_creation_height(self.pointer)
|
162
205
|
end
|
163
206
|
|
207
|
+
# Get tokens for box
|
208
|
+
# @return [Tokens]
|
164
209
|
def get_tokens
|
165
210
|
pointer = FFI::MemoryPointer.new(:pointer)
|
166
211
|
ergo_lib_ergo_box_candidate_tokens(self.pointer, pointer)
|
167
212
|
Sigma::Tokens.with_raw_pointer(pointer)
|
168
213
|
end
|
169
214
|
|
215
|
+
# Get ErgoTree for box
|
216
|
+
# @return [ErgoTree]
|
170
217
|
def get_ergo_tree
|
171
218
|
pointer = FFI::MemoryPointer.new(:pointer)
|
172
219
|
ergo_lib_ergo_box_candidate_ergo_tree(self.pointer, pointer)
|
173
220
|
Sigma::ErgoTree.with_raw_pointer(pointer)
|
174
221
|
end
|
175
222
|
|
223
|
+
# Get box value
|
224
|
+
# @return [BoxValue]
|
176
225
|
def get_box_value
|
177
226
|
pointer = FFI::MemoryPointer.new(:pointer)
|
178
227
|
ergo_lib_ergo_box_candidate_box_value(self.pointer, pointer)
|
179
228
|
Sigma::BoxValue.with_raw_pointer(pointer)
|
180
229
|
end
|
181
230
|
|
231
|
+
# Equality check
|
232
|
+
# @param ebc_two [ErgoBoxCandidate]
|
233
|
+
# @return [bool]
|
182
234
|
def ==(ebc_two)
|
183
235
|
ergo_lib_ergo_box_candidate_eq(self.pointer, ebc_two.pointer)
|
184
236
|
end
|
@@ -197,6 +249,7 @@ module Sigma
|
|
197
249
|
end
|
198
250
|
end
|
199
251
|
|
252
|
+
# An ordered collection of ErgoBoxCandidate
|
200
253
|
class ErgoBoxCandidates
|
201
254
|
extend FFI::Library
|
202
255
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -209,6 +262,8 @@ module Sigma
|
|
209
262
|
|
210
263
|
attr_accessor :pointer
|
211
264
|
|
265
|
+
# Create an empty collection
|
266
|
+
# @return [ErgoBoxCandidates]
|
212
267
|
def self.create
|
213
268
|
pointer = FFI::MemoryPointer.new(:pointer)
|
214
269
|
ergo_lib_ergo_box_candidates_new(pointer)
|
@@ -216,18 +271,29 @@ module Sigma
|
|
216
271
|
init(pointer)
|
217
272
|
end
|
218
273
|
|
274
|
+
# Takes ownership of an existing ErgoBoxCandidates Pointer.
|
275
|
+
# @note A user of sigma_rb generally does not need to call this function
|
276
|
+
# @param pointer [FFI::MemoryPointer]
|
277
|
+
# @return [ErgoBoxCandidates]
|
219
278
|
def self.with_raw_pointer(pointer)
|
220
279
|
init(pointer)
|
221
280
|
end
|
222
281
|
|
282
|
+
# Get length of collection
|
283
|
+
# @return [Integer]
|
223
284
|
def len
|
224
285
|
ergo_lib_ergo_box_candidates_len(self.pointer)
|
225
286
|
end
|
226
287
|
|
288
|
+
# Add to collection
|
289
|
+
# @param ergo_box_candidate [ErgoBoxCandidate]
|
227
290
|
def add(ergo_box_candidate)
|
228
291
|
ergo_lib_ergo_box_candidates_add(ergo_box_candidate.pointer, self.pointer)
|
229
292
|
end
|
230
293
|
|
294
|
+
# Get item at specified index or return nil if no item exists
|
295
|
+
# @param index [Integer]
|
296
|
+
# @return [ErgoBoxCandidate, nil]
|
231
297
|
def get(index)
|
232
298
|
pointer = FFI::MemoryPointer.new(:pointer)
|
233
299
|
res = ergo_lib_ergo_box_candidates_get(self.pointer, index, pointer)
|
@@ -253,6 +319,26 @@ module Sigma
|
|
253
319
|
end
|
254
320
|
end
|
255
321
|
|
322
|
+
# Box (aka coin, or an unspent output) is a basic concept of a UTXO-based cryptocurrency.
|
323
|
+
# In Bitcoin, such an object is associated with some monetary value (arbitrary,
|
324
|
+
# but with predefined precision, so we use integer arithmetic to work with the value),
|
325
|
+
# and also a guarding script (aka proposition) to protect the box from unauthorized opening.
|
326
|
+
#
|
327
|
+
# In other way, a box is a state element locked by some proposition (ErgoTree).
|
328
|
+
#
|
329
|
+
# In Ergo, box is just a collection of registers, some with mandatory types and semantics,
|
330
|
+
# others could be used by applications in any way.
|
331
|
+
# We add additional fields in addition to amount and proposition~(which stored in the registers R0 and R1).
|
332
|
+
# Namely, register R2 contains additional tokens (a sequence of pairs (token identifier, value)).
|
333
|
+
# Register R3 contains height when block got included into the blockchain and also transaction
|
334
|
+
# identifier and box index in the transaction outputs.
|
335
|
+
# Registers R4-R9 are free for arbitrary usage.
|
336
|
+
#
|
337
|
+
# A transaction is unsealing a box. As a box can not be open twice, any further valid transaction
|
338
|
+
# can not be linked to the same box.
|
339
|
+
# Ergo box, that is taking part in some transaction on the chain Differs with ``ErgoBoxCandidate``
|
340
|
+
# by added transaction id and an index in the input of that transaction
|
341
|
+
|
256
342
|
class ErgoBox
|
257
343
|
extend FFI::Library
|
258
344
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -273,6 +359,17 @@ module Sigma
|
|
273
359
|
|
274
360
|
attr_accessor :pointer
|
275
361
|
|
362
|
+
# Safe maximum number of tokens in the box
|
363
|
+
# Calculated from the max box size (4kb) limit and the size of the token (32 bytes)
|
364
|
+
MAX_TOKENS_COUNT = 100
|
365
|
+
|
366
|
+
# Create a new box
|
367
|
+
# @param box_value: [BoxValue] amount of money associated with box
|
368
|
+
# @param creation_height: [Integer] height when a transaction containing the box is created
|
369
|
+
# @param contract: [Contract] guarding contract which should be evaluted to true in order to open(spend) this box
|
370
|
+
# @param tx_id: [TxId] transaction id in which this box was "created" (participated in outputs)
|
371
|
+
# @param index: [Integer] index (in outputs) in the transaction
|
372
|
+
# @return [ErgoBox]
|
276
373
|
def self.create(box_value:,
|
277
374
|
creation_height:,
|
278
375
|
contract:,
|
@@ -289,10 +386,18 @@ module Sigma
|
|
289
386
|
init(eb_pointer)
|
290
387
|
end
|
291
388
|
|
389
|
+
# Takes ownership of an existing ErgoBox Pointer.
|
390
|
+
# @note A user of sigma_rb generally does not need to call this function
|
391
|
+
# @param pointer [FFI::MemoryPointer]
|
392
|
+
# @return [ErgoBox]
|
292
393
|
def self.with_raw_pointer(unread_pointer)
|
293
394
|
init(unread_pointer)
|
294
395
|
end
|
295
396
|
|
397
|
+
# Parse and create from json.
|
398
|
+
# Supports Ergo Node/Explorer API and box values and token amount encoded as strings
|
399
|
+
# @param json_str [String]
|
400
|
+
# @return [ErgoBox]
|
296
401
|
def self.with_json(json_str)
|
297
402
|
pointer = FFI::MemoryPointer.new(:pointer)
|
298
403
|
error = ergo_lib_ergo_box_from_json(json_str, pointer)
|
@@ -300,22 +405,32 @@ module Sigma
|
|
300
405
|
init(pointer)
|
301
406
|
end
|
302
407
|
|
408
|
+
# Get box id
|
409
|
+
# @return [BoxId]
|
303
410
|
def get_box_id
|
304
411
|
box_id_ptr = FFI::MemoryPointer.new(:pointer)
|
305
412
|
ergo_lib_ergo_box_id(self.pointer, box_id_ptr)
|
306
413
|
Sigma::BoxId.with_raw_pointer(box_id_ptr)
|
307
414
|
end
|
308
415
|
|
416
|
+
# Get box value
|
417
|
+
# @return [BoxValue]
|
309
418
|
def get_box_value
|
310
419
|
box_value_ptr = FFI::MemoryPointer.new(:pointer)
|
311
420
|
ergo_lib_ergo_box_value(self.pointer, box_value_ptr)
|
312
421
|
Sigma::BoxValue.with_raw_pointer(box_value_ptr)
|
313
422
|
end
|
314
423
|
|
424
|
+
# Get box creation height
|
425
|
+
# @return [Integer]
|
315
426
|
def get_creation_height
|
316
427
|
ergo_lib_ergo_box_creation_height(self.pointer)
|
317
428
|
end
|
318
429
|
|
430
|
+
# Returns value (ErgoTree constant) stored in the register or `nil` if the register is empty
|
431
|
+
# @param register_id [Integer]
|
432
|
+
# @return [Constant, nil]
|
433
|
+
# @see REGISTER_ID_ENUM
|
319
434
|
def get_register_value(register_id)
|
320
435
|
constant_ptr = FFI::MemoryPointer.new(:pointer)
|
321
436
|
res = ergo_lib_ergo_box_register_value(self.pointer, register_id, constant_ptr)
|
@@ -327,18 +442,24 @@ module Sigma
|
|
327
442
|
end
|
328
443
|
end
|
329
444
|
|
445
|
+
# Get tokens for box
|
446
|
+
# @return [Tokens]
|
330
447
|
def get_tokens
|
331
448
|
tokens_ptr = FFI::MemoryPointer.new(:pointer)
|
332
449
|
ergo_lib_ergo_box_tokens(self.pointer, tokens_ptr)
|
333
450
|
Sigma::Tokens.with_raw_pointer(tokens_ptr)
|
334
451
|
end
|
335
452
|
|
453
|
+
# Get ergo tree for box
|
454
|
+
# @return [ErgoTree]
|
336
455
|
def get_ergo_tree
|
337
456
|
ergo_tree_ptr = FFI::MemoryPointer.new(:pointer)
|
338
457
|
ergo_lib_ergo_box_ergo_tree(self.pointer, ergo_tree_ptr)
|
339
458
|
Sigma::ErgoTree.with_raw_pointer(ergo_tree_ptr)
|
340
459
|
end
|
341
460
|
|
461
|
+
# JSON representation as text (compatible with Ergo Node/Explorer API, numbers are encoded as numbers)
|
462
|
+
# @return [String]
|
342
463
|
def to_json
|
343
464
|
s_ptr = FFI::MemoryPointer.new(:pointer, 1)
|
344
465
|
error = ergo_lib_ergo_box_to_json(self.pointer, s_ptr)
|
@@ -349,6 +470,9 @@ module Sigma
|
|
349
470
|
str
|
350
471
|
end
|
351
472
|
|
473
|
+
# JSON representation according to EIP-12
|
474
|
+
# @see <https://github.com/ergoplatform/eips/pull/23> PR with EIP-12
|
475
|
+
# @return [String]
|
352
476
|
def to_json_eip12
|
353
477
|
s_ptr = FFI::MemoryPointer.new(:pointer, 1)
|
354
478
|
error = ergo_lib_ergo_box_to_json_eip12(self.pointer, s_ptr)
|
@@ -359,6 +483,9 @@ module Sigma
|
|
359
483
|
str
|
360
484
|
end
|
361
485
|
|
486
|
+
# Equality check
|
487
|
+
# @param ergo_box_two [ErgoBox]
|
488
|
+
# @return [bool]
|
362
489
|
def ==(ergo_box_two)
|
363
490
|
ergo_lib_ergo_box_eq(self.pointer, ergo_box_two.pointer)
|
364
491
|
end
|
@@ -377,6 +504,7 @@ module Sigma
|
|
377
504
|
end
|
378
505
|
end
|
379
506
|
|
507
|
+
# An ordered collection of ErgoBox
|
380
508
|
class ErgoBoxes
|
381
509
|
extend FFI::Library
|
382
510
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -389,10 +517,16 @@ module Sigma
|
|
389
517
|
|
390
518
|
attr_accessor :pointer
|
391
519
|
|
520
|
+
# Takes ownership of an existing ErgoBoxes Pointer.
|
521
|
+
# @note A user of sigma_rb generally does not need to call this function
|
522
|
+
# @param pointer [FFI::MemoryPointer]
|
523
|
+
# @return [ErgoBoxes]
|
392
524
|
def self.with_raw_pointer(unread_pointer)
|
393
525
|
init(unread_pointer)
|
394
526
|
end
|
395
527
|
|
528
|
+
# Create an empty collection
|
529
|
+
# @return [ErgoBoxes]
|
396
530
|
def self.create
|
397
531
|
pointer = FFI::MemoryPointer.new(:pointer)
|
398
532
|
ergo_lib_ergo_boxes_new(pointer)
|
@@ -400,7 +534,9 @@ module Sigma
|
|
400
534
|
init(pointer)
|
401
535
|
end
|
402
536
|
|
403
|
-
#
|
537
|
+
# Create collection from ErgoBox Array JSON (Node API)
|
538
|
+
# @param array_of_json_elements [Array<String>]
|
539
|
+
# @note Parameter is an ARRAY of JSON Strings
|
404
540
|
def self.from_json(array_of_json_elements)
|
405
541
|
boxes = array_of_json_elements.map do |json|
|
406
542
|
Sigma::ErgoBox.with_json(json)
|
@@ -412,14 +548,21 @@ module Sigma
|
|
412
548
|
container
|
413
549
|
end
|
414
550
|
|
551
|
+
# Get length of collection
|
552
|
+
# @return [Integer]
|
415
553
|
def len
|
416
554
|
ergo_lib_ergo_boxes_len(self.pointer)
|
417
555
|
end
|
418
556
|
|
557
|
+
# Add to collection
|
558
|
+
# @param ergo_box [ErgoBox]
|
419
559
|
def add(ergo_box)
|
420
560
|
ergo_lib_ergo_boxes_add(ergo_box.pointer, self.pointer)
|
421
561
|
end
|
422
562
|
|
563
|
+
# Get item at specified index or return nil if no item exists
|
564
|
+
# @param index [Integer]
|
565
|
+
# @return [ErgoBox, nil]
|
423
566
|
def get(index)
|
424
567
|
pointer = FFI::MemoryPointer.new(:pointer)
|
425
568
|
res = ergo_lib_ergo_boxes_get(self.pointer, index, pointer)
|
@@ -445,6 +588,7 @@ module Sigma
|
|
445
588
|
end
|
446
589
|
end
|
447
590
|
|
591
|
+
# Pair of (value, tokens) for a box
|
448
592
|
class ErgoBoxAssetsData
|
449
593
|
extend FFI::Library
|
450
594
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -457,28 +601,43 @@ module Sigma
|
|
457
601
|
|
458
602
|
attr_accessor :pointer
|
459
603
|
|
604
|
+
# Create new instance
|
605
|
+
# @param box_value: [BoxValue]
|
606
|
+
# @param tokens: [Tokens]
|
607
|
+
# @return [ErgoBoxAssetsData]
|
460
608
|
def self.create(box_value:, tokens:)
|
461
609
|
pointer = FFI::MemoryPointer.new(:pointer)
|
462
610
|
ergo_lib_ergo_box_assets_data_new(box_value.pointer, tokens.pointer, pointer)
|
463
611
|
init(pointer)
|
464
612
|
end
|
465
613
|
|
614
|
+
# Takes ownership of an existing ErgoBoxAssetsData Pointer.
|
615
|
+
# @note A user of sigma_rb generally does not need to call this function
|
616
|
+
# @param pointer [FFI::MemoryPointer]
|
617
|
+
# @return [ErgoBoxAssetsData]
|
466
618
|
def self.with_raw_pointer(pointer)
|
467
619
|
init(pointer)
|
468
620
|
end
|
469
621
|
|
622
|
+
# get box value
|
623
|
+
# @return [BoxValue]
|
470
624
|
def get_box_value
|
471
625
|
pointer = FFI::MemoryPointer.new(:pointer)
|
472
626
|
ergo_lib_ergo_box_assets_data_value(self.pointer, pointer)
|
473
627
|
Sigma::BoxValue.with_raw_pointer(pointer)
|
474
628
|
end
|
475
629
|
|
630
|
+
# get box tokens
|
631
|
+
# @return [Tokens]
|
476
632
|
def get_box_tokens
|
477
633
|
pointer = FFI::MemoryPointer.new(:pointer)
|
478
634
|
ergo_lib_ergo_box_assets_data_tokens(self.pointer, pointer)
|
479
635
|
Sigma::Tokens.with_raw_pointer(pointer)
|
480
636
|
end
|
481
637
|
|
638
|
+
# Equality check
|
639
|
+
# @param eb_asset_data_two [ErgoBoxAssetsData]
|
640
|
+
# @return [bool]
|
482
641
|
def ==(eb_asset_data_two)
|
483
642
|
ergo_lib_ergo_box_assets_data_eq(self.pointer, eb_asset_data_two.pointer)
|
484
643
|
end
|
@@ -497,6 +656,7 @@ module Sigma
|
|
497
656
|
end
|
498
657
|
end
|
499
658
|
|
659
|
+
# An ordered collection of ErgoBoxAssetsData
|
500
660
|
class ErgoBoxAssetsDataList
|
501
661
|
extend FFI::Library
|
502
662
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -509,10 +669,16 @@ module Sigma
|
|
509
669
|
|
510
670
|
attr_accessor :pointer
|
511
671
|
|
672
|
+
# Takes ownership of an existing ErgoBoxAssetsDataList Pointer.
|
673
|
+
# @note A user of sigma_rb generally does not need to call this function
|
674
|
+
# @param pointer [FFI::MemoryPointer]
|
675
|
+
# @return [ErgoBoxAssetsDataList]
|
512
676
|
def self.with_raw_pointer(unread_pointer)
|
513
677
|
init(unread_pointer)
|
514
678
|
end
|
515
679
|
|
680
|
+
# Create an empty collection
|
681
|
+
# @return [ErgoBoxAssetsDataList]
|
516
682
|
def self.create
|
517
683
|
pointer = FFI::MemoryPointer.new(:pointer)
|
518
684
|
ergo_lib_ergo_box_assets_data_list_new(pointer)
|
@@ -520,14 +686,21 @@ module Sigma
|
|
520
686
|
init(pointer)
|
521
687
|
end
|
522
688
|
|
689
|
+
# Get length of collection
|
690
|
+
# @return [Integer]
|
523
691
|
def len
|
524
692
|
ergo_lib_ergo_box_assets_data_list_len(self.pointer)
|
525
693
|
end
|
526
694
|
|
695
|
+
# Add to collection
|
696
|
+
# @param ergo_box_assets_data [ErgoBoxAssetsData]
|
527
697
|
def add(ergo_box_assets_data)
|
528
698
|
ergo_lib_ergo_box_assets_data_list_add(ergo_box_assets_data.pointer, self.pointer)
|
529
699
|
end
|
530
700
|
|
701
|
+
# Get item at specified index or return nil if no item exists
|
702
|
+
# @param index [Integer]
|
703
|
+
# @return [ErgoBoxAssetsData, nil]
|
531
704
|
def get(index)
|
532
705
|
pointer = FFI::MemoryPointer.new(:pointer)
|
533
706
|
res = ergo_lib_ergo_box_assets_data_list_get(self.pointer, index, pointer)
|