이더리움

23.03.12 SSZ Simple Serialize

슈팅스타제제 2023. 3. 12. 23:08

SSZ 란?

SSZ 는 비콘 체인에서 사용하는 직렬화 방법으로 Merklization 을 하기 위한 데이터 정렬 작업이다. 

실행 레이어에서 RLP 직렬화 작업이 이루어졌다면, 합의 레이어에서는 SSZ 로 직렬화 작업이 이루어진다. 

 

그러면 직렬화란 무엇인가?

데이터 구조를 저장 또는 다른 노드와 데이터 통신할 경우, 파싱할 수 있는 형태로 만들기 위해서 변환하는 작업을 말한다. 

 

예를 들어 참조형 데이터를 통신하는 경우, 메모리 주소에 있는 값을 참조하게 되는데 

이때, 데이터를 받은 노드의 메모리 주소에는 다른 값이 존재할 수 있기 때문에

참조형 데이터의 주소값에 대한 데이터를 값 타입 데이터로 변환하는 작업을 거쳐야 한다. 

 

이더리움에서의 직렬화는 unsigned intboolean 의 기본 타입 변수로 변환하는 것이다.

 

SSZ 의 offset 과 바이트 스트림 형태

위 타입의 변수는 고정 길이로 little-endian 바이트로 변환하는 작업만 하면 되지만 

Struct 타입과 같은 가변 길이의 데이터는 offset 이 적용된 값으로 처리된다. 

 

아래는 Struct -> unsigned int 로 offset 을 적용한 직렬화 예시이다. 

struct Dummy {
    number1: u64, 
    number2: u64, 
    vector: Vec<u8>, 
    number3: u64
}

dummy = Dummy {
    number1: 37, 
    number2: 55, 
    vector: vec![1, 2, 3, 4], 
    number3: 22,
}

serialized = ssz.serialized(dummy)

serialized 에 담기는 값은 다음과 같다. 

[37, 0, 0, 0, 55, 0, 0, 0, 16, 0, 0, 0, 22, 0, 0, 0, 1, 2, 3, 4]

이때, 벡터 위치에는 offset 값이 들어가고 벡터 값은 number 3 의 값 뒤에 위치한다. 

여기서, 16의 의미는 벡터에 대한 값이 어느 위치에서 시작하는지 나타내는 값이다!!

(벡터값 1, 2, 3, 4 가 인덱스 16 에서 시작하므로 해당 값을 넣어준 것이며,

가변 길이 타입의 실제 값은 직렬화 데이터 끝에 있는 힙에 저장된다.)

 

그리고 number 1 변수를 little-endian 바이트로 인코딩한 것은 실제로 32비트의 값을 가지지만, 

예시에서는 u64 변수와 벡터 변수의 위치 관계를 명시하기 위해서[37, 0, 0, 0, ...] 의 4비트 자리로 표현하였다!

 

실제 인코딩된 바이트 스트림 형태는 다음과 같다. 

[
  10100101000000000000000000000000  # little-endian encoding of `number1`
  10110111000000000000000000000000  # little-endian encoding of `number2`.
  10010000000000000000000000000000  # The "offset" that indicates where the value of `vector` starts (little-endian 16).
  10010110000000000000000000000000  # little-endian encoding of `number3`.
  10000001100000101000001110000100   # The actual value of the `bytes` field.
]

 

Merklization 

SSZ 직렬화 과정을 거치면 머클 루트 계산 가능하다!

 

위에서 계산한 SSZ 값에 대한 머클 루트를 계산하는데

이때, 각 leaf 에 대한 일반화 지수에 대한 계산 식은 다음과 같다. (결국에는 노드 인덱스)

2 ** 요소의 depth + 해당 열에서 요소의 index 

MultiProof

Merklization 는 proof (아마 트랜잭션 결과에 대한 proof 말하는 듯?) 루트값에 대한 검증이 가능하다. 

예를 들어 아래와 같은 트리 형태인 경우,

9번 값을 검증하기 위해 먼저, 해시(8, 9) 와 해시(4) 가 같은지 확인해야 하고

해당 값에 5를 해시하고(=> 해시 2) 또, 해당 값에 3을 해시하여 (=> 해시 루트 1) 

1번 인덱스의 해시 루트 값을 생성하는 식이다. 

따라서, 이 과정에서 데이터가 잘못되었을 경우, 루트값이 바뀌므로 다중 증명 검증이 가능하다. 

 

위 직렬화는 노드의 트랜잭션 처리를 위한 개념이지만, 데이터가 어떻게 직렬화된 것인지 알아보는 것은

곧 인코딩이 어떻게 처리되었는지 이해하는 것이기 때문에 필요한 개념이라고 생각한다. 

각 네트워크의 주소 유효성 검사, 니모닉 유효성 검사를 무지성 처리하기 전에

어떤 인코딩 방식으로 데이터가 처리되었는지 확인해봐야겠다~!~!

 

참고문서링크 

https://ethereum.org/en/developers/docs/data-structures-and-encoding/ssz/

 

Home | ethereum.org

Ethereum is a global, decentralized platform for money and new kinds of applications. On Ethereum, you can write code that controls money, and build applications accessible anywhere in the world.

ethereum.org