package beaconclient import ( "bytes" "errors" "github.com/protolambda/zrnt/eth2/beacon/altair" "github.com/protolambda/zrnt/eth2/beacon/bellatrix" "github.com/protolambda/zrnt/eth2/beacon/common" "github.com/protolambda/zrnt/eth2/beacon/phase0" "github.com/protolambda/zrnt/eth2/configs" "github.com/protolambda/ztyp/codec" "github.com/protolambda/ztyp/tree" log "github.com/sirupsen/logrus" "strconv" ) type Eth1Data common.Eth1Data type Root common.Root type Signature common.BLSSignature type Slot uint64 type Epoch uint64 type ExecutionPayloadHeader common.ExecutionPayloadHeader func ParseSlot(v string) (Slot, error) { slotNum, err := strconv.ParseUint(v, 10, 64) return Slot(slotNum), err } func (s *Slot) Format() string { return strconv.FormatUint(uint64(*s), 10) } func (s *Slot) Number() uint64 { return uint64(*s) } func (s *Slot) Plus(v uint64) Slot { return Slot(v + s.Number()) } func (s *Slot) PlusInt(v int) Slot { return s.Plus(uint64(v)) } func (e *Epoch) Format() string { return strconv.FormatUint(uint64(*e), 10) } type BeaconBlock struct { spec *common.Spec bellatrix *bellatrix.BeaconBlock altair *altair.BeaconBlock phase0 *phase0.BeaconBlock } type BeaconBlockBody struct { spec *common.Spec bellatrix *bellatrix.BeaconBlockBody altair *altair.BeaconBlockBody phase0 *phase0.BeaconBlockBody } type BeaconState struct { spec *common.Spec bellatrix *bellatrix.BeaconState altair *altair.BeaconState phase0 *phase0.BeaconState } type SignedBeaconBlock struct { spec *common.Spec bellatrix *bellatrix.SignedBeaconBlock altair *altair.SignedBeaconBlock phase0 *phase0.SignedBeaconBlock } func (s *SignedBeaconBlock) UnmarshalSSZ(ssz []byte) error { spec := chooseSpec(s.spec) var bellatrix bellatrix.SignedBeaconBlock err := bellatrix.Deserialize(spec, makeDecodingReader(ssz)) if nil == err { s.bellatrix = &bellatrix s.altair = nil s.phase0 = nil log.Info("Unmarshalled Bellatrix SignedBeaconBlock") return nil } var altair altair.SignedBeaconBlock err = altair.Deserialize(spec, makeDecodingReader(ssz)) if nil == err { s.bellatrix = nil s.altair = &altair s.phase0 = nil log.Info("Unmarshalled Altair SignedBeaconBlock") return nil } var phase0 phase0.SignedBeaconBlock err = phase0.Deserialize(spec, makeDecodingReader(ssz)) if nil == err { s.bellatrix = nil s.altair = nil s.phase0 = &phase0 log.Info("Unmarshalled Phase0 SignedBeaconBlock") return nil } s.bellatrix = nil s.altair = nil s.phase0 = nil log.Warning("Unable to unmarshal SignedBeaconBlock") return err } func (s *SignedBeaconBlock) MarshalSSZ() ([]byte, error) { spec := chooseSpec(s.spec) var err error var buf bytes.Buffer encodingWriter := codec.NewEncodingWriter(&buf) if s.IsBellatrix() { err = s.bellatrix.Serialize(spec, encodingWriter) } if s.IsAltair() { err = s.altair.Serialize(spec, encodingWriter) } if s.IsPhase0() { err = s.phase0.Serialize(spec, encodingWriter) } if err != nil { return nil, err } return buf.Bytes(), err } func (s *SignedBeaconBlock) IsBellatrix() bool { return s.bellatrix != nil } func (s *SignedBeaconBlock) IsAltair() bool { return s.altair != nil } func (s *SignedBeaconBlock) IsPhase0() bool { return s.phase0 != nil } func (s *SignedBeaconBlock) GetBellatrix() *bellatrix.SignedBeaconBlock { return s.bellatrix } func (s *SignedBeaconBlock) GetAltair() *altair.SignedBeaconBlock { return s.altair } func (s *SignedBeaconBlock) GetPhase0() *phase0.SignedBeaconBlock { return s.phase0 } func (s *SignedBeaconBlock) Signature() Signature { if s.IsBellatrix() { return Signature(s.bellatrix.Signature) } if s.IsAltair() { return Signature(s.altair.Signature) } if s.IsPhase0() { return Signature(s.phase0.Signature) } return Signature{} } func (s *SignedBeaconBlock) Block() *BeaconBlock { if s.IsBellatrix() { return &BeaconBlock{bellatrix: &s.bellatrix.Message, spec: s.spec} } if s.IsAltair() { return &BeaconBlock{altair: &s.altair.Message, spec: s.spec} } if s.IsPhase0() { return &BeaconBlock{phase0: &s.phase0.Message, spec: s.spec} } return nil } func (b *BeaconBlock) IsBellatrix() bool { return b.bellatrix != nil } func (b *BeaconBlock) IsAltair() bool { return b.altair != nil } func (b *BeaconBlock) IsPhase0() bool { return b.phase0 != nil } func (s *BeaconBlock) GetBellatrix() *bellatrix.BeaconBlock { return s.bellatrix } func (s *BeaconBlock) GetAltair() *altair.BeaconBlock { return s.altair } func (s *BeaconBlock) GetPhase0() *phase0.BeaconBlock { return s.phase0 } func (b *BeaconBlock) ParentRoot() Root { if b.IsBellatrix() { return Root(b.bellatrix.ParentRoot) } if b.IsAltair() { return Root(b.altair.ParentRoot) } if b.IsPhase0() { return Root(b.phase0.ParentRoot) } return Root{} } func (b *BeaconBlock) StateRoot() Root { if b.IsBellatrix() { return Root(b.bellatrix.StateRoot) } if b.IsAltair() { return Root(b.altair.StateRoot) } if b.IsPhase0() { return Root(b.phase0.StateRoot) } return Root{} } func (b *BeaconBlock) Body() *BeaconBlockBody { if b.IsBellatrix() { return &BeaconBlockBody{bellatrix: &b.bellatrix.Body, spec: b.spec} } if b.IsAltair() { return &BeaconBlockBody{altair: &b.altair.Body, spec: b.spec} } if b.IsPhase0() { return &BeaconBlockBody{phase0: &b.phase0.Body, spec: b.spec} } return nil } func (b *BeaconBlockBody) IsBellatrix() bool { return b.bellatrix != nil } func (b *BeaconBlockBody) IsAltair() bool { return b.altair != nil } func (b *BeaconBlockBody) IsPhase0() bool { return b.phase0 != nil } func (b *BeaconBlockBody) Eth1Data() Eth1Data { if b.IsBellatrix() { return Eth1Data(b.bellatrix.Eth1Data) } if b.IsAltair() { return Eth1Data(b.altair.Eth1Data) } if b.IsPhase0() { return Eth1Data(b.phase0.Eth1Data) } return Eth1Data{} } func (b *BeaconBlockBody) ExecutionPayloadHeader() *ExecutionPayloadHeader { if b.IsBellatrix() { payloadHeader := b.bellatrix.ExecutionPayload.Header(chooseSpec(b.spec)) return (*ExecutionPayloadHeader)(payloadHeader) } return nil } func (b *BeaconBlock) HashTreeRoot() Root { spec := chooseSpec(b.spec) hashFn := tree.GetHashFn() if b.IsBellatrix() { return Root(b.bellatrix.HashTreeRoot(spec, hashFn)) } if b.IsAltair() { return Root(b.altair.HashTreeRoot(spec, hashFn)) } if b.IsPhase0() { return Root(b.phase0.HashTreeRoot(spec, hashFn)) } return Root{} } func (s *BeaconState) UnmarshalSSZ(ssz []byte) error { spec := chooseSpec(s.spec) var bellatrix bellatrix.BeaconState err := bellatrix.Deserialize(spec, makeDecodingReader(ssz)) if nil == err { s.bellatrix = &bellatrix s.altair = nil s.phase0 = nil log.Info("Unmarshalled Bellatrix BeaconState") return nil } var altair altair.BeaconState err = altair.Deserialize(spec, makeDecodingReader(ssz)) if nil == err { s.bellatrix = nil s.altair = &altair s.phase0 = nil log.Info("Unmarshalled Altair BeaconState") return nil } var phase0 phase0.BeaconState err = phase0.Deserialize(spec, makeDecodingReader(ssz)) if nil == err { s.bellatrix = nil s.altair = nil s.phase0 = &phase0 log.Info("Unmarshalled Phase0 BeaconState") return nil } s.bellatrix = nil s.altair = nil s.phase0 = nil log.Warning("Unable to unmarshal BeaconState") return err } func (s *BeaconState) MarshalSSZ() ([]byte, error) { spec := chooseSpec(s.spec) var err error var buf bytes.Buffer encodingWriter := codec.NewEncodingWriter(&buf) if s.IsBellatrix() { err = s.bellatrix.Serialize(spec, encodingWriter) } else if s.IsAltair() { err = s.altair.Serialize(spec, encodingWriter) } else if s.IsPhase0() { err = s.phase0.Serialize(spec, encodingWriter) } else { err = errors.New("BeaconState not set") } if nil != err { return nil, err } return buf.Bytes(), nil } func (s *BeaconState) IsBellatrix() bool { return s.bellatrix != nil } func (s *BeaconState) IsAltair() bool { return s.altair != nil } func (s *BeaconState) IsPhase0() bool { return s.phase0 != nil } func (s *BeaconState) HashTreeRoot() Root { spec := chooseSpec(s.spec) hashFn := tree.GetHashFn() if s.IsBellatrix() { return Root(s.bellatrix.HashTreeRoot(spec, hashFn)) } if s.IsAltair() { return Root(s.altair.HashTreeRoot(spec, hashFn)) } if s.IsPhase0() { return Root(s.phase0.HashTreeRoot(spec, hashFn)) } return Root{} } func (s *BeaconState) GetBellatrix() *bellatrix.BeaconState { return s.bellatrix } func (s *BeaconState) GetAltair() *altair.BeaconState { return s.altair } func (s *BeaconState) GetPhase0() *phase0.BeaconState { return s.phase0 } func chooseSpec(spec *common.Spec) *common.Spec { if nil == spec { return configs.Mainnet } return spec } func makeDecodingReader(ssz []byte) *codec.DecodingReader { return codec.NewDecodingReader(bytes.NewReader(ssz), uint64(len(ssz))) }