콘텐츠로 이동

v0.0

엔터프라이즈 멀티체인 서명 펌웨어 요구사항 명세서

1. Executive Summary

본 문서는 D'CENT X 엔터프라이즈 콜드월렛의 Secure Element(SE) 내부 멀티체인 서명 기능에 대한 펌웨어 요구사항을 정의한다. BTC(PSBT + Schnorr + MuSig2), EVM(RLP + ECDSA + EIP-712), ERC-20/스테이블코인 서명을 SE 리소스 제약 내에서 구현하기 위한 상세 요구사항을 FW-SIGN- ID 체계로 관리한다.

지원 범위: - BTC: PSBT(BIP-174/370) 파싱, Schnorr 서명(BIP-340), MuSig2 2라운드 프로토콜(BIP-327), BIP-373 PSBT 확장 - EVM: RLP 디코딩(EIP-1559 Type 2), ECDSA 서명(secp256k1), EIP-155 Chain ID, EIP-712 Structured Data - ERC-20: ABI 디코딩(transfer, approve, transferFrom), SE 토큰 DB, 함수 셀렉터 DB - 확장: Chain Parser Interface, 향후 체인(Solana, Cosmos, Tron) 파서 추가 구조

설계 기반: - Phase 5 firmware-signing-interface.md — SE 앱릿 구조 및 Signing Applet 인터페이스 - Phase 5 airgap-communication-protocol.md — CBOR 스키마, NFC APDU 커맨드셋 - Phase 5 chain-abstraction-layer.md — 체인 추상화 인터페이스 - Phase 6 hardware-capability-assessment.md — SE 리소스 버짓


2. BTC 서명 펌웨어 요구사항

2.1. PSBT 파싱 및 서명

SE 내부에서 PSBT(Partially Signed Bitcoin Transaction) 바이너리를 직접 파싱하여 서명에 필요한 데이터를 추출한다.

PSBT 디코딩 요구사항:

항목 요구사항 SE 리소스 영향
PSBTv0 (BIP-174) 디코딩 글로벌 맵 + 입력 맵 + 출력 맵 파싱 RAM 8KB 내 스트리밍 파싱
PSBTv2 (BIP-370) 디코딩 Creator/Constructor/Signer 역할 분리 지원 PSBTv0과 동일 버퍼 공유
입력(Input) 파싱 UTXO 참조(txid+vout), scriptPubKey, witness 추출 입력당 ~100B
출력(Output) 파싱 scriptPubKey → 주소 변환, value(satoshis) 추출 출력당 ~60B
Change Output 감지 BIP-44/84/86 경로 매칭으로 잔금 출력 식별 키 파생 경로 비교
수수료 계산 입력 합계 - 출력 합계 uint64 연산
Sighash 계산 BIP-341 Taproot sighash (SHA-256 기반) SHA-256 HW 가속

스트리밍 파싱 전략:

대용량 PSBT(>8KB) 처리를 위한 single-pass 스트리밍 파싱:

[1] PSBT 헤더 파싱 (magic bytes + 버전)
[2] 글로벌 맵 스트리밍 파싱 → 필요 필드만 추출 + 즉시 해시 업데이트
[3] 입력 맵 순차 파싱 (N개):
    - 각 입력의 sighash 기여분 계산
    - UTXO 참조 + 금액 추출
    - 처리 완료 후 입력 버퍼 해제
[4] 출력 맵 순차 파싱 (M개):
    - 수신 주소 + 금액 추출
    - Change 출력 식별
    - WYSIWYS 표시 데이터 생성
[5] 최종 sighash 완성 → Schnorr 서명 입력

2.2. Schnorr 서명 (BIP-340)

항목 요구사항 비고
커브 secp256k1 ECDSA와 동일 커브, HW 가속 공유
서명 크기 64 bytes (r, s) ECDSA(65B)보다 1바이트 작음
Nonce 생성 RFC 6979 확장 (결정적 + 보조 랜덤) TRNG 시드 혼합
서명 검증 batch verification 미지원 (SE 리소스) 단일 검증만
X-only 공개키 32 bytes (y 좌표 제거) BIP-340 표준
Tagged Hash SHA-256("BIP0340/challenge" || ...) BIP-340 표준 해시

2.3. MuSig2 (BIP-327) 2라운드 프로토콜

D'CENT X SE 내부에서 MuSig2 서명의 한 참여자(signer) 역할을 수행한다.

Round 1: Nonce 생성

입력: derivation_path, message_hash(선택)
처리:
  1. 결정적 nonce 시드 생성:
     nonce_seed = HMAC-SHA256(private_key, session_id || counter || random)
     - session_id: 요청 UUID
     - counter: SE 서명 카운터
     - random: TRNG 8 bytes (추가 엔트로피)
  2. 두 개의 public nonce 생성:
     R1 = nonce_seed_1 * G
     R2 = nonce_seed_2 * G
  3. 상태 저장:
     MuSig2Session {
       session_id: bytes(16)       // UUID
       nonce_secret_1: bytes(32)   // 비밀 nonce 1
       nonce_secret_2: bytes(32)   // 비밀 nonce 2
       created_counter: uint32     // 생성 시점 카운터
       timeout_counter: uint32     // 만료 카운터 (현재 + 100)
     }
  4. public_nonce = R1 || R2 (66 bytes) 반환

보안 제약:
  - 최대 2개 동시 MuSig2 세션 (SE 저장 공간 제약)
  - 세션 타임아웃: 서명 카운터 100 경과 시 자동 만료
  - 동일 nonce 재사용 절대 금지 (private key 노출 위험)

Round 2: Partial Signature 생성

입력: session_id, aggregated_nonce(66B), sighash
처리:
  1. 세션 조회: session_id로 저장된 MuSig2Session 검색
     - 미발견 → MUSIG2_SESSION_NOT_FOUND (0x35) 에러
     - 타임아웃 → MUSIG2_SESSION_EXPIRED (0x36) 에러
  2. Aggregated nonce 검증:
     R_agg = NonceAgg([R1_all, R2_all])  // 모든 참여자 nonce 집계
  3. 부분 서명 생성:
     partial_sig = Sign_partial(nonce_secret, private_key, R_agg, sighash)
  4. 세션 정리: nonce_secret 즉시 삭제 (1회용)
  5. partial_sig (32 bytes) 반환

보안 제약:
  - Round 2는 동일 세션에 대해 1회만 실행 가능
  - 실행 후 nonce 비밀값 즉시 폐기
  - 동일 sighash에 대한 다중 partial_sig 생성 금지

SE 내부 MuSig2 상태 관리:

항목 크기 설명
세션 저장 66B/세션 x 2 = 132B EEPROM Secure Storage
임시 연산 ~256B RAM (Round 2 시)
성능 Round 1: ~110ms, Round 2: ~120ms SE HW 가속 기준

2.4. BIP-373 PSBT 확장 필드

MuSig2 관련 PSBT 확장 필드의 SE 내부 처리:

PSBT 필드 키 타입 처리
MUSIG2_PARTICIPANT_PUBKEYS 입력 맵 참여자 공개키 목록 추출 → Signer 인덱스 확인
MUSIG2_PUB_NONCE 입력 맵 타 참여자 public nonce 추출 → Round 2 입력
MUSIG2_PARTIAL_SIG 출력 SE에서 생성한 partial signature 기록

2.5. 키 파생

경로 용도 BIP 비고
m/44'/0'/N'/0/M BTC Legacy (P2PKH) BIP-44 하위 호환
m/84'/0'/N'/0/M BTC Native SegWit (P2WPKH) BIP-84 권장
m/86'/0'/N'/0/M BTC Taproot (P2TR) BIP-86 MuSig2 필수

SE 내부 키 파생 구현: - BIP-32 HMAC-SHA512 체인 키 유도 - 하드닝 키 파생(m/44'h) 지원 필수 - 최대 파생 깊이: 5단계 (m/purpose'/coin'/account'/change/index) - 파생 시간: ~20ms/단계, 5단계 = ~100ms

2.6. 성능 요구

시나리오 자동 처리 시간 목표 항목
BTC 단순 전송 (1 입력, 2 출력) < 2초 PSBT 파싱 + sighash + Schnorr 서명
BTC 다중 입력 (5 입력, 2 출력) < 4초 스트리밍 PSBT 파싱
MuSig2 Round 1 < 1초 Nonce 생성 + 저장
MuSig2 Round 2 < 1.5초 세션 조회 + partial sig + 정리
전체 BTC 서명 파이프라인 < 5초 WYSIWYS + 정책 + 서명 (사용자 대기 제외)

3. EVM 서명 펌웨어 요구사항

3.1. RLP 디코딩

SE 내부에서 EVM 트랜잭션의 RLP(Recursive Length Prefix) 인코딩을 디코딩한다.

지원 트랜잭션 타입:

타입 식별 디코딩 우선순위
Legacy (Type 0) 첫 바이트 >= 0xC0 직접 RLP 필수
EIP-2930 (Type 1) 첫 바이트 = 0x01 0x01 || RLP 높음
EIP-1559 (Type 2) 첫 바이트 = 0x02 0x02 || RLP 필수 (기본)
EIP-4844 (Type 3) 첫 바이트 = 0x03 향후 확장 중간

RLP 디코딩 구현:

RLP 디코딩 규칙:
  - 단일 바이트 [0x00, 0x7F]: 값 자체
  - 짧은 문자열 [0x80, 0xB7]: 길이 = 첫 바이트 - 0x80
  - 긴 문자열 [0xB8, 0xBF]: 길이의 바이트 수 = 첫 바이트 - 0xB7
  - 짧은 리스트 [0xC0, 0xF7]: 길이 = 첫 바이트 - 0xC0
  - 긴 리스트 [0xF8, 0xFF]: 길이의 바이트 수 = 첫 바이트 - 0xF7

EIP-1559 필드 추출:
  [chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas,
   gas_limit, to, value, data, access_list, v, r, s]

SE 리소스 영향: - RLP 디코딩 버퍼: ~2KB (최대 트랜잭션 크기 제한) - calldata 파싱: 함수 셀렉터(4B) + 파라미터 → 별도 ABI 디코딩

3.2. ECDSA 서명 (secp256k1)

항목 요구사항
해시 알고리즘 keccak256 (SHA-3 변형)
서명 출력 v (1B) + r (32B) + s (32B) = 65 bytes
v 값 EIP-155: chain_id * 2 + 35/36
Nonce 생성 RFC 6979 (결정적)
서명 정규화 Low-S normalization (s < n/2)
keccak256 구현 SE 소프트웨어 구현 필요 (SHA-256과 다름) [HW-CONFIRM]

keccak256 관련 참고: 대부분의 SE는 SHA-256 하드웨어 가속을 제공하나, keccak256은 별도 구현이 필요할 수 있다. EVM 서명 성능은 keccak256 구현 방식(HW/SW)에 크게 의존한다.

3.3. EIP-155 Chain ID

서명에 Chain ID를 포함하여 크로스체인 리플레이 공격을 방지한다.

Chain ID 네트워크 SE 표시명
1 Ethereum Mainnet "Ethereum"
137 Polygon "Polygon"
56 BNB Smart Chain "BNB Chain"
42161 Arbitrum One "Arbitrum"
10 Optimism "Optimism"
43114 Avalanche C-Chain "Avalanche"

SE 내부에 상위 10개 Chain ID → 네트워크명 매핑 테이블을 저장한다. 미등록 Chain ID는 숫자 표시 ("Chain #[ID]").

3.4. EIP-712 Structured Data

EIP-712 구조화 데이터 서명 지원 (Safe multisig 등에서 사용):

EIP-712 서명 프로세스:
  1. domain_separator (32B) 수신
  2. message_hash (32B) 수신
  3. 최종 해시: keccak256("\x19\x01" || domain_separator || message_hash)
  4. ECDSA 서명 생성

WYSIWYS 표시:
  - domain: 앱 이름, 체인 ID, 컨트랙트 주소
  - message: typed data 주요 필드 (파라미터 표시)
  - 파싱 불가 시: Raw hash 표시 + CRITICAL 경고

3.5. 키 파생

경로 용도 비고
m/44'/60'/0'/0/N Ethereum 표준 MetaMask 호환
m/44'/60'/N'/0/0 Ledger 방식 계정 인덱스 위치 차이
m/44'/966'/0'/0/N Polygon (SLIP-0044) 독립 경로 사용 시

기본 채택: m/44'/60'/0'/0/N (Ethereum 표준, MetaMask 호환)

3.6. 성능 요구

시나리오 자동 처리 시간 목표
EVM 단순 전송 (ETH transfer) < 1초
ERC-20 transfer < 1.5초
EIP-712 Safe execTransaction < 2초
전체 EVM 서명 파이프라인 < 2초 (사용자 대기 제외)

4. ERC-20/스테이블코인 서명 지원

4.1. ABI 디코딩

SE 내부에서 EVM calldata의 ABI(Application Binary Interface)를 디코딩한다.

지원 함수:

함수 Selector 파라미터 디코딩 결과
transfer(address,uint256) 0xa9059cbb to(20B), amount(32B) 수신자 + 금액
approve(address,uint256) 0x095ea7b3 spender(20B), amount(32B) 승인 대상 + 한도
transferFrom(address,address,uint256) 0x23b872dd from, to, amount 출금원 + 수신자 + 금액

ABI 디코딩 로직:

ABI 디코딩:
  1. calldata 첫 4바이트 → 함수 셀렉터 추출
  2. SE 함수 셀렉터 DB에서 매칭 조회
  3. 매칭 시: 파라미터 ABI 디코딩 (32B 단위 파싱)
  4. 미매칭 시: CAUTION 경고 + Raw Hex 표시

파라미터 디코딩 규칙:
  - address: 32B 중 하위 20B 추출
  - uint256: 32B big-endian → 금액 변환
  - bytes: offset + length 기반 동적 디코딩
  - 중첩 구조체: 재귀적 디코딩 (최대 depth 3)

4.2. SE 내부 토큰 데이터베이스

초기 등록 토큰 (5종):

토큰 체인 컨트랙트 주소 Decimals 크기
USDT Ethereum (1) 0xdAC17F958D2ee523a2206206994597C13D831ec7 6 40B
USDC Ethereum (1) 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 6 40B
DAI Ethereum (1) 0x6B175474E89094C44Da98b954EedeAC495271d0F 18 40B
WBTC Ethereum (1) 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599 8 40B
USDT Tron (195) TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t 6 40B

토큰 DB 구조:

TokenEntry {
  chain_id: uint32           // 4B
  contract_address: bytes(20) // 20B
  decimals: uint8            // 1B
  symbol: bytes(8)           // 8B (UTF-8, null-padded)
  flags: uint8               // 1B (검증 상태 등)
  reserved: bytes(6)         // 6B (향후 확장)
}
// 항목당 40 bytes, 최대 50개 = 2,000B (2KB)

토큰 DB 업데이트: - 업데이트 방식: 관리자 쿼럼 승인 + 에어갭 펌웨어 업데이트 경유 - 무결성 검증: 전체 DB의 SHA-256 해시를 SE 내부에 별도 저장 - 미등록 토큰: decimals 0 처리 + "소수점 미확인" 경고 WYSIWYS 표시

4.3. SE 내부 함수 셀렉터 데이터베이스

초기 등록 셀렉터 (10종):

# 셀렉터 함수 카테고리 위험도
1 0xa9059cbb ERC-20 transfer 토큰 낮음
2 0x095ea7b3 ERC-20 approve 토큰 높음 (무제한 승인 가능)
3 0x23b872dd ERC-20 transferFrom 토큰 중간
4 0x42842e0e ERC-721 safeTransferFrom NFT 중간
5 0x6a761202 Safe execTransaction 멀티시그 높음
6 0x0d582f13 Safe addOwnerWithThreshold 멀티시그 최고
7 0x694e80c3 Safe changeThreshold 멀티시그 최고
8 0xa22cb465 ERC-721 setApprovalForAll NFT 높음
9 0x2e1a7d4d WETH withdraw DeFi 중간
10 0xd0e30db0 WETH deposit DeFi 낮음

셀렉터 DB 구조:

SelectorEntry {
  selector: bytes(4)         // 4B — 함수 셀렉터
  category: uint8            // 1B — 카테고리 (0=토큰, 1=NFT, 2=멀티시그, 3=DeFi, 4=기타)
  risk_level: uint8          // 1B — 위험도 (0=낮음, 1=중간, 2=높음, 3=최고)
  param_count: uint8         // 1B — 파라미터 수
  param_types: bytes(4)      // 4B — 파라미터 타입 (address=0x01, uint256=0x02, bytes=0x03, ...)
  display_name_offset: uint8 // 1B — 표시명 오프셋 (별도 문자열 테이블)
  flags: bytes(4)            // 4B — 플래그 (approve 무제한 감지 등)
}
// 항목당 16 bytes, 최대 256개 = 4,096B (4KB)

5. 향후 체인 확장 요구사항

5.1. Chain Parser Interface

SE 내부에서 체인별 파서를 분리 관리하는 표준 인터페이스:

ChainParserInterface {
  // 체인 식별
  getChainId() → uint32                    // SLIP-0044 coin type
  getSupportedTxTypes() → [uint8]          // 지원 트랜잭션 타입

  // 트랜잭션 파싱
  parse(raw_tx: bytes) → ParsedTransaction // 바이너리 → 구조체
  calculateSighash(parsed: ParsedTransaction, input_index: uint8) → bytes(32)

  // WYSIWYS 지원
  formatDisplay(parsed: ParsedTransaction) → [DisplayPage]
  getWarningLevel(parsed: ParsedTransaction) → WarningLevel

  // 서명 생성
  getSignAlgorithm() → SignAlgorithm       // ECDSA, Schnorr, Ed25519
  getDerivationPath(account: uint32) → string
}

ParsedTransaction {
  chain_id: uint32
  tx_type: uint8
  recipients: [{address: bytes, amount: bytes(32), asset_type: uint8}]
  fee: {amount: bytes(32), unit: string}
  nonce: uint64
  metadata: bytes                          // 체인별 추가 데이터
}

SignAlgorithm: ECDSA_SECP256K1 | SCHNORR_SECP256K1 | EDDSA_ED25519

5.2. 확장 대상 체인

체인 TX 포맷 서명 알고리즘 SE 추가 리소스 도입 시기
Tron Protobuf ECDSA (secp256k1) 파서 ~2KB ROM Phase 1 출시 (USDT)
Solana Borsh Ed25519 Ed25519 HW 지원 필요, 파서 ~4KB Phase 2
Cosmos Protobuf (amino/direct) ECDSA (secp256k1) 파서 ~2KB ROM Phase 2
Polkadot SCALE Sr25519 신규 커브 필요, 파서 ~4KB Phase 3

5.3. 플러그인 방식 파서 로딩

펌웨어 업데이트를 통한 체인 파서 추가 구조:

파서 추가 워크플로우:
  1. 신규 체인 파서 코드 개발 (ChainParserInterface 구현)
  2. 펌웨어 빌드에 파서 포함
  3. 코드 서명 + Admin 쿼럼 승인
  4. 에어갭 펌웨어 업데이트로 설치
  5. ChainRegistry에 자동 등록

ChainRegistry:
  - 설치된 파서 목록 관리
  - chain_id 기반 라우팅
  - GetDeviceInfo 응답에 supported_chains 반영

6. Signing Applet 상세 요구사항 목록

firmware-signing-interface.md 섹션 3.4의 [1]~[6] 단계별 구현 요구사항:

ID 요구사항명 설명 우선순위 SE 리소스 영향 연계 문서
FW-SIGN-01 PSBT v0/v2 바이너리 디코딩 BIP-174/370 PSBT 바이너리를 SE 내부에서 파싱, 입력/출력/글로벌 맵 추출 필수 RAM 8KB (스트리밍) firmware-signing-interface.md [1]
FW-SIGN-02 PSBT 스트리밍 파싱 엔진 8KB RAM 제약 내 single-pass 파싱, 청크 단위 해시 업데이트 필수 RAM 8KB 최적화 hardware-capability-assessment.md
FW-SIGN-03 Schnorr 서명 생성 (BIP-340) secp256k1 Schnorr 서명, Tagged Hash, X-only 공개키 필수 RAM 512B, ~100ms firmware-signing-interface.md [5]
FW-SIGN-04 MuSig2 Round 1 — Nonce 생성 결정적 nonce 생성, public nonce 반환, 세션 상태 저장 필수 저장 66B/세션, ~110ms BIP-327
FW-SIGN-05 MuSig2 Round 2 — Partial Sig Aggregated nonce 수신, partial signature 생성, 세션 정리 필수 RAM 256B, ~120ms BIP-327
FW-SIGN-06 MuSig2 세션 관리 최대 2세션, 타임아웃(카운터 100), nonce 1회 사용 강제 필수 저장 132B 섹션 2.3
FW-SIGN-07 BIP-373 PSBT 확장 필드 처리 MuSig2 participant pubkeys, nonces, partial sigs 파싱 필수 PSBT 파싱 확장 BIP-373
FW-SIGN-08 EVM RLP 디코딩 EIP-1559 Type 2 우선, Legacy/Type 1 호환, calldata 추출 필수 RAM 2KB 섹션 3.1
FW-SIGN-09 ECDSA 서명 (secp256k1) keccak256 해시 + ECDSA 서명, v/r/s 반환, EIP-155 Chain ID 필수 RAM 256B, ~100ms firmware-signing-interface.md [5]
FW-SIGN-10 EIP-712 Structured Data 서명 domain separator + message hash 처리, typed data 서명 필수 RAM 128B 섹션 3.4
FW-SIGN-11 ABI 디코딩 엔진 함수 셀렉터 매칭 + 파라미터 디코딩 (address, uint256, bytes) 필수 RAM 512B 섹션 4.1
FW-SIGN-12 SE 토큰 DB 관리 토큰 등록/조회/업데이트, 초기 5종, 최대 50개, 무결성 해시 필수 저장 2KB 섹션 4.2
FW-SIGN-13 SE 함수 셀렉터 DB 관리 셀렉터 등록/조회/업데이트, 초기 10종, 최대 256개 필수 저장 4KB 섹션 4.3
FW-SIGN-14 BIP-32 HD 키 파생 BIP-44/84/86 경로 지원, 최대 5단계, 하드닝 파생 필수 RAM 128B, ~100ms 섹션 2.5
FW-SIGN-15 Chain Parser Interface chain_id 라우팅, parse/sighash/formatDisplay 인터페이스 높음 인터페이스 정의만 섹션 5.1
FW-SIGN-16 EIP-155 Chain ID 관리 상위 10개 Chain ID → 네트워크명 매핑, 미등록 ID 숫자 표시 높음 저장 ~200B 섹션 3.3
FW-SIGN-17 Sighash 계산 (BTC) BIP-341 Taproot sighash, SegWit sighash 필수 SHA-256 HW 섹션 2.1
FW-SIGN-18 keccak256 구현 EVM 서명용 keccak256 해시, HW 가속 또는 SW 구현 필수 ROM ~2KB (SW 시) 섹션 3.2
FW-SIGN-19 Nonce 생성 (RFC 6979) 결정적 nonce (ECDSA/Schnorr 공용), TRNG 보조 엔트로피 필수 RAM 64B 섹션 2.2
FW-SIGN-20 서명 카운터 관리 전역 카운터 단조 증가, EEPROM NV 저장, 서명 성공 시만 증가 필수 저장 4B firmware-signing-interface.md [5]

7. 테스트 벡터 및 검증 기준

7.1. 정상 케이스

TC-SIGN-01: BTC 단순 전송

입력:
  - PSBT: 1 입력 (P2TR UTXO, 0.5 BTC) → 2 출력 (0.3 BTC 전송, 0.1999 BTC 잔금)
  - 경로: m/86'/0'/0'/0/0
  - 서명 방식: Schnorr (BIP-340)

기대 출력:
  - SE_PARSE_HASH: SHA-256(recipient || 30000000 sat || 100000 sat fee || "BTC")
  - 서명: 64 bytes Schnorr signature
  - 카운터: 이전 + 1
  - 응답 코드: 0x00 (SUCCESS)

TC-SIGN-02: MuSig2 2-of-2

Round 1:
  입력: session_id, derivation_path m/86'/0'/0'/0/0
  기대 출력: public_nonce (66 bytes), 세션 저장 확인

Round 2:
  입력: session_id, aggregated_nonce, sighash
  기대 출력: partial_sig (32 bytes), 세션 삭제 확인
  검증: 2개 partial_sig 집계 → 유효한 Schnorr 서명

TC-SIGN-03: EVM 단순 전송

입력:
  - RLP: EIP-1559 Type 2, chain_id=1, to=0x742d...bD14, value=1 ETH, data=0x
  - 경로: m/44'/60'/0'/0/0

기대 출력:
  - SE_PARSE_HASH: SHA-256(recipient || 1 ETH || gas_fee || chain_id=1)
  - 서명: v (1B) + r (32B) + s (32B) = 65 bytes ECDSA
  - 응답 코드: 0x00 (SUCCESS)

TC-SIGN-04: ERC-20 transfer

입력:
  - RLP: to=USDT 컨트랙트, value=0, data=0xa9059cbb + recipient + 1000 USDT
  - 토큰 DB: USDT (decimals=6)

기대 출력:
  - WYSIWYS 표시: "토큰 전송: 1,000.00 USDT → 0x742d...bD14"
  - 서명: ECDSA 65 bytes
  - 응답 코드: 0x00 (SUCCESS)

7.2. 에러 케이스

TC ID 시나리오 기대 에러 코드 기대 동작
TC-ERR-01 미지원 chain_type (0x03) 0x40 (UNSUPPORTED_CHAIN) 파싱 거부, 에러 반환
TC-ERR-02 잘못된 PSBT (magic bytes 불일치) 0x41 (PARSE_ERROR) 파싱 실패, 에러 반환
TC-ERR-03 미지원 EIP 타입 (Type 4) 0x42 (UNSUPPORTED_TX_TYPE) 에러 반환
TC-ERR-04 MuSig2 세션 미존재 0x35 (MUSIG2_SESSION_NOT_FOUND) 에러 반환
TC-ERR-05 MuSig2 세션 타임아웃 0x36 (MUSIG2_SESSION_EXPIRED) 세션 삭제 + 에러
TC-ERR-06 PSBT 크기 초과 (>100KB) 0x43 (PAYLOAD_TOO_LARGE) 수신 거부
TC-ERR-07 정책 버전 불일치 0x24 (POLICY_VERSION_MISMATCH) 서명 거부
TC-ERR-08 미등록 함수 셀렉터 (에러 아님) CAUTION 경고 + 사용자 판단

본 문서는 Phase 6 Firmware Requirements의 두 번째 산출물(1/2)로, D'CENT X SE 멀티체인 서명 기능의 펌웨어 요구사항을 정의한다. Phase 5 firmware-signing-interface.md의 Signing Applet 구현을 상세화하며, FW-SIGN-01~20의 요구사항 ID 체계로 추적 가능하다. Phase 4 wysiwys-design.md의 체인별 파싱 범위와 Phase 5 chain-abstraction-layer.md의 체인 추상화 인터페이스를 펌웨어 구현 수준으로 변환하였다.


관련 문서