sigma_rb 0.1.3 → 0.2.0
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 +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
@@ -3,6 +3,7 @@ require_relative './util.rb'
|
|
3
3
|
require 'ffi-compiler/loader'
|
4
4
|
|
5
5
|
module Sigma
|
6
|
+
# An ErgoBoxCandidate Builder
|
6
7
|
class ErgoBoxCandidateBuilder
|
7
8
|
extend FFI::Library
|
8
9
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -23,7 +24,11 @@ module Sigma
|
|
23
24
|
attach_function :ergo_lib_ergo_box_candidate_builder_add_token, [:pointer, :pointer, :pointer], :void
|
24
25
|
|
25
26
|
attr_accessor :pointer
|
26
|
-
|
27
|
+
# Create builder with required box parameters
|
28
|
+
# @param box_value: [BoxValue] amount of money associated with the box
|
29
|
+
# @param contract: [Contract] guarding contract, which should be evaluated to true in order to open(spend) this box
|
30
|
+
# @param creation_height: [Integer] height when a transaction containing the box is created. It should not exceed height of the block, containing the transaction with this box.
|
31
|
+
# @return [ErgoBoxCandidateBuilder]
|
27
32
|
def self.create(box_value:, contract:, creation_height:)
|
28
33
|
pointer = FFI::MemoryPointer.new(:pointer)
|
29
34
|
ergo_lib_ergo_box_candidate_builder_new(box_value.pointer, contract.pointer, creation_height, pointer)
|
@@ -31,32 +36,46 @@ module Sigma
|
|
31
36
|
init(pointer)
|
32
37
|
end
|
33
38
|
|
39
|
+
# Set minimal value (per byte of the serialized box size)
|
40
|
+
# @param min_box_value [Uint32] Unsigned 32-bit integer
|
41
|
+
# @return [ErgoBoxCandidateBuilder] updated ErgoBoxCandidateBuilder (self)
|
34
42
|
def set_min_box_value_per_byte(min_box_value)
|
35
43
|
ergo_lib_ergo_box_candidate_builder_set_min_box_value_per_byte(self.pointer, min_box_value)
|
36
44
|
self
|
37
45
|
end
|
38
46
|
|
47
|
+
# Get minimal value (per byte of the serialized box size)
|
48
|
+
# @return [Integer]
|
39
49
|
def get_min_box_value_per_byte
|
40
50
|
ergo_lib_ergo_box_candidate_builder_min_box_value_per_byte(self.pointer)
|
41
51
|
end
|
42
52
|
|
53
|
+
# Set new box value
|
54
|
+
# @param box_value [BoxValue]
|
55
|
+
# @return [ErgoBoxCandidate] updated ErgoBoxCandidateBuilder (self)
|
43
56
|
def set_value(box_value)
|
44
57
|
ergo_lib_ergo_box_candidate_builder_set_value(self.pointer, box_value.pointer)
|
45
58
|
self
|
46
59
|
end
|
47
60
|
|
61
|
+
# Get box value
|
62
|
+
# @return [BoxValue]
|
48
63
|
def get_value
|
49
64
|
pointer = FFI::MemoryPointer.new(:pointer)
|
50
65
|
ergo_lib_ergo_box_candidate_builder_value(self.pointer, pointer)
|
51
66
|
Sigma::BoxValue.with_raw_pointer(pointer)
|
52
67
|
end
|
53
68
|
|
69
|
+
# Calulate serialized box size (in bytes)
|
70
|
+
# @return [Integer]
|
54
71
|
def calc_box_size_bytes
|
55
72
|
res = ergo_lib_ergo_box_candidate_builder_calc_box_size_bytes(self.pointer)
|
56
73
|
Util.check_error!(res[:error])
|
57
74
|
res[:value]
|
58
75
|
end
|
59
76
|
|
77
|
+
# Calculate minimal box value for the current box serialized size (in bytes)
|
78
|
+
# @return [BoxValue]
|
60
79
|
def calc_min_box_value
|
61
80
|
pointer = FFI::MemoryPointer.new(:pointer)
|
62
81
|
error = ergo_lib_ergo_box_candidate_calc_min_box_value(self.pointer, pointer)
|
@@ -64,10 +83,18 @@ module Sigma
|
|
64
83
|
Sigma::BoxValue.with_raw_pointer(pointer)
|
65
84
|
end
|
66
85
|
|
86
|
+
# Set register (R4-R9) to the given value
|
87
|
+
# @param register_id [Integer]
|
88
|
+
# @param constant [Constant]
|
89
|
+
# @see REGISTER_ID_ENUM
|
67
90
|
def set_register_value(register_id, constant)
|
68
91
|
ergo_lib_ergo_box_candidate_builder_set_register_value(self.pointer, register_id, constant.pointer)
|
69
92
|
end
|
70
93
|
|
94
|
+
# Gets register value or nil if empty
|
95
|
+
# @param register_id [Integer]
|
96
|
+
# @return [Constant, nil]
|
97
|
+
# @see REGISTER_ID_ENUM
|
71
98
|
def get_register_value(register_id)
|
72
99
|
pointer = FFI::MemoryPointer.new(:pointer)
|
73
100
|
res = ergo_lib_ergo_box_candidate_builder_register_value(self.pointer, register_id, pointer)
|
@@ -79,11 +106,22 @@ module Sigma
|
|
79
106
|
end
|
80
107
|
end
|
81
108
|
|
109
|
+
# Delete register value (make register empty) for the given register id (R4-R9)
|
110
|
+
# @param register_id [Integer]
|
111
|
+
# @return [ErgoBoxCandidate] updated ErgoBoxCandidateBuilder (self)
|
112
|
+
# @see REGISTER_ID_ENUM
|
82
113
|
def delete_register_value(register_id)
|
83
114
|
ergo_lib_ergo_box_candidate_builder_delete_register_value(self.pointer, register_id)
|
84
115
|
self
|
85
116
|
end
|
86
117
|
|
118
|
+
# Mint token, as defined in EIP-004
|
119
|
+
# @param token: [Token]
|
120
|
+
# @param name: [String] Token name, will be encoded in R4
|
121
|
+
# @param description: [String] Token description, will be encoded in R5
|
122
|
+
# @param num_decimals: [Integer] Number of decimals, will be encoded in R6
|
123
|
+
# @return [ErgoBoxCandidateBuilder] updated ErgoBoxCandidateBuilder (self)
|
124
|
+
# @see https://github.com/ergoplatform/eips/blob/master/eip-0004.md EIP-004
|
87
125
|
def mint_token(token:, name:, description:, num_decimals:)
|
88
126
|
ergo_lib_ergo_box_candidate_builder_mint_token(
|
89
127
|
self.pointer,
|
@@ -95,11 +133,17 @@ module Sigma
|
|
95
133
|
self
|
96
134
|
end
|
97
135
|
|
136
|
+
# Add given token_id and token_amount
|
137
|
+
# @param token_id [TokenId]
|
138
|
+
# @param token_amount [TokenAmount]
|
139
|
+
# @return [ErgoBoxCandidateBuilder] updated ErgoBoxCandidateBuilder (self)
|
98
140
|
def add_token(token_id, token_amount)
|
99
141
|
ergo_lib_ergo_box_candidate_builder_add_token(self.pointer, token_id.pointer, token_amount.pointer)
|
100
142
|
self
|
101
143
|
end
|
102
144
|
|
145
|
+
# Build the box candidate
|
146
|
+
# @return [ErgoBoxCandidate]
|
103
147
|
def build
|
104
148
|
pointer = FFI::MemoryPointer.new(:pointer)
|
105
149
|
error = ergo_lib_ergo_box_candidate_builder_build(self.pointer, pointer)
|
@@ -3,6 +3,7 @@ require_relative './util.rb'
|
|
3
3
|
require 'ffi-compiler/loader'
|
4
4
|
|
5
5
|
module Sigma
|
6
|
+
# Blockchain state (last headers, etc)
|
6
7
|
class ErgoStateContext
|
7
8
|
extend FFI::Library
|
8
9
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -13,6 +14,10 @@ module Sigma
|
|
13
14
|
|
14
15
|
attr_accessor :pointer
|
15
16
|
|
17
|
+
# Createa new context
|
18
|
+
# @param pre_header [PreHeader]
|
19
|
+
# @param headers [Headers]
|
20
|
+
# @return [ErgoStateContext]
|
16
21
|
def self.create(pre_header:, headers:)
|
17
22
|
pointer = FFI::MemoryPointer.new(:pointer)
|
18
23
|
error = ergo_lib_ergo_state_context_new(pre_header.pointer, headers.pointer, pointer)
|
@@ -20,6 +25,9 @@ module Sigma
|
|
20
25
|
init(pointer)
|
21
26
|
end
|
22
27
|
|
28
|
+
# Equality check
|
29
|
+
# @param esc_two [ErgoStateContext]
|
30
|
+
# @return [bool]
|
23
31
|
def ==(esc_two)
|
24
32
|
ergo_lib_ergo_state_context_eq(self.pointer, esc.pointer)
|
25
33
|
end
|
data/lib/sigma/ergo_tree.rb
CHANGED
@@ -3,12 +3,14 @@ require_relative './util.rb'
|
|
3
3
|
require 'ffi-compiler/loader'
|
4
4
|
|
5
5
|
module Sigma
|
6
|
+
# The root of ErgoScript IR. Serialized instances of this class are self sufficient and can be passed around.
|
6
7
|
class ErgoTree
|
7
8
|
extend FFI::Library
|
8
9
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
9
10
|
typedef :pointer, :error_pointer
|
10
11
|
attach_function :ergo_lib_ergo_tree_delete, [:pointer], :void
|
11
12
|
attach_function :ergo_lib_ergo_tree_eq, [:pointer, :pointer], :bool
|
13
|
+
attach_function :ergo_lib_ergo_tree_from_bytes, [:pointer, :uint, :pointer], :error_pointer
|
12
14
|
attach_function :ergo_lib_ergo_tree_from_base16_bytes, [:pointer, :pointer], :error_pointer
|
13
15
|
attach_function :ergo_lib_ergo_tree_to_base16_bytes, [:pointer, :pointer], :error_pointer
|
14
16
|
attach_function :ergo_lib_ergo_tree_to_bytes, [:pointer, :pointer], :error_pointer
|
@@ -20,10 +22,29 @@ module Sigma
|
|
20
22
|
attach_function :ergo_lib_ergo_tree_get_constant, [:pointer, :uint8, :pointer], ReturnOption.by_value
|
21
23
|
attr_accessor :pointer
|
22
24
|
|
25
|
+
# Takes ownership of an existing ErgoTree Pointer.
|
26
|
+
# @note A user of sigma_rb generally does not need to call this function
|
27
|
+
# @param pointer [FFI::MemoryPointer]
|
28
|
+
# @return [ErgoTree]
|
23
29
|
def self.with_raw_pointer(unread_pointer)
|
24
30
|
init(unread_pointer)
|
25
31
|
end
|
26
32
|
|
33
|
+
# Decode from encoded serialized ErgoTree
|
34
|
+
# @param bytes [Array<uint8>] Array of unsigned 8-bit integers (0-255)
|
35
|
+
# @return [ErgoTree]
|
36
|
+
def self.from_bytes(bytes)
|
37
|
+
pointer = FFI::MemoryPointer.new(:pointer)
|
38
|
+
b_ptr = FFI::MemoryPointer.new(:uint8, bytes.size)
|
39
|
+
b_ptr.write_array_of_uint8(bytes)
|
40
|
+
error = ergo_lib_ergo_tree_from_bytes(b_ptr, bytes.size, pointer)
|
41
|
+
Util.check_error!(error)
|
42
|
+
init(pointer)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Decode from a base16 encoded serialized ErgoTree
|
46
|
+
# @param encoded_str [String]
|
47
|
+
# @return [ErgoTree]
|
27
48
|
def self.from_base16_encoded_string(encoded_str)
|
28
49
|
pointer = FFI::MemoryPointer.new(:pointer)
|
29
50
|
error = ergo_lib_ergo_tree_from_base16_bytes(encoded_str, pointer)
|
@@ -32,6 +53,8 @@ module Sigma
|
|
32
53
|
init(pointer)
|
33
54
|
end
|
34
55
|
|
56
|
+
# Convert to base16 encoded serialized bytes
|
57
|
+
# @return [String]
|
35
58
|
def to_base16_encoded_string
|
36
59
|
s_ptr = FFI::MemoryPointer.new(:pointer, 1)
|
37
60
|
error = ergo_lib_ergo_tree_to_base16_bytes(self.pointer, s_ptr)
|
@@ -42,6 +65,8 @@ module Sigma
|
|
42
65
|
str
|
43
66
|
end
|
44
67
|
|
68
|
+
# Convert to serialized bytes
|
69
|
+
# @return [Array<uint8>] Array of 8-bit integers (0-255)
|
45
70
|
def to_bytes
|
46
71
|
res = ergo_lib_ergo_tree_bytes_len(self.pointer)
|
47
72
|
Util.check_error!(res[:error])
|
@@ -52,6 +77,8 @@ module Sigma
|
|
52
77
|
bytes_ptr.read_array_of_uint8(bytes_length)
|
53
78
|
end
|
54
79
|
|
80
|
+
# Serialized proposition expression of SigmaProp type with ConstantPlaceholder nodes instead of Constant nodes.
|
81
|
+
# @return [Array<uint8>] Array of 8-bit integers (0-255)
|
55
82
|
def to_template_bytes
|
56
83
|
res = ergo_lib_ergo_tree_template_bytes_len(self.pointer)
|
57
84
|
Util.check_error!(res[:error])
|
@@ -62,12 +89,17 @@ module Sigma
|
|
62
89
|
bytes_ptr.read_array_of_uint8(bytes_length)
|
63
90
|
end
|
64
91
|
|
92
|
+
# Returns the number of constants stored in the serialized ``ErgoTree`` or throws error if the parsing of constants failed
|
93
|
+
# @return [Integer]
|
65
94
|
def constants_length
|
66
95
|
res = ergo_lib_ergo_tree_constants_len(self.pointer)
|
67
96
|
Util.check_error!(res[:error])
|
68
97
|
res[:value]
|
69
98
|
end
|
70
99
|
|
100
|
+
# Return constant with given index (as stored in serialized ErgoTree) if it exists. Throws if constant parsing failed. Returns nil if no constant exists at given index
|
101
|
+
# @param index [Integer]
|
102
|
+
# @return [Constant, nil]
|
71
103
|
def get_constant(index)
|
72
104
|
pointer = FFI::MemoryPointer.new(:pointer)
|
73
105
|
res = ergo_lib_ergo_tree_get_constant(self.pointer, index, pointer)
|
@@ -79,6 +111,10 @@ module Sigma
|
|
79
111
|
end
|
80
112
|
end
|
81
113
|
|
114
|
+
# Replace the constant of the ``ErgoTree`` with the given `constant` at position `index`. Throws if no constant exists at `index`.
|
115
|
+
# @param index: [Integer]
|
116
|
+
# @param constant: [Constant]
|
117
|
+
# @return [ErgoTree] ErgoTree with constant replaced (updates self)
|
82
118
|
def replace_constant(index:, constant:)
|
83
119
|
pointer = FFI::MemoryPointer.new(:pointer)
|
84
120
|
error = ergo_lib_ergo_tree_with_constant(self.pointer, index, constant.pointer, pointer)
|
@@ -89,6 +125,8 @@ module Sigma
|
|
89
125
|
self.class.init(pointer, obj: self)
|
90
126
|
end
|
91
127
|
|
128
|
+
# Equality check
|
129
|
+
# @param ergo_tree_two [ErgoTree]
|
92
130
|
def ==(ergo_tree_two)
|
93
131
|
ergo_lib_ergo_tree_eq(self.pointer, ergo_tree_two.pointer)
|
94
132
|
end
|
@@ -105,7 +143,5 @@ module Sigma
|
|
105
143
|
)
|
106
144
|
obj
|
107
145
|
end
|
108
|
-
|
109
|
-
|
110
146
|
end
|
111
147
|
end
|
data/lib/sigma/input.rb
CHANGED
@@ -3,6 +3,7 @@ require_relative './util.rb'
|
|
3
3
|
require 'ffi-compiler/loader'
|
4
4
|
|
5
5
|
module Sigma
|
6
|
+
# Signed inputs used in signed transactions
|
6
7
|
class Input
|
7
8
|
extend FFI::Library
|
8
9
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -12,16 +13,24 @@ module Sigma
|
|
12
13
|
attach_function :ergo_lib_input_box_id, [:pointer, :pointer], :void
|
13
14
|
attach_function :ergo_lib_input_spending_proof, [:pointer, :pointer], :void
|
14
15
|
|
16
|
+
# Takes ownership of an existing Input Pointer.
|
17
|
+
# @note A user of sigma_rb generally does not need to call this function
|
18
|
+
# @param pointer [FFI::MemoryPointer]
|
19
|
+
# @return [Input]
|
15
20
|
def self.with_raw_pointer(pointer)
|
16
21
|
init(pointer)
|
17
22
|
end
|
18
23
|
|
24
|
+
# Get box id
|
25
|
+
# @return [BoxId]
|
19
26
|
def get_box_id
|
20
27
|
pointer = FFI::MemoryPointer.new(:pointer)
|
21
28
|
ergo_lib_input_box_id(self.pointer, pointer)
|
22
29
|
Sigma::BoxId.with_raw_pointer(pointer)
|
23
30
|
end
|
24
31
|
|
32
|
+
# Get spending proof
|
33
|
+
# @return [ProverResult]
|
25
34
|
def get_spending_proof
|
26
35
|
pointer = FFI::MemoryPointer.new(:pointer)
|
27
36
|
ergo_lib_input_spending_proof(self.pointer, pointer)
|
@@ -42,6 +51,7 @@ module Sigma
|
|
42
51
|
end
|
43
52
|
end
|
44
53
|
|
54
|
+
# An ordered collectino of Input
|
45
55
|
class Inputs
|
46
56
|
extend FFI::Library
|
47
57
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -54,10 +64,16 @@ module Sigma
|
|
54
64
|
|
55
65
|
attr_accessor :pointer
|
56
66
|
|
67
|
+
# Takes ownership of an existing Inputs Pointer.
|
68
|
+
# @note A user of sigma_rb generally does not need to call this function
|
69
|
+
# @param pointer [FFI::MemoryPointer]
|
70
|
+
# @return [Inputs]
|
57
71
|
def self.with_raw_pointer(unread_pointer)
|
58
72
|
init(unread_pointer)
|
59
73
|
end
|
60
74
|
|
75
|
+
# Create an empty collection
|
76
|
+
# @return [Inputs]
|
61
77
|
def self.create
|
62
78
|
pointer = FFI::MemoryPointer.new(:pointer)
|
63
79
|
ergo_lib_inputs_new(pointer)
|
@@ -65,14 +81,21 @@ module Sigma
|
|
65
81
|
init(pointer)
|
66
82
|
end
|
67
83
|
|
84
|
+
# Get length of collection
|
85
|
+
# @return [Integer]
|
68
86
|
def len
|
69
87
|
ergo_lib_inputs_len(self.pointer)
|
70
88
|
end
|
71
89
|
|
90
|
+
# Add to collection
|
91
|
+
# @param input [Input]
|
72
92
|
def add(input)
|
73
93
|
ergo_lib_inputs_add(input.pointer, self.pointer)
|
74
94
|
end
|
75
95
|
|
96
|
+
# Get item at specified index or return nil if no item exists
|
97
|
+
# @params index [Integer]
|
98
|
+
# @return [Input, nil]
|
76
99
|
def get(index)
|
77
100
|
pointer = FFI::MemoryPointer.new(:pointer)
|
78
101
|
res = ergo_lib_inputs_get(self.pointer, index, pointer)
|
@@ -98,6 +121,7 @@ module Sigma
|
|
98
121
|
end
|
99
122
|
end
|
100
123
|
|
124
|
+
# Proof of correctness for transaction spending
|
101
125
|
class ProverResult
|
102
126
|
extend FFI::Library
|
103
127
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -109,6 +133,8 @@ module Sigma
|
|
109
133
|
attach_function :ergo_lib_prover_result_proof_len, [:pointer], :uint
|
110
134
|
attr_accessor :pointer
|
111
135
|
|
136
|
+
# Get proof bytes
|
137
|
+
# @return [Array<uint8>] Array of 8-bit integers [0-255]
|
112
138
|
def to_bytes
|
113
139
|
proof_len = ergo_lib_prover_result_proof_len(self.pointer)
|
114
140
|
b_ptr = FFI::MemoryPointer.new(:uint8, proof_len)
|
@@ -116,12 +142,16 @@ module Sigma
|
|
116
142
|
b_ptr.get_array_of_uint8(0, proof_len)
|
117
143
|
end
|
118
144
|
|
145
|
+
# Get context extension
|
146
|
+
# @return [ContextExtension]
|
119
147
|
def get_context_extension
|
120
148
|
pointer = FFI::MemoryPointer.new(:pointer)
|
121
149
|
ergo_lib_prover_result_context_extension(self.pointer, pointer)
|
122
150
|
Sigma::ContextExtension.with_raw_pointer(pointer)
|
123
151
|
end
|
124
152
|
|
153
|
+
# JSON representation as text (compatible with Ergo Node/Explorer API, numbers are encoded as numbers)
|
154
|
+
# @return [String]
|
125
155
|
def to_json
|
126
156
|
s_ptr = FFI::MemoryPointer.new(:pointer, 1)
|
127
157
|
error = ergo_lib_prover_result_to_json(self.pointer, s_ptr)
|
@@ -132,6 +162,10 @@ module Sigma
|
|
132
162
|
str
|
133
163
|
end
|
134
164
|
|
165
|
+
# Takes ownership of an existing ProverResult Pointer.
|
166
|
+
# @note A user of sigma_rb generally does not need to call this function
|
167
|
+
# @param pointer [FFI::MemoryPointer]
|
168
|
+
# @return [ProverResult]
|
135
169
|
def self.with_raw_pointer(pointer)
|
136
170
|
init(pointer)
|
137
171
|
end
|
@@ -148,9 +182,9 @@ module Sigma
|
|
148
182
|
)
|
149
183
|
obj
|
150
184
|
end
|
151
|
-
|
152
185
|
end
|
153
186
|
|
187
|
+
# Unsigned inputs used in constructing unsigned transactions
|
154
188
|
class UnsignedInput
|
155
189
|
extend FFI::Library
|
156
190
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -161,16 +195,24 @@ module Sigma
|
|
161
195
|
|
162
196
|
attr_accessor :pointer
|
163
197
|
|
198
|
+
# Takes ownership of an existing UnsignedInput Pointer.
|
199
|
+
# @note A user of sigma_rb generally does not need to call this function
|
200
|
+
# @param pointer [FFI::MemoryPointer]
|
201
|
+
# @return [UnsignedInput]
|
164
202
|
def self.with_raw_pointer(pointer)
|
165
203
|
init(pointer)
|
166
204
|
end
|
167
205
|
|
206
|
+
# Get box id
|
207
|
+
# @return [BoxId]
|
168
208
|
def get_box_id
|
169
209
|
pointer = FFI::MemoryPointer.new(:pointer)
|
170
210
|
ergo_lib_unsigned_input_box_id(self.pointer, pointer)
|
171
211
|
Sigma::BoxId.with_raw_pointer(pointer)
|
172
212
|
end
|
173
213
|
|
214
|
+
# Get context extension
|
215
|
+
# @return [ContextExension]
|
174
216
|
def get_context_extension
|
175
217
|
pointer = FFI::MemoryPointer.new(:pointer)
|
176
218
|
ergo_lib_unsigned_input_context_extension(self.pointer, pointer)
|
@@ -191,6 +233,7 @@ module Sigma
|
|
191
233
|
end
|
192
234
|
end
|
193
235
|
|
236
|
+
# An ordered collection of UnsignedInput
|
194
237
|
class UnsignedInputs
|
195
238
|
extend FFI::Library
|
196
239
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -203,10 +246,16 @@ module Sigma
|
|
203
246
|
|
204
247
|
attr_accessor :pointer
|
205
248
|
|
249
|
+
# Takes ownership of an existing UnsignedInputs Pointer.
|
250
|
+
# @note A user of sigma_rb generally does not need to call this function
|
251
|
+
# @param pointer [FFI::MemoryPointer]
|
252
|
+
# @return [UnsignedInputs]
|
206
253
|
def self.with_raw_pointer(unread_pointer)
|
207
254
|
init(unread_pointer)
|
208
255
|
end
|
209
256
|
|
257
|
+
# Create an empty collection
|
258
|
+
# @return [UnsignedInputs]
|
210
259
|
def self.create
|
211
260
|
pointer = FFI::MemoryPointer.new(:pointer)
|
212
261
|
ergo_lib_unsigned_inputs_new(pointer)
|
@@ -214,14 +263,21 @@ module Sigma
|
|
214
263
|
init(pointer)
|
215
264
|
end
|
216
265
|
|
266
|
+
# Get length of collection
|
267
|
+
# @return [Integer]
|
217
268
|
def len
|
218
269
|
ergo_lib_unsigned_inputs_len(self.pointer)
|
219
270
|
end
|
220
271
|
|
272
|
+
# Add to collection
|
273
|
+
# @param unsigned_input [UnsignedInput]
|
221
274
|
def add(unsigned_input)
|
222
275
|
ergo_lib_unsigned_inputs_add(unsigned_input.pointer, self.pointer)
|
223
276
|
end
|
224
277
|
|
278
|
+
# Get item at specified index or return nil if no item exists
|
279
|
+
# @params index [Integer]
|
280
|
+
# @return [UnsignedInput, nil]
|
225
281
|
def get(index)
|
226
282
|
pointer = FFI::MemoryPointer.new(:pointer)
|
227
283
|
res = ergo_lib_unsigned_inputs_get(self.pointer, index, pointer)
|
data/lib/sigma/merkle_proof.rb
CHANGED
@@ -31,6 +31,10 @@ module Sigma
|
|
31
31
|
init(pointer)
|
32
32
|
end
|
33
33
|
|
34
|
+
# Adds a new node and it's hash to the MerkleProof. Hash must be 32 bytes in size
|
35
|
+
# @param hash: [Array<uint8, 32>]
|
36
|
+
# @param side: [Integer]
|
37
|
+
# @see NODE_SIDE_ENUM
|
34
38
|
def add_node(hash:, side:)
|
35
39
|
b_ptr = FFI::MemoryPointer.new(:uint8, hash.size)
|
36
40
|
b_ptr.write_array_of_uint8(hash)
|
@@ -38,7 +42,9 @@ module Sigma
|
|
38
42
|
Util.check_error!(error)
|
39
43
|
end
|
40
44
|
|
41
|
-
#
|
45
|
+
# Validates the MerkleProof against the provided root hash
|
46
|
+
# @param hash [Array<uint8>, String]
|
47
|
+
# @return [bool]
|
42
48
|
def valid(hash)
|
43
49
|
if hash.is_a?(Array)
|
44
50
|
valid_with_array(hash)
|
data/lib/sigma/nipopow.rb
CHANGED
@@ -14,6 +14,9 @@ module Sigma
|
|
14
14
|
|
15
15
|
attr_accessor :pointer
|
16
16
|
|
17
|
+
# Parse NiPoPow from json
|
18
|
+
# @param json [String]
|
19
|
+
# @return [NipopowProof]
|
17
20
|
def self.with_json(json)
|
18
21
|
pointer = FFI::MemoryPointer.new(:pointer)
|
19
22
|
error = ergo_lib_nipopow_proof_from_json(json, pointer)
|
@@ -21,6 +24,9 @@ module Sigma
|
|
21
24
|
init(pointer)
|
22
25
|
end
|
23
26
|
|
27
|
+
# Implementation of the ≥ algorithm from [`KMZ17`], see Algorithm 4
|
28
|
+
# @return [bool]
|
29
|
+
# @see https://fc20.ifca.ai/preproceedings/74.pdf KMZ17
|
24
30
|
def is_better_than(other_proof)
|
25
31
|
pointer = FFI::MemoryPointer.new(:pointer)
|
26
32
|
res = ergo_lib_nipopow_proof_is_better_than(self.pointer, other_proof.pointer)
|
@@ -28,6 +34,8 @@ module Sigma
|
|
28
34
|
res[:value]
|
29
35
|
end
|
30
36
|
|
37
|
+
# JSON representation
|
38
|
+
# @return [String]
|
31
39
|
def to_json
|
32
40
|
s_ptr = FFI::MemoryPointer.new(:pointer, 1)
|
33
41
|
error = ergo_lib_nipopow_proof_to_json(self.pointer, s_ptr)
|
@@ -52,6 +60,8 @@ module Sigma
|
|
52
60
|
end
|
53
61
|
end
|
54
62
|
|
63
|
+
# A verifier for PoPoW proofs. During its lifetime, it processes many proofs with the aim of
|
64
|
+
# deducing at any given point what is the best (sub)chain rooted at the specified genesis.
|
55
65
|
class NipopowVerifier
|
56
66
|
extend FFI::Library
|
57
67
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -62,18 +72,25 @@ module Sigma
|
|
62
72
|
attach_function :ergo_lib_nipopow_verifier_process, [:pointer,:pointer], :error_pointer
|
63
73
|
attr_accessor :pointer
|
64
74
|
|
75
|
+
# Create new instance
|
76
|
+
# @param genesis_block_id [BlockId]
|
77
|
+
# @return [NipopowVerifier]
|
65
78
|
def self.create(genesis_block_id)
|
66
79
|
pointer = FFI::MemoryPointer.new(:pointer)
|
67
80
|
ergo_lib_nipopow_verifier_new(genesis_block_id.pointer, pointer)
|
68
81
|
init(pointer)
|
69
82
|
end
|
70
83
|
|
84
|
+
# Returns chain of `BlockHeader`s from the best proof.
|
85
|
+
# @return [BlockHeaders]
|
71
86
|
def best_chain
|
72
87
|
pointer = FFI::MemoryPointer.new(:pointer)
|
73
88
|
ergo_lib_nipopow_verifier_best_chain(self.pointer, pointer)
|
74
89
|
BlockHeaders.with_raw_pointer(pointer)
|
75
90
|
end
|
76
91
|
|
92
|
+
# Process given proof
|
93
|
+
# @param proof [NipopowProof]
|
77
94
|
def process(proof)
|
78
95
|
error = ergo_lib_nipopow_verifier_process(self.pointer, proof.pointer)
|
79
96
|
Util.check_error!(error)
|
@@ -104,6 +121,9 @@ module Sigma
|
|
104
121
|
attach_function :ergo_lib_po_pow_header_eq, [:pointer, :pointer], :bool
|
105
122
|
attr_accessor :pointer
|
106
123
|
|
124
|
+
# Create from json
|
125
|
+
# @param json [String]
|
126
|
+
# @return [PoPowHeader]
|
107
127
|
def self.with_json(json)
|
108
128
|
pointer = FFI::MemoryPointer.new(:pointer)
|
109
129
|
error = ergo_lib_popow_header_from_json(json, pointer)
|
@@ -111,6 +131,8 @@ module Sigma
|
|
111
131
|
init(pointer)
|
112
132
|
end
|
113
133
|
|
134
|
+
# JSON representation
|
135
|
+
# @return [String]
|
114
136
|
def to_json
|
115
137
|
s_ptr = FFI::MemoryPointer.new(:pointer, 1)
|
116
138
|
error = ergo_lib_popow_header_to_json(self.pointer, s_ptr)
|
@@ -121,6 +143,8 @@ module Sigma
|
|
121
143
|
str
|
122
144
|
end
|
123
145
|
|
146
|
+
# Get header
|
147
|
+
# @return [BlockHeader]
|
124
148
|
def get_header
|
125
149
|
pointer = FFI::MemoryPointer.new(:pointer)
|
126
150
|
error = ergo_lib_popow_header_get_header(self.pointer, pointer)
|
@@ -128,6 +152,8 @@ module Sigma
|
|
128
152
|
BlockHeader.with_raw_pointer(pointer)
|
129
153
|
end
|
130
154
|
|
155
|
+
# Get interlinks
|
156
|
+
# @return [BlockIds]
|
131
157
|
def get_interlinks
|
132
158
|
pointer = FFI::MemoryPointer.new(:pointer)
|
133
159
|
error = ergo_lib_popow_header_get_interlinks(self.pointer, pointer)
|
@@ -135,6 +161,9 @@ module Sigma
|
|
135
161
|
BlockIds.with_raw_pointer(pointer)
|
136
162
|
end
|
137
163
|
|
164
|
+
# Equality check
|
165
|
+
# @param other_header [PoPowHeader]
|
166
|
+
# @return [bool]
|
138
167
|
def ==(other_header)
|
139
168
|
ergo_lib_po_pow_header_eq(self.pointer, other_header.pointer)
|
140
169
|
end
|
data/lib/sigma/pre_header.rb
CHANGED
@@ -3,6 +3,7 @@ require_relative './util.rb'
|
|
3
3
|
require 'ffi-compiler/loader'
|
4
4
|
|
5
5
|
module Sigma
|
6
|
+
# Block header with the current `spendingTransaction`, that can be predicted by a miner before its formation
|
6
7
|
class PreHeader
|
7
8
|
extend FFI::Library
|
8
9
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -12,12 +13,18 @@ module Sigma
|
|
12
13
|
attach_function :ergo_lib_pre_header_eq, [:pointer, :pointer], :bool
|
13
14
|
attr_accessor :pointer
|
14
15
|
|
16
|
+
# Create using data from block_header
|
17
|
+
# @param block_header [BlockHeader]
|
18
|
+
# @return [PreHeader]
|
15
19
|
def self.with_block_header(block_header)
|
16
20
|
pointer = FFI::MemoryPointer.new(:pointer)
|
17
21
|
ergo_lib_preheader_from_block_header(block_header.pointer, pointer)
|
18
22
|
init(pointer)
|
19
23
|
end
|
20
24
|
|
25
|
+
# Equality check
|
26
|
+
# @param ph_two [PreHeader]
|
27
|
+
# @return [bool]
|
21
28
|
def ==(ph_two)
|
22
29
|
ergo_lib_pre_header_eq(self.pointer, ph_two.pointer)
|
23
30
|
end
|
@@ -3,6 +3,13 @@ require_relative './util.rb'
|
|
3
3
|
require 'ffi-compiler/loader'
|
4
4
|
|
5
5
|
module Sigma
|
6
|
+
# Represent `reduced` transaction, i.e. unsigned transaction where each unsigned input
|
7
|
+
# is augmented with ReducedInput which contains a script reduction result.
|
8
|
+
# After an unsigned transaction is reduced it can be signed without context.
|
9
|
+
# Thus, it can be serialized and transferred for example to Cold Wallet and signed
|
10
|
+
# in an environment where secrets are known.
|
11
|
+
# see EIP-19 for more details
|
12
|
+
# @see https://github.com/ergoplatform/eips/blob/f280890a4163f2f2e988a0091c078e36912fc531/eip-0019.md EIP-19
|
6
13
|
class ReducedTransaction
|
7
14
|
extend FFI::Library
|
8
15
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -12,6 +19,13 @@ module Sigma
|
|
12
19
|
attach_function :ergo_lib_reduced_tx_unsigned_tx, [:pointer, :pointer], :void
|
13
20
|
attr_accessor :pointer
|
14
21
|
|
22
|
+
# Create `reduced` transaction, i.e. unsigned transaction where each unsigned input
|
23
|
+
# is augmented with ReducedInput which contains a script reduction result.
|
24
|
+
# @param unsigned_tx: [UnsignedTransaction]
|
25
|
+
# @param boxes_to_spend: [ErgoBoxes]
|
26
|
+
# @param data_boxes: [ErgoBoxes]
|
27
|
+
# @param state_context: [ErgoStateContext]
|
28
|
+
# @return [ReducedTransaction]
|
15
29
|
def self.from_unsigned_tx(unsigned_tx:, boxes_to_spend:, data_boxes:, state_context:)
|
16
30
|
pointer = FFI::MemoryPointer.new(:pointer)
|
17
31
|
error = ergo_lib_reduced_tx_from_unsigned_tx(
|
@@ -25,10 +39,16 @@ module Sigma
|
|
25
39
|
init(pointer)
|
26
40
|
end
|
27
41
|
|
42
|
+
# Takes ownership of an existing ReducedTransaction Pointer.
|
43
|
+
# @note A user of sigma_rb generally does not need to call this function
|
44
|
+
# @param pointer [FFI::MemoryPointer]
|
45
|
+
# @return [ReducedTransaction]
|
28
46
|
def self.with_raw_pointer(pointer)
|
29
47
|
init(pointer)
|
30
48
|
end
|
31
49
|
|
50
|
+
# Get unsigned transaction
|
51
|
+
# @return [UnsignedTransaction]
|
32
52
|
def get_unsigned_transaction
|
33
53
|
pointer = FFI::MemoryPointer.new(:pointer)
|
34
54
|
ergo_lib_reduced_tx_unsigned_tx(self.pointer, pointer)
|
@@ -49,6 +69,7 @@ module Sigma
|
|
49
69
|
end
|
50
70
|
end
|
51
71
|
|
72
|
+
# Propositions list (public keys)
|
52
73
|
class Propositions
|
53
74
|
extend FFI::Library
|
54
75
|
ffi_lib FFI::Compiler::Loader.find('csigma')
|
@@ -58,12 +79,16 @@ module Sigma
|
|
58
79
|
attach_function :ergo_lib_propositions_add_proposition_from_bytes, [:pointer, :pointer, :uint], :error_pointer
|
59
80
|
attr_accessor :pointer
|
60
81
|
|
82
|
+
# Create an empty collection
|
83
|
+
# @return [Propositions]
|
61
84
|
def self.create
|
62
85
|
pointer = FFI::MemoryPointer.new(:pointer)
|
63
86
|
ergo_lib_propositions_new(pointer)
|
64
87
|
init(pointer)
|
65
88
|
end
|
66
89
|
|
90
|
+
# Add a proposition
|
91
|
+
# @param bytes [Array<uint8>] Array of 8-bit integers (0-255)
|
67
92
|
def add_proposition(bytes)
|
68
93
|
b_ptr = FFI::MemoryPointer.new(:uint8, bytes.size)
|
69
94
|
b_ptr.write_array_of_uint8(bytes)
|