diff --git a/blockchain/block/block.go b/blockchain/block/block.go index 7131186157..f1df44f549 100644 --- a/blockchain/block/block.go +++ b/blockchain/block/block.go @@ -8,6 +8,7 @@ package block import ( "time" + "github.com/ethereum/go-ethereum/core/types" "github.com/iotexproject/go-pkgs/hash" "github.com/iotexproject/iotex-proto/golang/iotextypes" "github.com/pkg/errors" @@ -120,3 +121,33 @@ func (b *Block) HasBlob() bool { } return false } + +func (b *Block) WithBlobSidecars(sidecars []*types.BlobTxSidecar, txhash []string, deser *action.Deserializer) (*Block, error) { + scMap := make(map[hash.Hash256]*types.BlobTxSidecar) + for i := range txhash { + h, err := hash.HexStringToHash256(txhash[i]) + if err != nil { + return nil, err + } + scMap[h] = sidecars[i] + } + for i, act := range b.Actions { + h, _ := act.Hash() + if sc, ok := scMap[h]; ok { + // add the sidecar to this action + pb := act.Proto() + blobData := pb.GetCore().GetBlobTxData() + if blobData == nil { + // this is not a blob tx, something's wrong + return nil, errors.Wrap(action.ErrInvalidAct, "tx is not blob type") + } + blobData.BlobTxSidecar = action.ToProtoSideCar(sc) + actWithBlob, err := deser.ActionToSealedEnvelope(pb) + if err != nil { + return nil, err + } + b.Actions[i] = actWithBlob + } + } + return b, nil +} diff --git a/blockchain/blockdao/blockdao.go b/blockchain/blockdao/blockdao.go index 842d252f08..60a900c802 100644 --- a/blockchain/blockdao/blockdao.go +++ b/blockchain/blockdao/blockdao.go @@ -19,6 +19,7 @@ import ( "github.com/iotexproject/iotex-core/action" "github.com/iotexproject/iotex-core/blockchain/block" + "github.com/iotexproject/iotex-core/db" "github.com/iotexproject/iotex-core/pkg/lifecycle" "github.com/iotexproject/iotex-core/pkg/log" "github.com/iotexproject/iotex-core/pkg/prometheustimer" @@ -308,14 +309,14 @@ func (dao *blockDAO) PutBlock(ctx context.Context, blk *block.Block) error { func (dao *blockDAO) GetBlob(h hash.Hash256) (*types.BlobTxSidecar, string, error) { if dao.blobStore == nil { - return nil, "", errors.New("blob store is not available") + return nil, "", errors.Wrap(db.ErrNotExist, "blob store is not available") } return dao.blobStore.GetBlob(h) } func (dao *blockDAO) GetBlobsByHeight(height uint64) ([]*types.BlobTxSidecar, []string, error) { if dao.blobStore == nil { - return nil, nil, errors.New("blob store is not available") + return nil, nil, errors.Wrap(db.ErrNotExist, "blob store is not available") } return dao.blobStore.GetBlobsByHeight(height) } diff --git a/chainservice/builder.go b/chainservice/builder.go index afd486abfa..97388a8005 100644 --- a/chainservice/builder.go +++ b/chainservice/builder.go @@ -524,11 +524,27 @@ func (builder *Builder) buildBlockSyncer() error { p2pAgent := builder.cs.p2pAgent chain := builder.cs.chain consens := builder.cs.consensus + blockdao := builder.cs.blockdao blocksync, err := blocksync.NewBlockSyncer( builder.cfg.BlockSync, chain.TipHeight, - builder.cs.blockdao.GetBlockByHeight, + func(height uint64) (*block.Block, error) { + blk, err := blockdao.GetBlockByHeight(height) + if err != nil { + return blk, err + } + sidecars, hashes, err := blockdao.GetBlobsByHeight(height) + if errors.Cause(err) == db.ErrNotExist { + // the block does not have blob or blob has expired + return blk, nil + } + if err != nil { + return nil, err + } + deser := (&action.Deserializer{}).SetEvmNetworkID(builder.cfg.Chain.EVMNetworkID) + return blk.WithBlobSidecars(sidecars, hashes, deser) + }, func(blk *block.Block) error { if err := consens.ValidateBlockFooter(blk); err != nil { log.L().Debug("Failed to validate block footer.", zap.Error(err), zap.Uint64("height", blk.Height()))