diff --git a/access/grpc/convert/convert.go b/access/grpc/convert/convert.go index 683108b1d..ea8a1eaa6 100644 --- a/access/grpc/convert/convert.go +++ b/access/grpc/convert/convert.go @@ -166,8 +166,11 @@ func MessageToAccountKeys(m []*entities.AccountKey) ([]flow.AccountKey, error) { } func BlockToMessage(b flow.Block) (*entities.Block, error) { - t := timestamppb.New(b.BlockHeader.Timestamp) + header, err := BlockHeaderToMessage(b.BlockHeader) + if err != nil { + return nil, err + } return &entities.Block{ Id: b.BlockHeader.ID.Bytes(), @@ -176,6 +179,7 @@ func BlockToMessage(b flow.Block) (*entities.Block, error) { Timestamp: t, CollectionGuarantees: CollectionGuaranteesToMessages(b.BlockPayload.CollectionGuarantees), BlockSeals: BlockSealsToMessages(b.BlockPayload.Seals), + BlockHeader: header, }, nil } @@ -187,11 +191,25 @@ func MessageToBlock(m *entities.Block) (flow.Block, error) { timestamp = m.GetTimestamp().AsTime() } + tc, err := MessageToTimeoutCertificate(m.BlockHeader.GetLastViewTc()) + if err != nil { + return flow.Block{}, err + } + header := &flow.BlockHeader{ - ID: flow.HashToID(m.GetId()), - ParentID: flow.HashToID(m.GetParentId()), - Height: m.GetHeight(), - Timestamp: timestamp, + ID: flow.HashToID(m.GetId()), + ParentID: flow.HashToID(m.GetParentId()), + Height: m.GetHeight(), + Timestamp: timestamp, + PayloadHash: m.BlockHeader.GetPayloadHash(), + View: m.BlockHeader.GetView(), + ParentVoterSigData: m.BlockHeader.GetParentVoterSigData(), + ProposerID: flow.HashToID(m.BlockHeader.GetProposerId()), + ProposerSigData: m.BlockHeader.GetProposerSigData(), + ChainID: flow.HashToID([]byte(m.BlockHeader.GetChainId())), + ParentVoterIndices: m.BlockHeader.GetParentVoterIndices(), + LastViewTimeoutCertificate: tc, + ParentView: m.BlockHeader.GetParentView(), } guarantees, err := MessagesToCollectionGuarantees(m.GetCollectionGuarantees()) @@ -217,12 +235,25 @@ func MessageToBlock(m *entities.Block) (flow.Block, error) { func BlockHeaderToMessage(b flow.BlockHeader) (*entities.BlockHeader, error) { t := timestamppb.New(b.Timestamp) + tc, err := TimeoutCertificateToMessage(b.LastViewTimeoutCertificate) + if err != nil { + return nil, err + } return &entities.BlockHeader{ - Id: b.ID.Bytes(), - ParentId: b.ParentID.Bytes(), - Height: b.Height, - Timestamp: t, + Id: b.ID.Bytes(), + ParentId: b.ParentID.Bytes(), + Height: b.Height, + Timestamp: t, + PayloadHash: b.PayloadHash, + View: b.View, + ParentVoterSigData: b.ParentVoterSigData, + ProposerId: b.ProposerID.Bytes(), + ProposerSigData: b.ProposerSigData, + ChainId: string(b.ChainID.Bytes()), + ParentVoterIndices: b.ParentVoterIndices, + LastViewTc: tc, + ParentView: b.ParentView, }, nil } @@ -237,11 +268,81 @@ func MessageToBlockHeader(m *entities.BlockHeader) (flow.BlockHeader, error) { timestamp = m.GetTimestamp().AsTime() } + tc, err := MessageToTimeoutCertificate(m.GetLastViewTc()) + if err != nil { + return flow.BlockHeader{}, err + } + return flow.BlockHeader{ - ID: flow.HashToID(m.GetId()), - ParentID: flow.HashToID(m.GetParentId()), - Height: m.GetHeight(), - Timestamp: timestamp, + ID: flow.HashToID(m.GetId()), + ParentID: flow.HashToID(m.GetParentId()), + Height: m.GetHeight(), + Timestamp: timestamp, + PayloadHash: m.GetPayloadHash(), + View: m.GetView(), + ParentVoterSigData: m.GetParentVoterSigData(), + ProposerID: flow.HashToID(m.GetProposerId()), + ProposerSigData: m.GetProposerSigData(), + ChainID: flow.HashToID([]byte(m.GetChainId())), + ParentVoterIndices: m.GetParentVoterIndices(), + LastViewTimeoutCertificate: tc, + ParentView: m.GetParentView(), + }, nil +} + +func MessageToTimeoutCertificate(m *entities.TimeoutCertificate) (flow.TimeoutCertificate, error) { + if m == nil { + return flow.TimeoutCertificate{}, ErrEmptyMessage + } + + qc, err := MessageToQuorumCertificate(m.GetHighestQc()) + if err != nil { + return flow.TimeoutCertificate{}, err + } + + return flow.TimeoutCertificate{ + View: m.GetView(), + HighQCViews: m.GetHighQcViews(), + HighestQC: qc, + SignerIndices: m.GetSignerIndices(), + SigData: m.GetSigData(), + }, nil +} + +func TimeoutCertificateToMessage(tc flow.TimeoutCertificate) (*entities.TimeoutCertificate, error) { + qc, err := QuorumCertificateToMessage(tc.HighestQC) + if err != nil { + return nil, err + } + + return &entities.TimeoutCertificate{ + View: tc.View, + HighQcViews: tc.HighQCViews, + HighestQc: qc, + SignerIndices: tc.SignerIndices, + SigData: tc.SigData, + }, nil +} + +func MessageToQuorumCertificate(m *entities.QuorumCertificate) (flow.QuorumCertificate, error) { + if m == nil { + return flow.QuorumCertificate{}, ErrEmptyMessage + } + + return flow.QuorumCertificate{ + View: m.GetView(), + BlockID: flow.HashToID(m.GetBlockId()), + SignerIndices: m.GetSignerIndices(), + SigData: m.GetSigData(), + }, nil +} + +func QuorumCertificateToMessage(qc flow.QuorumCertificate) (*entities.QuorumCertificate, error) { + return &entities.QuorumCertificate{ + View: qc.View, + BlockId: qc.BlockID.Bytes(), + SignerIndices: qc.SignerIndices, + SigData: qc.SigData, }, nil } diff --git a/block.go b/block.go index 3b67d1748..3a27c0ad6 100644 --- a/block.go +++ b/block.go @@ -30,11 +30,35 @@ type Block struct { // BlockHeader is a summary of a full block. type BlockHeader struct { - ID Identifier - ParentID Identifier - Height uint64 - Timestamp time.Time - Status BlockStatus + ID Identifier + ParentID Identifier + Height uint64 + Timestamp time.Time + Status BlockStatus + PayloadHash []byte + View uint64 + ParentVoterSigData []byte + ProposerID Identifier + ProposerSigData []byte + ChainID Identifier + ParentVoterIndices []byte + LastViewTimeoutCertificate TimeoutCertificate + ParentView uint64 +} + +type TimeoutCertificate struct { + View uint64 + HighQCViews []uint64 + HighestQC QuorumCertificate + SignerIndices []byte + SigData []byte +} + +type QuorumCertificate struct { + View uint64 + BlockID Identifier + SignerIndices []byte + SigData []byte } // BlockStatus represents the status of a block. diff --git a/test/entities.go b/test/entities.go index c784de16b..65d25147c 100644 --- a/test/entities.go +++ b/test/entities.go @@ -166,6 +166,7 @@ type BlockHeaders struct { count int ids *Identifiers startTime time.Time + bytes *Bytes } func BlockHeaderGenerator() *BlockHeaders { @@ -175,17 +176,43 @@ func BlockHeaderGenerator() *BlockHeaders { count: 1, ids: IdentifierGenerator(), startTime: startTime.UTC(), + bytes: BytesGenerator(), } } func (g *BlockHeaders) New() flow.BlockHeader { defer func() { g.count++ }() + qc := flow.QuorumCertificate{ + View: 42, + BlockID: g.ids.New(), + SignerIndices: g.bytes.New(), + SigData: g.bytes.New(), + } + + tc := flow.TimeoutCertificate{ + View: 42, + HighQCViews: []uint64{42}, + HighestQC: qc, + SignerIndices: g.bytes.New(), + SigData: g.bytes.New(), + } + return flow.BlockHeader{ - ID: g.ids.New(), - ParentID: g.ids.New(), - Height: uint64(g.count), - Timestamp: g.startTime.Add(time.Hour * time.Duration(g.count)), + ID: g.ids.New(), + ParentID: g.ids.New(), + Height: uint64(g.count), + Timestamp: g.startTime.Add(time.Hour * time.Duration(g.count)), + Status: flow.BlockStatusUnknown, + PayloadHash: g.bytes.New(), + View: 42, + ParentVoterSigData: g.bytes.New(), + ProposerID: g.ids.New(), + ProposerSigData: g.bytes.New(), + ChainID: g.ids.New(), + ParentVoterIndices: g.bytes.New(), + LastViewTimeoutCertificate: tc, + ParentView: 42, } } @@ -604,8 +631,8 @@ func BytesGenerator() *Bytes { } } -func (b *Bytes) New() []byte { - randomBytes := make([]byte, b.count) +func (g *Bytes) New() []byte { + randomBytes := make([]byte, g.count) _, err := rand.Read(randomBytes) if err != nil { panic("failed to generate random bytes")