76: Add indexing of ExecutionPayloads (and other Merge-related updates). #73
@ -20,6 +20,7 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
consensus "github.com/umbracle/go-eth-consensus"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -29,11 +30,6 @@ import (
|
|||||||
|
|
||||||
"github.com/jarcoal/httpmock"
|
"github.com/jarcoal/httpmock"
|
||||||
. "github.com/onsi/ginkgo/v2"
|
. "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"
|
"github.com/r3labs/sse"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
@ -49,10 +45,10 @@ var (
|
|||||||
port int = 8080
|
port int = 8080
|
||||||
protocol string = "http"
|
protocol string = "http"
|
||||||
dbHost string = "localhost"
|
dbHost string = "localhost"
|
||||||
dbPort int = 8076
|
dbPort int = 15432
|
||||||
dbName string = "vulcanize_testing"
|
dbName string = "postgres"
|
||||||
dbUser string = "vdbm"
|
dbUser string = "postgres"
|
||||||
dbPassword string = "password"
|
dbPassword string = "secret12"
|
||||||
dbDriver string = "pgx"
|
dbDriver string = "pgx"
|
||||||
bcUniqueIdentifier int = 100
|
bcUniqueIdentifier int = 100
|
||||||
dummyParentRoot string = "46f98c08b54a71dfda4d56e29ec3952b8300cd8d6b67a9b6c562ae96a7a25a42"
|
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() {
|
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"])
|
testSszRoot(BeaconNodeTester.TestEvents["100"])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
Context("Altair: We have a correctly formated SSZ SignedBeaconBlock and BeaconState", func() {
|
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"])
|
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) {
|
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;`
|
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 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)
|
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())
|
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.
|
// 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) {
|
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;`
|
sqlStatement := `SELECT slot, state_root, mh_key FROM eth_beacon.state WHERE slot=$1 AND state_root=$2;`
|
||||||
var slot int
|
var slot int
|
||||||
var stateRoot, mh_key string
|
var stateRoot, mhKey string
|
||||||
row := db.QueryRow(context.Background(), sqlStatement, querySlot, queryStateRoot)
|
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())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
return slot, stateRoot, mh_key
|
return slot, stateRoot, mhKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count the entries in the knownGaps table.
|
// 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.
|
// 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.
|
// 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)
|
dat, err := os.ReadFile(slotFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Can't find the slot file, %s", slotFile)
|
return nil, fmt.Errorf("Can't find the slot file, %s", slotFile)
|
||||||
}
|
}
|
||||||
block := &st.SignedBeaconBlock{}
|
var block beaconclient.SignedBeaconBlock
|
||||||
err = block.UnmarshalSSZ(dat)
|
err = block.UnmarshalSSZ(dat)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
return block, nil
|
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
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a file with the BeaconState in SSZ and return the SSZ object
|
// 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)
|
dat, err := os.ReadFile(slotFile)
|
||||||
if err != nil {
|
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())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
state, err := versionedUnmarshaler.UnmarshalBeaconState(dat)
|
return &beaconState, nil
|
||||||
Expect(err).ToNot(HaveOccurred())
|
|
||||||
return state, versionedUnmarshaler, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// An object that is used to aggregate test functions. Test functions are needed because we need to
|
// 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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Expect(block.IsPhase0()).To(BeTrue())
|
||||||
|
var phase0 = block.GetPhase0()
|
||||||
|
|
||||||
slot, err := strconv.ParseUint(Message.HeadMessage.Slot, 10, 64)
|
slot, err := strconv.ParseUint(Message.HeadMessage.Slot, 10, 64)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
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())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
if Message.MimicConfig.ParentRoot == "" {
|
if Message.MimicConfig.ParentRoot == "" {
|
||||||
block.Block.ParentRoot, err = hex.DecodeString(dummyParentRoot)
|
phase0.Block.ParentRoot, err = decodeRoot(dummyParentRoot)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
} else {
|
} else {
|
||||||
block.Block.ParentRoot, err = hex.DecodeString(Message.MimicConfig.ParentRoot)
|
phase0.Block.ParentRoot, err = decodeRoot(Message.MimicConfig.ParentRoot)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
}
|
}
|
||||||
return block.MarshalSSZ()
|
return block.MarshalSSZ()
|
||||||
case "altair":
|
case "altair":
|
||||||
block, err := readSignedBeaconBlockAltair(slotFile)
|
block, err := readSignedBeaconBlock(slotFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Expect(block.IsAltair()).To(BeTrue())
|
||||||
|
var altair = block.GetAltair()
|
||||||
slot, err := strconv.ParseUint(Message.HeadMessage.Slot, 10, 64)
|
slot, err := strconv.ParseUint(Message.HeadMessage.Slot, 10, 64)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
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())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
if Message.MimicConfig.ParentRoot == "" {
|
if Message.MimicConfig.ParentRoot == "" {
|
||||||
block.Block.ParentRoot, err = hex.DecodeString(dummyParentRoot)
|
altair.Block.ParentRoot, err = decodeRoot(dummyParentRoot)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
} else {
|
} else {
|
||||||
block.Block.ParentRoot, err = hex.DecodeString(Message.MimicConfig.ParentRoot)
|
altair.Block.ParentRoot, err = decodeRoot(Message.MimicConfig.ParentRoot)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
}
|
}
|
||||||
return block.MarshalSSZ()
|
return block.MarshalSSZ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if sszIdentifier == "state" {
|
if sszIdentifier == "state" {
|
||||||
state, _, err := readBeaconState(slotFile)
|
state, err := readBeaconState(slotFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
slot, err := strconv.ParseUint(Message.HeadMessage.Slot, 10, 64)
|
slot, err := strconv.ParseUint(Message.HeadMessage.Slot, 10, 64)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
err = state.SetSlot(types.Slot(slot))
|
if state.IsBellatrix() {
|
||||||
Expect(err).ToNot(HaveOccurred())
|
state.GetBellatrix().Slot = slot
|
||||||
|
} else if state.IsAltair() {
|
||||||
|
state.GetAltair().Slot = slot
|
||||||
|
} else {
|
||||||
|
state.GetPhase0().Slot = slot
|
||||||
|
}
|
||||||
return state.MarshalSSZ()
|
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.
|
// This function will make sure we are properly able to get the SszRoot of the SignedBeaconBlock and the BeaconState.
|
||||||
func testSszRoot(msg Message) {
|
func testSszRoot(msg Message) {
|
||||||
state, vm, err := readBeaconState(msg.BeaconState)
|
state, err := readBeaconState(msg.BeaconState)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
stateRoot, err := state.HashTreeRoot(context.Background())
|
stateRoot, err := state.HashTreeRoot()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(msg.HeadMessage.State).To(Equal("0x" + hex.EncodeToString(stateRoot[:])))
|
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())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
blockRoot, err := block.Block().HashTreeRoot()
|
blockRoot, err := block.Block().HashTreeRoot()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(msg.HeadMessage.Block).To(Equal("0x" + hex.EncodeToString(blockRoot[:])))
|
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
|
||||||
|
}
|
||||||
|
366
pkg/beaconclient/consensus.go
Normal file
366
pkg/beaconclient/consensus.go
Normal file
@ -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
|
||||||
|
}
|
@ -24,8 +24,6 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
consensus "github.com/umbracle/go-eth-consensus"
|
consensus "github.com/umbracle/go-eth-consensus"
|
||||||
"github.com/umbracle/go-eth-consensus/http"
|
|
||||||
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -54,10 +52,10 @@ type ProcessSlot struct {
|
|||||||
// BeaconBlock
|
// BeaconBlock
|
||||||
|
|
||||||
SszSignedBeaconBlock []byte // The entire SSZ encoded SignedBeaconBlock
|
SszSignedBeaconBlock []byte // The entire SSZ encoded SignedBeaconBlock
|
||||||
FullSignedBeaconBlock consensus.SignedBeaconBlockBellatrix // The unmarshaled BeaconState object, the unmarshalling could have errors.
|
FullSignedBeaconBlock SignedBeaconBlock // The unmarshaled BeaconState object, the unmarshalling could have errors.
|
||||||
|
|
||||||
// BeaconState
|
// BeaconState
|
||||||
FullBeaconState consensus.BeaconStateBellatrix // The unmarshaled BeaconState object, the unmarshalling could have errors.
|
FullBeaconState BeaconState // The unmarshaled BeaconState object, the unmarshalling could have errors.
|
||||||
SszBeaconState []byte // The entire SSZ encoded BeaconState
|
SszBeaconState []byte // The entire SSZ encoded BeaconState
|
||||||
|
|
||||||
// DB Write objects
|
// DB Write objects
|
||||||
@ -247,19 +245,24 @@ func (ps *ProcessSlot) getSignedBeaconBlock(serverAddress string) error {
|
|||||||
} else {
|
} else {
|
||||||
blockIdentifier = strconv.Itoa(ps.Slot)
|
blockIdentifier = strconv.Itoa(ps.Slot)
|
||||||
}
|
}
|
||||||
client := http.New(serverAddress)
|
|
||||||
|
|
||||||
var signedBeaconBlock consensus.SignedBeaconBlockBellatrix
|
blockEndpoint := serverAddress + BcBlockQueryEndpoint + blockIdentifier
|
||||||
err := client.Get(BcBlockQueryEndpoint+blockIdentifier, &signedBeaconBlock)
|
sszSignedBeaconBlock, rc, err := querySsz(blockEndpoint, strconv.Itoa(ps.Slot))
|
||||||
if err != nil {
|
|
||||||
|
if err != nil || rc != 200 {
|
||||||
loghelper.LogSlotError(strconv.Itoa(ps.Slot), err).Error("Unable to properly query the slot.")
|
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 {
|
if err != nil {
|
||||||
loghelper.LogSlotError(strconv.Itoa(ps.Slot), err).Error("Unable to marshal SignedBeaconBlock to SSZ.")
|
loghelper.LogSlotError(strconv.Itoa(ps.Slot), err).Error("Unable to unmarshal SignedBeaconBlock for slot.")
|
||||||
ps.FullSignedBeaconBlock = consensus.SignedBeaconBlockBellatrix{}
|
ps.FullSignedBeaconBlock = SignedBeaconBlock{}
|
||||||
ps.SszSignedBeaconBlock = []byte{}
|
ps.SszSignedBeaconBlock = []byte{}
|
||||||
ps.ParentBlockRoot = ""
|
ps.ParentBlockRoot = ""
|
||||||
ps.Status = "skipped"
|
ps.Status = "skipped"
|
||||||
@ -269,7 +272,7 @@ func (ps *ProcessSlot) getSignedBeaconBlock(serverAddress string) error {
|
|||||||
ps.FullSignedBeaconBlock = signedBeaconBlock
|
ps.FullSignedBeaconBlock = signedBeaconBlock
|
||||||
ps.SszSignedBeaconBlock = sszSignedBeaconBlock
|
ps.SszSignedBeaconBlock = sszSignedBeaconBlock
|
||||||
|
|
||||||
ps.ParentBlockRoot = rootToHex(&ps.FullSignedBeaconBlock.Block.ParentRoot)
|
ps.ParentBlockRoot = rootToHex(ps.FullSignedBeaconBlock.Block().ParentRoot())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,18 +284,18 @@ func (ps *ProcessSlot) getBeaconState(serverEndpoint string) error {
|
|||||||
} else {
|
} else {
|
||||||
stateIdentifier = strconv.Itoa(ps.Slot)
|
stateIdentifier = strconv.Itoa(ps.Slot)
|
||||||
}
|
}
|
||||||
client := http.New(serverEndpoint)
|
|
||||||
|
|
||||||
var beaconState consensus.BeaconStateBellatrix
|
stateEndpoint := serverEndpoint + BcStateQueryEndpoint + stateIdentifier
|
||||||
err := client.Get(BcStateQueryEndpoint+stateIdentifier, &beaconState)
|
sszBeaconState, _, err := querySsz(stateEndpoint, strconv.Itoa(ps.Slot))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
loghelper.LogSlotError(strconv.Itoa(ps.Slot), err).Error("Unable to properly query the BeaconState.")
|
loghelper.LogSlotError(strconv.Itoa(ps.Slot), err).Error("Unable to properly query the BeaconState.")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
sszBeaconState, err := beaconState.MarshalSSZ()
|
var beaconState BeaconState
|
||||||
|
err = beaconState.UnmarshalSSZ(sszBeaconState)
|
||||||
if err != nil {
|
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
|
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.
|
// 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) {
|
func (ps *ProcessSlot) checkPreviousSlot(tx sql.Tx, ctx context.Context, previousSlot int, previousBlockRoot string, knownGapsTableIncrement int) {
|
||||||
parentRoot := rootToHex(&ps.FullSignedBeaconBlock.Block.ParentRoot)
|
parentRoot := rootToHex(ps.FullSignedBeaconBlock.Block().ParentRoot())
|
||||||
slot := int(ps.FullBeaconState.Slot)
|
slot := int(ps.FullBeaconState.Slot())
|
||||||
if previousSlot == slot {
|
if previousSlot == slot {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"slot": slot,
|
"slot": slot,
|
||||||
@ -366,21 +369,21 @@ func (ps *ProcessSlot) provideFinalHash() (string, string, string, error) {
|
|||||||
if ps.StateRoot != "" {
|
if ps.StateRoot != "" {
|
||||||
stateRoot = ps.StateRoot
|
stateRoot = ps.StateRoot
|
||||||
} else {
|
} else {
|
||||||
stateRoot = rootToHex(&ps.FullSignedBeaconBlock.Block.StateRoot)
|
stateRoot = rootToHex(ps.FullSignedBeaconBlock.Block().StateRoot())
|
||||||
log.Debug("StateRoot: ", stateRoot)
|
log.Debug("StateRoot: ", stateRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ps.BlockRoot != "" {
|
if ps.BlockRoot != "" {
|
||||||
blockRoot = ps.BlockRoot
|
blockRoot = ps.BlockRoot
|
||||||
} else {
|
} else {
|
||||||
rawBlockRoot, err := ps.FullSignedBeaconBlock.Block.HashTreeRoot()
|
rawBlockRoot, err := ps.FullSignedBeaconBlock.Block().HashTreeRoot()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", "", err
|
return "", "", "", err
|
||||||
}
|
}
|
||||||
blockRoot = byteArrayToHex(&rawBlockRoot)
|
blockRoot = byteArrayToHex(&rawBlockRoot)
|
||||||
log.WithFields(log.Fields{"blockRoot": blockRoot}).Debug("Block Root from ssz")
|
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
|
return blockRoot, stateRoot, eth1BlockHash, nil
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,31 @@ type BlockRootMessage struct {
|
|||||||
Root string `json:"root"`
|
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.
|
// A function to query the blockroot for a given slot.
|
||||||
func queryBlockRoot(endpoint string, slot string) (string, error) {
|
func queryBlockRoot(endpoint string, slot string) (string, error) {
|
||||||
log.WithFields(log.Fields{"endpoint": endpoint}).Debug("Querying endpoint")
|
log.WithFields(log.Fields{"endpoint": endpoint}).Debug("Querying endpoint")
|
||||||
|
Loading…
Reference in New Issue
Block a user