bitcoinkernel 0.1.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.
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BitcoinKernel
4
+ # Represents a transaction ID (txid).
5
+ class Txid < FFI::AutoPointer
6
+ # @param [FFI::Pointer] ptr Pointer to btck_Txid
7
+ # @param [Boolean] owned Whether this object owns the pointer.
8
+ # When obtained via Transaction#txid_ptr, the pointer is NOT owned
9
+ # and depends on the lifetime of the parent Transaction.
10
+ # In that case, owned should be false to prevent double-free.
11
+ def initialize(ptr, owned: true)
12
+ super(ptr)
13
+ self.autorelease = owned
14
+ end
15
+
16
+ def self.release(ptr)
17
+ BitcoinKernel.btck_txid_destroy(ptr)
18
+ end
19
+
20
+ # Get the txid as raw bytes.
21
+ # @return [String] 32-byte binary string
22
+ def to_bytes
23
+ output = FFI::MemoryPointer.new(:uint8, 32)
24
+ BitcoinKernel.btck_txid_to_bytes(self, output)
25
+ output.read_bytes(32)
26
+ end
27
+
28
+ # Get the txid as hex string (little-endian, as commonly displayed).
29
+ # @return [String]
30
+ def to_hex
31
+ to_bytes.reverse.unpack1('H*')
32
+ end
33
+
34
+ # Compare two txids for equality.
35
+ # @param [Txid] other The other txid to compare
36
+ # @return [Boolean]
37
+ def ==(other)
38
+ return false unless other.is_a?(Txid)
39
+ BitcoinKernel.btck_txid_equals(self, other) == 1
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BitcoinKernel
4
+ # Base class for receiving validation interface callbacks.
5
+ # Subclass this and override the methods you need.
6
+ #
7
+ # @example
8
+ # class MyValidationInterface < BitcoinKernel::ValidationInterface
9
+ # def block_checked(block, state)
10
+ # if state.valid?
11
+ # puts "Block valid: #{block.block_hash.to_hex}"
12
+ # end
13
+ # end
14
+ #
15
+ # def block_connected(block, entry)
16
+ # puts "Block connected at height #{entry.height}"
17
+ # end
18
+ # end
19
+ #
20
+ # vi = MyValidationInterface.new
21
+ # options = BitcoinKernel::ContextOptions.create
22
+ # options.set_validation_interface(vi)
23
+ class ValidationInterface
24
+ def initialize
25
+ # Store procs to prevent garbage collection
26
+ @stored_procs = []
27
+ end
28
+
29
+ # Called when a block has been fully validated.
30
+ # @param [Block] block The validated block
31
+ # @param [BlockValidationState] state The validation state
32
+ def block_checked(block, state)
33
+ # Override in subclass
34
+ end
35
+
36
+ # Called when a block extends the header chain with valid PoW.
37
+ # @param [Block] block The block
38
+ # @param [BlockTreeEntry] entry The block tree entry
39
+ def pow_valid_block(block, entry)
40
+ # Override in subclass
41
+ end
42
+
43
+ # Called when a block is connected to the best chain.
44
+ # @param [Block] block The connected block
45
+ # @param [BlockTreeEntry] entry The block tree entry
46
+ def block_connected(block, entry)
47
+ # Override in subclass
48
+ end
49
+
50
+ # Called when a block is disconnected during a reorg.
51
+ # @param [Block] block The disconnected block
52
+ # @param [BlockTreeEntry] entry The block tree entry
53
+ def block_disconnected(block, entry)
54
+ # Override in subclass
55
+ end
56
+
57
+ # Build the FFI callbacks struct.
58
+ # @return [ValidationInterfaceCallbacks]
59
+ # @api private
60
+ def to_ffi_callbacks
61
+ callbacks = ValidationInterfaceCallbacks.new
62
+
63
+ callbacks[:user_data] = FFI::Pointer::NULL
64
+ callbacks[:user_data_destroy] = nil
65
+
66
+ block_checked_proc = create_block_checked_proc
67
+ @stored_procs << block_checked_proc
68
+ callbacks[:block_checked] = block_checked_proc
69
+
70
+ pow_valid_block_proc = create_block_entry_proc(:pow_valid_block)
71
+ @stored_procs << pow_valid_block_proc
72
+ callbacks[:pow_valid_block] = pow_valid_block_proc
73
+
74
+ block_connected_proc = create_block_entry_proc(:block_connected)
75
+ @stored_procs << block_connected_proc
76
+ callbacks[:block_connected] = block_connected_proc
77
+
78
+ block_disconnected_proc = create_block_entry_proc(:block_disconnected)
79
+ @stored_procs << block_disconnected_proc
80
+ callbacks[:block_disconnected] = block_disconnected_proc
81
+
82
+ callbacks
83
+ end
84
+
85
+ private
86
+
87
+ def create_block_checked_proc
88
+ proc do |_user_data, block_ptr, state_ptr|
89
+ # Copy the block since the pointer may not be owned
90
+ copied_ptr = BitcoinKernel.btck_block_copy(block_ptr)
91
+ block = Block.new(copied_ptr)
92
+ state = BlockValidationState.new(state_ptr)
93
+ block_checked(block, state)
94
+ end
95
+ end
96
+
97
+ def create_block_entry_proc(method_name)
98
+ proc do |_user_data, block_ptr, entry_ptr|
99
+ # Copy the block since the pointer may not be owned
100
+ copied_ptr = BitcoinKernel.btck_block_copy(block_ptr)
101
+ block = Block.new(copied_ptr)
102
+ entry = BlockTreeEntry.new(entry_ptr, owned: false)
103
+ send(method_name, block, entry)
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BitcoinKernel
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,207 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "bitcoinkernel/version"
4
+ require 'ffi'
5
+
6
+ # Bitcoin Kernel bindings.
7
+ module BitcoinKernel
8
+ class Error < StandardError; end
9
+
10
+ extend FFI::Library
11
+ ffi_lib(ENV['LIB_BITCOINKERNEL_PATH'])
12
+
13
+ # Chain types
14
+ module ChainType
15
+ MAINNET = 0
16
+ TESTNET = 1
17
+ TESTNET_4 = 2
18
+ SIGNET = 3
19
+ REGTEST = 4
20
+ end
21
+
22
+ # Validation modes
23
+ module ValidationMode
24
+ VALID = 0
25
+ INVALID = 1
26
+ INTERNAL_ERROR = 2
27
+ end
28
+
29
+ # Block validation results
30
+ module BlockValidationResult
31
+ UNSET = 0
32
+ CONSENSUS = 1
33
+ CACHED_INVALID = 2
34
+ INVALID_HEADER = 3
35
+ MUTATED = 4
36
+ MISSING_PREV = 5
37
+ INVALID_PREV = 6
38
+ TIME_FUTURE = 7
39
+ HEADER_LOW_WORK = 8
40
+ end
41
+
42
+ # Script verification flags
43
+ module ScriptFlags
44
+ NONE = 0
45
+ P2SH = (1 << 0)
46
+ DERSIG = (1 << 2)
47
+ NULLDUMMY = (1 << 4)
48
+ CHECKLOCKTIMEVERIFY = (1 << 9)
49
+ CHECKSEQUENCEVERIFY = (1 << 10)
50
+ WITNESS = (1 << 11)
51
+ TAPROOT = (1 << 17)
52
+ ALL = P2SH | DERSIG | NULLDUMMY | CHECKLOCKTIMEVERIFY | CHECKSEQUENCEVERIFY | WITNESS | TAPROOT
53
+ end
54
+
55
+ # Load Logging module early (required for attach_function)
56
+ require_relative 'bitcoinkernel/logging'
57
+
58
+ # Callback for serializing data
59
+ callback :btck_write_bytes, [:pointer, :size_t, :pointer], :int
60
+
61
+ # Validation interface callbacks
62
+ callback :btck_validation_interface_block_checked, [:pointer, :pointer, :pointer], :void
63
+ callback :btck_validation_interface_pow_valid_block, [:pointer, :pointer, :pointer], :void
64
+ callback :btck_validation_interface_block_connected, [:pointer, :pointer, :pointer], :void
65
+ callback :btck_validation_interface_block_disconnected, [:pointer, :pointer, :pointer], :void
66
+ callback :btck_destroy_callback, [:pointer], :void
67
+
68
+ # Validation interface callbacks struct
69
+ class ValidationInterfaceCallbacks < FFI::Struct
70
+ layout :user_data, :pointer,
71
+ :user_data_destroy, :btck_destroy_callback,
72
+ :block_checked, :btck_validation_interface_block_checked,
73
+ :pow_valid_block, :btck_validation_interface_pow_valid_block,
74
+ :block_connected, :btck_validation_interface_block_connected,
75
+ :block_disconnected, :btck_validation_interface_block_disconnected
76
+ end
77
+
78
+ # Logging
79
+ attach_function :btck_logging_disable, [], :void
80
+ attach_function :btck_logging_set_options, [Logging::Options.by_value], :void
81
+ attach_function :btck_logging_set_level_category, [:uint8, :uint8], :void
82
+ attach_function :btck_logging_enable_category, [:uint8], :void
83
+ attach_function :btck_logging_disable_category, [:uint8], :void
84
+
85
+ # Chain parameters
86
+ attach_function :btck_chain_parameters_create, [:uint8], :pointer
87
+ attach_function :btck_chain_parameters_destroy, [:pointer], :void
88
+
89
+ # Context options
90
+ attach_function :btck_context_options_create, [], :pointer
91
+ attach_function :btck_context_options_set_chainparams, [:pointer, :pointer], :void
92
+ attach_function :btck_context_options_set_validation_interface, [:pointer, ValidationInterfaceCallbacks.by_value], :void
93
+ attach_function :btck_context_options_destroy, [:pointer], :void
94
+
95
+ # Context
96
+ attach_function :btck_context_create, [:pointer], :pointer
97
+ attach_function :btck_context_destroy, [:pointer], :void
98
+ attach_function :btck_context_interrupt, [:pointer], :int
99
+
100
+ # Chainstate manager options
101
+ attach_function :btck_chainstate_manager_options_create, [:pointer, :string, :size_t, :string, :size_t], :pointer
102
+ attach_function :btck_chainstate_manager_options_set_worker_threads_num, [:pointer, :int], :void
103
+ attach_function :btck_chainstate_manager_options_set_wipe_dbs, [:pointer, :int, :int], :int
104
+ attach_function :btck_chainstate_manager_options_update_block_tree_db_in_memory, [:pointer, :int], :void
105
+ attach_function :btck_chainstate_manager_options_update_chainstate_db_in_memory, [:pointer, :int], :void
106
+ attach_function :btck_chainstate_manager_options_destroy, [:pointer], :void
107
+
108
+ # Chainstate manager
109
+ attach_function :btck_chainstate_manager_create, [:pointer], :pointer
110
+ attach_function :btck_chainstate_manager_process_block, [:pointer, :pointer, :pointer], :int
111
+ attach_function :btck_chainstate_manager_get_active_chain, [:pointer], :pointer
112
+ attach_function :btck_chainstate_manager_get_block_tree_entry_by_hash, [:pointer, :pointer], :pointer
113
+ attach_function :btck_chainstate_manager_destroy, [:pointer], :void
114
+
115
+ # Block
116
+ attach_function :btck_block_create, [:pointer, :size_t], :pointer
117
+ attach_function :btck_block_copy, [:pointer], :pointer
118
+ attach_function :btck_block_count_transactions, [:pointer], :size_t
119
+ attach_function :btck_block_get_transaction_at, [:pointer, :size_t], :pointer
120
+ attach_function :btck_block_get_hash, [:pointer], :pointer
121
+ attach_function :btck_block_to_bytes, [:pointer, :btck_write_bytes, :pointer], :int
122
+ attach_function :btck_block_destroy, [:pointer], :void
123
+
124
+ # Block hash
125
+ attach_function :btck_block_hash_create, [:pointer], :pointer
126
+ attach_function :btck_block_hash_equals, [:pointer, :pointer], :int
127
+ attach_function :btck_block_hash_to_bytes, [:pointer, :pointer], :void
128
+ attach_function :btck_block_hash_destroy, [:pointer], :void
129
+
130
+ # Block validation state
131
+ attach_function :btck_block_validation_state_get_validation_mode, [:pointer], :uint8
132
+ attach_function :btck_block_validation_state_get_block_validation_result, [:pointer], :uint32
133
+
134
+ # Chain
135
+ attach_function :btck_chain_get_height, [:pointer], :int32
136
+ attach_function :btck_chain_get_by_height, [:pointer, :int], :pointer
137
+ attach_function :btck_chain_contains, [:pointer, :pointer], :int
138
+
139
+ # Block tree entry
140
+ attach_function :btck_block_tree_entry_get_height, [:pointer], :int32
141
+ attach_function :btck_block_tree_entry_get_block_hash, [:pointer], :pointer
142
+ attach_function :btck_block_tree_entry_get_previous, [:pointer], :pointer
143
+ attach_function :btck_block_tree_entry_equals, [:pointer, :pointer], :int
144
+
145
+ # Block read (requires ChainstateManager)
146
+ attach_function :btck_block_read, [:pointer, :pointer], :pointer
147
+
148
+ # Transaction
149
+ attach_function :btck_transaction_create, [:pointer, :size_t], :pointer
150
+ attach_function :btck_transaction_copy, [:pointer], :pointer
151
+ attach_function :btck_transaction_to_bytes, [:pointer, :btck_write_bytes, :pointer], :int
152
+ attach_function :btck_transaction_count_outputs, [:pointer], :size_t
153
+ attach_function :btck_transaction_count_inputs, [:pointer], :size_t
154
+ attach_function :btck_transaction_get_output_at, [:pointer, :size_t], :pointer
155
+ attach_function :btck_transaction_get_input_at, [:pointer, :size_t], :pointer
156
+ attach_function :btck_transaction_get_txid, [:pointer], :pointer
157
+ attach_function :btck_transaction_destroy, [:pointer], :void
158
+
159
+ # Transaction output
160
+ attach_function :btck_transaction_output_create, [:pointer, :int64], :pointer
161
+ attach_function :btck_transaction_output_get_script_pubkey, [:pointer], :pointer
162
+ attach_function :btck_transaction_output_get_amount, [:pointer], :int64
163
+ attach_function :btck_transaction_output_destroy, [:pointer], :void
164
+
165
+ # Script pubkey
166
+ attach_function :btck_script_pubkey_create, [:pointer, :size_t], :pointer
167
+ attach_function :btck_script_pubkey_verify, [:pointer, :int64, :pointer, :pointer, :uint, :uint32, :pointer], :int
168
+ attach_function :btck_script_pubkey_to_bytes, [:pointer, :btck_write_bytes, :pointer], :int
169
+ attach_function :btck_script_pubkey_destroy, [:pointer], :void
170
+
171
+ # Precomputed transaction data
172
+ attach_function :btck_precomputed_transaction_data_create, [:pointer, :pointer, :size_t], :pointer
173
+ attach_function :btck_precomputed_transaction_data_destroy, [:pointer], :void
174
+
175
+ # Txid
176
+ attach_function :btck_txid_equals, [:pointer, :pointer], :int
177
+ attach_function :btck_txid_to_bytes, [:pointer, :pointer], :void
178
+ attach_function :btck_txid_destroy, [:pointer], :void
179
+
180
+ # Transaction input
181
+ attach_function :btck_transaction_input_get_out_point, [:pointer], :pointer
182
+ attach_function :btck_transaction_input_destroy, [:pointer], :void
183
+
184
+ # Transaction out point
185
+ attach_function :btck_transaction_out_point_get_index, [:pointer], :uint32
186
+ attach_function :btck_transaction_out_point_get_txid, [:pointer], :pointer
187
+ attach_function :btck_transaction_out_point_destroy, [:pointer], :void
188
+
189
+ autoload :Serializable, 'bitcoinkernel/serializable'
190
+ autoload :Block, 'bitcoinkernel/block'
191
+ autoload :BlockHash, 'bitcoinkernel/block_hash'
192
+ autoload :Transaction, 'bitcoinkernel/transaction'
193
+ autoload :TransactionInput, 'bitcoinkernel/transaction_input'
194
+ autoload :TransactionOutPoint, 'bitcoinkernel/transaction_out_point'
195
+ autoload :TransactionOutput, 'bitcoinkernel/transaction_output'
196
+ autoload :ScriptPubkey, 'bitcoinkernel/script_pubkey'
197
+ autoload :Txid, 'bitcoinkernel/txid'
198
+ autoload :ChainParameters, 'bitcoinkernel/chain_parameters'
199
+ autoload :ContextOptions, 'bitcoinkernel/context_options'
200
+ autoload :Context, 'bitcoinkernel/context'
201
+ autoload :ChainstateManagerOptions, 'bitcoinkernel/chainstate_manager_options'
202
+ autoload :ChainstateManager, 'bitcoinkernel/chainstate_manager'
203
+ autoload :Chain, 'bitcoinkernel/chain'
204
+ autoload :BlockTreeEntry, 'bitcoinkernel/block_tree_entry'
205
+ autoload :BlockValidationState, 'bitcoinkernel/block_validation_state'
206
+ autoload :ValidationInterface, 'bitcoinkernel/validation_interface'
207
+ end
@@ -0,0 +1,4 @@
1
+ module Bitcoinkernel
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bitcoinkernel
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - azuchi
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: ffi
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: 1.17.2
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: 1.17.2
26
+ description: Ruby bindings for BitcoinKernel.
27
+ email:
28
+ - azuchi@chaintope.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - ".rspec"
34
+ - ".ruby-gemset"
35
+ - ".ruby-version"
36
+ - CODE_OF_CONDUCT.md
37
+ - LICENSE.txt
38
+ - README.md
39
+ - Rakefile
40
+ - lib/bitcoinkernel.rb
41
+ - lib/bitcoinkernel/block.rb
42
+ - lib/bitcoinkernel/block_hash.rb
43
+ - lib/bitcoinkernel/block_tree_entry.rb
44
+ - lib/bitcoinkernel/block_validation_state.rb
45
+ - lib/bitcoinkernel/chain.rb
46
+ - lib/bitcoinkernel/chain_parameters.rb
47
+ - lib/bitcoinkernel/chainstate_manager.rb
48
+ - lib/bitcoinkernel/chainstate_manager_options.rb
49
+ - lib/bitcoinkernel/context.rb
50
+ - lib/bitcoinkernel/context_options.rb
51
+ - lib/bitcoinkernel/logging.rb
52
+ - lib/bitcoinkernel/script_pubkey.rb
53
+ - lib/bitcoinkernel/serializable.rb
54
+ - lib/bitcoinkernel/transaction.rb
55
+ - lib/bitcoinkernel/transaction_input.rb
56
+ - lib/bitcoinkernel/transaction_out_point.rb
57
+ - lib/bitcoinkernel/transaction_output.rb
58
+ - lib/bitcoinkernel/txid.rb
59
+ - lib/bitcoinkernel/validation_interface.rb
60
+ - lib/bitcoinkernel/version.rb
61
+ - sig/bitcoinkernel.rbs
62
+ homepage: https://github.com/azuchi/bitcoinkernelrb
63
+ licenses:
64
+ - MIT
65
+ metadata:
66
+ homepage_uri: https://github.com/azuchi/bitcoinkernelrb
67
+ source_code_uri: https://github.com/azuchi/bitcoinkernelrb
68
+ changelog_uri: https://github.com/azuchi/bitcoinkernelrb
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: 3.1.0
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubygems_version: 3.6.9
84
+ specification_version: 4
85
+ summary: Ruby bindings for BitcoinKernel.
86
+ test_files: []