federated-signer-node is the listener / federated-signer-node service used by the current bridge-utexo federated signing stack.
The code still uses some old naming such as listener, tricorn, and FederatedSignerNode in proto packages. Treat that as protocol compatibility and legacy naming, not as a different product model.
One running instance of this repository represents one federation participant.
It sits between:
- the federated-signer orchestrator in
bridge-utexo - the local Parent Adapter
- the local Nitro Enclave
- optionally an EVM node
- optionally the rgb-multisig-bridge hub
Bridge
|
v
Federated-signer orchestrator
|
v
Federated-signer-node / listener
| \
| \
v v
Parent Adapter EVM node
|
v
Nitro Enclave
Optional on the same node:
federated-signer-node <-> rgb-multisig-bridge
This repository now contains three runtime capabilities that can be enabled independently by config.
Code:
Role:
- polls the configured EVM bridge contract
- persists detected
FundsInevents into SQLite - tracks the last scanned block
- marks rows finalized using the chain finalized block
This is used by the signing path that must prove an EVM FundsIn really happened and is finalized before the enclave signs the outbound PSBT flow.
Code:
- cmd/listener/main.go
- internal/federatedsignergrpc/service.go
- internal/federatedsignergrpc/grpc.go
- internal/listenerenclaveclient
Role:
- exposes
FederatedSignerNode.Sign - exposes
FederatedSignerNode.PublicKey - exposes
ListenerHealth.Healthon the same port - validates and enriches orchestrator bootstrap payloads
- forwards the enriched request to the enclave through the Parent Adapter
This is the main runtime mode for the current bridge stack.
Code:
Role:
- connects to
rgb-multisig-bridge - syncs multisig operations from the hub
- responds as this cosigner
- stores RGB bridge audit state in SQLite
- can sign hub PSBTs either through
rgb-lib-goor via the enclave
This path is compiled only with -tags rgb. The Docker build uses that tag by default.
The listener does not sign arbitrary opaque bytes. It validates bridge-specific context first, then sends an enriched payload to the enclave.
Input bootstrap:
Flow:
- The orchestrator calls
FederatedSignerNode.Signwithdata_type=TRANSACTION. - The listener reads
tx_hashandoperation_idxfrom the bootstrap payload. - The listener checks that the EVM event exists in
evm_eventsand is finalized. - The listener rejects
tx_hashvalues already present inprocessed_events. - The listener fetches the PSBT from
rgb-multisig-bridge. - The listener builds
EnrichedPsbtPayload. - The listener calls
EnclaveService.Signthrough the Parent Adapter. - On success, the listener records the EVM tx hash in
processed_events.
Input bootstrap:
Flow:
- The orchestrator calls
FederatedSignerNode.Signwithdata_type=SWAP. - The listener validates the consignment.
- The listener parses
fundsOutcalldata and checks token, recipient, amount, and commission. - If
ORCHESTRATOR_RGB_EVM_TRANSFER_DB_CHECK=true, the listener requires a matchingrgb_bridge_eventsrow by consignment hash and cross-checks the amount. - The listener injects chain ID, proxy contract, consignment hash, and validated amounts into
EnrichedEvmPayload. - The listener calls
EnclaveService.Sign. - The enclave returns the EVM signature.
FederatedSignerNode.PublicKey is just proxied to the enclave through the Parent Adapter.
ListenerHealth.Health reports:
- geth syncing state
- current and highest block
- last finalized block
- whether the enclave is reachable
The service uses SQLite, not PostgreSQL.
Code:
Main tables:
evm_events: detected EVM bridge eventslistener_blocks: last scanned EVM blockprocessed_events: EVM tx hashes already consumed by successful sign flowrgb_bridge_events: RGB hub operation audit trail and transfer linkage
| Proto file | Purpose |
|---|---|
| proto/signer/signer.proto | shared signing messages |
| proto/orchestrator-listener.proto | orchestrator -> listener RPC |
| proto/orchestrator-listener-health.proto | operational health RPC |
| proto/listener-enclave.proto | listener -> parent adapter -> enclave RPC |
| proto/enriched/enriched-payload.proto | bootstrap and enriched payload messages |
| proto/bridge-orchestrator.proto | bridge -> orchestrator RPC contract reference |
Regenerate Go code after proto edits:
bash scripts/gen-proto.shCurrent example files:
Important current envs:
NODE_ADDRESS: EVM RPC endpointCHAIN_ID: EVM chain ID used in enriched EVM signing payloadBRIDGE_CONTRACT_ADDRESS: EVM bridge contract watched by the listenerPROXY_CONTRACT_ADDRESS: proxy contract used in RGB -> EVM signing checksPARENT_ADAPTER_GRPC: TCP address of the Parent AdapterGRPC_LISTEN_ADDR: listener gRPC address exposed to the orchestratorEVM_LISTENER_ENABLED: enables EVM indexing/finality trackingORCHESTRATOR_GRPC_ENABLED: enables the gRPC listener node APIORCHESTRATOR_RGB_EVM_TRANSFER_DB_CHECK: requires RGB hub DB correlation for SWAP signingRGB_MULTISIG_BRIDGE_ENABLED: enables RGB hub cosigner mode
Important note:
- the committed examples are single-node examples
- the multi-node compose setup expects per-node files such as
.listener-node-1.env,.listener-node-2.env,.listener-node-3.env - those per-node files are environment-specific derivatives of the example listener config
Without RGB-specific runtime:
go run cmd/listener/main.go run -fWith RGB hub support:
go run -tags rgb cmd/listener/main.go run -fPrimary Dockerfile:
Current multi-node stack reference:
That compose file models:
- 3 enclaves
- 3 parent adapters
- 3 listener nodes
- shared operational logging via Dozzle
Practical note:
- deploy/local/docker-compose.yml is an older single-listener setup and may need adjustments before use with the current runtime
When updating docs for this repository, assume:
- this repo is the federated-signer-node / listener only
- the orchestrator lives in
bridge-utexo - the enclave and parent adapter are downstream dependencies, not implemented here
- the important current paths are:
- orchestrator-facing gRPC signing
- EVM event validation/finality
- RGB multisig bridge synchronization