Use ETH1 Block To Determine Genesis State (#3911)

* use eth1Block to determine genesis state

* add proto file

* fix test

* fix test
This commit is contained in:
Nishant Das 2019-11-02 04:10:05 +08:00 committed by Raul Jordan
parent ab92326dfb
commit 103bdfc688
3 changed files with 472 additions and 57 deletions

View File

@ -33,6 +33,45 @@ func (s *Service) Eth2GenesisPowchainInfo() (uint64, *big.Int) {
return s.eth2GenesisTime, s.chainStartBlockNumber
}
// ProcessETH1Block processes the logs from the provided eth1Block.
func (s *Service) ProcessETH1Block(ctx context.Context, blkNum *big.Int) error {
query := ethereum.FilterQuery{
Addresses: []common.Address{
s.depositContractAddress,
},
FromBlock: blkNum,
ToBlock: blkNum,
}
logs, err := s.httpLogger.FilterLogs(ctx, query)
if err != nil {
return err
}
for _, log := range logs {
if err := s.ProcessLog(ctx, log); err != nil {
return errors.Wrap(err, "could not process log")
}
}
if !s.chainStarted {
blk, err := s.blockFetcher.BlockByNumber(ctx, blkNum)
if err != nil {
return errors.Wrap(err, "could not get eth1 block")
}
if blk == nil {
return errors.Wrap(err, "got empty block from powchain service")
}
if blk.Hash() == [32]byte{} {
return errors.New("got empty blockhash from powchain service")
}
timeStamp := blk.Time()
triggered := state.IsValidGenesisState(s.activeValidatorCount, timeStamp)
if triggered {
s.setGenesisTime(timeStamp)
s.ProcessChainStart(uint64(s.eth2GenesisTime), blk.Hash(), blk.Number())
}
}
return nil
}
// ProcessLog is the main method which handles the processing of all
// logs from the deposit contract on the ETH1.0 chain.
func (s *Service) ProcessLog(ctx context.Context, depositLog gethTypes.Log) error {
@ -43,24 +82,6 @@ func (s *Service) ProcessLog(ctx context.Context, depositLog gethTypes.Log) erro
if err := s.ProcessDepositLog(ctx, depositLog); err != nil {
return errors.Wrap(err, "Could not process deposit log")
}
if !s.chainStarted {
if depositLog.BlockHash == [32]byte{} {
return errors.New("got empty blockhash from powchain service")
}
blk, err := s.blockFetcher.BlockByHash(ctx, depositLog.BlockHash)
if err != nil {
return errors.Wrap(err, "could not get eth1 block")
}
if blk == nil {
return errors.Wrap(err, "got empty block from powchain service")
}
timeStamp := blk.Time()
triggered := state.IsValidGenesisState(s.activeValidatorCount, timeStamp)
if triggered {
s.setGenesisTime(timeStamp)
s.ProcessChainStart(uint64(s.eth2GenesisTime), depositLog.BlockHash, blk.Number())
}
}
return nil
}
log.WithField("signature", fmt.Sprintf("%#x", depositLog.Topics[0])).Debug("Not a valid event signature")
@ -229,17 +250,23 @@ func (s *Service) processPastLogs(ctx context.Context) error {
s.depositContractAddress,
},
}
logs, err := s.httpLogger.FilterLogs(ctx, query)
if err != nil {
return err
}
for _, log := range logs {
if err := s.ProcessLog(ctx, log); err != nil {
return errors.Wrap(err, "could not process log")
if len(logs) > 0 {
start := logs[0].BlockNumber
end := s.blockHeight.Uint64()
// Process logs from each block one by one
for i := start; i <= end; i++ {
err := s.ProcessETH1Block(ctx, big.NewInt(int64(i)))
if err != nil {
return err
}
}
}
s.lastRequestedBlock.Set(s.blockHeight)
currentState, err := s.beaconDB.HeadState(ctx)
@ -260,24 +287,10 @@ func (s *Service) requestBatchedLogs(ctx context.Context) error {
// We request for the nth block behind the current head, in order to have
// stabilized logs when we retrieve it from the 1.0 chain.
requestedBlock := big.NewInt(0).Sub(s.blockHeight, big.NewInt(params.BeaconConfig().LogBlockDelay))
query := ethereum.FilterQuery{
Addresses: []common.Address{
s.depositContractAddress,
},
FromBlock: s.lastRequestedBlock.Add(s.lastRequestedBlock, big.NewInt(1)),
ToBlock: requestedBlock,
}
logs, err := s.httpLogger.FilterLogs(ctx, query)
if err != nil {
return err
}
// Only process log slices which are larger than zero.
if len(logs) > 0 {
for _, log := range logs {
if err := s.ProcessLog(ctx, log); err != nil {
return errors.Wrap(err, "could not process log")
}
for i := s.lastRequestedBlock.Uint64() + 1; i <= requestedBlock.Uint64(); i++ {
err := s.ProcessETH1Block(ctx, big.NewInt(int64(i)))
if err != nil {
return err
}
}
@ -290,24 +303,11 @@ func (s *Service) requestBatchedLogs(ctx context.Context) error {
func (s *Service) requestMissingLogs(ctx context.Context, blkNumber uint64, wantedIndex int64) error {
// We request from the last requested block till the current block(exclusive)
beforeCurrentBlk := big.NewInt(int64(blkNumber) - 1)
query := ethereum.FilterQuery{
Addresses: []common.Address{
s.depositContractAddress,
},
FromBlock: big.NewInt(0).Add(s.lastRequestedBlock, big.NewInt(1)),
ToBlock: beforeCurrentBlk,
}
logs, err := s.httpLogger.FilterLogs(ctx, query)
if err != nil {
return err
}
// Only process log slices which are larger than zero.
if len(logs) > 0 {
for _, log := range logs {
if err := s.ProcessLog(ctx, log); err != nil {
return errors.Wrap(err, "could not process log")
}
for i := s.lastRequestedBlock.Uint64() + 1; i <= beforeCurrentBlk.Uint64(); i++ {
err := s.ProcessETH1Block(ctx, big.NewInt(int64(i)))
if err != nil {
return err
}
}

View File

@ -346,6 +346,11 @@ func TestProcessETH2GenesisLog(t *testing.T) {
web3Service.ProcessLog(context.Background(), log)
}
err = web3Service.ProcessETH1Block(context.Background(), big.NewInt(int64(logs[len(logs)-1].BlockNumber)))
if err != nil {
t.Fatal(err)
}
cachedDeposits := web3Service.ChainStartDeposits()
if len(cachedDeposits) != depositsReqForChainStart {
t.Errorf(

View File

@ -0,0 +1,410 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: proto/beacon/db/finalized_block_root_container.proto
package db
import (
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
type FinalizedBlockRootContainer struct {
ParentRoot []byte `protobuf:"bytes,1,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty"`
ChildRoot []byte `protobuf:"bytes,2,opt,name=child_root,json=childRoot,proto3" json:"child_root,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *FinalizedBlockRootContainer) Reset() { *m = FinalizedBlockRootContainer{} }
func (m *FinalizedBlockRootContainer) String() string { return proto.CompactTextString(m) }
func (*FinalizedBlockRootContainer) ProtoMessage() {}
func (*FinalizedBlockRootContainer) Descriptor() ([]byte, []int) {
return fileDescriptor_f952363f5bc83b7b, []int{0}
}
func (m *FinalizedBlockRootContainer) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *FinalizedBlockRootContainer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_FinalizedBlockRootContainer.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalTo(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *FinalizedBlockRootContainer) XXX_Merge(src proto.Message) {
xxx_messageInfo_FinalizedBlockRootContainer.Merge(m, src)
}
func (m *FinalizedBlockRootContainer) XXX_Size() int {
return m.Size()
}
func (m *FinalizedBlockRootContainer) XXX_DiscardUnknown() {
xxx_messageInfo_FinalizedBlockRootContainer.DiscardUnknown(m)
}
var xxx_messageInfo_FinalizedBlockRootContainer proto.InternalMessageInfo
func (m *FinalizedBlockRootContainer) GetParentRoot() []byte {
if m != nil {
return m.ParentRoot
}
return nil
}
func (m *FinalizedBlockRootContainer) GetChildRoot() []byte {
if m != nil {
return m.ChildRoot
}
return nil
}
func init() {
proto.RegisterType((*FinalizedBlockRootContainer)(nil), "prysm.beacon.db.FinalizedBlockRootContainer")
}
func init() {
proto.RegisterFile("proto/beacon/db/finalized_block_root_container.proto", fileDescriptor_f952363f5bc83b7b)
}
var fileDescriptor_f952363f5bc83b7b = []byte{
// 196 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x32, 0x29, 0x28, 0xca, 0x2f,
0xc9, 0xd7, 0x4f, 0x4a, 0x4d, 0x4c, 0xce, 0xcf, 0xd3, 0x4f, 0x49, 0xd2, 0x4f, 0xcb, 0xcc, 0x4b,
0xcc, 0xc9, 0xac, 0x4a, 0x4d, 0x89, 0x4f, 0xca, 0xc9, 0x4f, 0xce, 0x8e, 0x2f, 0xca, 0xcf, 0x2f,
0x89, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d, 0xd2, 0x03, 0x2b, 0x17, 0xe2, 0x2f,
0x28, 0xaa, 0x2c, 0xce, 0xd5, 0x83, 0xe8, 0xd2, 0x4b, 0x49, 0x52, 0x8a, 0xe5, 0x92, 0x76, 0x83,
0x69, 0x74, 0x02, 0xe9, 0x0b, 0xca, 0xcf, 0x2f, 0x71, 0x86, 0xe9, 0x12, 0x92, 0xe7, 0xe2, 0x2e,
0x48, 0x2c, 0x4a, 0xcd, 0x2b, 0x01, 0x1b, 0x27, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0x13, 0xc4, 0x05,
0x11, 0x02, 0xa9, 0x14, 0x92, 0xe5, 0xe2, 0x4a, 0xce, 0xc8, 0xcc, 0x49, 0x81, 0xc8, 0x33, 0x81,
0xe5, 0x39, 0xc1, 0x22, 0x20, 0x69, 0x27, 0x9b, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63,
0x7c, 0xf0, 0x48, 0x8e, 0x31, 0x4a, 0x2f, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f,
0x57, 0x1f, 0xec, 0x90, 0xc4, 0x92, 0xcc, 0xe4, 0x9c, 0xc4, 0xa4, 0x62, 0x08, 0x4f, 0x1f, 0xcd,
0x4b, 0x49, 0x6c, 0x60, 0x01, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xd3, 0xda, 0x04,
0xec, 0x00, 0x00, 0x00,
}
func (m *FinalizedBlockRootContainer) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *FinalizedBlockRootContainer) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if len(m.ParentRoot) > 0 {
dAtA[i] = 0xa
i++
i = encodeVarintFinalizedBlockRootContainer(dAtA, i, uint64(len(m.ParentRoot)))
i += copy(dAtA[i:], m.ParentRoot)
}
if len(m.ChildRoot) > 0 {
dAtA[i] = 0x12
i++
i = encodeVarintFinalizedBlockRootContainer(dAtA, i, uint64(len(m.ChildRoot)))
i += copy(dAtA[i:], m.ChildRoot)
}
if m.XXX_unrecognized != nil {
i += copy(dAtA[i:], m.XXX_unrecognized)
}
return i, nil
}
func encodeVarintFinalizedBlockRootContainer(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return offset + 1
}
func (m *FinalizedBlockRootContainer) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.ParentRoot)
if l > 0 {
n += 1 + l + sovFinalizedBlockRootContainer(uint64(l))
}
l = len(m.ChildRoot)
if l > 0 {
n += 1 + l + sovFinalizedBlockRootContainer(uint64(l))
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func sovFinalizedBlockRootContainer(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
}
func sozFinalizedBlockRootContainer(x uint64) (n int) {
return sovFinalizedBlockRootContainer(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *FinalizedBlockRootContainer) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowFinalizedBlockRootContainer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: FinalizedBlockRootContainer: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: FinalizedBlockRootContainer: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ParentRoot", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowFinalizedBlockRootContainer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthFinalizedBlockRootContainer
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthFinalizedBlockRootContainer
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ParentRoot = append(m.ParentRoot[:0], dAtA[iNdEx:postIndex]...)
if m.ParentRoot == nil {
m.ParentRoot = []byte{}
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ChildRoot", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowFinalizedBlockRootContainer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthFinalizedBlockRootContainer
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthFinalizedBlockRootContainer
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ChildRoot = append(m.ChildRoot[:0], dAtA[iNdEx:postIndex]...)
if m.ChildRoot == nil {
m.ChildRoot = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipFinalizedBlockRootContainer(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthFinalizedBlockRootContainer
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthFinalizedBlockRootContainer
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipFinalizedBlockRootContainer(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowFinalizedBlockRootContainer
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowFinalizedBlockRootContainer
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
return iNdEx, nil
case 1:
iNdEx += 8
return iNdEx, nil
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowFinalizedBlockRootContainer
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthFinalizedBlockRootContainer
}
iNdEx += length
if iNdEx < 0 {
return 0, ErrInvalidLengthFinalizedBlockRootContainer
}
return iNdEx, nil
case 3:
for {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowFinalizedBlockRootContainer
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
innerWire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
innerWireType := int(innerWire & 0x7)
if innerWireType == 4 {
break
}
next, err := skipFinalizedBlockRootContainer(dAtA[start:])
if err != nil {
return 0, err
}
iNdEx = start + next
if iNdEx < 0 {
return 0, ErrInvalidLengthFinalizedBlockRootContainer
}
}
return iNdEx, nil
case 4:
return iNdEx, nil
case 5:
iNdEx += 4
return iNdEx, nil
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
}
panic("unreachable")
}
var (
ErrInvalidLengthFinalizedBlockRootContainer = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowFinalizedBlockRootContainer = fmt.Errorf("proto: integer overflow")
)