16. Signing State Machine

Co-Signer Engine routing · 3-share ceremony · zero-trust handoff

Two-Tier Co-Signer Model (★ Stage 8)

mpc-cmp.md, p.5-6 직접 인용: "None of the parties (neither Fireblocks nor the customer) can sign a transaction alone."

Tier정체Key share정책
Customer Co-SignerMobile device (Keychain/TEE) 또는 SGX server1/3Customer 측
Fireblocks Co-Signers (2)Azure SGX server2/3"Safeguards in case keys owned by customers are compromised" — tx amount threshold, destination address integrity

Co-Signer Broker + Aggregator Architecture

  • Co-Signer Broker: MPC 메시지 + end cert 를 broadcast (chain of trust 검증)
  • Aggregator: partial signature 들을 full signature 로 결합 → Blockchain
  • "data is not passed between them during signing" — 각 co-signer 는 독립 partial sig 생성 (zero-trust)

Signing State Machine

stateDiagram-v2
  [*] --> QUEUED : Secure Vault → Co-Signer Engine (Step 9)
  QUEUED --> ROUTING : UUID + Policy rules cached
  ROUTING --> AWAITING_CUSTOMER : route to Co-Signer 3 (mobile/SGX)
  ROUTING --> AWAITING_FB_1 : route to Co-Signer 1 (FB Azure SGX)
  ROUTING --> AWAITING_FB_2 : route to Co-Signer 2 (FB Azure SGX)

  AWAITING_CUSTOMER --> PARTIAL_SIG_3 : signed (PIN+biometric or API)
  AWAITING_CUSTOMER --> REJECTED : customer co-signer reject
  AWAITING_FB_1 --> PARTIAL_SIG_1 : FB safeguards pass
  AWAITING_FB_1 --> REJECTED : safeguard violation (amount/destination)
  AWAITING_FB_2 --> PARTIAL_SIG_2 : FB safeguards pass

  PARTIAL_SIG_1 --> AGGREGATING : all 3 collected
  PARTIAL_SIG_2 --> AGGREGATING
  PARTIAL_SIG_3 --> AGGREGATING

  AGGREGATING --> VERIFYING : Auth Engine hash 검증 (Step 11)
  VERIFYING --> SIGNED : Secure Vault tx 조립 (Step 12)
  VERIFYING --> FAILED : hash mismatch
  SIGNED --> READY_TO_BROADCAST
  REJECTED --> [*]
      
Figure 8. Signing state machine — 3-share ceremony, parallel collection. Either party reject = REJECTED. Auth Engine 가 partial sig hash 검증.

Special Branches

  • Hosted MPC: 3 share 모두 customer 환경 — Fireblocks 0 share. signing_events.co_signer_location 가 모두 'customer'
  • Solana Sign-Only: SIGNED 상태에서 broadcast 안 함, payload client 에 반환. NOT BROADCAST BY FIREBLOCKS 태그
  • Cached signature (Raw Signing): 동일 raw data 재서명 시 전체 ceremony 우회 — SIGNED 직접 진입
  • Co-signer rejection at PENDING_SIGNATURE → tx 전체가 CANCELLED (transaction state machine 참조)

DB Schema

CREATE TABLE signing_requests (
  id                BINARY(16) PRIMARY KEY,
  transaction_id    BINARY(16) NOT NULL,
  workspace_id      BINARY(16) NOT NULL,
  policy_rule_id    BINARY(16),                       -- triggering rule
  co_signer_set_id  BINARY(16) NOT NULL,              -- 3-share set 식별자
  state             ENUM('QUEUED', 'ROUTING', 'AGGREGATING', 'VERIFYING',
                          'SIGNED', 'REJECTED', 'FAILED') NOT NULL,
  queued_at         DATETIME(6) NOT NULL,
  signed_at         DATETIME(6),                      -- ★ set-once
  KEY (transaction_id),
  KEY (workspace_id, state)
);

-- append-only: BEFORE UPDATE / DELETE 트리거로 강제
CREATE TABLE signing_events (
  id                BINARY(16) PRIMARY KEY,
  signing_request_id BINARY(16) NOT NULL,
  co_signer_id      BINARY(16) NOT NULL,
  co_signer_role    ENUM('customer-mobile', 'customer-sgx', 'fb-azure-sgx') NOT NULL,
  share_index       TINYINT NOT NULL,                 -- 1, 2, or 3
  event_type        ENUM('partial-sig', 'reject') NOT NULL,
  partial_sig_hash  BINARY(32),                       -- Auth Engine 검증용
  mrenclave_at_signing BINARY(32),                    -- SGX MRENCLAVE (★ set-once)
  occurred_at       DATETIME(6) NOT NULL,
  KEY (signing_request_id)
);

CREATE TABLE callback_invocations (
  -- API Co-Signer 의 Callback Handler 호출 (optional)
  id                BINARY(16) PRIMARY KEY,
  signing_request_id BINARY(16) NOT NULL,
  callback_endpoint_id BINARY(16) NOT NULL,
  request_url       VARCHAR(255) NOT NULL,            -- /v2/tx_sign_request or /tx_sign_request
  request_jwt_or_json ENUM('jwt', 'json') NOT NULL,
  response_decision ENUM('approve', 'reject', 'ignore', 'retry') NOT NULL,
  latency_ms        INT,
  invoked_at        DATETIME(6) NOT NULL
);

SGX MRENCLAVE 의 의미

Fireblocks 의 Co-Signer 가 SGX enclave 안에서 실행되므로, 각 signing 시점의 enclave measurement (MRENCLAVE) 가 audit trail 에 기록됨. 외부 감사자는 attested MRENCLAVE 와 known-good 값을 비교해 enclave integrity 검증.