Ana içeriğe geç
Change page

Basit serileştirme

Son düzenleme: @Berke37(opens in a new tab), 23 Kasım 2023

Basit serileştirme (SSZ), İşaret Zincirinde kullanılan serileştirme yöntemidir. Bu, yürütüm katmanında kullanılan RLP serileştirmesini, eş keşif protokolü hariç fikir birliği katmanının tamamında değiştirir. SSZ, belirleyici ve aynı zamanda Merkle işlemini verimli bir şekilde gerçekleştirebilecek şekilde tasarlanmıştır. SSZ'nin iki bileşeni olduğu düşünülebilir: bir serileştirme şeması ve serileştirilmiş veri yapısıyla etkili bir şekilde çalışacak şekilde tasarlanmış bir Merkle işlemi şeması.

SSZ nasıl çalışır?

Serileştirme

SSZ, kendini tanımlamayan bir serileştirme şemasıdır; aksine önceden bilinmesi gereken bir şemaya dayanır. SSZ serileştirmesinin amacı, nesneleri keyfi karmaşıklıkta bayt dizeleri olarak temsil etmektir. Bu, "temel tipler" için oldukça basit bir süreçtir. Öğe, onaltılık baytlara dönüştürülür. Temel tipler şunlardır:

  • işaretsiz tam sayılar
  • Boole değerleri

Karmaşık "bileşik" tipler için serileştirme daha karmaşıktır çünkü bileşik tip, farklı türleri veya farklı boyutları olan birden çok öğeyi veya her ikisini birden içerebilir. Bu nesnelerin hepsi sabit uzunluklara sahipse (yani öğelerin boyutu her zaman gerçek değerlerine bakılmaksızın sabitse) serileştirme, bileşik tipteki her bir öğenin küçük uçlu bayt dizisine dönüştürülmesinden ibarettir. Bu bayt dizileri bir araya getirilir. Serileştirilmiş nesne, sabit uzunluktaki öğelerin bayt listesi temsilini, seri halden çıkarılan nesnede görünen sıra ile aynı düzende içerir.

Değişken uzunluğa sahip tipler için gerçek veri, serileştirilmiş nesnede o öğenin konumunda bir "kayma" değeri ile değiştirilir. Gerçek veri, serileştirilmiş nesnenin sonunda bir yığına eklenir. Kayma değeri, gerçek verinin yığındaki başlangıç noktasının indeksi olup ilgili baytları gösteren bir işaretçi olarak görev yapar.

Aşağıdaki örnek, hem sabit hem de değişken uzunluktaki öğelere sahip bir kapsayıcı için dengelemenin nasıl çalıştığını gösterir:

1
2 struct Dummy {
3
4 number1: u64,
5 number2: u64,
6 vector: Vec<u8>,
7 number3: u64
8 }
9
10 dummy = Dummy{
11
12 number1: 37,
13 number2: 55,
14 vector: vec![1,2,3,4],
15 number3: 22,
16 }
17
18 serialized = ssz.serialize(dummy)
19
Tümünü göster

serialized aşağıdaki yapıya sahip olacaktır ( burada sadece 4 bite doldurulmuş, gerçekte 32 bite doldurulur, int gösterimi açıklık amacıyla tutulur):

1[37, 0, 0, 0, 55, 0, 0, 0, 16, 0, 0, 0, 22, 0, 0, 0, 1, 2, 3, 4]
2------------ ----------- ----------- ----------- ----------
3 | | | | |
4 number1 number2 offset for number 3 value for
5 vector vector
6

açıklık sağlamak için çizgilere bölünmüştür:

1[
2 37, 0, 0, 0, # little-endian encoding of `number1`.
3 55, 0, 0, 0, # little-endian encoding of `number2`.
4 16, 0, 0, 0, # The "offset" that indicates where the value of `vector` starts (little-endian 16).
5 22, 0, 0, 0, # little-endian encoding of `number3`.
6 1, 2, 3, 4, # The actual values in `vector`.
7]

Bu hala bir basitleştirmedir; yukarıdaki şemaladaki tam sayılar ve sıfırlar aslında aşağıdaki gibi bayt listeleri olarak depolanır:

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

Bu nedenle, değişken uzunluktaki tiplerin gerçek değerleri, serileştirilmiş nesnenin sonunda bir yığında saklanır ve kaymaları, sıralı alan listesinde doğru pozisyonlarında depolanır.

Ayrıca, BitList türü gibi özel muamele gerektiren bazı durumlar da bulunur. Bu durumlar, serileştirmede uzunluk sınırlamasının eklenmesini ve seri halden çıkarma sırasında kaldırılmasını gerektirir. Detaylı bilgiler SSZ spesifikasyonunda(opens in a new tab) mevcuttur.

Seri durumdan çıkarma

Bu nesneyi seri durumdan çıkarmak için şema gereklidir. Şema, serileştirilmiş verinin kesin düzenini tanımlar, böylece her bir özel öğe, bayt grubundan anlamlı bir nesneye, öğelerin doğru türüne, değerine, boyutuna ve konumuna sahip şekilde seri halden çıkarılabilir. Şema, hangi değerlerin gerçek değerler olduğunu ve hangi değerlerin kayma olduğunu seri durumdan çıkarıcıya bildiren unsurdur. Bir nesne serileştirildiğinde tüm alan adları kaybolur ancak bunlar, seri halden çıkarma sırasında şemaya göre tekrar oluşturulur.

Bu konuyla ilgili interaktif bir açıklamayı ssz.dev(opens in a new tab) adresinde bulabilirsiniz.

Merkle işlemini gerçekleştirme

Bu SSZ serileştirilmiş nesnesi, daha sonra aynı verinin bir Merkle ağacı gösterimine dönüştürülebilir. İlk olarak, serileştirilmiş nesnedeki 32 baytlık parçaların sayısı belirlenir. Bunlar, ağacın "yaprakları"dır. Toplam yaprak sayısı, yaprakları karma hale getirerek sonunda tek bir karma ağaç kökü üretmek için 2'nin bir katı olmalıdır. Eğer bu doğal olarak böyle değilse, 32 baytlık sıfırlar içeren ekstra yapraklar eklenir. Diyagram olarak ifade etmek gerekirse:

1 hash tree root
2 / \
3 / \
4 / \
5 / \
6 hash of leaves hash of leaves
7 1 and 2 3 and 4
8 / \ / \
9 / \ / \
10 / \ / \
11 leaf1 leaf2 leaf3 leaf4
Tümünü göster

Ağacın yapraklarının, yukarıdaki örnekte olduğu gibi doğal olarak eşit şekilde dağılmadığı durumlar da vardır. Örneğin yaprak 4, Merkle ağacına ilave "derinlik" eklenmesini gerektiren ve dolayısıyla eşit olmayan bir ağaç oluşmasına yol açan birden fazla öğeye sahip bir kapsayıcı olabilir.

Bu ağaç öğelerine yaprak X, düğüm X gibi isimler yerine genelleştirilmiş indeksler verebiliriz. Bu, kök = 1 ile başlayan ve her seviyede soldan sağa sayılan genelleştirilmiş indekslerle yapılır. Bu, yukarıda açıklanan genelleştirilmiş indekstir. Serileştirilmiş listedeki her öğenin, 2**depth + idx'e eşit bir genelleştirilmiş dizini vardır; burada idx, serileştirilmiş nesnedeki sıfır dizinli konumudur ve derinlik, Merkle ağacındaki düzey sayısıdır ve öğe (yaprak) sayısının iki tabanındaki logaritması olarak belirlenebilir.

Genelleştirilmiş indeksler

Bir genelleştirilmiş indeks, her düğümün bir genelleştirilmiş indeksi temsil ettiği ikili bir Merkle ağacındaki bir düğümü temsil eden tam sayıdır, burada her düğümün genelleştirilmiş indeksi 2 ** depth + index in row şeklindedir.

1 1 --depth = 0 2**0 + 0 = 1
2 2 3 --depth = 1 2**1 + 0 = 2, 2**1+1 = 3
3 4 5 6 7 --depth = 2 2**2 + 0 = 4, 2**2 + 1 = 5...
4

Bu gösterim, Merkle ağacındaki her bir veri parçası için bir düğüm oluşturur.

Çoklu kanıtlar

Belirli bir öğeyi temsil eden genelleştirilmiş endekslerin listesini sağlamak, onu karma ağaç kökü ile karşılaştırarak doğrulamamıza olanak tanır. Bu kök, gerçekliğin kabul edilmiş versiyonudur. Sağladığımız herhangi bir veri, Merkle ağacında (genelleştirilmiş indeksi tarafından belirlenir) doğru yere yerleştirilerek ve kökün sabit kaldığı gözlemlenerek bu gerçekliğe karşı doğrulanabilir. Belirli bir genelleştirilmiş indeks kümesinin içeriğini doğrulamak için gereken en küçük düğüm kümesini hesaplamak için burada(opens in a new tab) spesifikasyon içinde özel fonksiyonlar bulunmaktadır.

Örneğin, aşağıdaki ağaçta indeks 9'daki verileri doğrulamak için 8, 9, 5, 3, 1 indekslerindeki verilerin özetine ihtiyacımız vardır. (8,9) karmasının karma (4) ile eşit olması gerekir, bu, 5 ile karma hale getirilerek 2 elde edilir ve bu da 3 ile karma hale getirilerek ağaç kökü 1 elde edilir. 9 için yanlış veri sağlanırsa, kök de değişir; bunu tespit eder ve dalı doğrulayamayız.

1* = data required to generate proof
2
3 1*
4 2 3*
5 4 5* 6 7
68* 9* 10 11 12 13 14 15
7

Daha fazla okuma

Bu makale yararlı oldu mu?