- Convert Windows CRLF line endings to Unix LF for all deploy.sh files
- Add executable permission to all deploy.sh scripts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update all .env.example files with production topology documentation
- Add network configuration for Server A (119.145.15.38/192.168.1.100) and Server B (192.168.1.111)
- Document service ports and connection URLs for all microservices
- Add architecture diagrams in comments for easy reference
- Include security notes and key generation commands
Files updated:
- backend/services/.env.example (main config)
- backend/services/identity-service/.env.example
- backend/services/mpc-service/.env.example
- backend/services/blockchain-service/.env.example
- backend/mpc-system/.env.example
- backend/api-gateway/.env.example
- backend/infrastructure/.env.example
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
When signing with a subset of parties (e.g., party-1 and party-3 in 2-of-3),
the TSS library creates a sorted array of party IDs. Messages contain the
original keygen party index, but we need to map it to the sorted array index.
This fixes the 'invalid FromPartyIndex' error when signing with non-consecutive
party indices.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add PartyIndex field to protobuf ParticipantInfo message
- Pass original PartyIndex from account shares to session coordinator
- Use original PartyIndex instead of loop variable when creating participants
- This fixes TSS signing failures when non-consecutive parties are selected
Wait 500ms after subscribing to messages to ensure all parties have
completed subscription before starting TSS protocol. This prevents
broadcast messages from being lost when some parties haven't subscribed yet.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add logging at key points to trace keygen_session_id flow:
- Account Handler: log keygen_session_id when creating signing session
- Session Coordinator: log keygen_session_id in CreateSession and JoinSession
- Message Router: log keygen_session_id when proxying JoinSession
- Server Party: log keygen_session_id when joining session
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
For sign sessions, this column stores the reference to the keygen session
whose key shares should be used for signing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Regenerate protobuf Go code with KeygenSessionId fields
- Session Coordinator correctly parses, stores, and returns keygen_session_id
- Message Router Client parses keygen_session_id in JoinSession response
- participate_signing.go uses keygen_session_id for precise share lookup
- Database schema already includes keygen_session_id column
This fixes the signing issue where wrong keyshares were loaded for multi-account scenarios.
- Add keygen_session_id field to CreateSessionRequest and SessionInfo protobuf
- Modify CreateSigningSessionAuto to accept and pass keygenSessionID
- Update Account Handler to pass account's keygen_session_id when creating signing session
- This enables parties to load the correct keyshare by session ID
TSS threshold semantics: for threshold parameter t, the required number of signers is t+1.
For 2-of-3 with t=2, we need 2+1=3 signers (all parties must participate).
Previous error: 't+1=3 is not satisfied by the key count of 2'
Fix: Changed from selecting t parties to selecting t+1 parties.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
For 2-of-3 threshold signing, only 2 parties should participate in signing, not all 3. This fixes the 'failed to calculate Bob_mid' error that occurred when all parties tried to sign.
Changes:
- Modified CreateSigningSession to select exactly threshold_t parties when no signing config exists
- For 2-of-3: now selects 2 parties instead of all 3
- Added logging to show party selection details
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Only username is required, all other fields (email, phone, public_key, etc.) are now optional.
Changes:
- Modified 001_init_schema.up.sql to remove NOT NULL constraints
- Added partial unique index for email (only for non-NULL values)
- Created migration 006_make_email_optional for existing databases
- Set default status to 'active'
This allows automatic account creation from keygen without requiring user info.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Previously, signing incorrectly required all n parties from keygen to participate. For 2-of-3 threshold, it required all 3 parties instead of just 2.
Root cause: tss.NewParameters was using len(currentSigners) instead of the original n from keygen.
Changes:
- Added TotalParties field to SigningConfig to store original n from keygen
- Modified participate_signing.go to read threshold_n from database
- Updated tss.NewParameters to use TotalParties instead of current signer count
- Added logging to show t, n, and current_signers
For 2-of-3: threshold_t=2, threshold_n=3, any 2 parties can now sign.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Created test_signing.go to test MPC signing functionality:
- Generates JWT token for authentication
- Creates SHA-256 hash of test message
- Calls POST /api/v1/mpc/sign API
- Tests signing with persistent parties (non-delegate mode)
Usage: go run test_signing.go
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added comprehensive debug logging to track message conversion and
party index mapping in keygen protocol:
1. Log party index map construction with all participants
2. Log received MPC messages before conversion
3. Log when messages are dropped due to unknown sender
4. Log successful message conversion and TSS forwarding
5. Show known_parties map when dropping messages
This will help identify why delegate party receives messages but
doesn't process them during keygen.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed the acknowledgment goroutine in GetPendingMessages to use parent
context instead of context.Background(), preventing orphan goroutines
that can't be cancelled.
This completes all context bug fixes:
- server-party-api event handler (commit 450163a)
- server-party event handler (commit 99ff3ac)
- message acknowledgment in SubscribeMessages (commit 450163a)
- message acknowledgment in GetPendingMessages (this commit)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fixed server-party event handler to use parent context with timeout
- Prevents orphan goroutines when session fails or party exits
- Consistent with server-party-api fix
- Fixed delegate party event handler to use parent context with timeout
- Fixed message acknowledgment to use parent context
- Prevents orphan goroutines when session fails or party exits
- Resolves system crash after delegate party failure
Add PARTY_ROLE=delegate environment variable to server-party-api service
to fix nil pointer dereference when determining party role during keygen.
Without this variable, the party defaults to "persistent" role which tries
to access keyShareRepo (nil for delegate parties), causing a panic.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Update session repository to properly handle delegate_party_id column:
- Add delegate_party_id to Save method INSERT and UPDATE statements
- Add DelegatePartyID field to sessionRow struct
- Update FindByUUID, FindByStatus, FindExpired, FindActive SELECT queries
- Update scanSessions method to scan and pass delegate_party_id
- Remove placeholder empty string, now loads actual value from database
This completes the delegate party functionality by ensuring the delegate party ID
is persisted and retrieved correctly from the database.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add delegate_party_id column to track which party is acting as delegate
(generates and returns user share instead of storing it).
Changes:
- Add delegate_party_id VARCHAR(255) column with default empty string
- Add partial index for faster lookups when delegate party is present
- Include up and down migrations
This fixes the issue where delegate party selection worked but the delegate_party
field was not being returned in API responses due to missing database column.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed critical bug where PartyComposition (persistent/delegate party counts) was being sent
by account-service in gRPC request but was not being extracted and passed to the CreateSession
use case, causing delegate party selection to fail.
Changes:
- Extract PartyComposition from protobuf request and pass to CreateSessionInput
- Add logging for party composition values in gRPC handler
- Return delegate_party_id and selected_parties in CreateSessionResponse
- Load session after creation to get delegate party ID
This fixes the issue where require_delegate=true had no effect and all parties selected
were persistent parties instead of 2 persistent + 1 delegate.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add ACCOUNT_SERVICE_ADDR environment variable pointing to account-service:8080
- Fixes "connection refused" error when session-coordinator tries to auto-create account after keygen
- Session-coordinator can now properly call account service to create account records
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add explicit PARTY_ID environment variable for delegate party
- Set PARTY_ID=delegate-party for server-party-api service
- This ensures the delegate party properly registers to Message Router party pool
- Enables delegate party selection for keygen sessions with require_delegate=true
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove dynamic participant addition in JoinSession
- Participants must be pre-created in CreateSession
- Add ErrPartyNotInvited error for unauthorized join attempts
- Fix Redis adapter to include version parameter in ReconstructSession
- This fixes VSS verification failures caused by inconsistent party indices
Implement version-based optimistic locking to prevent concurrent update conflicts
when multiple parties simultaneously report completion during keygen operations.
Changes:
- Add version column to mpc_sessions table (migration 004)
- Add Version field to MPCSession entity
- Define ErrOptimisticLockConflict error
- Update SessionPostgresRepo.Update() to check version and increment on success
- Add automatic retry logic (max 3 attempts) to ReportCompletionUseCase
- Update Save and all query methods (FindByStatus, FindExpired, etc.) to handle version field
This replaces pessimistic locking (FOR UPDATE) with optimistic locking using
the industry-standard pattern: WHERE version = $n and checking rowsAffected.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed JWT secret in test_create_session.go to use the same secret key
as configured in .env file, resolving 401 Unauthorized errors during
keygen session creation tests.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed Development from false to true to test if this is preventing
debug logs from being output. Development mode may affect how the
logger handles different log levels.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added Log.Debug() and Log.Info() calls immediately after Build()
to test if the logger can output debug logs right after creation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added debug output to track:
1. AtomicLevel value when created
2. AtomicLevel value after Build()
3. Log.Level() value after Build()
This will help identify if Build() or something else is changing the level.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added test debug log immediately after logger initialization.
If debug logging is working, we should see this message.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added println statements to trace:
1. Level value after UnmarshalText
2. Logger level after Build()
This will help diagnose why debug level is not being applied.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Problem: Logger was always using info level despite MPC_LOGGER_LEVEL=debug
Root cause: The init() function in logger.go was calling InitProduction()
which created a zap.NewProduction() logger with hardcoded info level.
This happened before main() called logger.Init(cfg), so the config was
being ignored.
Solution:
1. Removed init() function to prevent early logger initialization
2. Added zap.ReplaceGlobals() in Init() to ensure config takes effect
3. Removed unused "os" import
References:
- https://pkg.go.dev/go.uber.org/zap
- https://stackoverflow.com/questions/57745017/🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>