diff --git a/go.mod b/go.mod index 8a8bad8b..c0e9a6cc 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( dario.cat/mergo v1.0.0 - github.com/attestantio/go-eth2-client v0.21.3 + github.com/attestantio/go-eth2-client v0.0.0-20240507092336-27309754c54f github.com/aws/aws-sdk-go-v2 v1.26.1 github.com/aws/aws-sdk-go-v2/config v1.27.11 github.com/aws/aws-sdk-go-v2/credentials v1.17.11 @@ -21,6 +21,7 @@ require ( github.com/lib/pq v1.10.9 github.com/mattn/go-sqlite3 v1.14.22 github.com/mitchellh/mapstructure v1.5.0 + github.com/pk910/dynamic-ssz v0.0.3 github.com/pressly/goose/v3 v3.20.0 github.com/protolambda/bls12-381-util v0.1.0 github.com/protolambda/zrnt v0.32.3 @@ -116,6 +117,7 @@ require ( golang.org/x/tools v0.20.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/Knetic/govaluate.v3 v3.0.0 // indirect gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect diff --git a/go.sum b/go.sum index 296154e1..2626297d 100644 --- a/go.sum +++ b/go.sum @@ -13,8 +13,8 @@ github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDO github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= -github.com/attestantio/go-eth2-client v0.21.3 h1:m4Tzgb5AZkcjvtpmeZSiFireIhdZVK/fSAntJKAH8qM= -github.com/attestantio/go-eth2-client v0.21.3/go.mod h1:vhb0ZoQ6bz0kkoyxVbHDRrZTOJbwlY6udFkwfwrJZTE= +github.com/attestantio/go-eth2-client v0.0.0-20240507092336-27309754c54f h1:k4axih4fc/7Atb9eTsPsPFxlGGb501o+ryUt9q0stR8= +github.com/attestantio/go-eth2-client v0.0.0-20240507092336-27309754c54f/go.mod h1:Ht9tN0WlhpgIWWO7Hqfi3/nq2rUGQv/zCd/BMI93a84= github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA= github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to= @@ -322,6 +322,10 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= +github.com/pk910/dynamic-ssz v0.0.3 h1:fCWzFowq9P6SYCc7NtJMkZcIHk+r5hSVD+32zVi6Aio= +github.com/pk910/dynamic-ssz v0.0.3/go.mod h1:b6CrLaB2X7pYA+OSEEbkgXDEcRnjLOZIxZTsMuO/Y9c= +github.com/pk910/go-eth2-client v0.0.0-20240503111248-b7b883e07eca h1:+SeQtXs6iJyVQX294Ci37a9F5gvlnhIKTj0XvKP1rEQ= +github.com/pk910/go-eth2-client v0.0.0-20240503111248-b7b883e07eca/go.mod h1:CilNSTpoxAEvYGi5fuWHpj+lN3GC552OtHUops1ctwg= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -548,6 +552,8 @@ golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSm golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/Knetic/govaluate.v3 v3.0.0 h1:18mUyIt4ZlRlFZAAfVetz4/rzlJs9yhN+U02F4u1AOc= +gopkg.in/Knetic/govaluate.v3 v3.0.0/go.mod h1:csKLBORsPbafmSCGTEh3U7Ozmsuq8ZSIlKk1bcqph0E= gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y= gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/indexer/ssz_helper.go b/indexer/ssz_helper.go index 7dd25f71..4c787605 100644 --- a/indexer/ssz_helper.go +++ b/indexer/ssz_helper.go @@ -10,32 +10,50 @@ import ( "github.com/attestantio/go-eth2-client/spec/deneb" "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/ethpandaops/dora/utils" + dynssz "github.com/pk910/dynamic-ssz" + "gopkg.in/yaml.v3" ) +var staticConfigSpec map[string]any var jsonVersionOffset uint64 = 0x70000000 +func getConfigSpec() map[string]any { + if staticConfigSpec != nil { + return staticConfigSpec + } + + staticConfigSpec = map[string]any{} + specYaml, err := yaml.Marshal(utils.Config.Chain.Config) + if err != nil { + yaml.Unmarshal(specYaml, staticConfigSpec) + } + return staticConfigSpec +} + func MarshalVersionedSignedBeaconBlockSSZ(block *spec.VersionedSignedBeaconBlock) (version uint64, ssz []byte, err error) { if utils.Config.KillSwitch.DisableSSZEncoding { // SSZ encoding disabled, use json instead return marshalVersionedSignedBeaconBlockJson(block) } + dynSsz := dynssz.NewDynSsz(getConfigSpec()) + switch block.Version { case spec.DataVersionPhase0: version = uint64(block.Version) - ssz, err = block.Phase0.MarshalSSZ() + ssz, err = dynSsz.MarshalSSZ(block.Phase0) case spec.DataVersionAltair: version = uint64(block.Version) - ssz, err = block.Altair.MarshalSSZ() + ssz, err = dynSsz.MarshalSSZ(block.Altair) case spec.DataVersionBellatrix: version = uint64(block.Version) - ssz, err = block.Bellatrix.MarshalSSZ() + ssz, err = dynSsz.MarshalSSZ(block.Bellatrix) case spec.DataVersionCapella: version = uint64(block.Version) - ssz, err = block.Capella.MarshalSSZ() + ssz, err = dynSsz.MarshalSSZ(block.Capella) case spec.DataVersionDeneb: version = uint64(block.Version) - ssz, err = block.Deneb.MarshalSSZ() + ssz, err = dynSsz.MarshalSSZ(block.Deneb) default: err = fmt.Errorf("unknown block version") } @@ -49,30 +67,32 @@ func UnmarshalVersionedSignedBeaconBlockSSZ(version uint64, ssz []byte) (*spec.V block := &spec.VersionedSignedBeaconBlock{ Version: spec.DataVersion(version), } + dynSsz := dynssz.NewDynSsz(getConfigSpec()) + switch block.Version { case spec.DataVersionPhase0: block.Phase0 = &phase0.SignedBeaconBlock{} - if err := block.Phase0.UnmarshalSSZ(ssz); err != nil { + if err := dynSsz.UnmarshalSSZ(block.Phase0, ssz); err != nil { return nil, fmt.Errorf("failed to decode phase0 signed beacon block: %v", err) } case spec.DataVersionAltair: block.Altair = &altair.SignedBeaconBlock{} - if err := block.Altair.UnmarshalSSZ(ssz); err != nil { + if err := dynSsz.UnmarshalSSZ(block.Altair, ssz); err != nil { return nil, fmt.Errorf("failed to decode altair signed beacon block: %v", err) } case spec.DataVersionBellatrix: block.Bellatrix = &bellatrix.SignedBeaconBlock{} - if err := block.Bellatrix.UnmarshalSSZ(ssz); err != nil { + if err := dynSsz.UnmarshalSSZ(block.Bellatrix, ssz); err != nil { return nil, fmt.Errorf("failed to decode bellatrix signed beacon block: %v", err) } case spec.DataVersionCapella: block.Capella = &capella.SignedBeaconBlock{} - if err := block.Capella.UnmarshalSSZ(ssz); err != nil { + if err := dynSsz.UnmarshalSSZ(block.Capella, ssz); err != nil { return nil, fmt.Errorf("failed to decode capella signed beacon block: %v", err) } case spec.DataVersionDeneb: block.Deneb = &deneb.SignedBeaconBlock{} - if err := block.Deneb.UnmarshalSSZ(ssz); err != nil { + if err := dynSsz.UnmarshalSSZ(block.Deneb, ssz); err != nil { return nil, fmt.Errorf("failed to decode deneb signed beacon block: %v", err) } default: diff --git a/rpc/beaconapi.go b/rpc/beaconapi.go index 214ffc26..9f6cf6e2 100644 --- a/rpc/beaconapi.go +++ b/rpc/beaconapi.go @@ -149,6 +149,7 @@ func (bc *BeaconClient) Initialize() error { http.WithTimeout(10 * time.Minute), // TODO (when upstream PR is merged) //http.WithConnectionCheck(false), + http.WithCustomSpecSupport(true), } // set log level @@ -179,6 +180,24 @@ func (bc *BeaconClient) Initialize() error { return nil } +func (bc *BeaconClient) GetSpecs() (map[string]any, error) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + provider, isProvider := bc.clientSvc.(eth2client.SpecProvider) + if !isProvider { + return nil, fmt.Errorf("get spec not supported") + } + result, err := provider.Spec(ctx, &api.SpecOpts{ + Common: api.CommonOpts{ + Timeout: 0, + }, + }) + if err != nil { + return nil, err + } + return result.Data, nil +} + func (bc *BeaconClient) GetGenesis() (*v1.Genesis, error) { ctx, cancel := context.WithCancel(context.Background()) defer cancel()