Class: Confium::TC::NetworkCoordinator

Inherits:
Object
  • Object
show all
Defined in:
lib/confium/tc/network_coordinator.rb

Overview

Networked threshold-signing coordinator service.

Wraps Confium::TC::Coordinator (real CMP20/GG18 combine) behind a TCP socket so signers on separate machines submit commitments and shares from their own processes:

service = Confium::TC::NetworkCoordinator.new(quorum_id: 'root')
service.start                       # binds 127.0.0.1:<ephemeral>
client = Confium::TC::SignerClient.new(port: service.port)
sid = client.create_session(message: data, threshold: 3)
client.submit_share(sid, 'signer-1', share_blob)
client.aggregate(sid)               # => 64-byte signature

Protocol: one JSON object per line (NDJSON); binary fields are hex-encoded. Unknown operations and Coordinator errors come back as ..., "message": ... lines.

Transport security: none yet — plain TCP intended for loopback or private networks. The upstream noise-transport session protocol replaces this wholesale (see TODO.full/01-multi-host-threshold-signing.md).

Defined Under Namespace

Classes: RequestError

Constant Summary collapse

HANDLERS =
{
  'create' => lambda do |coord, req|
    session_id = coord.create_session(
      message: [req.fetch('message_hex')].pack('H*'),
      threshold: req.fetch('threshold'),
      scheme: req['scheme'] || 'CMP20-ECDSA-P256'
    )
    { 'session_id' => session_id }
  end,
  'commitment' => lambda do |coord, req|
    session_id = req.fetch('session_id')
    coord.submit_commitment(
      session_id, req.fetch('signer_id'),
      [req.fetch('bytes_hex')].pack('H*')
    )
    { 'ok' => true, 'state' => coord.session_state(session_id).to_s }
  end,
  'share' => lambda do |coord, req|
    coord.submit_share(
      req.fetch('session_id'), req.fetch('signer_id'),
      [req.fetch('bytes_hex')].pack('H*')
    )
    { 'ok' => true }
  end,
  'aggregate' => lambda do |coord, req|
    signature = coord.aggregate(req.fetch('session_id'))
    { 'signature_hex' => signature.unpack1('H*') }
  end
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(quorum_id:, host: '127.0.0.1', port: 0, coordinator: nil) ⇒ NetworkCoordinator

Returns a new instance of NetworkCoordinator.



65
66
67
68
69
70
71
72
73
# File 'lib/confium/tc/network_coordinator.rb', line 65

def initialize(quorum_id:, host: '127.0.0.1', port: 0, coordinator: nil)
  @quorum_id = quorum_id
  @host = host
  @port = port
  @coordinator = coordinator || Coordinator.new(quorum_id: quorum_id)
  @server = nil
  @accept_thread = nil
  @mutex = Mutex.new
end

Instance Attribute Details

#portObject (readonly)

Returns the value of attribute port.



63
64
65
# File 'lib/confium/tc/network_coordinator.rb', line 63

def port
  @port
end

#quorum_idObject (readonly)

Returns the value of attribute quorum_id.



63
64
65
# File 'lib/confium/tc/network_coordinator.rb', line 63

def quorum_id
  @quorum_id
end

Instance Method Details

#running?Boolean

Returns:

  • (Boolean)


95
96
97
# File 'lib/confium/tc/network_coordinator.rb', line 95

def running?
  !@server.nil?
end

#startObject



75
76
77
78
79
80
81
82
83
# File 'lib/confium/tc/network_coordinator.rb', line 75

def start
  raise 'already started' if @server

  # RBS socket lib lacks the (host, port) overload for new
  @server = TCPServer.new(@host.to_s, @port) # steep:ignore
  @port = @server.addr[1]
  @accept_thread = Thread.new { accept_loop }
  self
end

#stopObject



85
86
87
88
89
90
91
92
93
# File 'lib/confium/tc/network_coordinator.rb', line 85

def stop
  return unless @server

  server = @server
  @server = nil
  server.close
  @accept_thread&.join(5)
  nil
end