feat: find epoch accumulator by epoch hash

This commit is contained in:
fearlessfe 2024-01-20 19:49:53 +08:00 committed by Chen Kai
parent 577a61c863
commit d6b4e9393a
3 changed files with 125 additions and 1 deletions

View file

@ -1,6 +1,7 @@
package history
import (
"bytes"
_ "embed"
"encoding/binary"
"errors"
@ -200,6 +201,15 @@ func (f MasterAccumulator) VerifyHeader(header types.Header, headerProof BlockHe
return false, nil
}
func (f MasterAccumulator) Contains(epochHash []byte) bool {
for _, h := range f.HistoricalEpochs {
if bytes.Equal(h, epochHash) {
return true
}
}
return false
}
func MixInLength(root [32]byte, length uint64) []byte {
hash := ssz.NewHasher()
hash.AppendBytes32(root[:])

View file

@ -215,6 +215,44 @@ func (h *HistoryNetwork) GetReceipts(blockHash []byte) ([]*types.Receipt, error)
return nil, storage.ErrContentNotFound
}
func (h *HistoryNetwork) GetEpochAccumulator(epochHash []byte) (*EpochAccumulator, error) {
contentKey := newContentKey(EpochAccumulatorType, epochHash).encode()
contentId := h.portalProtocol.ToContentId(contentKey)
res, err := h.portalProtocol.Get(contentId)
// other error
if err != nil && err != storage.ErrContentNotFound {
return nil, err
}
// no error
if err == nil {
epochAccu, err := decodeEpochAccumulator(res)
return epochAccu, err
}
for retries := 0; retries < requestRetries; retries++ {
content, err := h.portalProtocol.ContentLookup(contentKey)
if err != nil {
continue
}
epochAccu, err := decodeEpochAccumulator(content)
if err != nil {
continue
}
hash, err := epochAccu.HashTreeRoot()
if err != nil {
continue
}
mixHash := MixInLength(hash, epochSize)
if !bytes.Equal(mixHash, epochHash) {
continue
}
// TODO handle the error
_ = h.portalProtocol.Put(contentId, content)
return epochAccu, nil
}
return nil, storage.ErrContentNotFound
}
func (h *HistoryNetwork) verifyHeader(header *types.Header, proof BlockHeaderProof) (bool, error) {
return h.masterAccumulator.VerifyHeader(*header, proof)
}
@ -462,7 +500,24 @@ func (h *HistoryNetwork) validateContent(contentKey []byte, content []byte) erro
_, err = ValidatePortalReceiptsBytes(content, header.ReceiptHash.Bytes())
return err
case EpochAccumulatorType:
// TODO
if !h.masterAccumulator.Contains(contentKey[1:]) {
return errors.New("epoch hash is not existed")
}
epochAcc, err := decodeEpochAccumulator(content)
if err != nil {
return err
}
hash, err := epochAcc.HashTreeRoot()
if err != nil {
return err
}
epochHash := MixInLength(hash, epochSize)
if !bytes.Equal(contentKey[1:], epochHash) {
return errors.New("epoch accumulator has invalid root hash")
}
return nil
}
return errors.New("unknown content type")
}
@ -501,3 +556,9 @@ func DecodeBlockHeaderWithProof(content []byte) (*BlockHeaderWithProof, error) {
err := headerWithProof.UnmarshalSSZ(content)
return headerWithProof, err
}
func decodeEpochAccumulator(data []byte) (*EpochAccumulator, error) {
epochAccu := new(EpochAccumulator)
err := epochAccu.UnmarshalSSZ(data)
return epochAccu, err
}

File diff suppressed because one or more lines are too long