본문으로 건너뛰기

JIT 증거 복원

구현됨

구현 저장소: BackwardLabs/daejang-jit-engine @ 8cb725d

요청된 subject에 필요한 거래 증거만 복원해 Observation을 만든다.

왜 필요한 거래만 복원하는가

전체 체인의 상세 실행 데이터를 계속 저장하면 trace와 state 수집 비용이 너무 크다. 반대로 block number, transaction index, match bits 같은 최소 역색인만으로는 다음 내용을 확정할 수 없다.

  • 그 위치가 index snapshot이 가리킨 동일 canonical block인지
  • 실제 transaction hash와 inclusion이 무엇인지
  • coarse match가 실제 account 참여인지 false positive인지
  • 관련된 정확한 logIndex, traceAddress, authorizationIndex가 무엇인지
  • 실행이 성공, revert, reorg 중 어느 상태인지
  • account 관점의 자산 수량 부호와 Observation origin이 무엇인지
  • 결과가 불완전한 이유가 증거 누락인지 schema 표현 한계인지

그래서 역색인과 canonical Observation 사이에 replay 계층을 둔다. 재현 가능하고, 멱등적이며, 실패를 숨기지 않는다.

역색인 hit 자체는 결코 관련성의 증거로 인정되지 않는다. 엔진은 provider에서 block과 transaction을 다시 해석하고, 관측한 block hash를 기록한다.

JIT 처리 흐름 한눈에 보기

이 그림은 JIT의 핵심 흐름만 보여준다. 전체 체인을 다시 훑지 않고 역색인으로 범위를 좁힌 뒤, 각 후보를 canonical 실행 증거와 대조해 Observation을 만든다.

단계맡는 일
지갑 주소 조회요청한 지갑 주소를 기준으로 account 범위를 정한다
역색인 조회해당 지갑과 관련될 가능성이 있는 transaction으로 범위를 좁힌다
체인 증거 확인관련 transaction, receipt, log, trace와 state evidence를 복원하고 검증한다
Observation검증된 실행 결과에서 확인한 account 범위 사실만 기록한다

이 흐름 뒤에서는 schema 검증과 저장도 수행하며, unsupported 또는 불완전한 evidence에는 명시적인 outcome을 남긴다. JIT 경로는 의도적으로 Observation에서 멈춘다. Swap, bridge, self-transfer, valuation, 취득가액, 세무 의미는 이후 계층이 담당한다.

입력 계약

interface StartJitRun {
generationId: string;
subjectId: string;
indexSnapshotId: string;
evidenceProfile: 'EVM_ACCOUNT_FULL';
accounts: Array<{
accountId: string;
chainId: string;
address: string;
ownershipFrom: string;
ownershipTo?: string;
}>;
candidates: Array<{
accountId: string;
chainId: string;
blockNumber: string;
transactionIndex?: number;
blockEventIndex?: number;
matchBits: number;
}>;
}

accountscandidates는 모두 비어 있을 수 없고, 모든 candidate는 같은 요청 안의 account를 참조해야 한다.

정규화와 검증

필드규칙
IDletter, digit, ., _, :, -
chainIdCAIP-2 EVM 형식 eip155:<10진수 chain id>. candidate의 chain은 account의 chain과 같아야 한다
address20-byte 0x EVM 주소, 소문자로 정규화. EIP-55 checksum은 요구하지 않는다
ownership windowRFC 3339 timestamp를 [ownershipFrom, ownershipTo)로 해석. 끝은 선택이며 시작보다 앞설 수 없다
blockNumber선행 0 없는 음이 아닌 canonical 10진 문자열. 단 0은 예외
candidate 좌표transactionIndex 또는 blockEventIndex 중 정확히 하나
matchBits0x01..0x80 범위의 알려진 bit들의 0이 아닌 bitwise OR
evidence profileEVM_ACCOUNT_FULL로 고정. 요청별 축소 profile은 받지 않는다
중복 candidate한 snapshot 안에서 동일 locator의 첫 번째가 canonical이고, 이후는 DUPLICATE로 종결
알 수 없는 필드정규화 과정에서 제거

Match bits

Bit의미
0x01TX_FROM
0x02TX_TO
0x04ASSET_FROM
0x08ASSET_TO
0x10ERC4337_ACCOUNT
0x20EIP7702_AUTHORITY_CANDIDATE
0x40NATIVE_INTERNAL_FROM
0x80NATIVE_INTERNAL_TO

match bit는 발견 힌트다. exact-hit 재구성은 여전히 NOT_RELEVANT를 반환할 수 있다. internal call, log, authorization 좌표는 실행 증거에서 재구성하며, 외부 candidate 좌표로 받지 않는다.

구현된 기능

  • 불변 selection snapshot과 selection digest
  • 후보 거래의 exact hit 및 bounded closure 선택
  • provider retry·failover, 체인 identity 확인, provider divergence 감지
  • canonical transaction, receipt, log, trace 기반 증거 수집
  • ERC-20, ERC-721, ERC-1155 transfer Observation
  • ERC-4337 UserOperationEvent, EIP-7702 authorization, withdrawal 관측
  • reorg 및 inclusion revision 처리
  • 실행 결과 cache, singleflight, bounded concurrency
  • CUE schema 검증
  • CandidateQueryServiceJitEngineService를 제공하는 Go gRPC daemon jitd
  • Unix peer UID 또는 mTLS subject 기반 접근 제어
  • artifact staging과 terminal commit을 포함한 저장 adapter
  • graceful shutdown, health endpoint, secret redaction

지갑·프로토콜 가정

  • 입력 주소를 EOA로 가정하지 않는다. EOA, contract wallet, ERC-4337 smart account 주소를 모두 WALLET account로 만든다.
  • EIP-7702 candidate는 복원한 authorization과 적용 전후 account state로 검증한다. candidate bit만으로 Observation을 만들지 않는다.
  • ERC-4337 userOpHashuserOpIndex는 native 실행 증거로 보존한다. 고정된 schema에 일급 USER_OPERATION 좌표가 없으므로, 해당 작업은 임의의 transaction 좌표로 매핑되지 않고 partial 또는 unsupported로 종결된다.
  • 현재 ERC4337_ACCOUNT exact match는 user operation의 sender다. paymaster와 실제 gas payer 역할은 wallet hit가 되기 전에 별도의 discovery semantics가 필요하다.
  • transaction 없는 block credit과 withdrawal은 blockEventIndex를 사용한다. 고정된 schema에 transaction 없는 Observation origin이 없으므로, 현재 UNSUPPORTED로 종결하며 native 좌표를 보존한다.

하지 않는 일

다음 기능은 JIT 엔진의 책임이 아니다.

  • swap, bridge, self-transfer 같은 경제적 event 판정
  • Posting, KRW valuation, 취득가액, 세무 정책 적용
  • 최종 report 생성 또는 GIWA commitment 제출
  • ERC-4337 paymaster나 실제 gas payer를 wallet 소유 관계로 추론
  • schema에 없는 좌표를 임의로 생성
  • 이미 발행한 generation을 제자리에서 수정

범위에 대한 두 가지 추가 사항:

  • 출력 discovery 범위는 account별로 해석된 candidate block의 최소·최대에서 유도한다. 엔진이 그 구간의 모든 block을 독립적으로 스캔했다는 주장이 아니다.
  • artifact 보존, eviction, EVICTED lifecycle은 durable production store가 필요하며 in-memory 참조 구현에는 없다.

고정 schema 계약

항목
저장소BackwardLabs/schema
모듈 digestd08257dbf7f22a381540cc1331ca6047a53bf0863eaa42d28d8db65bde371303

검증

기본 브랜치에서 go test ./..., go vet ./..., go build ./...가 통과한다.

이 테스트는 fixture, mock provider, transport, storage adapter 경계를 확인한다. 상용 RPC provider나 전체 제품 경로에 대한 동작은 증명하지 않는다.