> ## Documentation Index
> Fetch the complete documentation index at: https://docs.datafdn.org/llms.txt
> Use this file to discover all available pages before exploring further.

# 커널 업그레이드

> DKG 위원회 Validator의 story-kernel 바이너리 업그레이드 가이드

## 커널 업그레이드 워크플로 (Aeneid)

Aeneid 테스트넷 DKG 위원회 Validator의 story-kernel 바이너리를 업그레이드합니다.
DKG 온체인 업그레이드 메커니즘을 사용합니다: 새 MRENCLAVE 화이트리스트 등록, 업그레이드 스케줄링, 듀얼 커널 리셰어링, 그리고 컷오버.

***

## 사전 요구사항

* 현재 DKG 라운드가 **Active** 단계일 때 업그레이드를 시작하는 것을 권장합니다
* 모든 Validator 머신에 새 story-kernel 바이너리가 빌드되어 있어야 합니다(동일한 MRENCLAVE를 생성해야 함)
* `whitelistEnclaveType` 및 `scheduleUpgrade`를 위한 DKG 컨트랙트에 대한 Timelock/owner 액세스
* 새 커널 클라이언트의 SGXValidationHook 프록시 주소를 알고 있어야 함

## 1단계: 새 커널 빌드

**각 Validator 머신**에서 새 story-kernel 바이너리를 빌드하세요(MRENCLAVE가 일치해야 하므로 절대 SCP로 바이너리를 전송하지 마세요).

```bash theme={null}
cd ~/story-kernel
git pull origin release/0.1
make clean && make build-with-cpp && make all-gramine
NEW_MRENCLAVE=$(cat story-kernel.manifest.sgx.d/mrenclave.txt)
echo "New MRENCLAVE: $NEW_MRENCLAVE"
```

진행하기 전에 모든 Validator가 **동일한** `NEW_MRENCLAVE` 값을 생성하는지 확인하세요.

## 2단계: 듀얼 커널 시작

새 커널은 별도의 포트에서 기존 커널과 함께 실행됩니다. DATA Foundation CL은 각 커널을 `code_commitment`(MRENCLAVE)로 식별합니다.

```bash theme={null}
# 기존 커널: 이미 :50051에서 실행 중
# 새 커널: :50052에서 별도 home 디렉토리로 시작

# 두 커널 모두 리스닝 중인지 확인
sudo lsof -i :50051 | grep LISTEN  # 기존
sudo lsof -i :50052 | grep LISTEN  # 새
```

<Warning>
  새 커널은 다음이 별도로 필요합니다:

  * Home 디렉토리 (별도의 라이트 클라이언트 상태)
  * 다른 `listen_addr` (`:50052`)을 가진 Gramine manifest
</Warning>

## 3단계: DATA Foundation Config 업데이트 + 재시작

새 커널 엔드포인트를 `story.toml`에 추가하세요:

```toml theme={null}
kernel-endpoints = ["127.0.0.1:50051", "127.0.0.1:50052"]
```

story를 재시작하세요:

```bash theme={null}
sudo systemctl restart story
```

**두 커널이 모두** 연결되었는지 확인하세요:

```bash theme={null}
journalctl -u story --since '1 minute ago' | grep "Connected to kernel"
# 서로 다른 code_commitment 값을 가진 두 항목이 표시되어야 합니다
# 확인: connected_clients=2
```

## 4단계: 온체인 화이트리스트 + 업그레이드 스케줄링

현재 DKG 라운드가 **Active** 단계가 될 때까지 기다린 후:

```bash theme={null}
DKG="0xCcCcCC0000000000000000000000000000000004"
ENCLAVE_TYPE="0x0000000000000000000000000000000000000000000000000000000000000001"
SGX_HOOK="<sgx_hook_proxy_addr>"

# 1. 새 MRENCLAVE 화이트리스트 등록
cast send $DKG 'whitelistEnclaveType(bytes32,(bytes32,address),bool)' \
    $ENCLAVE_TYPE "(0x$NEW_MRENCLAVE,$SGX_HOOK)" true \
    --rpc-url $RPC --private-key $KEY --legacy --gas-price 30000000000

# 2. 업그레이드 스케줄링 (activation = 현재 높이 + 버퍼)
CURRENT=$(cast block-number --rpc-url $RPC)
ACTIVATION=$((CURRENT + 50))
cast send $DKG 'scheduleUpgrade(uint256,string)' $ACTIVATION "v<version>" \
    --rpc-url $RPC --private-key $KEY --legacy --gas-price 30000000000
```

<Note>
  Aeneid에서 DKG 컨트랙트 작업은 Timelock(minDelay=600s)을 거칩니다.
  Timelock 트랜잭션을 스케줄링하고, 10분 대기 후 실행하세요.
</Note>

## 5단계: 업그레이드 리셰어링 대기

```bash theme={null}
# activation 모니터링
while true; do
  HEIGHT=$(curl -s localhost:26657/status | python3 -c "import sys,json; print(json.load(sys.stdin)['result']['sync_info']['latest_block_height'])")
  echo "Height: $HEIGHT / $ACTIVATION"
  if [ "$HEIGHT" -ge "$ACTIVATION" ]; then break; fi
  sleep 5
done

# 업그레이드 리셰어링 라운드 시작 확인
journalctl -u story --since '5 minutes ago' | grep 'is_upgrade.*true'

# 완료 대기
timeout 3600 bash -c "while ! journalctl -u story --since '1 hour ago' | grep -q 'DKG finalization phase complete'; do sleep 15; done"
```

## 6단계: 새 커널로 컷오버

업그레이드 리셰어링이 성공적으로 완료된 후:

```bash theme={null}
# 1. 기존 커널 중지
sudo systemctl stop story-kernel  # :50051의 기존

# 2. story.toml을 새 커널만 사용하도록 업데이트
sed -i 's|kernel-endpoints = \["127.0.0.1:50051", "127.0.0.1:50052"\]|kernel-endpoints = ["127.0.0.1:50052"]|' \
    ~/.story/story/config/story.toml

# 3. story 재시작
sudo systemctl restart story

# 4. 검증
journalctl -u story --since '1 minute ago' | grep "Connected to kernel"
# 새 code_commitment를 가진 1개 항목이 표시되어야 합니다
```

***

## 검증 체크리스트

* [ ] 모든 Validator가 동일한 `NEW_MRENCLAVE`를 빌드함
* [ ] 모든 Validator에서 두 커널이 모두 연결됨 (`connected_clients=2`)
* [ ] `whitelistEnclaveType` 트랜잭션 확인됨 (enclave type 1에 새 MRENCLAVE 등록)
* [ ] 대상 activation 높이와 함께 `scheduleUpgrade` 트랜잭션 확인됨
* [ ] `is_upgrade=true`로 업그레이드 리셰어링 라운드 시작됨
* [ ] 기존 커널이 deal을 생성하고, 새 커널이 응답 처리
* [ ] 모든 위원회 멤버에서 `DKG finalization phase complete`
* [ ] 기존 커널 중지, config가 새 커널만 사용하도록 업데이트됨
* [ ] 새 DKG 라운드가 새 커널에서 정상적으로 진행됨

## 문제 해결

| 증상                                       | 원인                             | 해결 방법                                          |
| ---------------------------------------- | ------------------------------ | ---------------------------------------------- |
| 재시작 후 `connected_clients=1`              | 새 커널이 실행되지 않거나 포트 불일치          | `lsof -i :50052` 확인, Gramine manifest 확인       |
| "no new kernel client found for upgrade" | DATA Foundation이 새 커널에 연결되지 않음 | `kernel-endpoints`에 두 포트가 모두 있는지 확인, story 재시작 |
| activation 높이에서 업그레이드 라운드가 시작되지 않음       | 스케줄링 시 Active 단계가 아니었음         | 다음 Active 단계 동안 재스케줄링                          |
| Finalization 실패                          | 업그레이드된 위원회 멤버 부족               | 모든 Validator가 듀얼 커널을 실행 중인지 확인                 |
