mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-10 22:13:47 +00:00
feat: find epoch accumulator by epoch hash
This commit is contained in:
parent
577a61c863
commit
d6b4e9393a
3 changed files with 125 additions and 1 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
package history
|
package history
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
@ -200,6 +201,15 @@ func (f MasterAccumulator) VerifyHeader(header types.Header, headerProof BlockHe
|
||||||
return false, nil
|
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 {
|
func MixInLength(root [32]byte, length uint64) []byte {
|
||||||
hash := ssz.NewHasher()
|
hash := ssz.NewHasher()
|
||||||
hash.AppendBytes32(root[:])
|
hash.AppendBytes32(root[:])
|
||||||
|
|
|
||||||
|
|
@ -215,6 +215,44 @@ func (h *HistoryNetwork) GetReceipts(blockHash []byte) ([]*types.Receipt, error)
|
||||||
return nil, storage.ErrContentNotFound
|
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) {
|
func (h *HistoryNetwork) verifyHeader(header *types.Header, proof BlockHeaderProof) (bool, error) {
|
||||||
return h.masterAccumulator.VerifyHeader(*header, proof)
|
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())
|
_, err = ValidatePortalReceiptsBytes(content, header.ReceiptHash.Bytes())
|
||||||
return err
|
return err
|
||||||
case EpochAccumulatorType:
|
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")
|
return errors.New("unknown content type")
|
||||||
}
|
}
|
||||||
|
|
@ -501,3 +556,9 @@ func DecodeBlockHeaderWithProof(content []byte) (*BlockHeaderWithProof, error) {
|
||||||
err := headerWithProof.UnmarshalSSZ(content)
|
err := headerWithProof.UnmarshalSSZ(content)
|
||||||
return headerWithProof, err
|
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
Loading…
Reference in a new issue