EIP-8130 키스토어 계정 (Keystore Accounts)
콜 결정 없음 · 계정 추상화 · 원문 상태 Draft · 2025-10-14 작성
계정마다 여러 서명 키(액터)를 온체인 키스토어에 등록하고 키별로 권한 범위와 만료를 정할 수 있게 합니다. 어떤 트랜잭션 형식에서도 같은 권한 설정이 통합니다.
왜 필요한가
지금 계정 추상화 제안 가운데 검증을 지갑 코드에 맡기는 방식은 노드가 트랜잭션을 받기 전에 임의의 EVM 코드를 미리 실행해 봐야 합니다. 그래서 전체 상태 접근, 추적 인프라, 잘못된 제출의 비용을 막는 평판 시스템까지 필요해집니다. 이 제안은 '누가 서명했나'(인증)와 '그 키가 무엇을 할 수 있나'(권한)를 분리합니다. 각 키는 서명을 검사하는 인증자(authenticator) 계약을 미리 선언하므로, 노드는 임의 코드를 돌려 보는 대신 소수의 표준 인증자 집합만 받아들이면 됩니다. 검증 비용이 예측 가능해지고 패스키나 양자내성 서명 같은 새 알고리즘도 계정을 옮기지 않고 새 인증자를 가리키는 키를 하나 추가하는 것만으로 쓸 수 있습니다. 또 하나의 계약 집합과 하나의 서명 변경 형식으로 여러 체인과 여러 전송 경로에서 같은 키 설정을 관리할 수 있어 이식성이 좋아집니다.
무엇이 바뀌나
지금
- EOA는 secp256k1 키 하나가 계정의 전부이고 키를 바꾸거나 나눌 방법이 없습니다
- 패스키 같은 새 서명 방식을 쓰려면 스마트 계정을 새로 배포해야 합니다
- 세션 키의 권한 제한은 지갑 코드마다 제각각이라 노드가 미리 알 수 없습니다
EIP-8130 이후
- 한 계정에 여러 액터를 등록하고 키마다 권한 범위, 만료, 정책을 정합니다
- 표준 인증자 집합(secp256k1, P-256, 패스키, 위임)으로 검증 비용이 예측 가능해집니다
- 새 서명 알고리즘은 새 액터를 등록하기만 하면 되고 계정 주소는 그대로입니다
- 같은 설정이 일반 EVM 호출, ERC-4337, 프레임 계정, 네이티브 AA 트랜잭션에서 동일하게 동작합니다
누구에게 영향이 있나
- 사용자: 키 하나에 묶이지 않고 패스키, 세션 키 등 여러 키를 같은 계정에서 쓸 수 있습니다. 배포 전 주소로 자금을 먼저 받을 수도 있습니다.
- 지갑·앱 개발자: 구독 결제나 지출 한도 같은 제한 키를 표준 방식(정책과 관리자 계약)으로 구현할 수 있고 체인마다 같은 주소와 설정을 재사용합니다.
- 클라이언트 팀: AA 트랜잭션 타입과 통합하면 키스토어 읽기와 표준 인증자를 네이티브로 구현할 수 있으며 결과는 계약 실행과 동일해야 합니다.
- L2: 트랜잭션 검증 경로에서 표준 인증자만 받는 정책(canonical-only)을 택할 수 있고 동반 ERC 절차로 집합을 확장할 수 있습니다.
심층 설명
액터와 인증자: 인증과 권한의 분리
계정은 KEYSTORE_ADDRESS에 있는 키스토어 계약에 액터를 등록합니다. 각 액터는 인증자 계약에 묶이고 인증자는 IAuthenticator.authenticate(hash, data)로 서명을 검사해 32바이트 식별자 actorId를 돌려줍니다. 인증자는 '누가 서명했나'만 답하고 그 액터가 무엇을 할 수 있는지는 키스토어에 저장된 scope가 정합니다. 소비자(consumer)는 키스토어로 권한을 확인하는 모든 시스템으로, 네이티브 AA 트랜잭션 타입, EIP-8141 프레임 계정, ERC-4337 계정, 서명을 검증하는 애플리케이션이 모두 해당합니다. EOA는 자기 secp256k1 키가 키스토어 쓰기 없이 암묵적 관리자 액터(self-actor)가 되므로 기존 계정은 그대로 동작하고 채택은 전적으로 선택입니다.
표준 인증자 집합
네이티브로 검증하는 소비자가 반드시 받아야 하는 초기 집합은 넷입니다. k1(secp256k1, 네이티브 센티널 K1_AUTHENTICATOR), p256(P-256), passkey(WebAuthn/FIDO2), delegate(서명 위임)입니다. delegate는 계정 A가 계정 B의 키로 서명하는 것을 허용하되, 중첩된 인증자가 다시 delegate이면 안 되고 표준 인증자여야 해서 검증량이 묶입니다. 표준 인증자는 체인마다 같은 CREATE2 주소에 배포되고 동반 ERC(번호 미정)로 목록화됩니다. 베이스 레이어에서 인슈라인된 집합을 바꾸려면 하드포크가 필요합니다. 양자내성 같은 새 알고리즘이 추가돼도 기존 계정은 새 인증자를 가리키는 액터를 하나 등록하면 되고 마이그레이션이나 주소 변경이 없습니다.
actor_config 저장 구조와 스코프 비트마스크
각 액터는 슬롯 하나에 authenticator(20) ‖ expiry(6) ‖ scope(2) ‖ reserved(4)로 패킹됩니다. expiry는 uint48 유닉스 초이고 0이면 무기한, scope는 uint16 비트마스크입니다. scope 0x0000은 무제한이자 관리자(admin) 판정식이라, 설정 변경 권한은 정확히 scope == 0x00인 액터에만 있습니다. 비트는 OPERATOR(0x01, 임의 대상 개시와 ERC-1271 수준의 계정 서명), SELF_PAYER(0x02, 자기 가스 지불), SPONSOR_PAYER(0x04, 타인 가스 대납), POLICY(0x08, 관리자 계약으로만 개시), NONCE(0x10, 순차 논스 채널 사용)입니다. 판정은 fail-closed로, 알 수 없는 비트는 아무 권한도 주지 않습니다. 유효성은 actor_config 한 번 읽기로 끝나 검증과 무효화가 싸고 예측 가능합니다.
액터 정책: 세션 키의 단일 대상 제한
두 가지 결정이 독립적입니다. 무엇이 저장되는가는 policyData의 길이가 정합니다. 비어 있거나 정확히 manager(20바이트) ‖ commitment(32바이트)여야 하고 다른 길이는 거부됩니다. 발신이 묶이는가는 POLICY 비트와 OPERATOR 부재가 정합니다. POLICY가 켜진 액터는 저장된 manager 한 곳에만 호출할 수 있고 트랜잭션 최상위 value는 0이어야 하므로, ETH 이동은 관리자와 계정 코드 안에서만 일어납니다. 관리자 계약이 커밋을 읽어(getPolicyCommitment) 제시된 파라미터를 검증하고 승인된 동작만 수행합니다. 관리자는 완전한 신뢰 대상이므로 감사된 비업그레이드 계약을 써야 하고 revokeActor는 actor_config와 정책 슬롯을 함께 지웁니다. OPERATOR는 POLICY를 무효화하므로 정책 키에 OPERATOR를 함께 주면 안 됩니다.
변경 채널, 에포크, 계정 잠금
모든 액터·잠금 변경은 관리자 서명이 붙은 배치로 단일 진입점 applySignedAccountChanges를 지나며 누구나 중계할 수 있습니다. Local 채널의 시퀀스는 local_epoch(상위 32비트) || local_sequence(하위 32비트)이고, Multichain 채널(chain_id 0)은 단순 단조 카운터로 체인 간 액터 상태 동기화에 씁니다. 하위 절반이 UNSEQUENCED(2^32-1)면 카운터를 소모하지 않는 JIT 배치로, 에포크가 바뀌기 전까지 재사용 가능합니다. IncrementLocalEpoch는 이전 에포크의 미반영 로컬 서명을 전부 취소하지만 살아 있는 액터나 Multichain 채널은 건드리지 않습니다. Lock은 모든 권한 변경을 막고 Unlock과 IncrementLocalEpoch만 허용하며 unlock_delay는 uint16 범위(최대 약 18.2시간)로 묶여 계정이 설정 회전을 영구히 잠그는 일을 막습니다.
계정 생성과 주소 유도
createAccount(userSalt, bytecode, initialActors)는 EIP-1014의 CREATE2 공식으로 주소를 유도하고 런타임 바이트코드를 실행 없이 그 주소에 직접 놓습니다. initial_actors는 actorId 오름차순으로 정렬해 leaf 해시들을 묶은 actors_commitment를 만들고 effective_salt = keccak256(user_salt || actors_commitment)로 주소를 계산합니다. 초기 액터가 솔트에 커밋되므로 다른 액터 구성으로 선점 배포하는 공격이 막히고 같은 입력이면 어느 체인에서나 같은 주소가 나와 배포 전 주소로 자금을 받을 수 있습니다. expiry와 manager = account는 생성 시 표현할 수 없고 이후 설정 변경으로 추가합니다. 이미 배포된 계정은 importAccount()를 자기 자신이 호출해 등록하며 계정 코드의 confirmKeystoreImport()가 돌려준 액터 집합과 다이제스트가 맞아야 설치됩니다.
AA 트랜잭션 타입과의 통합
이 문서는 네이티브 AA 트랜잭션 타입 제안과의 통합을 함께 명세합니다. sender_auth와 payer_auth는 authenticator || data 형태로 authenticateActor와 동일하게 해석되고 예약 범위에서 계정 변경 엔트리 0x02(생성)와 0x03(설정 변경)을 할당합니다. 표준 인증자는 인슈라인된 고정 비용으로, 그 외 인증자는 MAX_AUTHENTICATION_GAS로 제한된 STATICCALL로 측정해 받는데, 수용 정책은 체인이 정합니다(L1은 허용적, L2는 표준 전용이 전형). 생성 비용은 32,000에 배포 바이트당 200을 더하고 초기 액터 슬롯 쓰기당 22,100입니다. 정책 게이트 위반은 ActorPolicyViolation으로 해당 단계가 되돌려지는 실행 결과이지 유효성 오류가 아닙니다. 키스토어 상태가 빈 계정은 통합 전후로 유효성, 실행 결과, 가스가 동일합니다.
상태와 진행 상황
이 EIP는 Draft 상태라 명세가 바뀔 수 있습니다. 계약 내부(정확한 저장 패킹, 타입해시, 이벤트 ABI, 함수 본문)는 base 조직의 EIP-8130 저장소(src/Keystore.sol)가 권위 있는 출처이고 구현은 이와 일치해야 합니다. 콜 기록을 보면 8월 13일 ACDE #243에서 네이티브 계정 추상화 구현을 프레임 방식(EIP-8141)으로 할지 이 제안(EIP-8130)으로 할지에 대한 결정이 8월 25일 AA 브레이크아웃과 8월 27일 ACDE로 미뤄졌고 8월 27일 ACDE #244에서도 결정 없이 논의만 있었습니다. 어느 방식을 채택할지는 아직 정해지지 않았습니다.