SCALE 인코딩
Substrate은 네트워크를 통해 데이터를 보내고 받는 방식을 최적화하기 위해 가벼우면서도 효율적인 인코딩 및 디코딩 프로그램을 사용합니다. 데이터를 직렬화하고 역직렬화하는 프로그램은 SCALE 코덱이라고 하며, SCALE은 simple concatenated aggregate little-endian의 약자입니다.
SCALE 코덱은 런타임과 외부 노드 간의 통신에 있어서 중요한 구성 요소입니다.
이는 Substrate WebAssembly 런타임과 같은 자원 제한적인 실행 환경에서 데이터의 고성능 및 복사 없는 인코딩 및 디코딩을 위해 설계되었습니다.
SCALE 코덱은 자체적으로 설명하지 않습니다. 디코딩 컨텍스트가 인코딩된 데이터에 대한 모든 유형 지식을 가지고 있다고 가정합니다. Parity에서 유지 관리하는 프론트엔드 라이브러리는 RPC와 런타임 간의 상호작용을 인코딩하고 디코딩하기 위해 SCALE 코덱의 Rust 구현인 parity-scale-codec
크레이트를 사용합니다.
SCALE 코덱은 Substrate 및 블록체인 시스템에 유리합니다. 그 이유는 다음과 같습니다:
serde와 같은 일반적인 직렬화 프레임워크에 비해 가볍습니다. 이러한 프레임워크는 바이너리 파일의 크기를 부풀릴 수 있는 상당한 보일러플레이트를 추가합니다.
Rust
libstd
를 사용하지 않으므로 Substrate 런타임과 같이 Wasm으로 컴파일되는no_std
환경과 호환됩니다.#[derive(Encode, Decode)]
를 사용하여 새로운 유형에 대한 코덱 로직을 파생시키기 위해 Rust에서 큰 지원을 받도록 구축되었습니다.
Substrate에서 기존의 Rust 코덱 라이브러리를 재사용하는 대신 인코딩 스키마를 정의하는 것이 중요합니다. 이는 Substrate 블록체인 간의 상호 운용성을 지원하려는 다른 플랫폼 및 언어에서 이 코덱을 다시 구현해야 하기 때문입니다.
다음 표는 Parity SCALE 코덱의 Rust 구현이 다른 유형을 어떻게 인코딩하는지를 보여줍니다.
다양한 유형의 SCALE 코덱 예시
고정폭 정수
기본 정수는 고정폭 리틀 엔디언(LE) 형식을 사용하여 인코딩됩니다.
부호 있는 8비트 정수 69
0x45
부호 없는 16비트 정수 42
0x2a00
부호 없는 32비트 정수 16777215
0xffffff00
콤팩트/일반 정수
"콤팩트" 또는 일반 정수 인코딩은 큰 정수(2**536까지)를 인코딩하는 데 충분하며, 대부분의 값에 대해 고정폭 버전보다 효율적입니다. (단, 1바이트 값의 경우 고정폭 정수가 항상 더 좋습니다.)
부호 없는 정수 0
0x00
부호 없는 정수 1
0x04
부호 없는 정수 42
0xa8
부호 없는 정수 69
0x1501
부호 없는 정수 65535
0xfeff0300
BigInt(100000000000000)
0x0b00407a10f35a
부울
부울 값은 단일 바이트의 가장 낮은 자릿수를 사용하여 인코딩됩니다.
false
0x00
true
0x01
결과
결과는 특정 작업이 성공했는지 또는 실패했는지를 나타내는 일반적으로 사용되는 enum입니다.
Ok(42)
0x002a
Err(false)
0x0100
옵션
특정 유형의 하나 또는 제로 값입니다.
Some
0x01
뒤에 인코딩된 값
None
0x00
뒤에 인코딩된 값
벡터 (리스트, 시리즈, 세트)
동일한 유형의 값의 컬렉션이 인코딩되며, 각 항목의 인코딩이 차례로 연결된 "콤팩트" 인코딩으로 시작됩니다.
부호 없는 16비트 정수의 벡터: [4, 8, 15, 16, 23, 42]
0x18040008000f00100017002a00
문자열
문자열은 유효한 UTF8 시퀀스를 포함하는 바이트(Vec<u8>
)의 벡터입니다.
튜플
각각 다른 유형을 가진 고정 크기의 값의 시리즈입니다. 이는 각 인코딩된 값의 연결로 간단히 구성됩니다.
콤팩트 부호 없는 정수와 부울의 튜플: (3, false)
0x0c00
구조체
구조체의 경우 값은 이름이 지정되지만 인코딩에는 무관합니다(이름은 무시됩니다 - 순서만 중요합니다). 모든 컨테이너는 요소를 연속적으로 저장합니다. 요소의 순서는 고정되어 있지 않으며, 컨테이너에 따라 다르며 디코딩 시에 의존할 수 없습니다. 이는 암시적으로 특정 순서를 강제하는 지정된 구조체로 바이트 배열을 디코딩한 다음 다시 인코딩하면 원래 디코딩된 원본과 다른 바이트 배열이 될 수 있다는 것을 의미합니다.
항상 바이트 요소가 오름차순으로 있는 SortedVecAsc<u8>
구조체: SortedVecAsc::from([3, 5, 2, 8])
[3, 2, 5, 8]
enum (태그-유니온)
고정된 수의 변형으로, 각각 상호 배타적이고 추가적인 값 또는 값의 시리즈를 나타낼 수 있습니다. 값이 있는 변형을 식별하는 첫 번째 바이트로 인코딩됩니다. 추가적인 바이트는 변형이 함께하는 데이터를 인코딩하는 데 사용됩니다. 따라서 256개 이상의 변형은 지원되지 않습니다.
Int(42)
와 Bool(true)
인 enum IntOrBool { Int(u8), Bool(bool),}
0x002a
와 0x0101
SCALE 코덱은 다른 언어에서도 구현되어 있습니다. 예를 들어:
Python:
polkascan/py-scale-codec
Golang:
itering/scale.go
JavaScript:
polkadot-js/api
TypeScript:
parity-scale-codec-ts
,scale-ts
,soramitsu/scale-codec-js-library
AssemblyScript:
LimeChain/as-scale-codec
Haskell:
airalab/hs-web3
Java:
emeraldpay/polkaj
Ruby:
wuminzhe/scale_rb
Last updated