From 2a426c260c994ab3589f7acdc6d5260327b18f60 Mon Sep 17 00:00:00 2001 From: Thomas E Lackey Date: Wed, 7 Sep 2022 13:38:58 -0500 Subject: [PATCH] Add wrapper types (tests mostly working). --- pkg/beaconclient/capturehead_test.go | 124 ++++----- pkg/beaconclient/consensus.go | 366 +++++++++++++++++++++++++++ pkg/beaconclient/processslot.go | 53 ++-- pkg/beaconclient/queryserver.go | 25 ++ 4 files changed, 475 insertions(+), 93 deletions(-) create mode 100644 pkg/beaconclient/consensus.go diff --git a/pkg/beaconclient/capturehead_test.go b/pkg/beaconclient/capturehead_test.go index 1c569df..617ae56 100644 --- a/pkg/beaconclient/capturehead_test.go +++ b/pkg/beaconclient/capturehead_test.go @@ -20,6 +20,7 @@ import ( "encoding/hex" "encoding/json" "fmt" + consensus "github.com/umbracle/go-eth-consensus" "net/http" "os" "path/filepath" @@ -29,11 +30,6 @@ import ( "github.com/jarcoal/httpmock" . "github.com/onsi/ginkgo/v2" - "github.com/prysmaticlabs/prysm/beacon-chain/state" - si "github.com/prysmaticlabs/prysm/consensus-types/interfaces" - types "github.com/prysmaticlabs/prysm/consensus-types/primitives" - dt "github.com/prysmaticlabs/prysm/encoding/ssz/detect" - st "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/r3labs/sse" log "github.com/sirupsen/logrus" @@ -49,10 +45,10 @@ var ( port int = 8080 protocol string = "http" dbHost string = "localhost" - dbPort int = 8076 - dbName string = "vulcanize_testing" - dbUser string = "vdbm" - dbPassword string = "password" + dbPort int = 15432 + dbName string = "postgres" + dbUser string = "postgres" + dbPassword string = "secret12" dbDriver string = "pgx" bcUniqueIdentifier int = 100 dummyParentRoot string = "46f98c08b54a71dfda4d56e29ec3952b8300cd8d6b67a9b6c562ae96a7a25a42" @@ -332,12 +328,12 @@ var _ = Describe("Capturehead", Label("head"), func() { }) }) Context("Phase 0: We have a correctly formated SSZ SignedBeaconBlock and BeaconState", func() { - It("Should be able to get each objects root hash.", func() { + It("Should be able to get each objects root hash (100).", func() { testSszRoot(BeaconNodeTester.TestEvents["100"]) }) }) Context("Altair: We have a correctly formated SSZ SignedBeaconBlock and BeaconState", func() { - It("Should be able to get each objects root hash.", func() { + It("Should be able to get each objects root hash (2375703).", func() { testSszRoot(BeaconNodeTester.TestEvents["2375703"]) }) }) @@ -566,22 +562,22 @@ func queryDbSlotAndBlock(db sql.Database, querySlot string, queryBlockRoot strin func queryDbSignedBeaconBlock(db sql.Database, querySlot string, queryBlockRoot string) (int, string, string, string, string) { sqlStatement := `SELECT slot, block_root, parent_block_root, eth1_block_hash, mh_key FROM eth_beacon.signed_block WHERE slot=$1 AND block_root=$2;` var slot int - var blockRoot, parent_block_root, eth1_block_hash, mh_key string + var blockRoot, parentBlockRoot, eth1BlockHash, mhKey string row := db.QueryRow(context.Background(), sqlStatement, querySlot, queryBlockRoot) - err := row.Scan(&slot, &blockRoot, &parent_block_root, ð1_block_hash, &mh_key) + err := row.Scan(&slot, &blockRoot, &parentBlockRoot, ð1BlockHash, &mhKey) Expect(err).ToNot(HaveOccurred()) - return slot, blockRoot, parent_block_root, eth1_block_hash, mh_key + return slot, blockRoot, parentBlockRoot, eth1BlockHash, mhKey } // A helper function to query the eth_beacon.signed_block table based on the slot and block_root. func queryDbBeaconState(db sql.Database, querySlot string, queryStateRoot string) (int, string, string) { sqlStatement := `SELECT slot, state_root, mh_key FROM eth_beacon.state WHERE slot=$1 AND state_root=$2;` var slot int - var stateRoot, mh_key string + var stateRoot, mhKey string row := db.QueryRow(context.Background(), sqlStatement, querySlot, queryStateRoot) - err := row.Scan(&slot, &stateRoot, &mh_key) + err := row.Scan(&slot, &stateRoot, &mhKey) Expect(err).ToNot(HaveOccurred()) - return slot, stateRoot, mh_key + return slot, stateRoot, mhKey } // Count the entries in the knownGaps table. @@ -620,55 +616,27 @@ func writeSlot(db sql.Database, slot string) { // Read a file with the SignedBeaconBlock in SSZ and return the SSZ object. This is used for testing only. // We can't use the readSignedBeaconBlockInterface to update struct fields so this is the workaround. -func readSignedBeaconBlock(slotFile string) (*st.SignedBeaconBlock, error) { +func readSignedBeaconBlock(slotFile string) (*beaconclient.SignedBeaconBlock, error) { dat, err := os.ReadFile(slotFile) if err != nil { return nil, fmt.Errorf("Can't find the slot file, %s", slotFile) } - block := &st.SignedBeaconBlock{} + var block beaconclient.SignedBeaconBlock err = block.UnmarshalSSZ(dat) Expect(err).ToNot(HaveOccurred()) - return block, nil -} - -// Read a file with the SignedBeaconBlock in SSZ and return the SSZ object. This is used for testing only. -// We can't use the readSignedBeaconBlockInterface to update struct fields so this is the workaround. -func readSignedBeaconBlockAltair(slotFile string) (*st.SignedBeaconBlockAltair, error) { - dat, err := os.ReadFile(slotFile) - if err != nil { - return nil, fmt.Errorf("Can't find the slot file, %s", slotFile) - } - block := &st.SignedBeaconBlockAltair{} - err = block.UnmarshalSSZ(dat) - Expect(err).ToNot(HaveOccurred()) - return block, nil -} - -// Read a file with the SignedBeaconBlock in SSZ and return the SSZ objects interface. This is production like. -// It will provide the correct struct for the given fork. -func readSignedBeaconBlockInterface(slotFile string, vm *dt.VersionedUnmarshaler) (si.SignedBeaconBlock, error) { - dat, err := os.ReadFile(slotFile) - if err != nil { - return nil, fmt.Errorf("Can't find the slot file, %s", slotFile) - } - - block, err := vm.UnmarshalBeaconBlock(dat) - Expect(err).ToNot(HaveOccurred()) - return block, nil - + return &block, nil } // Read a file with the BeaconState in SSZ and return the SSZ object -func readBeaconState(slotFile string) (state.BeaconState, *dt.VersionedUnmarshaler, error) { +func readBeaconState(slotFile string) (*beaconclient.BeaconState, error) { dat, err := os.ReadFile(slotFile) if err != nil { - return nil, nil, fmt.Errorf("Can't find the slot file, %s", slotFile) + return nil, fmt.Errorf("Can't find the slot file, %s", slotFile) } - versionedUnmarshaler, err := dt.FromState(dat) + var beaconState beaconclient.BeaconState + err = beaconState.UnmarshalSSZ(dat) Expect(err).ToNot(HaveOccurred()) - state, err := versionedUnmarshaler.UnmarshalBeaconState(dat) - Expect(err).ToNot(HaveOccurred()) - return state, versionedUnmarshaler, nil + return &beaconState, nil } // An object that is used to aggregate test functions. Test functions are needed because we need to @@ -768,52 +736,62 @@ func (tbc TestBeaconNode) provideSsz(slotIdentifier string, sszIdentifier string if err != nil { return nil, err } + Expect(block.IsPhase0()).To(BeTrue()) + var phase0 = block.GetPhase0() + slot, err := strconv.ParseUint(Message.HeadMessage.Slot, 10, 64) Expect(err).ToNot(HaveOccurred()) - block.Block.Slot = types.Slot(slot) + phase0.Block.Slot = slot - block.Block.StateRoot, err = hex.DecodeString(Message.HeadMessage.State) + phase0.Block.StateRoot, err = decodeRoot(Message.HeadMessage.State) Expect(err).ToNot(HaveOccurred()) if Message.MimicConfig.ParentRoot == "" { - block.Block.ParentRoot, err = hex.DecodeString(dummyParentRoot) + phase0.Block.ParentRoot, err = decodeRoot(dummyParentRoot) Expect(err).ToNot(HaveOccurred()) } else { - block.Block.ParentRoot, err = hex.DecodeString(Message.MimicConfig.ParentRoot) + phase0.Block.ParentRoot, err = decodeRoot(Message.MimicConfig.ParentRoot) Expect(err).ToNot(HaveOccurred()) } return block.MarshalSSZ() case "altair": - block, err := readSignedBeaconBlockAltair(slotFile) + block, err := readSignedBeaconBlock(slotFile) if err != nil { return nil, err } + Expect(block.IsAltair()).To(BeTrue()) + var altair = block.GetAltair() slot, err := strconv.ParseUint(Message.HeadMessage.Slot, 10, 64) Expect(err).ToNot(HaveOccurred()) - block.Block.Slot = types.Slot(slot) + altair.Block.Slot = slot - block.Block.StateRoot, err = hex.DecodeString(Message.HeadMessage.State) + altair.Block.StateRoot, err = decodeRoot(Message.HeadMessage.State) Expect(err).ToNot(HaveOccurred()) if Message.MimicConfig.ParentRoot == "" { - block.Block.ParentRoot, err = hex.DecodeString(dummyParentRoot) + altair.Block.ParentRoot, err = decodeRoot(dummyParentRoot) Expect(err).ToNot(HaveOccurred()) } else { - block.Block.ParentRoot, err = hex.DecodeString(Message.MimicConfig.ParentRoot) + altair.Block.ParentRoot, err = decodeRoot(Message.MimicConfig.ParentRoot) Expect(err).ToNot(HaveOccurred()) } return block.MarshalSSZ() } } if sszIdentifier == "state" { - state, _, err := readBeaconState(slotFile) + state, err := readBeaconState(slotFile) if err != nil { return nil, err } slot, err := strconv.ParseUint(Message.HeadMessage.Slot, 10, 64) Expect(err).ToNot(HaveOccurred()) - err = state.SetSlot(types.Slot(slot)) - Expect(err).ToNot(HaveOccurred()) + if state.IsBellatrix() { + state.GetBellatrix().Slot = slot + } else if state.IsAltair() { + state.GetAltair().Slot = slot + } else { + state.GetPhase0().Slot = slot + } return state.MarshalSSZ() } } @@ -979,15 +957,25 @@ func (tbc TestBeaconNode) testKnownGapsMessages(bc *beaconclient.BeaconClient, t // This function will make sure we are properly able to get the SszRoot of the SignedBeaconBlock and the BeaconState. func testSszRoot(msg Message) { - state, vm, err := readBeaconState(msg.BeaconState) + state, err := readBeaconState(msg.BeaconState) Expect(err).ToNot(HaveOccurred()) - stateRoot, err := state.HashTreeRoot(context.Background()) + stateRoot, err := state.HashTreeRoot() Expect(err).ToNot(HaveOccurred()) Expect(msg.HeadMessage.State).To(Equal("0x" + hex.EncodeToString(stateRoot[:]))) - block, err := readSignedBeaconBlockInterface(msg.SignedBeaconBlock, vm) + block, err := readSignedBeaconBlock(msg.SignedBeaconBlock) Expect(err).ToNot(HaveOccurred()) blockRoot, err := block.Block().HashTreeRoot() Expect(err).ToNot(HaveOccurred()) Expect(msg.HeadMessage.Block).To(Equal("0x" + hex.EncodeToString(blockRoot[:]))) } + +func decodeRoot(raw string) (consensus.Root, error) { + value, err := hex.DecodeString(raw) + if err != nil { + return consensus.Root{}, err + } + var root consensus.Root + copy(root[:], value[:32]) + return root, nil +} diff --git a/pkg/beaconclient/consensus.go b/pkg/beaconclient/consensus.go new file mode 100644 index 0000000..ebf97dd --- /dev/null +++ b/pkg/beaconclient/consensus.go @@ -0,0 +1,366 @@ +package beaconclient + +import ( + "errors" + log "github.com/sirupsen/logrus" + consensus "github.com/umbracle/go-eth-consensus" +) + +type SignedBeaconBlock struct { + signedBeaconBlockBellatrix *consensus.SignedBeaconBlockBellatrix + signedBeaconBlockAltair *consensus.SignedBeaconBlockAltair + signedBeaconBlockPhase0 *consensus.SignedBeaconBlockPhase0 +} + +type BeaconBlock struct { + beaconBlockBellatrix *consensus.BeaconBlockBellatrix + beaconBlockAltair *consensus.BeaconBlockAltair + beaconBlockPhase0 *consensus.BeaconBlockPhase0 +} + +type BeaconBlockBody struct { + beaconBlockBodyBellatrix *consensus.BeaconBlockBodyBellatrix + beaconBlockBodyAltair *consensus.BeaconBlockBodyAltair + beaconBlockBodyPhase0 *consensus.BeaconBlockBodyPhase0 +} + +type BeaconState struct { + beaconStateBellatrix *consensus.BeaconStateBellatrix + beaconStateAltair *consensus.BeaconStateAltair + beaconStatePhase0 *consensus.BeaconStatePhase0 +} + +func (s *SignedBeaconBlock) UnmarshalSSZ(ssz []byte) error { + var bellatrix consensus.SignedBeaconBlockBellatrix + err := bellatrix.UnmarshalSSZ(ssz) + if nil == err { + s.signedBeaconBlockBellatrix = &bellatrix + s.signedBeaconBlockAltair = nil + s.signedBeaconBlockPhase0 = nil + log.Info("Unmarshalled Bellatrix SignedBeaconBlock") + return nil + } + + var altair consensus.SignedBeaconBlockAltair + err = altair.UnmarshalSSZ(ssz) + if nil == err { + s.signedBeaconBlockBellatrix = nil + s.signedBeaconBlockAltair = &altair + s.signedBeaconBlockPhase0 = nil + log.Info("Unmarshalled Altair SignedBeaconBlock") + return nil + } + + var phase0 consensus.SignedBeaconBlockPhase0 + err = phase0.UnmarshalSSZ(ssz) + if nil == err { + s.signedBeaconBlockBellatrix = nil + s.signedBeaconBlockAltair = nil + s.signedBeaconBlockPhase0 = &phase0 + log.Info("Unmarshalled Phase0 SignedBeaconBlock") + return nil + } + + s.signedBeaconBlockBellatrix = nil + s.signedBeaconBlockAltair = nil + s.signedBeaconBlockPhase0 = nil + + log.Warning("Unable to unmarshal SignedBeaconBlock") + return err +} + +func (s *SignedBeaconBlock) MarshalSSZ() ([]byte, error) { + if s.IsBellatrix() { + return s.signedBeaconBlockBellatrix.MarshalSSZ() + } + if s.IsAltair() { + return s.signedBeaconBlockAltair.MarshalSSZ() + } + if s.IsPhase0() { + return s.signedBeaconBlockPhase0.MarshalSSZ() + } + + return []byte{}, errors.New("SignedBeaconBlock not set") +} + +func (s *SignedBeaconBlock) IsBellatrix() bool { + return s.signedBeaconBlockBellatrix != nil +} + +func (s *SignedBeaconBlock) IsAltair() bool { + return s.signedBeaconBlockAltair != nil +} + +func (s *SignedBeaconBlock) IsPhase0() bool { + return s.signedBeaconBlockPhase0 != nil +} + +func (s *SignedBeaconBlock) GetBellatrix() *consensus.SignedBeaconBlockBellatrix { + return s.signedBeaconBlockBellatrix +} + +func (s *SignedBeaconBlock) GetAltair() *consensus.SignedBeaconBlockAltair { + return s.signedBeaconBlockAltair +} + +func (s *SignedBeaconBlock) GetPhase0() *consensus.SignedBeaconBlockPhase0 { + return s.signedBeaconBlockPhase0 +} + +func (s *SignedBeaconBlock) Signature() *consensus.Signature { + if s.IsBellatrix() { + return &s.signedBeaconBlockBellatrix.Signature + } + + if s.IsAltair() { + return &s.signedBeaconBlockAltair.Signature + } + + if s.IsPhase0() { + return &s.signedBeaconBlockPhase0.Signature + } + + return nil +} + +func (s *SignedBeaconBlock) Block() *BeaconBlock { + if s.IsBellatrix() { + return &BeaconBlock{beaconBlockBellatrix: s.signedBeaconBlockBellatrix.Block} + } + + if s.IsAltair() { + return &BeaconBlock{beaconBlockAltair: s.signedBeaconBlockAltair.Block} + } + + if s.IsPhase0() { + return &BeaconBlock{beaconBlockPhase0: s.signedBeaconBlockPhase0.Block} + } + + return nil +} + +func (b *BeaconBlock) IsBellatrix() bool { + return b.beaconBlockBellatrix != nil +} + +func (b *BeaconBlock) IsAltair() bool { + return b.beaconBlockAltair != nil +} + +func (b *BeaconBlock) IsPhase0() bool { + return b.beaconBlockPhase0 != nil +} + +func (s *BeaconBlock) GetBellatrix() *consensus.BeaconBlockBellatrix { + return s.beaconBlockBellatrix +} + +func (s *BeaconBlock) GetAltair() *consensus.BeaconBlockAltair { + return s.beaconBlockAltair +} + +func (s *BeaconBlock) GetPhase0() *consensus.BeaconBlockPhase0 { + return s.beaconBlockPhase0 +} + +func (b *BeaconBlock) ParentRoot() *consensus.Root { + if b.IsBellatrix() { + return &b.beaconBlockBellatrix.ParentRoot + } + + if b.IsAltair() { + return &b.beaconBlockAltair.ParentRoot + } + + if b.IsPhase0() { + return &b.beaconBlockPhase0.ParentRoot + } + + return nil +} + +func (b *BeaconBlock) StateRoot() *consensus.Root { + if b.IsBellatrix() { + return &b.beaconBlockBellatrix.StateRoot + } + + if b.IsAltair() { + return &b.beaconBlockAltair.StateRoot + } + + if b.IsPhase0() { + return &b.beaconBlockPhase0.StateRoot + } + + return nil +} + +func (b *BeaconBlock) Body() *BeaconBlockBody { + if b.IsBellatrix() { + return &BeaconBlockBody{beaconBlockBodyBellatrix: b.beaconBlockBellatrix.Body} + } + + if b.IsAltair() { + return &BeaconBlockBody{beaconBlockBodyAltair: b.beaconBlockAltair.Body} + } + + if b.IsPhase0() { + return &BeaconBlockBody{beaconBlockBodyPhase0: b.beaconBlockPhase0.Body} + } + + return nil +} + +func (b *BeaconBlockBody) IsBellatrix() bool { + return b.beaconBlockBodyBellatrix != nil +} + +func (b *BeaconBlockBody) IsAltair() bool { + return b.beaconBlockBodyAltair != nil +} + +func (b *BeaconBlockBody) IsPhase0() bool { + return b.beaconBlockBodyPhase0 != nil +} + +func (b *BeaconBlockBody) Eth1Data() *consensus.Eth1Data { + if b.IsBellatrix() { + return b.beaconBlockBodyBellatrix.Eth1Data + } + + if b.IsAltair() { + return b.beaconBlockBodyAltair.Eth1Data + } + + if b.IsPhase0() { + return b.beaconBlockBodyPhase0.Eth1Data + } + + return nil +} + +func (b *BeaconBlock) HashTreeRoot() ([32]byte, error) { + if b.IsBellatrix() { + return b.beaconBlockBellatrix.HashTreeRoot() + } + + if b.IsAltair() { + return b.beaconBlockAltair.HashTreeRoot() + } + + if b.IsPhase0() { + return b.beaconBlockPhase0.HashTreeRoot() + } + + return [32]byte{}, errors.New("BeaconBlock not set") +} + +func (s *BeaconState) UnmarshalSSZ(ssz []byte) error { + var bellatrix consensus.BeaconStateBellatrix + err := bellatrix.UnmarshalSSZ(ssz) + if nil == err { + s.beaconStateBellatrix = &bellatrix + s.beaconStateAltair = nil + s.beaconStatePhase0 = nil + log.Info("Unmarshalled Bellatrix BeaconState") + return nil + } + + var altair consensus.BeaconStateAltair + err = altair.UnmarshalSSZ(ssz) + if nil == err { + s.beaconStateBellatrix = nil + s.beaconStateAltair = &altair + s.beaconStatePhase0 = nil + log.Info("Unmarshalled Altair BeaconState") + return nil + } + + var phase0 consensus.BeaconStatePhase0 + err = phase0.UnmarshalSSZ(ssz) + if nil == err { + s.beaconStateBellatrix = nil + s.beaconStateAltair = nil + s.beaconStatePhase0 = &phase0 + log.Info("Unmarshalled Phase0 BeaconState") + return nil + } + + s.beaconStateBellatrix = nil + s.beaconStateAltair = nil + s.beaconStatePhase0 = nil + + log.Warning("Unable to unmarshal BeaconState") + return err +} + +func (s *BeaconState) MarshalSSZ() ([]byte, error) { + if s.IsBellatrix() { + return s.beaconStateBellatrix.MarshalSSZ() + } + if s.IsAltair() { + return s.beaconStateAltair.MarshalSSZ() + } + if s.IsPhase0() { + return s.beaconStatePhase0.MarshalSSZ() + } + + return []byte{}, errors.New("BeaconState not set") +} + +func (s *BeaconState) IsBellatrix() bool { + return s.beaconStateBellatrix != nil +} + +func (s *BeaconState) IsAltair() bool { + return s.beaconStateAltair != nil +} + +func (s *BeaconState) IsPhase0() bool { + return s.beaconStatePhase0 != nil +} + +func (s *BeaconState) Slot() uint64 { + if s.IsBellatrix() { + return s.beaconStateBellatrix.Slot + } + + if s.IsAltair() { + return s.beaconStateAltair.Slot + } + + if s.IsPhase0() { + return s.beaconStatePhase0.Slot + } + + // TODO(telackey): Something better than 0? + return 0 +} + +func (b *BeaconState) HashTreeRoot() ([32]byte, error) { + if b.IsBellatrix() { + return b.beaconStateBellatrix.HashTreeRoot() + } + + if b.IsAltair() { + return b.beaconStateAltair.HashTreeRoot() + } + + if b.IsPhase0() { + return b.beaconStatePhase0.HashTreeRoot() + } + + return [32]byte{}, errors.New("BeaconState not set") +} + +func (s *BeaconState) GetBellatrix() *consensus.BeaconStateBellatrix { + return s.beaconStateBellatrix +} + +func (s *BeaconState) GetAltair() *consensus.BeaconStateAltair { + return s.beaconStateAltair +} + +func (s *BeaconState) GetPhase0() *consensus.BeaconStatePhase0 { + return s.beaconStatePhase0 +} diff --git a/pkg/beaconclient/processslot.go b/pkg/beaconclient/processslot.go index ccdbd95..cff1815 100644 --- a/pkg/beaconclient/processslot.go +++ b/pkg/beaconclient/processslot.go @@ -24,8 +24,6 @@ import ( "encoding/hex" "fmt" consensus "github.com/umbracle/go-eth-consensus" - "github.com/umbracle/go-eth-consensus/http" - "strconv" "strings" "time" @@ -53,12 +51,12 @@ type ProcessSlot struct { PerformanceMetrics PerformanceMetrics // An object to keep track of performance metrics. // BeaconBlock - SszSignedBeaconBlock []byte // The entire SSZ encoded SignedBeaconBlock - FullSignedBeaconBlock consensus.SignedBeaconBlockBellatrix // The unmarshaled BeaconState object, the unmarshalling could have errors. + SszSignedBeaconBlock []byte // The entire SSZ encoded SignedBeaconBlock + FullSignedBeaconBlock SignedBeaconBlock // The unmarshaled BeaconState object, the unmarshalling could have errors. // BeaconState - FullBeaconState consensus.BeaconStateBellatrix // The unmarshaled BeaconState object, the unmarshalling could have errors. - SszBeaconState []byte // The entire SSZ encoded BeaconState + FullBeaconState BeaconState // The unmarshaled BeaconState object, the unmarshalling could have errors. + SszBeaconState []byte // The entire SSZ encoded BeaconState // DB Write objects DbSlotsModel *DbSlots // The model being written to the slots table. @@ -247,19 +245,24 @@ func (ps *ProcessSlot) getSignedBeaconBlock(serverAddress string) error { } else { blockIdentifier = strconv.Itoa(ps.Slot) } - client := http.New(serverAddress) - var signedBeaconBlock consensus.SignedBeaconBlockBellatrix - err := client.Get(BcBlockQueryEndpoint+blockIdentifier, &signedBeaconBlock) - if err != nil { + blockEndpoint := serverAddress + BcBlockQueryEndpoint + blockIdentifier + sszSignedBeaconBlock, rc, err := querySsz(blockEndpoint, strconv.Itoa(ps.Slot)) + + if err != nil || rc != 200 { loghelper.LogSlotError(strconv.Itoa(ps.Slot), err).Error("Unable to properly query the slot.") - return err + ps.FullSignedBeaconBlock = SignedBeaconBlock{} + ps.SszSignedBeaconBlock = []byte{} + ps.ParentBlockRoot = "" + ps.Status = "skipped" + return nil } - sszSignedBeaconBlock, err := signedBeaconBlock.MarshalSSZ() + var signedBeaconBlock SignedBeaconBlock + err = signedBeaconBlock.UnmarshalSSZ(sszSignedBeaconBlock) if err != nil { - loghelper.LogSlotError(strconv.Itoa(ps.Slot), err).Error("Unable to marshal SignedBeaconBlock to SSZ.") - ps.FullSignedBeaconBlock = consensus.SignedBeaconBlockBellatrix{} + loghelper.LogSlotError(strconv.Itoa(ps.Slot), err).Error("Unable to unmarshal SignedBeaconBlock for slot.") + ps.FullSignedBeaconBlock = SignedBeaconBlock{} ps.SszSignedBeaconBlock = []byte{} ps.ParentBlockRoot = "" ps.Status = "skipped" @@ -269,7 +272,7 @@ func (ps *ProcessSlot) getSignedBeaconBlock(serverAddress string) error { ps.FullSignedBeaconBlock = signedBeaconBlock ps.SszSignedBeaconBlock = sszSignedBeaconBlock - ps.ParentBlockRoot = rootToHex(&ps.FullSignedBeaconBlock.Block.ParentRoot) + ps.ParentBlockRoot = rootToHex(ps.FullSignedBeaconBlock.Block().ParentRoot()) return nil } @@ -281,18 +284,18 @@ func (ps *ProcessSlot) getBeaconState(serverEndpoint string) error { } else { stateIdentifier = strconv.Itoa(ps.Slot) } - client := http.New(serverEndpoint) - var beaconState consensus.BeaconStateBellatrix - err := client.Get(BcStateQueryEndpoint+stateIdentifier, &beaconState) + stateEndpoint := serverEndpoint + BcStateQueryEndpoint + stateIdentifier + sszBeaconState, _, err := querySsz(stateEndpoint, strconv.Itoa(ps.Slot)) if err != nil { loghelper.LogSlotError(strconv.Itoa(ps.Slot), err).Error("Unable to properly query the BeaconState.") return err } - sszBeaconState, err := beaconState.MarshalSSZ() + var beaconState BeaconState + err = beaconState.UnmarshalSSZ(sszBeaconState) if err != nil { - loghelper.LogSlotError(strconv.Itoa(ps.Slot), err).Error("Unable to marshal BeaconState.") + loghelper.LogSlotError(strconv.Itoa(ps.Slot), err).Error("Unable to unmarshal the BeaconState.") return err } @@ -303,8 +306,8 @@ func (ps *ProcessSlot) getBeaconState(serverEndpoint string) error { // Check to make sure that the previous block we processed is the parent of the current block. func (ps *ProcessSlot) checkPreviousSlot(tx sql.Tx, ctx context.Context, previousSlot int, previousBlockRoot string, knownGapsTableIncrement int) { - parentRoot := rootToHex(&ps.FullSignedBeaconBlock.Block.ParentRoot) - slot := int(ps.FullBeaconState.Slot) + parentRoot := rootToHex(ps.FullSignedBeaconBlock.Block().ParentRoot()) + slot := int(ps.FullBeaconState.Slot()) if previousSlot == slot { log.WithFields(log.Fields{ "slot": slot, @@ -366,21 +369,21 @@ func (ps *ProcessSlot) provideFinalHash() (string, string, string, error) { if ps.StateRoot != "" { stateRoot = ps.StateRoot } else { - stateRoot = rootToHex(&ps.FullSignedBeaconBlock.Block.StateRoot) + stateRoot = rootToHex(ps.FullSignedBeaconBlock.Block().StateRoot()) log.Debug("StateRoot: ", stateRoot) } if ps.BlockRoot != "" { blockRoot = ps.BlockRoot } else { - rawBlockRoot, err := ps.FullSignedBeaconBlock.Block.HashTreeRoot() + rawBlockRoot, err := ps.FullSignedBeaconBlock.Block().HashTreeRoot() if err != nil { return "", "", "", err } blockRoot = byteArrayToHex(&rawBlockRoot) log.WithFields(log.Fields{"blockRoot": blockRoot}).Debug("Block Root from ssz") } - eth1BlockHash = byteArrayToHex(&ps.FullSignedBeaconBlock.Block.Body.Eth1Data.BlockHash) + eth1BlockHash = byteArrayToHex(&ps.FullSignedBeaconBlock.Block().Body().Eth1Data().BlockHash) } return blockRoot, stateRoot, eth1BlockHash, nil } diff --git a/pkg/beaconclient/queryserver.go b/pkg/beaconclient/queryserver.go index d78ae94..7d1478b 100644 --- a/pkg/beaconclient/queryserver.go +++ b/pkg/beaconclient/queryserver.go @@ -37,6 +37,31 @@ type BlockRootMessage struct { Root string `json:"root"` } +// A helper function to query endpoints that utilize slots. +func querySsz(endpoint string, slot string) ([]byte, int, error) { + log.WithFields(log.Fields{"endpoint": endpoint}).Debug("Querying endpoint") + client := &http.Client{} + req, err := http.NewRequest("GET", endpoint, nil) + if err != nil { + loghelper.LogSlotError(slot, err).Error("Unable to create a request!") + return nil, 0, fmt.Errorf("Unable to create a request!: %s", err.Error()) + } + req.Header.Set("Accept", "application/octet-stream") + response, err := client.Do(req) + if err != nil { + loghelper.LogSlotError(slot, err).Error("Unable to query Beacon Node!") + return nil, 0, fmt.Errorf("Unable to query Beacon Node: %s", err.Error()) + } + defer response.Body.Close() + rc := response.StatusCode + body, err := ioutil.ReadAll(response.Body) + if err != nil { + loghelper.LogSlotError(slot, err).Error("Unable to turn response into a []bytes array!") + return nil, rc, fmt.Errorf("Unable to turn response into a []bytes array!: %s", err.Error()) + } + return body, rc, nil +} + // A function to query the blockroot for a given slot. func queryBlockRoot(endpoint string, slot string) (string, error) { log.WithFields(log.Fields{"endpoint": endpoint}).Debug("Querying endpoint")