ថ្ងៃនេះអតិថិជន Consensus មិនអាចផ្តល់នូវទិន្នន័យផ្ទាល់ខ្លួនពី BeaconState ជាមួយនឹងការសាកល្បងដែលត្រូវការដើម្បីត្រួតពិនិត្យវា។ ប្រព័ន្ធអតិថិជនពន្លឺរបស់ Ethereum បានកំណត់របៀបសាកល្បងមួយចំនួនប៉ុន្តែមិនមានវិធីសាស្រ្តគ្រប់គ្រងឬស្តង់ដារសម្រាប់អតិថិជនដើម្បីបង្កើតឬផ្គត់ផ្គង់សាកល្បងទាំងអស់នេះ។ ទាញយកការសាកល្បងទាំងអស់ មិនមែនជាការពិតប្រាកដទេ—អាជីវកម្មសម្រាប់ នៅជុំវិញ , ដែលមានទំហំទូលំទូលាយណាស់ដើម្បីផ្ញើនៅលើបណ្តាញយ៉ាងឆាប់រហ័សនិងធ្វើឱ្យទំហំមិនចាំបាច់ទៅលើការដំឡើងនិងអ្នកប្រើទាំងពីរ។ ឧបករណ៍ពិន្ទុនេះបង្ហាញថាតើបញ្ចប់ដំឡើងដែលប្រើដើម្បីទទួលបានស្ថានភាពពេញវ័យត្រូវបានគោលបំណងសម្រាប់ការដំឡើងគ្រាន់តែប៉ុន្តែមិនត្រូវបានប្រើនៅក្នុងពិភពលោកពិតប្រាកដ។ ហ្វេសប៊ុក លក្ខខណ្ឌ 12,145,344 271 MB លទ្ធផលល្អបំផុតគឺការប្រើប្រាស់ នេះជាប្រយោជន៍ជាពិសេសដោយសារតែទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំ Merkle proofs or multiproofs ដោយសារតែនេះយើងត្រូវការវិធីគ្រប់គ្រងនិងស្តង់ដារសម្រាប់អតិថិជនដើម្បីសួរ នេះបានកាត់បន្ថយទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំទំហំ ការអនុវត្តពិសេសនៃ ) ។ ទិន្នន័យដែលអ្នកត្រូវតែ ក្រុមហ៊ុន Nimbus historical_summaries ការធ្វើការនេះគឺជាការសំខាន់សម្រាប់អនាគតនៃ Ethereum ។ SSZ ត្រូវបានក្លាយជាមជ្ឈមណ្ឌលនៃប្រព័ន្ធប្រតិបត្តិការ: វាគឺជាការផ្លាស់ប្តូរ RLP ជាមួយ SSZ និងការ (គេស្គាល់ផងដែរថា លោក Will ដូច្នេះការបង្កើតវិធីសាស្រ្តដែលមានប្រសិទ្ធិភាពនិងមានប្រសិទ្ធិភាពសម្រាប់ការចូលទិន្នន័យដែលមានមូលដ្ឋានលើការសាកល្បងគឺជាដំណោះស្រាយសំខាន់ក្នុងការធ្វើឱ្យប្រសើរឡើងប្រព័ន្ធប្រតិបត្តិការចុងក្រោយ។ ម្សៅ (EIP-7919) beam chain lean chain អំណោយ Proposed Solution: Introducing the SSZ Query Language (SSZ-QL) គោលបំណងដែលបានផ្តល់ជូន: ការបង្កើតប្រភេទ SSZ Query Language (SSZ-QL) គំនិតនៃ SSZ-QL បានចាប់ផ្តើមដោយ សួរសំខាន់របស់គាត់គឺជាការពិតប្រាកដប៉ុន្តែមានប្រសិទ្ធិភាព: លោក Kissling “What if we had a standard way to request SSZ field — together with a Merkle proof — directly from any consensus client?” any ទាំងអស់ ឥឡូវនេះអតិថិជន Consensus មិនផ្តល់ជូននូវវិធីសាស្រ្តជាទូទៅឬស្តង់ដារដើម្បីទិញទិន្នន័យ SSZ ជាពិសេសជាមួយនឹងការសាកល្បង។ មានដំណោះស្រាយ ad-hoc មួយចំនួន (ដូចជាការទិន្នន័យមូលដ្ឋានរបស់ Nimbus ដែលប្រើដោយការត្រួតពិនិត្យ ), ប៉ុន្តែមិនមានភាសាសួរ SSZ ដែលមានប្រសិទ្ធិភាពនិងមានប្រសិទ្ធិភាពអាចរកបាន - និងមិនមានអ្វីដែលបានរចនាឡើងនៅពេលដែលគំនិតនេះត្រូវបានសរសេរ។ Web3 សៀវភៅ គម្រោងរបស់ Etan បានសរសេរអ្វីដែលជា SSZ Query Language អាចអនុញ្ញាតឱ្យ: ការសរសេរសរសេរសរសេរសរសេរសរសេរសរសេរសរសេរសរសេរសរសេរសរសេរសរសេរ ការជ្រើសរើសថាមានការអភិវឌ្ឍពេញលេញឬបង្ហាញតែជា hash_tree_root ។ តម្រង (ដូចជាការស្វែងរកប្រតិបត្តិការដែលមានមូលដ្ឋានមួយចំនួន) ការប្រើប្រាស់ការផ្លាស់ប្តូរបន្ទាប់ (ដូចជាការស្វែងរកការទទួលស្គាល់នៅលើឧបករណ៍ដូចគ្នាជាមួយនឹងប្រតិបត្តិការដែលសមរម្យ) ការបញ្ជាក់អំពីកន្លែងដែលគោលបំណងគោលបំណងគោលបំណងគោលបំណង អនុញ្ញាតឱ្យអតិថិជនជឿទុកចិត្តក្នុងការអនុញ្ញាតឱ្យអតិថិជនជឿទុកចិត្តក្នុងការអនុញ្ញាតឱ្យអតិថិជនជឿទុកចិត្តក្នុងការអនុញ្ញាតឱ្យអតិថិជនជឿទុកចិត្តក្នុងការអនុញ្ញាតឱ្យអតិថិជនជឿទុកចិត្ត ប្រភេទ API នេះអាចត្រូវបានប្រើដោយអតិថិជន Consensus និង Execution ទាំងពីរ។ ជាមួយនឹងប្រភេទ SSZ ដែលសមស្របទៅមុខ (ដូចជាប្រភេទ SSZ ពី ), រចនាសម្ព័ន្ធសំណួរនិងការឆ្លើយតបអាចត្រូវបានបង្កើតដោយស្វ័យប្រវត្តិ។ អាសយដ្ឋាន: EIP-7495 ដោយផ្អែកលើគំនិតនេះ , ដែលកំពុងធ្វើការនេះជាផ្នែកមួយនៃគម្រោង EPF របស់ពួកគេនៅក្នុង prysm, គឺដើម្បីបន្ថែមបញ្ចប់ API Beacon ថ្មីដែលគាំទ្រសម្រាប់ SSZ Query Language (SSZ-QL) ។ ការបញ្ចប់នេះអនុញ្ញាតឱ្យអ្នកប្រើដើម្បីទទួលបានទិន្នន័យ SSZ ទាំងអស់ដែលពួកគេត្រូវការ - មិនមែនច្រើនទៀតទេ - ជាមួយនឹងការសាកល្បង Merkle ដែលត្រឹមត្រូវវា។ កំណែដំបូងនឹងផ្តល់ជូននូវកំណត់លក្ខណៈពិសេសទាបប៉ុណ្ណោះប៉ុន្តែមានប្រសិទ្ធិភាពដែលបានផ្តល់ជូននូវទំហំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូល the proposed solution by and យោបល់ លោក Fernando យោបល់ លោក Fernando លើសពីកំណែទំហំទូលាយនេះក៏មានគោលបំណងដើម្បីបង្កើតឯកសារ SSZ-QL ជាពេញលេញ។ កំណែទំហំទូលាយនេះនឹងគាំទ្រនូវលក្ខណៈពិសេសខ្ពស់ដូចជាការត្រួតពិនិត្យទម្រង់ទម្រង់ទិន្នន័យនិងការជ្រើសរើសតម្រូវការ anchor points ដោយផ្ទាល់ខ្លួនទាំងអស់ជាមួយនឹងការបង្ហាញ Merkle ។ ពួកគេត្រូវបានគេស្គាល់ថាឯកសារដែលមានលក្ខណៈពិសេសបន្ថែមទៀតនេះត្រូវបានផ្តល់នូវការរួមបញ្ចូលនៅក្នុងលក្ខណៈពិសេសអនុម័តទូទៅហើយគម្រោងដំបូងគឺអាចរកបានសម្រាប់ការពិនិត្យឡើងវិញ។ ការយល់ដឹងអំពីឧបករណ៍បញ្ជាទូទៅ (GI) មុនពេលទូទៅក្នុង SSZ-QL In SSZ, every object — including the entire វាត្រូវបានបង្ហាញថា A . A វាគឺជាលេខមួយដែលអាចរកឃើញតែមួយគត់ នៅខាងក្នុងរោងចក្រនេះ BeaconState binary Merkle tree generalized index (GI) any node លក្ខខណ្ឌនេះគឺជាការងាយស្រួល: កុំព្យូទ័រ Root Node មាន index:GI = 1 ។ សម្រាប់កូដណាមួយដែលមានអេក្រង់ i:កុមារខាងលិច = 2*i,កុមារខាងលិច = 2*i + 1 ដូច្នេះដែកទាំងអស់នេះត្រូវបានកំណត់ដូច្នេះ: GI:1 / \ GI:2 GI:3 / \ / \ GI:4 GI:5 GI:6 GI:7 ... គោលបំណងនេះធ្វើឱ្យប្រសិនបើអ្នកដឹងថា អ្នកអាចដឹងថាតើវាមានទីតាំងស្ថិតនៅក្នុងខ្នាតនិង hashes ដែលអ្នកត្រូវរួមបញ្ចូលដើម្បីត្រួតពិនិត្យវា។ generalized index of a leaf Example with Beacon State: 0 GenesisTime string 1 GenesisValidatorsRoot string 2 Slot string 3 Fork *Fork 4 LatestBlockHeader *BeaconBlockHeader 5 BlockRoots []string 6 StateRoots []string 7 HistoricalRoots []string 8 Eth1Data *Eth1Data 9 Eth1DataVotes []*Eth1Data 10 Eth1DepositIndex string 11 Validators []*Validator ← (p = 11) 12 Balances []string 13 RandaoMixes []string 14 Slashings []string 15 PreviousEpochAttestations []*pendingAttestation 16 CurrentEpochAttestations []*pedningAttestation 17 JustificationBits string 18 PreviousJustifiedCheckpoint *Checkpoint 19 CurrentJustifiedCheckpoint *Checkpoint 20 FinalizedCheckpoint *Checkpoint មាន 21 កន្លែងដែលមានកម្រិតខ្ពស់បំផុត (ឧទ្ទិស 0..20) ដើម្បីដាក់ទាំងនេះទៅក្នុងខ្នាត Merkle, SSZ pads ពួកគេទៅកាន់ថាមពលបន្ទាប់នៃពីរ (32). កម្រិតខ្ពស់ = 5 ។ សៀវភៅដែលមានទំហំខ្ពស់បំផុតមានទំហំ GI: 32 ... 63 យើងបានកំណត់ GI សម្រាប់មជ្ឈមណ្ឌលកម្រិតខ្ពស់ដោយប្រើ: គំនិត : GI_top = 2^depth + field_index សម្រាប់ , ឧបករណ៍ index = .validators 11 ដូច្នេះ GI_validators = 2^5 + 11 = 32 + 11 = 43. ម្សៅនេះ ( ) គឺជាគោលបំណងនៃការទាំងអស់ ក្នុងអំឡុងពេលពិភពលោក ខ្សែភាពយន្ត 43 validator’s subtree BeaconState Multi-Level Proof: Example With validators[42].withdrawal_credentials ឥឡូវនេះគិតថាយើងចង់សាកល្បងសម្រាប់: BeaconState.validators[42].withdrawal_credentials នេះតម្រូវ : two levels of proof Prove that the entire validator’s subtree is included in the BeaconState root We already know: Top-level GI for validators = 43 Using GI 43, the consensus client collects the sibling hashes on the path from leaf 43 up to root (e.g., ). GI 43 → 21 → 10 → 5 → 2 → 1 This gives the proof: validators_root ---> BeaconState_root Prove that is inside the validator’s subtree validator[42].withdrawal_credentials Now treat the . validators list as its own Merkle tree Inside this subtree: Validator is the 42-nd element → it maps to some leaf index (e.g. chunk ) inside this subtree. 42 k Withdrawal credentials lives inside one of the 32-byte SSZ chunks of validator #42 (for example chunk — number doesn’t matter, just concept). k = 128 We now generate: leaf (withdrawal_credentials chunk) ---> validators_root by collecting sibling hashes inside the local validator-subtree. Final Combined Proof You end up with: 1. Local Level Proof Proves withdrawal_credentials --> validator_root 2. Top-level branch proof Proves validator_root --> BeaconState_root A verifier can now reconstruct the BeaconState root from only: the requested leaf the two lists of sibling nodes the known BeaconState root No full state download needed. ┌───────────────────────────────┐ │ BeaconState Root │ └───────────────────────────────┘ ▲ │ (Top-level Merkle Proof) │ Sibling hashes for GI = 43 │ ┌─────────────────────────────────────────┐ │ validators_root (GI = 43) │ └─────────────────────────────────────────┘ ▲ │ (Local Subtree Proof) │ Proof inside validators list │ for index = 42 │ ┌─────────────────────────────────────────────────────────┐ │ Validator[42] Subtree (list element #42) │ └─────────────────────────────────────────────────────────┘ ▲ │ (Field-level Merkle Proof) │ Sibling hashes inside the │ validator struct │ ┌──────────────────────────────────────────┐ │ validator[42].withdrawal_credentials │ ← requested field └──────────────────────────────────────────┘ Understanding SSZ Serialization Before Computing Generalized Indices ការយល់ដឹងអំពី SSZ serialization មុនពេលទិន្នន័យទិន្នន័យ generalized ការគណនានៃការត្រឹមត្រូវ , you must first understand how SSZ និង ប្រភេទទិន្នន័យផ្សេងគ្នា Generalized indices don’t exist in isolation—they are derived from the , និងទំហំនៃខ្នាតនេះត្រូវបានផ្អែកយ៉ាងពេញលេញពីរបៀបដែល SSZ បានអនុម័តឧបករណ៍ Go Struct ដែលមានមូលដ្ឋាន។ generalized index ស៊េរី មូលដ្ឋាន គំរូនៃខ្នាត Merkle ក្នុង SSZ ទាំងអស់គ្នានេះអាចជាផ្នែកមួយនៃផ្នែកមួយទាំងពីរ: Base Types (fixed-size values) , , , etc. These are straightforward — they always serialize into a fixed number of bytes. uint64 Bytes32 Bytes20 uint256 Composite Types (like BeaconState), (fixed length), (variable length), , And each of them is serialized in a slightly different way. Container Vector[T, N] List[T, N] Bitvector[N] Bitlist[N] To compute a for any field inside a state, the SSZ tree must first know . This is why the generated files include tags such as: generalized index (g-index) how that field is serialized *.pb.go ssz-size:"8192,32" → Vector ssz-max:"16" → List ssz-size:"?,32" → List of Vector ដើម្បីទិន្នន័យឧបករណ៍បញ្ជាទិន្នន័យទិន្នន័យទិន្នន័យទិន្នន័យទិន្នន័យទិន្នន័យទិន្នន័យទិន្នន័យ អំពី សម្ភារៈ នេះ : SSZ structure សត្វដែលមាន ប្រសិនបើជារៀងរាល់ជារៀងរាល់គឺជា List ឬ Vector ។ ទោះជាយ៉ាងណាក៏ដោយខ្ញុំព្យូទ័រទាំងអស់ដែលមានតម្រូវការ និងរបៀបដែលអ្នកគាំទ្រគួរតែដំណើរការ នេះគឺជាអ្វីដែលការ វាត្រូវបានធ្វើនៅក្នុង Prysm ដែលមានទីតាំងស្ថិតនៅ AnalyzeObject encoding/ssz/query/analyzer.go // AnalyzeObject analyzes given object and returns its SSZ information. func AnalyzeObject(obj SSZObject) (*SszInfo, error) { value := reflect.ValueOf(obj) info, err := analyzeType(value, nil) if err != nil { return nil, fmt.Errorf("could not analyze type %s: %w", value.Type().Name(), err) } // Populate variable-length information using the actual value. err = PopulateVariableLengthInfo(info, value) if err != nil { return nil, fmt.Errorf("could not populate variable length info for type %s: %w", value.Type().Name(), err) } return info, nil } What analyzeType Does នេះជាកម្មវិធីដែល ទិន្នន័យពី វាគឺជា a វាមាន វាត្រូវបានផ្អែកលើតម្លៃពេលដំណើរការពិតប្រាកដប៉ុណ្ណោះនៅលើប្រភេទ Go និងស្លាក struct ។ analyzeType examines a Go value using reflection what kind of SSZ type ដំណោះស្រាយដំណោះស្រាយដំណោះស្រាយ not នៅពេលដែលអ្នកផ្តល់ឱ្យវាអាសយដ្ឋានឬ struct នេះវា: សូមពិនិត្យមើលប្រភេទ Go (uint, struct, slice, pointer ល។) ស្លាកស្លាកស្លាកស្លាកស្លាកស្លាកស្លាកស្លាកស្លាកស្លាកស្លាកស្លាកស្លាកស្លាកស្លាកស្លាកស្លាក Decides : whether this field is a basic SSZ type ( , , ) uint64 uint32 bool a Vector ( ) ssz-size:"N" a List ( ) ssz-max:"N" a Bitvector / Bitlist a Container (struct) Builds an that describes: SszInfo record the SSZ type (List, Vector, Container...) whether it is fixed-sized or variable-sized offsets of fields (for Containers) nested SSZ information for child fields Think of ដូច្នេះប្រហែលជាកម្មវិធីដែល ការផលិត A for this type. analyzeType scans the type definition static SSZ layout blueprint What PopulateVariableLengthInfo Does នៅពេលដែល ការសិក្សា The មួយចំនួននៃការ SSZ មិនអាចត្រូវបានបង្ហាញយ៉ាងពេញលេញដោយគ្មានការ . analyzeType ប្រភេទ លក្ខណៈពិសេស លក្ខខណ្ឌ: សៀវភៅ ([]T) តម្រូវឱ្យដឹងអំឡុងពេលវេលារបស់ពួកគេ កញ្ចប់កញ្ចប់កញ្ចប់កញ្ចប់កញ្ចប់កញ្ចប់កញ្ចប់កញ្ចប់កញ្ចប់កញ្ចប់កញ្ចប់ Nested lists need each element’s actual size សូមបញ្ជាក់ពីរបៀបដែលអ្នកចង់បញ្ចូលការបញ្ចូលទិន្នន័យ Runtime នេះ។ PopulateVariableLengthInfo នេះ : សូមមើលគំរូ SszInfo ដែលបានបង្កើតឡើងដោយ analyzeType សូមមើលតម្លៃពិតប្រាកដនៃការប្រែប្រែប្រួល។ Computes values that can only be known at runtime: length of Lists sizes of nested variable elements offsets of variable-sized fields inside Containers bitlist length from bytes វាត្រូវបានដំណើរការទាំងអស់ — ឧទាហរណ៍, កុំព្យូទ័រដែលមានសៀវភៅដែលមានសៀវភៅដែលមានសៀវភៅទាំងអស់នឹងត្រូវបានបំពេញ។ recursively សូមចង់ ដូច្នេះប្រហែលជាកម្មវិធីដែល និងបញ្ចប់ការវាយតម្លៃពិតប្រាកដដោយផ្អែកលើតម្លៃពិតប្រាកដដែលអ្នកផ្ញើ។ PopulateVariableLengthInfo takes the blueprint from analyzeType Example: សូមធ្វើតេស្តបច្ចុប្បន្នភាពបច្ចុប្បន្នភាពនេះជាមួយបច្ចុប្បន្នភាព BeaconState type BeaconState struct { state protoimpl.MessageState `protogen:"open.v1"` GenesisTime uint64 `protobuf:"varint,1001,opt,name=genesis_time,json=genesisTime,proto3" json:"genesis_time,omitempty"` GenesisValidatorsRoot []byte `protobuf:"bytes,1002,opt,name=genesis_validators_root,json=genesisValidatorsRoot,proto3" json:"genesis_validators_root,omitempty" ssz-size:"32"` Slot github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Slot `protobuf:"varint,1003,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Slot"` Fork *Fork `protobuf:"bytes,1004,opt,name=fork,proto3" json:"fork,omitempty"` LatestBlockHeader *BeaconBlockHeader `protobuf:"bytes,2001,opt,name=latest_block_header,json=latestBlockHeader,proto3" json:"latest_block_header,omitempty"` BlockRoots [][]byte `protobuf:"bytes,2002,rep,name=block_roots,json=blockRoots,proto3" json:"block_roots,omitempty" ssz-size:"8192,32"` StateRoots [][]byte `protobuf:"bytes,2003,rep,name=state_roots,json=stateRoots,proto3" json:"state_roots,omitempty" ssz-size:"8192,32"` HistoricalRoots [][]byte `protobuf:"bytes,2004,rep,name=historical_roots,json=historicalRoots,proto3" json:"historical_roots,omitempty" ssz-max:"16777216" ssz-size:"?,32"` Eth1Data *Eth1Data `protobuf:"bytes,3001,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` Eth1DataVotes []*Eth1Data `protobuf:"bytes,3002,rep,name=eth1_data_votes,json=eth1DataVotes,proto3" json:"eth1_data_votes,omitempty" ssz-max:"2048"` Eth1DepositIndex uint64 `protobuf:"varint,3003,opt,name=eth1_deposit_index,json=eth1DepositIndex,proto3" json:"eth1_deposit_index,omitempty"` Validators []*Validator `protobuf:"bytes,4001,rep,name=validators,proto3" json:"validators,omitempty" ssz-max:"1099511627776"` Balances []uint64 `protobuf:"varint,4002,rep,packed,name=balances,proto3" json:"balances,omitempty" ssz-max:"1099511627776"` RandaoMixes [][]byte `protobuf:"bytes,5001,rep,name=randao_mixes,json=randaoMixes,proto3" json:"randao_mixes,omitempty" ssz-size:"65536,32"` Slashings []uint64 `protobuf:"varint,6001,rep,packed,name=slashings,proto3" json:"slashings,omitempty" ssz-size:"8192"` PreviousEpochAttestations []*PendingAttestation `protobuf:"bytes,7001,rep,name=previous_epoch_attestations,json=previousEpochAttestations,proto3" json:"previous_epoch_attestations,omitempty" ssz-max:"4096"` CurrentEpochAttestations []*PendingAttestation `protobuf:"bytes,7002,rep,name=current_epoch_attestations,json=currentEpochAttestations,proto3" json:"current_epoch_attestations,omitempty" ssz-max:"4096"` JustificationBits github_com_OffchainLabs_go_bitfield.Bitvector4 `protobuf:"bytes,8001,opt,name=justification_bits,json=justificationBits,proto3" json:"justification_bits,omitempty" cast-type:"github.com/OffchainLabs/go-bitfield.Bitvector4" ssz-size:"1"` PreviousJustifiedCheckpoint *Checkpoint `protobuf:"bytes,8002,opt,name=previous_justified_checkpoint,json=previousJustifiedCheckpoint,proto3" json:"previous_justified_checkpoint,omitempty"` CurrentJustifiedCheckpoint *Checkpoint `protobuf:"bytes,8003,opt,name=current_justified_checkpoint,json=currentJustifiedCheckpoint,proto3" json:"current_justified_checkpoint,omitempty"` FinalizedCheckpoint *Checkpoint `protobuf:"bytes,8004,opt,name=finalized_checkpoint,json=finalizedCheckpoint,proto3" json:"finalized_checkpoint,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } package main import ( "fmt" "github.com/OffchainLabs/prysm/v7/encoding/ssz/query" eth "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1" ) func main() { v := &eth.BeaconState{} // Analyze it with Prysm’s existing SSZ analyzer info, _ := query.AnalyzeObject(v) fmt.Println(info.Print()) } ផលិតផល : BeaconState (Variable-size / size: 2687377) ├─ genesis_time (offset: 0) uint64 (Fixed-size / size: 8) ├─ genesis_validators_root (offset: 8) Bytes32 (Fixed-size / size: 32) ├─ slot (offset: 40) Slot (Fixed-size / size: 8) ├─ fork (offset: 48) Fork (Fixed-size / size: 16) │ ├─ previous_version (offset: 0) Bytes4 (Fixed-size / size: 4) │ ├─ current_version (offset: 4) Bytes4 (Fixed-size / size: 4) │ └─ epoch (offset: 8) Epoch (Fixed-size / size: 8) ├─ latest_block_header (offset: 64) BeaconBlockHeader (Fixed-size / size: 112) │ ├─ slot (offset: 0) Slot (Fixed-size / size: 8) │ ├─ proposer_index (offset: 8) ValidatorIndex (Fixed-size / size: 8) │ ├─ parent_root (offset: 16) Bytes32 (Fixed-size / size: 32) │ ├─ state_root (offset: 48) Bytes32 (Fixed-size / size: 32) │ └─ body_root (offset: 80) Bytes32 (Fixed-size / size: 32) ├─ block_roots (offset: 176) Vector[Bytes32, 8192] (Fixed-size / size: 262144) ├─ state_roots (offset: 262320) Vector[Bytes32, 8192] (Fixed-size / size: 262144) ├─ historical_roots (offset: 2687377) List[Bytes32, 16777216] (Variable-size / length: 0, size: 0) ├─ eth1_data (offset: 524468) Eth1Data (Fixed-size / size: 72) │ ├─ deposit_root (offset: 0) Bytes32 (Fixed-size / size: 32) │ ├─ deposit_count (offset: 32) uint64 (Fixed-size / size: 8) │ └─ block_hash (offset: 40) Bytes32 (Fixed-size / size: 32) ├─ eth1_data_votes (offset: 2687377) List[Eth1Data, 2048] (Variable-size / length: 0, size: 0) ├─ eth1_deposit_index (offset: 524544) uint64 (Fixed-size / size: 8) ├─ validators (offset: 2687377) List[Validator, 1099511627776] (Variable-size / length: 0, size: 0) ├─ balances (offset: 2687377) List[uint64, 1099511627776] (Variable-size / length: 0, size: 0) ├─ randao_mixes (offset: 524560) Vector[Bytes32, 65536] (Fixed-size / size: 2097152) ├─ slashings (offset: 2621712) Vector[uint64, 8192] (Fixed-size / size: 65536) ├─ previous_epoch_attestations (offset: 2687377) List[PendingAttestation, 4096] (Variable-size / length: 0, size: 0) ├─ current_epoch_attestations (offset: 2687377) List[PendingAttestation, 4096] (Variable-size / length: 0, size: 0) ├─ justification_bits (offset: 2687256) Bitvector[8] (Fixed-size / size: 1) ├─ previous_justified_checkpoint (offset: 2687257) Checkpoint (Fixed-size / size: 40) │ ├─ epoch (offset: 0) Epoch (Fixed-size / size: 8) │ └─ root (offset: 8) Bytes32 (Fixed-size / size: 32) ├─ current_justified_checkpoint (offset: 2687297) Checkpoint (Fixed-size / size: 40) │ ├─ epoch (offset: 0) Epoch (Fixed-size / size: 8) │ └─ root (offset: 8) Bytes32 (Fixed-size / size: 32) └─ finalized_checkpoint (offset: 2687337) Checkpoint (Fixed-size / size: 40) ├─ epoch (offset: 0) Epoch (Fixed-size / size: 8) └─ root (offset: 8) Bytes32 (Fixed-size / size: 32) In the SSZ analyzer output, the ទិន្នន័យដែលបានបង្ហាញសម្រាប់ជារៀងរាល់ជារៀងរាល់គឺជាទីតាំងបច្ចុប្បន្ននៃបច្ចុប្បន្ននេះនៅពេលដែលជារៀងរាល់ជារៀងរាល់ត្រូវបាន serialized according to SSZ rules ។ SSZ serialization បានបង្ហាញទាំងអស់ , tightly packed one after another, and the offset tells you where each of these fields starts within that packed byte stream. For example, in the line , the field វាគឺជាតម្លៃទំហំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំ នៅលើ SSZ-coded byte array ។ វាត្រូវបានអនុញ្ញាតឱ្យប្រសិនបើវាជាប្រភេទដែលមានទំហំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទូលំទ offset fixed-size fields first root (offset: 8) Bytes32 (Fixed-size / size: 32) root 8 size Example: Finding the Merkle Leaf for a Field Using the Offset ឧទាហរណ៍: ការស្វែងរកសៀវភៅ Merkle សម្រាប់កន្លែងដែលប្រើការផ្លាស់ប្តូរ សូមយកកន្លែងពិតប្រាកដពីផលិតផល SSZ Analyzer: ├─ fork (offset: 48) Fork (Fixed-size / size: 16) │ ├─ previous_version (offset: 0) Bytes4 (Fixed-size / size: 4) │ ├─ current_version (offset: 4) Bytes4 (Fixed-size / size: 4) │ └─ epoch (offset: 8) Epoch (Fixed-size / size: 8) We want to prove the field: fork.epoch ការ “fork” ក្នុង ចាប់ផ្តើមនៅ នៅលើប្រព័ន្ធប្រតិបត្តិការ serialized byte stream ។ BeaconState offset 48 នៅខាងក្នុង នេះ field starts at (បើយោងតាមការចាប់ផ្តើមនៃ Fork ។) fork epoch offset 8 ដូច្នេះ absolute_offset = base_offset_of_fork + offset_of_epoch_inside_fork absolute_offset = 48 + 8 = 56 bytes វាត្រូវបានចាប់ផ្តើមពី 56 បៃតងនៃ BeaconState ដែលត្រូវបាន serialized ជាពេញលេញ។ fork.epoch SSZ បានផ្លាស់ប្តូរ serialization ទៅ : 32-byte chunks Chunk 0 → bytes 0–31 លក្ខខណ្ឌ 1 → លក្ខខណ្ឌ 32–63 Chunk 2 → បៃតង 64–95 … Now find which chunk contains byte : 56 chunk_index = floor(56 / 32) = 1 ដូច្នេះ សៀវភៅដែលមាន ប្លាស្ទិច / Chunk 1 fork.epoch គឺជា ដំបូង fork.epoch 8-byte ក្នុងអំឡុងពេល 1 (Bytes 32–63): local_offset = 56 - 32 = 24 So inside the 32-byte leaf, the bytes look like: [ 0 … 23 ] → unrelated fields [ 24 … 31 ] → fork.epoch (8 bytes) To prove this value, you: ចុចទី 1 នេះគឺជាកន្លែងរបស់អ្នក។ When hashing up the tree, at each level: If chunk is a left child → record the right sibling hash. If chunk is a right child → record the left sibling hash. Continue until you reach the top Merkle root ។ The collected sibling hashes form your: ឱកាស SSZ Merkle proof branch for fork.epoch Anyone can verify this by recomputing: hash_tree_root(leaf + all_siblings) == state_root នេះបានបង្ហាញពីបញ្ចប់ថ្មីពីរដែលបង្ហាញពីកំណែដំបូងនៃ នៅលើ Prysm: SSZ Query Language (SSZ-QL) /prysm/v1/beacon/states/{state_id}/query /prysm/v1/beacon/blocks/{block_id}/query ទោះជាយ៉ាងណាក៏ដោយអ្នកគ្រប់គ្រងគោលបំណងរបស់ SSZ-QL និងអនុញ្ញាតឱ្យកុំព្យូទ័រអនុញ្ញាតឱ្យកុំព្យូទ័រអនុញ្ញាតឱ្យកុំព្យូទ័រអនុញ្ញាតឱ្យកុំព្យូទ័រអនុញ្ញាតឱ្យកុំព្យូទ័រអនុញ្ញាតឱ្យកុំព្យូទ័រអនុញ្ញាតឱ្យកុំព្យូទ័រអនុញ្ញាតឱ្យកុំព្យូទ័រអនុញ្ញាតឱ្យកុំព្យូទ័រអនុញ្ញាតឱ្យកុំព្យូទ័រអនុញ្ញាតឱ្យកុំព្យូទ័រអនុញ្ញាតឱ្យកុំព្យូទ័រអនុញ្ញាតឱ្យកុំព្យូទ័រអនុញ្ញាតឱ្យកុំព្យូទ័រអនុញ្ញាតឱ្យកុំព្យូទ័រអនុញ្ញាតឱ្យកុំព្យូទ ស្លាកនេះត្រូវបានបាត់បន្ថយ - PR នឹងបាត់បន្ថយការឆ្លើយតបដោយមិនមានការបង្ហាញពី Merkle ។ include_proof គោលបំណងនៃសំណួរនេះគឺ: type SSZQueryRequest struct { Query string `json:"query"` IncludeProof bool `json:"include_proof,omitempty"` } និងទីបញ្ចប់ទាំងពីរបានបង្ហាញការឆ្លើយតប SSZ-coded នៃគំរូនេះ: type SSZQueryResponse struct { state protoimpl.MessageState `protogen:"open.v1"` Root []byte `protobuf:"bytes,1,opt,name=root,proto3" json:"root,omitempty" ssz-size:"32"` Result []byte `protobuf:"bytes,2,opt,name=result,proto3" json:"result,omitempty" ssz-max:"1073741824"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } សម្រាប់ពិសេសពេញលេញនិងឧទាហរណ៍អ្នកអាចផ្លាស់ប្តូរទៅនេះ link និង ទិន្នន័យពីការដោះស្រាយ SSZ ហើយមិនប្រើសម្រាប់ឧបករណ៍ដោះស្រាយឧបករណ៍ដោះស្រាយ SSZ ។ For now, the implementation locates the requested field using the computed offset size ប្រសិនបើអ្នកមានព័ត៌មានបន្ថែមទៀតអ្នកអាចមើលឃើញការងាររបស់លោក Jun Song ដែលត្រូវបានអនុវត្តជាមួយ Fernando ជាផ្នែកមួយនៃគម្រោង EPF របស់ពួកគេនៅ prysm ។ For more information, you can check out ’s work — implemented together with as part of their EPF project in prysm. Jun Song Fernando ហ្វេសប៊ុក លោក Fernando