ferranbt / fastssz

Fast Ethereum2.0 SSZ encoder/decoder
MIT License
74 stars 44 forks source link

Documentation Request - Create a User Manual for Decoding SSZ #71

Closed abdulrabbani00 closed 2 years ago

abdulrabbani00 commented 2 years ago

Hello,

I would love to request further documentation so I can utilize this library to decode SSZ objects. My goal is:

  1. Import this library into my go project.
  2. Query a Beacon Client's API, such as eth/v1/events?topics=head, get the block and state hash.
  3. Utilize this libraries decode functionality, and decode the block and state hash into a Go native struct.
  4. Do as I please with the Go native struct.

If you can provide me with any guidance on how to turn an SSZ encoded hash (such as: 0x9a2fefd2fdb57f74993c7780ea5b9030d2897b615b89f808011ca5aebed54eaf) into a go-object, it would be immensely useful.

Thank You :D

rauljordan commented 2 years ago

hi @abdulrabbani00, the data returned from the events stream endpoint is just JSON data. The values within are just the hashes of blocks, state, attestations, or other data structures, not the actual data. Here's a simple Go script to read from the events endpoint:

package main

import (
    "encoding/json"
    "flag"
    "fmt"

    "github.com/r3labs/sse/v2"
)

var endpoint = flag.String("endpoint", "http://localhost:3500/eth/v1/events", "")

func main() {
    flag.Parse()
    client := sse.NewClient(*endpoint + "?topics=head")

    if err := client.SubscribeRaw(func(msg *sse.Event) {
        item := make(map[string]interface{})
        if err := json.Unmarshal(msg.Data, &item); err != nil {
            panic(err)
        }
        fmt.Printf("%v\n", item)
    }); err != nil {
        panic(err)
    }
}

The sample output is:

map[block:0xfa5057ba5ca2eb13717e7eff4ef920cbf59a35e504b8210c9f5d5519c928d3a7 current_duty_dependent_root:0x13f2bf1fe319dc33416931568ebab97045502f22d46fdf7a03e71b8b7495ee4d epoch_transition:false previous_duty_dependent_root:0xd708cda4370873dc3339ef9510542632fb92d2d0b4ea8bef9adbfced1f6e3320 slot:3553697 state:0x3e0271a31136c63512f156d0344d6184369d14987145b4b4f564d733ce2ceb98]

Here, I have a Go map where I can access its members. block:0xfa5057ba5ca2eb13717e7eff4ef920cbf59a35e504b8210c9f5d5519c928d3a7, for example, is not the raw data of a block, but just its block hash, basically. There's no need for SSZ decode here

abdulrabbani00 commented 2 years ago

Thank you so much for this insight @rauljordan. So if I understand correctly, the hash that is returned in the JSON body is not an SSZ encoded hash.

I was hoping to decode the block and state hash into a JSON object. It seems like the following endpoint does return an SSZ encoded byte object, eth/v2/beacon/blocks/head. Is there a way for me to utilize this library to decode the SSZ serialized object found here into JSON?

Thank you for the help.

abdulrabbani00 commented 2 years ago

@rauljordan - I've been applying around with the code base, I am able to unmarshal SSZ objects, but I am still not able to find a method for decoding them. Would it be possible for you to nudge me in the right direction?

Steps Taken

  1. curl http://localhost:5052/eth/v2/beacon/blocks/3264 -H "accept: application/octet-stream" --output ./head_block.ssz
  2. Ran the following code

    func TestUnMarshall(t *testing.T) {
    obj := new(SignedBeaconBlock)
    
    ser, err := ioutil.ReadFile("/path/to/head_block.ssz")
    if err != nil {
        t.Error(err)
    }
    fmt.Print("ser", ser)
    
    obj.UnmarshalSSZ(ser)
    t.Log(obj.Block.Slot)
    t.Log(obj.Block.ProposerIndex)
    t.Log(obj.Block.ParentRoot)
    t.Log(obj.Block.StateRoot)
    t.Log(obj.Block.Body)
    }

The end goal is to be able to decode the SSZ object into a struct and utilize the human readable values.

abdulrabbani00 commented 2 years ago

The above provided me what I needed, I was simply looking at the data incorrectly.