confium 0.5.0-aarch64-linux → 0.6.0-aarch64-linux

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.
@@ -16,19 +16,24 @@ module Confium
16
16
  # service_name: 'confium-issuer'
17
17
  # )
18
18
  #
19
- # Delivery is synchronous per record; failures are reported on
20
- # $stderr and the record is dropped (the audit core's policy — a
21
- # telemetry outage must never break signing). stdlib only.
19
+ # Delivery is synchronous per record, retried with exponential
20
+ # backoff (retries: attempts after the first, base doubled per
21
+ # attempt). After the final failure the record is dropped with a
22
+ # $stderr report — the audit core's policy: a telemetry outage
23
+ # must never break signing. stdlib only.
22
24
  class OtlpSink < Sink
23
25
  DEFAULT_ENDPOINT = 'http://localhost:4318/v1/logs'
24
26
  SEVERITY = { 'success' => 9, 'failure' => 17, 'error' => 17 }.freeze # INFO / ERROR
25
27
 
26
- def initialize(endpoint: DEFAULT_ENDPOINT, headers: {}, service_name: 'confium', timeout: 5)
28
+ def initialize(endpoint: DEFAULT_ENDPOINT, headers: {}, service_name: 'confium', timeout: 5,
29
+ retries: 2, retry_base: 0.1)
27
30
  super()
28
31
  @uri = URI.parse(endpoint)
29
32
  @headers = headers
30
33
  @service_name = service_name
31
34
  @timeout = timeout
35
+ @retries = retries
36
+ @retry_base = retry_base
32
37
  @dropped = 0
33
38
  end
34
39
 
@@ -37,8 +42,7 @@ module Confium
37
42
 
38
43
  def write(record)
39
44
  payload = envelope(record)
40
- response = Net::HTTP.post(@uri, JSON.generate(payload), headers.merge('Content-Type' => 'application/json'))
41
- raise "collector responded #{response.code}" unless response.is_a?(Net::HTTPSuccess)
45
+ deliver(JSON.generate(payload))
42
46
  rescue StandardError => e
43
47
  @dropped += 1
44
48
  warn "confium: OTLP delivery failed, audit record dropped (##{@dropped}): #{e.class}: #{e.message}"
@@ -48,6 +52,19 @@ module Confium
48
52
 
49
53
  private
50
54
 
55
+ # Attempts grow the backoff: retry_base * 2**attempt. When
56
+ # retry_base is 0 (specs) retries run without delay.
57
+ def deliver(body)
58
+ (@retries + 1).times do |attempt|
59
+ sleep(@retry_base * (2**attempt)) if attempt.positive? && @retry_base.positive?
60
+
61
+ response = Net::HTTP.post(@uri, body, headers.merge('Content-Type' => 'application/json'))
62
+ return response if response.is_a?(Net::HTTPSuccess)
63
+
64
+ raise "collector responded #{response.code}" if attempt == @retries
65
+ end
66
+ end
67
+
51
68
  def headers
52
69
  { 'User-Agent' => "confium-otlp-sink #{Confium::VERSION}" }.merge(@headers)
53
70
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Confium
4
+ # Pure resolution of which native-extension ABI windows to try, in
5
+ # order. Extracted from the loader so the decision — the piece with
6
+ # the release-incident history (3.1-window segfaults on 3.2, the
7
+ # cross-major 3.3→4.0 TypeError, windowless platform gems) — is
8
+ # testable without installing eight platform gems.
9
+ module NativeWindows
10
+ # Ordered candidate windows for +ruby_version+ (e.g. "3.4.8").
11
+ #
12
+ # Background: platform gems ship one extension per ABI window.
13
+ # Ruby 3.2 broke the 3.1 ABI (object shapes) and rb-sys references
14
+ # a VM pointer libruby stopped exporting in 3.3, so 3.1/3.2/4.0
15
+ # get exact-minor builds while a 3.3-window binary loads on both
16
+ # 3.3 and 3.4. The 3.3 fallback applies within the 3.x line
17
+ # alone: a cross-major load (4.x) fails TypedData class-identity
18
+ # checks, so 4.0 must not fall back to it.
19
+ def self.candidates(ruby_version)
20
+ minor = ruby_version[/\A\d+\.\d+/]
21
+ raise ArgumentError, "not a ruby version: #{ruby_version.inspect}" unless minor
22
+
23
+ major = ruby_version[/\A\d+/].to_i
24
+ if major == 3 && Gem::Version.new(ruby_version) >= Gem::Version.new('3.3')
25
+ [minor, '3.3'].uniq
26
+ else
27
+ [minor]
28
+ end
29
+ end
30
+ end
31
+ end
@@ -3,9 +3,13 @@
3
3
  # Confium::TC::Coordinator coordinates an in-process threshold
4
4
  # signing session: signers submit commitments and shares at their own
5
5
  # pace; once the threshold is met, aggregation runs the real
6
- # threshold-ECDSA combine (CMP20 or GG18 — the same in-process
7
- # drivers behind Confium::TC::Cmp20 / Confium::TC::Gg18) and returns
8
- # a 64-byte (r, s) signature verifiable under the quorum public key.
6
+ # threshold-ECDSA combine (CMP20 or GG18) and returns a 64-byte
7
+ # (r, s) signature verifiable under the quorum public key.
8
+ #
9
+ # The session semantics (state machine, duplicate-signer rejection,
10
+ # the combine) live in SigningSession; this class is the session
11
+ # registry and quorum-scoped entry point. NetworkCoordinator is the
12
+ # TCP/NDJSON adapter over the same sessions.
9
13
  #
10
14
  # Usage:
11
15
  # coordinator = Confium::TC::Coordinator.new(quorum_id: "biml-root")
@@ -27,54 +31,38 @@ module Confium
27
31
  @sessions = {}
28
32
  end
29
33
 
30
- SCHEMES = {
31
- 'CMP20-ECDSA-P256' => ->(shares, threshold, message) { Cmp20.sign(shares, threshold, message) },
32
- 'GG18-ECDSA-P256' => ->(shares, threshold, message) { Gg18.sign(shares, threshold, message) }
33
- }.freeze
34
-
35
- def create_session(message:, threshold:, unlock_window: 14_400, scheme: 'CMP20-ECDSA-P256')
36
- raise ArgumentError, "unknown scheme: #{scheme} (known: #{SCHEMES.keys.join(', ')})" unless SCHEMES.key?(scheme)
37
-
34
+ def create_session(message:, threshold:, unlock_window: SigningSession::DEFAULT_UNLOCK_WINDOW,
35
+ scheme: 'CMP20-ECDSA-P256')
38
36
  session_id = "session-#{@sessions.length + 1}"
39
- @sessions[session_id] = {
40
- message: message,
41
- threshold: threshold,
42
- unlock_window: unlock_window,
43
- scheme: scheme,
44
- state: :pending,
45
- commitments: [],
46
- shares: []
47
- }
37
+ @sessions[session_id] = SigningSession.new(
38
+ message: message, threshold: threshold,
39
+ unlock_window: unlock_window, scheme: scheme
40
+ )
48
41
  session_id
49
42
  end
50
43
 
51
44
  def session_state(session_id)
52
- @sessions.dig(session_id, :state)
45
+ fetch(session_id).state
53
46
  end
54
47
 
55
48
  def submit_commitment(session_id, signer_id, commitment_bytes)
56
- session = @sessions[session_id] or raise "Unknown session: #{session_id}"
57
- session[:commitments] << { signer_id: signer_id, bytes: commitment_bytes }
58
- return unless session[:commitments].length >= session[:threshold]
59
-
60
- session[:state] = :commitments_collected
49
+ fetch(session_id).add_commitment(signer_id, commitment_bytes)
61
50
  end
62
51
 
63
52
  def submit_share(session_id, signer_id, share_bytes)
64
- session = @sessions[session_id] or raise "Unknown session: #{session_id}"
65
- session[:shares] << { signer_id: signer_id, bytes: share_bytes }
53
+ fetch(session_id).add_share(signer_id, share_bytes)
66
54
  end
67
55
 
68
56
  def aggregate(session_id)
69
- session = @sessions[session_id] or raise "Unknown session: #{session_id}"
70
- raise ThresholdError, 'Threshold not met' if session[:shares].length < session[:threshold]
57
+ fetch(session_id).aggregate
58
+ end
71
59
 
72
- session[:state] = :completed
73
- SCHEMES.fetch(session[:scheme]).call(
74
- session[:shares].map { |s| s[:bytes] },
75
- session[:threshold],
76
- session[:message]
77
- )
60
+ private
61
+
62
+ def fetch(session_id)
63
+ @sessions.fetch(session_id) do
64
+ raise NotFoundError.new("Unknown session: #{session_id}", kind: :session, identifier: session_id)
65
+ end
78
66
  end
79
67
  end
80
68
  end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Confium
4
+ module TC
5
+ # One threshold-signing session: the state machine and the combine
6
+ # behind every coordinator surface. Coordinator (in-process) and
7
+ # NetworkCoordinator (TCP/NDJSON) are adapters over this class —
8
+ # they own registries and framing; the session owns the semantics:
9
+ #
10
+ # pending → commitments_collected (T distinct commitments)
11
+ # → completed (aggregate runs the scheme combine)
12
+ #
13
+ # Aggregate may be called again after completion — the combine
14
+ # randomizes its nonce, so each call yields a fresh (verifiable)
15
+ # signature over the same shares, which is what a network client
16
+ # retrying after a dropped response needs.
17
+ #
18
+ # Signer identity is load-bearing: one signer submitting two
19
+ # shares must never count twice toward the threshold, so
20
+ # commitments and shares are keyed by signer_id and duplicates
21
+ # raise.
22
+ class SigningSession
23
+ DEFAULT_UNLOCK_WINDOW = 14_400
24
+
25
+ SCHEMES = {
26
+ 'CMP20-ECDSA-P256' => ->(shares, threshold, message) { Cmp20.sign(shares, threshold, message) },
27
+ 'GG18-ECDSA-P256' => ->(shares, threshold, message) { Gg18.sign(shares, threshold, message) }
28
+ }.freeze
29
+
30
+ attr_reader :message, :threshold, :unlock_window, :scheme, :state
31
+
32
+ def initialize(message:, threshold:, unlock_window: DEFAULT_UNLOCK_WINDOW, scheme: 'CMP20-ECDSA-P256')
33
+ raise ArgumentError, "unknown scheme: #{scheme} (known: #{SCHEMES.keys.join(', ')})" unless SCHEMES.key?(scheme)
34
+
35
+ @message = message
36
+ @threshold = threshold
37
+ @unlock_window = unlock_window
38
+ @scheme = scheme
39
+ @state = :pending
40
+ # @type ivar @commitments: Hash[String, String]
41
+ @commitments = {}
42
+ # @type ivar @shares: Hash[String, String]
43
+ @shares = {}
44
+ end
45
+
46
+ def add_commitment(signer_id, commitment_bytes)
47
+ record(@commitments, signer_id, commitment_bytes)
48
+ @state = :commitments_collected if @commitments.length >= @threshold
49
+ self
50
+ end
51
+
52
+ def add_share(signer_id, share_bytes)
53
+ record(@shares, signer_id, share_bytes)
54
+ self
55
+ end
56
+
57
+ def commitment_count
58
+ @commitments.length
59
+ end
60
+
61
+ def share_count
62
+ @shares.length
63
+ end
64
+
65
+ def threshold_met?
66
+ @shares.length >= @threshold
67
+ end
68
+
69
+ def aggregate
70
+ unless threshold_met?
71
+ raise ThresholdError.new('Threshold not met', have_count: @shares.length, need_count: @threshold)
72
+ end
73
+
74
+ signature = SCHEMES.fetch(@scheme).call(@shares.values, @threshold, @message)
75
+ @state = :completed
76
+ signature
77
+ end
78
+
79
+ private
80
+
81
+ def record(store, signer_id, bytes)
82
+ if store.key?(signer_id)
83
+ raise ValidationError.new(
84
+ "duplicate submission from signer #{signer_id}",
85
+ param: :signer_id, expected: 'one submission per signer', actual: signer_id
86
+ )
87
+ end
88
+
89
+ store[signer_id] = bytes
90
+ end
91
+ end
92
+ end
93
+ end
data/lib/confium/tc.rb CHANGED
@@ -11,12 +11,10 @@
11
11
  # for the full interface specification.
12
12
  module Confium
13
13
  module TC
14
- # The native extension defines Confium::TC; this namespace file is
15
- # eager-required from confium.rb, so autoloads registered here do
16
- # fire. Coordinator and ShareFile are pure Ruby and load with the
17
- # namespace; Session wraps the engine via FFI and needs the
18
- # external libconfium dylib, so it stays lazy.
19
- autoload :Session, 'confium/tc/session'
14
+ # The native extension defines Confium::TC; this namespace file
15
+ # is eager-required from confium.rb, so autoloads never fire —
16
+ # the pure-Ruby companions load with the namespace directly.
17
+ require_relative 'tc/signing_session'
20
18
  require_relative 'tc/coordinator'
21
19
  require_relative 'tc/network_coordinator'
22
20
  require_relative 'tc/share_file'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Confium
4
- VERSION = '0.5.0'
4
+ VERSION = '0.6.0'
5
5
  end
data/lib/confium.rb CHANGED
@@ -10,25 +10,14 @@
10
10
  # are loaded lazily via autoload — see lib/confium/<name>.rb.
11
11
 
12
12
  require_relative 'confium/version'
13
+ require_relative 'confium/native_windows'
13
14
 
14
15
  begin
15
- # Pre-built platform gems ship one extension per C-ABI window
16
- # (Ruby 3.2 broke the 3.1 ABI — object shapes — and rb-sys
17
- # references the VM pointer libruby stopped exporting in 3.3, so
18
- # 3.1 and 3.2 get exact-minor builds while 3.3 covers 3.3+).
19
- # Source builds install the extension flat, without a version
20
- # directory.
21
- minor = RUBY_VERSION[/\A\d+\.\d+/]
16
+ # Pre-built platform gems ship one extension per ABI window (the
17
+ # window rules live in Confium::NativeWindows). Source builds
18
+ # install the extension flat, without a version directory.
22
19
  dlext = RbConfig::CONFIG['DLEXT'] || 'so'
23
- major = RUBY_VERSION[/\A\d+/].to_i
24
- # 3.3-window binaries load on 3.3/3.4 only; a cross-major load
25
- # (4.x) fails TypedData class checks, so the fallback applies
26
- # within the 3.x line alone.
27
- candidates = major == 3 && Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.3') ? [minor, '3.3'].uniq : [minor]
28
- # Windows gems carry an exact-minor window per Ruby (a PE import
29
- # names the version-specific ruby DLL); other platforms share the
30
- # 3.3 window for 3.3+. Prefer the exact minor when present.
31
- windowed = candidates.filter_map do |w|
20
+ windowed = Confium::NativeWindows.candidates(RUBY_VERSION).filter_map do |w|
32
21
  path = File.expand_path("confium_native/#{w}/confium_native.#{dlext}", __dir__ || '.')
33
22
  w if File.exist?(path)
34
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: confium
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: aarch64-linux
6
6
  authors:
7
7
  - Ribose Open
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-08-24 00:00:00.000000000 Z
11
+ date: 2026-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -100,10 +100,7 @@ files:
100
100
  - lib/confium.rb
101
101
  - lib/confium/audit.rb
102
102
  - lib/confium/audit/otlp_sink.rb
103
- - lib/confium/cfm.rb
104
103
  - lib/confium/composite.rb
105
- - lib/confium/crypto.rb
106
- - lib/confium/digest.rb
107
104
  - lib/confium/errors.rb
108
105
  - lib/confium/errors/coerce.rb
109
106
  - lib/confium/errors/crypto_error.rb
@@ -115,8 +112,7 @@ files:
115
112
  - lib/confium/errors/unresolved_signer_error.rb
116
113
  - lib/confium/errors/validation_error.rb
117
114
  - lib/confium/errors/verification_error.rb
118
- - lib/confium/ffi.rb
119
- - lib/confium/lib.rb
115
+ - lib/confium/native_windows.rb
120
116
  - lib/confium/openpgp.rb
121
117
  - lib/confium/pki.rb
122
118
  - lib/confium/pki/certificate_builder.rb
@@ -128,9 +124,8 @@ files:
128
124
  - lib/confium/tc.rb
129
125
  - lib/confium/tc/coordinator.rb
130
126
  - lib/confium/tc/network_coordinator.rb
131
- - lib/confium/tc/session.rb
132
- - lib/confium/tc/session_stub.rb
133
127
  - lib/confium/tc/share_file.rb
128
+ - lib/confium/tc/signing_session.rb
134
129
  - lib/confium/transparency.rb
135
130
  - lib/confium/transparency/ots.rb
136
131
  - lib/confium/version.rb
data/lib/confium/cfm.rb DELETED
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'ffi'
4
-
5
- module Confium
6
- class CFM
7
- attr_reader :ptr
8
-
9
- def initialize
10
- pptr = ::FFI::MemoryPointer.new(:pointer)
11
- Confium.call_ffi(:cfm_create, pptr)
12
- @ptr = ::FFI::AutoPointer.new(pptr.read_pointer, self.class.method(:destroy))
13
- end
14
-
15
- def self.destroy(ptr)
16
- Confium::Lib.cfm_destroy(ptr)
17
- end
18
-
19
- def load_plugin(name, path)
20
- Confium.call_ffi(:cfm_plugin_load, @ptr, name, path, nil, nil)
21
- end
22
- end
23
- end
@@ -1,51 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # {Confium::Crypto} is the registry namespace for Confium's cryptographic
4
- # interfaces.
5
- #
6
- # Mirroring the Rust plugin-interface registry (TODO #02), each Ruby
7
- # interface module (Digest, and future Cipher, AEAD, KDF, RNG, Signature,
8
- # KEM, ...) registers itself here on load rather than being enumerated in
9
- # a central case statement. This keeps the registry open for extension
10
- # (OCP) and makes the set of available interfaces a single source of
11
- # truth.
12
- #
13
- # Example:
14
- #
15
- # module Confium
16
- # module Digest
17
- # Confium::Crypto.register(:hash, self)
18
- # end
19
- # end
20
- #
21
- # Confium::Crypto.lookup(:hash) # => Confium::Digest
22
- module Confium
23
- module Crypto
24
- # @type ivar @interfaces: Hash[Symbol, untyped]
25
- @interfaces = {}
26
-
27
- class << self
28
- # Register an interface +klass+ under the symbolic +name+. Adding a
29
- # new interface is a one-line registration; no central switch needs
30
- # editing.
31
- def register(name, klass)
32
- @interfaces[name] = klass
33
- klass
34
- end
35
-
36
- # Resolve a registered interface by +name+. Raises ArgumentError if
37
- # nothing has been registered under that name.
38
- def lookup(name)
39
- @interfaces.fetch(name) do
40
- raise ArgumentError, "unknown interface #{name.inspect}"
41
- end
42
- end
43
-
44
- # Enumerate the names of every registered interface. Primarily for
45
- # introspection and tooling.
46
- def interfaces
47
- @interfaces.keys.dup
48
- end
49
- end
50
- end
51
- end
@@ -1,62 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'ffi'
4
- require 'digest'
5
-
6
- module Confium
7
- class Digest < ::Digest::Class
8
- attr_reader :name, :ptr
9
-
10
- def initialize(cfm, name)
11
- @name = name
12
- pptr = ::FFI::MemoryPointer.new(:pointer)
13
- Confium.call_ffi(:cfm_hash_create, cfm.ptr, pptr, name, nil, nil, nil)
14
- ptr = pptr.read_pointer
15
- raise if ptr.null?
16
-
17
- @ptr = ::FFI::AutoPointer.new(ptr, self.class.method(:destroy))
18
- end
19
-
20
- def initialize_copy(source)
21
- @name = source.name
22
- pptr = ::FFI::MemoryPointer.new(:pointer)
23
- Confium.call_ffi(:cfm_hash_clone, source.ptr, pptr)
24
- ptr = pptr.read_pointer
25
- @ptr = ::FFI::AutoPointer.new(ptr, self.class.method(:destroy))
26
- end
27
-
28
- def self.destroy(ptr)
29
- Confium::Lib.cfm_hash_destroy(ptr)
30
- end
31
-
32
- def block_length
33
- plength = ::FFI::MemoryPointer.new(:uint32)
34
- Confium.call_ffi(:cfm_hash_block_size, @ptr, plength)
35
- plength.read(:uint32)
36
- end
37
-
38
- def digest_length
39
- plength = ::FFI::MemoryPointer.new(:uint32)
40
- Confium.call_ffi(:cfm_hash_output_size, @ptr, plength)
41
- plength.read(:uint32)
42
- end
43
-
44
- def update(data)
45
- Confium.call_ffi(:cfm_hash_update, @ptr, data, data.bytesize)
46
- self
47
- end
48
-
49
- def reset
50
- Confium.call_ffi(:cfm_hash_reset, @ptr)
51
- self
52
- end
53
-
54
- def finish
55
- buf = ::FFI::MemoryPointer.new(:uint8, digest_length)
56
- Confium.call_ffi(:cfm_hash_finalize, @ptr, buf, buf.size)
57
- buf.read_bytes(buf.size)
58
- end
59
-
60
- alias << update
61
- end
62
- end
data/lib/confium/ffi.rb DELETED
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'ffi'
4
-
5
- # {Confium::FFI} is the namespace for everything that touches the native
6
- # Confium shared library through Ruby-FFI.
7
- #
8
- # This file registers autoload entries for the planned FFI helper modules
9
- # (Library, Error, Options). They are listed in the TODO #14 architecture
10
- # (see `TODO.finalize/14-ruby-bindings-architecture.md`) and will be added
11
- # as the bindings grow; until then the autoloads are inert — they only
12
- # trigger a load when the corresponding constant is first referenced.
13
- #
14
- # Note: the legacy FFI library wrapper still lives at `Confium::Lib`
15
- # (file `confium/lib.rb`) and is autoloaded from `confium.rb`. It will be
16
- # migrated into `Confium::FFI::Library` in a follow-up.
17
- module Confium
18
- module FFI
19
- autoload :Library, 'confium/ffi/library'
20
- autoload :Error, 'confium/ffi/error'
21
- autoload :Options, 'confium/ffi/options'
22
- end
23
- end
data/lib/confium/lib.rb DELETED
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'ffi'
4
-
5
- module Confium
6
- module Lib
7
- extend ::FFI::Library
8
-
9
- FFI_LAYOUT = {
10
- cfm_create: [%i[pointer], :uint32],
11
- cfm_destroy: [%i[pointer], :uint32],
12
- cfm_plugin_load: [%i[pointer string string pointer pointer], :uint32],
13
- cfm_hash_create: [%i[pointer pointer pointer pointer pointer pointer], :uint32],
14
- cfm_hash_output_size: [%i[pointer pointer], :uint32],
15
- cfm_hash_block_size: [%i[pointer pointer], :uint32],
16
- cfm_hash_update: [%i[pointer pointer uint32], :uint32],
17
- cfm_hash_reset: [%i[pointer], :uint32],
18
- cfm_hash_clone: [%i[pointer pointer], :uint32],
19
- cfm_hash_finalize: [%i[pointer pointer uint32], :uint32],
20
- cfm_hash_destroy: [%i[pointer], :void]
21
- }.freeze
22
-
23
- ffi_lib([ENV.fetch('CONFIUM_LIB', nil), 'confium', 'libconfium'].compact)
24
-
25
- FFI_LAYOUT.each do |func, ary|
26
- class_eval do
27
- attach_function(func, ary.first, ary.last)
28
- end
29
- rescue ::FFI::NotFoundError
30
- # that's okay
31
- end
32
- end
33
- end
@@ -1,51 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'confium/lib'
4
-
5
- # Confium::TC::Session wraps a threshold cryptography session.
6
- #
7
- # A session represents one signing or decryption operation involving
8
- # T-of-N parties. The session goes through states: pending →
9
- # commitments_collected → shares_collected → completed.
10
- #
11
- # Usage:
12
- # session = Confium::TC::Session.new(scheme: "FROST-ed25519",
13
- # threshold: 3,
14
- # num_parties: 5,
15
- # party_index: 0)
16
- # session.set_local_share(share_bytes)
17
- # session.round(incoming_messages) # returns outgoing messages
18
- # result = session.result if session.complete?
19
- module Confium
20
- module TC
21
- class Session
22
- attr_reader :scheme, :threshold, :num_parties, :party_index, :state
23
-
24
- def initialize(scheme:, threshold:, num_parties:, party_index:)
25
- @scheme = scheme
26
- @threshold = threshold
27
- @num_parties = num_parties
28
- @party_index = party_index
29
- @state = :pending
30
- @local_share = nil
31
- @result = nil
32
- end
33
-
34
- def set_local_share(share_bytes)
35
- raise ArgumentError, 'share must be a String' unless share_bytes.is_a?(String)
36
-
37
- @local_share = share_bytes
38
- end
39
-
40
- def complete?
41
- @state == :completed
42
- end
43
-
44
- def result
45
- raise 'Session not complete' unless complete?
46
-
47
- @result
48
- end
49
- end
50
- end
51
- end