You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
이 글에서는, IAction 기반 상태 전이 로직의 가정들과 한계점, 그리고 이후 발전 방향에 대한 아이디어를 소개합니다.
배경
Libplanet은 블록체인으로 동기화 할 상태를 전이시키기 위해, 사용하는 애플리케이션 쪽에서 상태 전이 코드를 직접 작성하도록 요구합니다. 이전 상태와 사용자의 입력을 받아 다음 상태를 반환하는 IAction.Execute()가 그것입니다. 이 단순하지만 직관적인 방법은, (몇가지 변주를 거치긴 했지만) 이후 수년간 Nine Chronicles의 개발에 채용되어, 게임 로직의 대부분이 이런 IAction의 구현들로 작성되었습니다.
문제점
1. 애플리케이션을 표현하기에 부족한 표현력
상태 전이 함수는 대부분의 애플리케이션을 간추려서 설명하기엔 적합한 메타포지만, 실 개발에 충분하진 않습니다. 많은 경우 애플리케이션은 다양한 기능을 지원하며, 이 때 이들을 더 작은 단위로 간추려서 추상화합니다.
Libplanet의 첫 버전(0.1.0)에선 IAction을 태깅 하는 것만으로 이를 표현하려고 했고, 0.2.0에선 PolymorphicAction<T>를 통해 ActionTypeAttribute에 의존한 액션 선택을 선택적으로 만들고, 애플리케이션쪽으로 미루려 했습니다. 하지만 이런 액션 선택이 일반적인 요구 사항이었기에 이는 결과적으로 실패한 시도로 간주됩니다. 1
그리하여 PolymorphicAction<T>와 StaticActionLoader를 거치지만, 여전히 ActionTypeAttribute에 의한 태깅에 의존한다는 점은 현재까지 이어집니다. 그리고 나인 크로니클의 경우엔 어떤 자동화된 도구나 타입 시스템가 아닌, 애플리케이션 개발자가 직접 입력한 임의의 문자열에 의존합니다.
2. 액션 유지 보수의 어려움
Libplanet은 사용자가 호출한 IAction 구현(이하 액션)과 인자를 블록 체인에 기록하며 그로 인해 전이된 상태의 요약(digest)을 블록에 기록하는 것으로 노드간의 상태 정합성 유지를 돕습니다. 이를 위해서 액션들은 항상 같은 입력에 대해서는 같은 출력을 반환하도록 요구됩니다. 즉 Libplanet을 사용한 애플리케이션에서는, 모든 액션은 제거될 수 없고 체인이 유지되는 한 계속 유지되어야 합니다.
단순히 클래스를 추가하고 지우지 않는 것이라면, 그래도 해볼만한 도전으로 보입니다.2 하지만 해결하기 까다로운 문제는, 이러한 액션들의 동작은, 그 자체뿐아니라 다른 클래스나 함수에 의존한다는 것입니다. �즉 어떤 액션의 동작을 수정하기 위해 공통 클래스나 함수를 고치면, 이를 사용하고 있는 다른 모든 액션들이 영향을 받을 수 있습니다. 이를 피하기 위해선, 의존하고 있는 공통 클래스나 함수를 개발자가 직접 파악하여 격리해야 합니다. (예시)
이 두 가지 특성으로 인해, 나인 크로니클의 게임 로직 수정은 어려운 일을 넘어서 점점 위험한 일이 되고 있습니다. 거의 대부분의 메인넷 노드를 플라네타리움이 직접 운영함에도 불구하고, 상태 불일치로 인한 체인 정지나 블록 동기화 실패는 2023년 5월까지 지속적으로 발생하는 중입니다.
2. 애플리케이션 배포의 어려움
애플리케이션 개발자가 구현한 액션 구현은, 그 애플리케이션 구현에 포함되어 실행됩니다. 이는 일반적인 애플리케이션 개발과 유사한 개발 도구들과 기법들을 활용할 수 있다는 장점도 있지만, 동시에 어떤 기능의 업데이트가 반드시 블록체인 노드 소프트웨어 전체의 업데이트를 필요로 한다는 단점을 수반합니다.
"Program"을 통해 액션 구현들을 구조화하더라도, 이전 상태를 똑같이 구현해야 하는 이상 네트워크에는 한 "Program"의 다른 구현이 있을 수 있습니다. "Program"마다 식별자를 따로 지정하는 것은 이런 여러 구현을 관리하는 것을 돕지만, 트랜잭션을 발생시키는 사용자가 이전 식별자를 계속 사용할 수 있기 때문에 문제를 완전히 해결하진 못합니다.
이 문제를 완화하기 위해, Ethereum의 프록시 업그레이드 패턴과 같은 방식을 고려할 수 있습니다. 가령 모든 "Program"마다 일종의 프록시("Proxy")를 가정하고, 그 프록시가 특정 시점의 "Program" 식별자를 가지고 있다고 가정하는 식이죠.
프록시가 참조할 "Program"의 식별자를 체인 상태 등에 기록하는 것만으로, 과거 시점의 트랜잭션을 실행할 때에도 알맞은 "Program"을 실행할 수 있습니다. 7
혹은, 모든 "Program"은 항상 버저닝 될 것을 가정하는 것으로, 실행기(e.g., ActionEvaluator)나 시스템 차원에서 이런 전달을 가정할 수도 있습니다.
vs Pluggin Lib9c (w/ DynamicActionLoader)
TBD
나인 크로니클의 마이그레이션
TBD
Footnotes
PolymorphicAction<T>(혹은 0.1.0의 BaseAction)은, 조회 해야 할 액션 구현의 종류를 <T>에 명시된 클래스의 하위 클래스로 제한하려는 의도도 있었습니다. 하지만 이는 주요한 동기는 아니었고, 불필요한 상속을 강제한다는 점에서 역시 좋은 방법은 아니라고 생각합니다. ↩
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
(For the sake of easy writing/reading, the rest part of this text will be written in Korean 😅, please use translate feature of GitHub Discussion )
요약
이 글에서는,
IAction
기반 상태 전이 로직의 가정들과 한계점, 그리고 이후 발전 방향에 대한 아이디어를 소개합니다.배경
Libplanet은 블록체인으로 동기화 할 상태를 전이시키기 위해, 사용하는 애플리케이션 쪽에서 상태 전이 코드를 직접 작성하도록 요구합니다. 이전 상태와 사용자의 입력을 받아 다음 상태를 반환하는
IAction.Execute()
가 그것입니다. 이 단순하지만 직관적인 방법은, (몇가지 변주를 거치긴 했지만) 이후 수년간 Nine Chronicles의 개발에 채용되어, 게임 로직의 대부분이 이런IAction
의 구현들로 작성되었습니다.문제점
1. 애플리케이션을 표현하기에 부족한 표현력
상태 전이 함수는 대부분의 애플리케이션을 간추려서 설명하기엔 적합한 메타포지만, 실 개발에 충분하진 않습니다. 많은 경우 애플리케이션은 다양한 기능을 지원하며, 이 때 이들을 더 작은 단위로 간추려서 추상화합니다.
Libplanet의 첫 버전(0.1.0)에선
IAction
을 태깅 하는 것만으로 이를 표현하려고 했고, 0.2.0에선PolymorphicAction<T>
를 통해ActionTypeAttribute
에 의존한 액션 선택을 선택적으로 만들고, 애플리케이션쪽으로 미루려 했습니다. 하지만 이런 액션 선택이 일반적인 요구 사항이었기에 이는 결과적으로 실패한 시도로 간주됩니다. 1그리하여
PolymorphicAction<T>
와StaticActionLoader
를 거치지만, 여전히ActionTypeAttribute
에 의한 태깅에 의존한다는 점은 현재까지 이어집니다. 그리고 나인 크로니클의 경우엔 어떤 자동화된 도구나 타입 시스템가 아닌, 애플리케이션 개발자가 직접 입력한 임의의 문자열에 의존합니다.2. 액션 유지 보수의 어려움
Libplanet은 사용자가 호출한
IAction
구현(이하 액션)과 인자를 블록 체인에 기록하며 그로 인해 전이된 상태의 요약(digest)을 블록에 기록하는 것으로 노드간의 상태 정합성 유지를 돕습니다. 이를 위해서 액션들은 항상 같은 입력에 대해서는 같은 출력을 반환하도록 요구됩니다. 즉 Libplanet을 사용한 애플리케이션에서는, 모든 액션은 제거될 수 없고 체인이 유지되는 한 계속 유지되어야 합니다.단순히 클래스를 추가하고 지우지 않는 것이라면, 그래도 해볼만한 도전으로 보입니다.2 하지만 해결하기 까다로운 문제는, 이러한 액션들의 동작은, 그 자체뿐아니라 다른 클래스나 함수에 의존한다는 것입니다. �즉 어떤 액션의 동작을 수정하기 위해 공통 클래스나 함수를 고치면, 이를 사용하고 있는 다른 모든 액션들이 영향을 받을 수 있습니다. 이를 피하기 위해선, 의존하고 있는 공통 클래스나 함수를 개발자가 직접 파악하여 격리해야 합니다. (예시)
이 두 가지 특성으로 인해, 나인 크로니클의 게임 로직 수정은 어려운 일을 넘어서 점점 위험한 일이 되고 있습니다. 거의 대부분의 메인넷 노드를 플라네타리움이 직접 운영함에도 불구하고, 상태 불일치로 인한 체인 정지나 블록 동기화 실패는 2023년 5월까지 지속적으로 발생하는 중입니다.
2. 애플리케이션 배포의 어려움
애플리케이션 개발자가 구현한 액션 구현은, 그 애플리케이션 구현에 포함되어 실행됩니다. 이는 일반적인 애플리케이션 개발과 유사한 개발 도구들과 기법들을 활용할 수 있다는 장점도 있지만, 동시에 어떤 기능의 업데이트가 반드시 블록체인 노드 소프트웨어 전체의 업데이트를 필요로 한다는 단점을 수반합니다.
제안
"Program" (가칭) 3
SystemAction
으로 불렸던 사전 정의 액션들도, 각 도메인(e.g., 토큰, PoS)에 맞는 "Program"에 속합니다.프록시를 통한 "Program" 버저닝
"Program"을 통해 액션 구현들을 구조화하더라도, 이전 상태를 똑같이 구현해야 하는 이상 네트워크에는 한 "Program"의 다른 구현이 있을 수 있습니다. "Program"마다 식별자를 따로 지정하는 것은 이런 여러 구현을 관리하는 것을 돕지만, 트랜잭션을 발생시키는 사용자가 이전 식별자를 계속 사용할 수 있기 때문에 문제를 완전히 해결하진 못합니다.
이 문제를 완화하기 위해, Ethereum의 프록시 업그레이드 패턴과 같은 방식을 고려할 수 있습니다. 가령 모든 "Program"마다 일종의 프록시("Proxy")를 가정하고, 그 프록시가 특정 시점의 "Program" 식별자를 가지고 있다고 가정하는 식이죠.
ActionEvaluator
)나 시스템 차원에서 이런 전달을 가정할 수도 있습니다.vs Pluggin Lib9c (w/
DynamicActionLoader
)TBD
나인 크로니클의 마이그레이션
TBD
Footnotes
PolymorphicAction<T>
(혹은 0.1.0의BaseAction
)은, 조회 해야 할 액션 구현의 종류를<T>
에 명시된 클래스의 하위 클래스로 제한하려는 의도도 있었습니다. 하지만 이는 주요한 동기는 아니었고, 불필요한 상속을 강제한다는 점에서 역시 좋은 방법은 아니라고 생각합니다. ↩실제로 플라네타리움은 2020년 나인 크로니클의 메인넷을 출시하는 시점부터 2023년 5월까지 이 접근을 유지하고 있으며, 이로 인해 현재 나인 크로니클에는 사용되는 액션보다 하위 호환을 위해 유지하는 액션이 더 많습니다. ↩
"Pluggable Lib9c" 에선 이를 "DLL"이나 "어셈블리"등으로 지칭했으나, 특정 구현을 연상시키는 것이 혼란을 가중시키는 것 같아 잠정적으로
Program
으로 칭합니다. ↩노드 구현을 통한 배급을 유지해도, 개발 난도 관리에는 이바지합니다. 하지만 배포 문제를 해결하기 위해선, 노드 구현에서 빼서 온체인화할 필요가 있습니다. ↩
온체인화가 이뤄진다면, 누구나 임의의 "Program"을 올릴 수 있기 때문에 접근 제어가 필요합니다. ↩
다만 반드시 Ethereum 식의 구현이 아니라, Solana의 Account 같은 접근도 가능은 하다고 생각합니다. ↩
이 경우, 프록시도 트랜잭션에 의해 전이되는 자체 상태를 가지므로 "Program"의 일종으로 정의할 수 있습니다. ↩
Beta Was this translation helpful? Give feedback.
All reactions