본문으로 건너뛰기

에포크, equivocation, 재구성

Sui에서 epoch은 네트워크가 정의하는 시간 구간이다. 이 시간 동안 Sui validator 집합과 그들의 stakes는 변하지 않는다. MainnetTestnet 모두에서 epoch은 약 24시간이다. Devnet의 epochs는 1시간이다. 이 기간은 validators가 임시적인 validator 변경을 걱정하지 않고 transactions를 효율적으로 처리할 수 있게 한다.

Epoch 값은 모든 트랜잭션의 metadata에 포함된다. transaction은 설정된 epoch 이전에 실행되는 경우에만 유효하다.

Equivocation

Sui에서 object versioning은 각 objectSequenceNumber가 object의 version을 가리키는 고유한 (ObjectId, SequenceNumber) 쌍으로 참조되도록 보장한다. 특정 version에서 object를 수정할 수 있는 transaction은 하나뿐이다. transaction이 object를 수정한 후에는 version이 증가한다. 이후 transactions에서는 최신 version만 사용할 수 있다. Object versioning은 transactions와 epochs 전반에서 objects의 상태를 추적한다.

Equivocation 은 owned object 쌍(ObjectId, SequenceNumber)이 여러 비-final transactions에서 동시에 사용될 때 발생한다. 여러 transactions에서 사용되는 어떤 object든 올바르게 관리되지 않으면 equivocation의 원천이 될 수 있다.

다음과 같은 경우 equivocation이 발생할 수 있다:

  • user 또는 smart contract가 첫 번째 transaction이 final되기 전에 동일한 (ObjectId, SequenceNumber)를 사용하는 두 개의 transactions를 제출하는 경우.

  • smart contract 코드의 의도치 않은 logic traps, 예를 들어 sponsored transactions을 처리할 때.

Locked objects

두 transactions가 모두 final되지 않았더라도 equivocated transactions를 제출하면 개발자와 사용자 모두에게 다른 문제가 계속 발생한다. 예를 들어 equivocation이 감지되면 관련 objects는 현재 epoch이 끝날 때까지 lock된다. 어느 transaction도 진행할 수 없고 해당 objects는 다른 어떤 transaction에서도 사용할 수 없다. 악의적인 행위자는 중요 objects를 lock하고 의도적으로 앱을 방해하기 위해 equivocated transactions를 의도적으로 제출할 수 있다.

smart contract에서 객체가 의도치 않게 잠기는 문제가 발생하면 자주 발생하는 오류 해결하기 문서를 참고한다. sui-tool 유틸리티를 설치하고 locked-object 명령을 사용해 특정 RPC 네트워크(--fullnode-rpc-url 값)에서 전달한 자산의 locked 상태를 확인할 수 있다. address를 제공하면 locked-object는 해당 address가 소유한 모든 gas objects가 lock되었는지 확인한다. 특정 object가 lock되었는지 확인하려면 object ID를 전달하라. 명령이 대상으로 삼는 object를 해제하려면 --rescue 플래그를 포함하라. object가 아직 validators의 과반수에 의해 lock되지 않았다면 rescue가 가능하다.

Double spending

user가 여러 transactions에서 동일한 coin object로 gas를 지불하려 할 때도 equivocation이 발생할 수 있다.

Sui의 versioning 아키텍처는 일련의 transactions 전반에서 동일한 gas coin을 안전하게 재사용할 수 있게 한다. 다른 처리와 함께 첫 번째 transaction은 coin의 version number를 증가시키고 이를 sender에게 반환한다. 다음 transaction은 그 coin의 업데이트된 version을 사용해 gas를 지불할 수 있다. 각 transaction이 같은 coin의 서로 다른 version을 참조하므로 이것은 equivocation을 방지한다.

double spending을 방지하기 위해 validators는 transactions를 검증하면서 objects를 lock한다.

Punishment for equivocation

Sui 네트워크에는 equivocation에 관여하는 validators를 처벌하기 위한 보호 장치가 있다. Sui의 object versioning은 equivocation을 방지하도록 설계되었지만 처벌은 여전히 필요하다. 예방만으로는 사용자가 equivocation을 시도하는 transactions를 제출하는 것을 막지 못하며, 이는 objects를 lock하고 네트워크 사용성을 저하시킨다. Equivocation에 대한 처벌은 우발적이거나 의도적인 남용 모두를 억제하여 개발자가 자신의 코드가 우발적으로 equivocation을 일으키지 않도록 동기를 부여한다.

Common pitfalls to avoid

  1. 대부분의 smart contracts에서 equivocation은 의도된 동작이 아니다. 의도치 않은 equivocation의 흔한 원천은 같은 address가 수행하는 여러 transactions에서 나온다. gas fees를 적절히 처리하지 않으면 하나 이상의 transaction에 같은 coin과 version을 사용하려다 smart contract를 lock할 수 있다.

    Recommendation: 단일 thread를 사용한다면 같은 owned object를 사용하는 transactions를 직렬화하라. PTB 구성하기는 transactions가 같은 owned object에 대해 여러 작업을 수행할 수 있게 한다. PTB는 본질적으로 단일한 직렬 transaction이므로 SequenceNumber 오류를 방지할 수 있다.

    Recommendation: 항상 PTB가 제공하는 고유한 batching을 활용하라. 예를 들어 많은 users에게 object를 mint하고 전송하려는 에어드롭 시나리오를 생각해 보자. PTB는 하나의 PTB에 최대 1,024개의 작업을 허용하므로 단일 transaction에서 512명의 users에게 에어드롭 object를 mint하고 전송할 수 있다. 이 접근 방식은 매번 한 사용자에게 mint 및 transfer를 수행하는 512개의 개별 transactions를 반복하는 것보다 훨씬 비용 효율적이다. transactions를 배치하면 병렬 실행의 필요성을 제거할 수 있지만 PTB의 원자적 특성을 고려해야 한다. 하나의 instruction이 실패하면 PTB 전체가 실패하기 때문이다. 따라서 일부 사용 사례에서는 병렬 transactions가 더 선호될 수 있다.

  2. 여러 threads의 병렬 transactions는 적절히 관리하지 않으면 의도치 않은 equivocation 오류를 일으킬 수 있다. owned object equivocation을 피하는 한 가지 방법은 각 transaction thread에 대해 별도의 owned object를 만드는 것이다. 이는 각 thread가 object input의 올바른 version을 사용하도록 보장한다.

    Recommendation: 여러 owned objects를 만드는 것이 실용적이지 않거나 원하지 않는 경우에는 threads 전반에서 사용되는 object 주위에 wrapper를 만들 수 있다. wrapper는 allowlist를 통해 자신의 object에 대한 접근을 승인하는 shared object이다. transaction이 wrapped object에 접근해야 할 때마다 같은 PTB에서 wrapper로부터 권한을 얻는다. authorization을 이전해야 할 때는 wrapper의 allowlist가 그에 맞게 업데이트된다. 이 접근 방식은 object wrapper가 자신의 object를 input으로 의존하는 직렬화된 transactions를 생성하기 때문에 지연 시간 병목을 만들 수 있다. Sui TypeScript SDK는 병렬 transactions를 효율적으로 처리하기 위한 executor class인 ParallelTransactionExecutor를 제공한다.

Reconfiguration

Reconfiguration은 각 epoch의 끝에서 발생하는 중요한 과정이다. 이는 다가오는 epoch에 맞추어 네트워크를 조정하기 위한 몇 가지 핵심 단계를 포함한다:

  1. Transactions 및 checkpoints의 finalization: 네트워크는 현재 epoch의 최종 transactions 및 checkpoints 집합에 대해 합의한다. 이는 모든 validators가 epoch 종료 시 동일한 상태를 가지도록 보장한다.

    • Synchronous moment: 이는 네트워크에서 유일한 완전 동기 이벤트이며 일관성을 유지하는 데 중요하다.
  2. Distribution of gas rewards: Computation gas fees는 validator staking reward pool에 분배되며 stakers는 이 풀에서 인출할 수 있다. Storage fees는 Sui 토크노믹스에서 중요한 역할을 하는 storage fund에 할당된다.

  3. Validator set change: epoch 동안의 보류된 staking 및 unstaking 요청은 final되어 validators의 stake 분배에 반영된다. 새로운 validators 추가와 기존 validators 제거를 포함한 보류 중인 validator change requests도 처리된다. 이것이 validator 집합과 stake 분배를 변경할 수 있는 유일한 기회이다.

  4. Protocol upgrade: 2f+1 validators가 동의하면 네트워크는 새 기능, 버그 수정, Move framework libraries 업데이트를 포함하는 새로운 protocol version으로 업그레이드할 수 있다.