Skip to content

Commit

Permalink
Merge pull request #211 from ipfs-force-community/feat/add-api-to-lis…
Browse files Browse the repository at this point in the history
…t-block

feat: add api to list blocks
  • Loading branch information
simlecode authored Jul 18, 2023
2 parents 35304ee + 9adf6a8 commit 6755e1e
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 77 deletions.
1 change: 1 addition & 0 deletions api/api_miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type MinerAPI interface {
ListAddress(context.Context) ([]types.MinerInfo, error) //perm:read
StatesForMining(context.Context, []address.Address) ([]types.MinerState, error) //perm:read
CountWinners(context.Context, []address.Address, abi.ChainEpoch, abi.ChainEpoch) ([]types.CountWinners, error) //perm:read
ListBlocks(ctx context.Context, params *types.BlocksQueryParams) ([]types.MinedBlock, error) //perm:read
WarmupForMiner(context.Context, address.Address) error //perm:write
Start(context.Context, []address.Address) error //perm:write
Stop(context.Context, []address.Address) error //perm:write
Expand Down
13 changes: 13 additions & 0 deletions api/proxy_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions miner/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ type IMinerManager interface {
ListAddress(context.Context) ([]types.MinerInfo, error)
StatesForMining(context.Context, []address.Address) ([]types.MinerState, error)
CountWinners(context.Context, []address.Address, abi.ChainEpoch, abi.ChainEpoch) ([]types.CountWinners, error)
ListBlocks(ctx context.Context, params *types.BlocksQueryParams) ([]types.MinedBlock, error)
WarmupForMiner(context.Context, address.Address) error
}
4 changes: 4 additions & 0 deletions miner/miningmgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ func (m *Miner) ListAddress(ctx context.Context) ([]types.MinerInfo, error) {
return minerInfos, nil
}

func (m *Miner) ListBlocks(ctx context.Context, params *types.BlocksQueryParams) ([]types.MinedBlock, error) {
return m.sf.ListBlock(ctx, params)
}

func (m *Miner) StatesForMining(ctx context.Context, addrs []address.Address) ([]types.MinerState, error) {
m.lkWPP.Lock()
defer m.lkWPP.Unlock()
Expand Down
16 changes: 8 additions & 8 deletions miner/multiminer.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ func (m *Miner) mine(ctx context.Context) {
if err := m.sf.PutBlock(ctx, &sharedTypes.BlockHeader{
Height: base.TipSet.Height() + base.NullRounds + 1,
Miner: res.addr,
}, base.TipSet.Height()+base.NullRounds, time.Time{}, slashfilter.ChainForked); err != nil {
}, base.TipSet.Height()+base.NullRounds, time.Time{}, types.ChainForked); err != nil {
log.Errorf("failed to record chain forked: %s", err)
}

Expand Down Expand Up @@ -456,7 +456,7 @@ func (m *Miner) mine(ctx context.Context) {
// Wait until the next epoch, plus the propagation delay, so a new tipset
// has enough time to form.
m.untilNextEpoch(base)

if len(winPoSts) == 0 {
base.NullRounds++
}
Expand Down Expand Up @@ -485,7 +485,7 @@ func (m *Miner) broadCastBlock(ctx context.Context, base MiningBase, bm *sharedT

if err := m.sf.MinedBlock(ctx, bm.Header, base.TipSet.Height()+base.NullRounds); err != nil {
log.Errorf("<!!> SLASH FILTER ERROR: %s", err)
if err = m.sf.PutBlock(ctx, bm.Header, base.TipSet.Height()+base.NullRounds, time.Time{}, slashfilter.Error); err != nil {
if err = m.sf.PutBlock(ctx, bm.Header, base.TipSet.Height()+base.NullRounds, time.Time{}, types.Error); err != nil {
log.Errorf("failed to put block: %s", err)
}

Expand All @@ -511,7 +511,7 @@ func (m *Miner) broadCastBlock(ctx context.Context, base MiningBase, bm *sharedT

if !bSubmitted {
log.Error("try to submit blocks to all nodes failed")
if err = m.sf.PutBlock(ctx, bm.Header, base.TipSet.Height()+base.NullRounds, time.Time{}, slashfilter.Error); err != nil {
if err = m.sf.PutBlock(ctx, bm.Header, base.TipSet.Height()+base.NullRounds, time.Time{}, types.Error); err != nil {
log.Errorf("failed to put block: %s", err)
}
return
Expand All @@ -525,7 +525,7 @@ func (m *Miner) broadCastBlock(ctx context.Context, base MiningBase, bm *sharedT
)
stats.Record(metricsCtx, metrics.NumberOfBlock.M(1))

if err = m.sf.PutBlock(ctx, bm.Header, base.TipSet.Height()+base.NullRounds, time.Time{}, slashfilter.Success); err != nil {
if err = m.sf.PutBlock(ctx, bm.Header, base.TipSet.Height()+base.NullRounds, time.Time{}, types.Success); err != nil {
log.Errorf("failed to put block: %s", err)
}
}
Expand Down Expand Up @@ -614,7 +614,7 @@ func (m *Miner) mineOneForAll(ctx context.Context, base *MiningBase) []*winPoStR
if err := m.sf.PutBlock(ctx, &sharedTypes.BlockHeader{
Height: base.TipSet.Height() + base.NullRounds + 1,
Miner: tAddr,
}, base.TipSet.Height()+base.NullRounds, time.Time{}, slashfilter.Timeout); err != nil {
}, base.TipSet.Height()+base.NullRounds, time.Time{}, types.Timeout); err != nil {
log.Errorf("failed to record mining timeout: %s", err)
}

Expand All @@ -637,7 +637,7 @@ func (m *Miner) mineOneForAll(ctx context.Context, base *MiningBase) []*winPoStR
if err := m.sf.PutBlock(ctx, &sharedTypes.BlockHeader{
Height: base.TipSet.Height() + base.NullRounds + 1,
Miner: tAddr,
}, base.TipSet.Height()+base.NullRounds, time.Time{}, slashfilter.Error); err != nil {
}, base.TipSet.Height()+base.NullRounds, time.Time{}, types.Error); err != nil {
log.Errorf("failed to record winner: %s", err)
}

Expand Down Expand Up @@ -840,7 +840,7 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase, account string, a
Height: base.TipSet.Height() + base.NullRounds + 1,
Miner: addr,
Parents: base.TipSet.Key().Cids(),
}, base.TipSet.Height()+base.NullRounds, time.Now(), slashfilter.Mining); err != nil {
}, base.TipSet.Height()+base.NullRounds, time.Now(), types.Mining); err != nil {
log.Errorf("failed to record winner: %s", err)
}

Expand Down
8 changes: 8 additions & 0 deletions node/impl/miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ func (m *MinerAPI) CountWinners(ctx context.Context, addrs []address.Address, st
return m.MiningAPI.CountWinners(ctx, addrsAllowed, start, end)
}

func (m *MinerAPI) ListBlocks(ctx context.Context, params *types.BlocksQueryParams) ([]types.MinedBlock, error) {
addrsAllowed := filter(params.Miners, func(addr address.Address) bool {
return jwtclient.CheckPermissionByMiner(ctx, m.AuthClient, addr) == nil
})
params.Miners = addrsAllowed
return m.MiningAPI.ListBlocks(ctx, params)
}

func (m *MinerAPI) WarmupForMiner(ctx context.Context, maddr address.Address) error {
if err := jwtclient.CheckPermissionByMiner(ctx, m.AuthClient, maddr); err != nil {
return err
Expand Down
31 changes: 3 additions & 28 deletions node/modules/slashfilter/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"time"

"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs-force-community/sophon-miner/types"

vtypes "github.com/filecoin-project/venus/venus-shared/types"
)
Expand All @@ -16,35 +17,9 @@ const (
MySQL BlockStoreType = "mysql"
)

type StateMining int

const (
Mining StateMining = iota
Success
Timeout
ChainForked
Error
)

func (sm StateMining) String() string {
switch sm {
case Mining:
return "Mining"
case Success:
return "Success"
case Timeout:
return "TimeOut"
case ChainForked:
return "ChainForked"
case Error:
return "Error"
default:
return "unknown"
}
}

type SlashFilterAPI interface {
HasBlock(ctx context.Context, bh *vtypes.BlockHeader) (bool, error)
MinedBlock(ctx context.Context, bh *vtypes.BlockHeader, parentEpoch abi.ChainEpoch) error
PutBlock(ctx context.Context, bh *vtypes.BlockHeader, parentEpoch abi.ChainEpoch, t time.Time, state StateMining) error
PutBlock(ctx context.Context, bh *vtypes.BlockHeader, parentEpoch abi.ChainEpoch, t time.Time, state types.StateMining) error
ListBlock(ctx context.Context, params *types.BlocksQueryParams) ([]MinedBlock, error)
}
8 changes: 6 additions & 2 deletions node/modules/slashfilter/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ func (f *localSlashFilter) HasBlock(ctx context.Context, bh *vtypes.BlockHeader)
return f.byEpoch.Has(ctx, epochKey)
}

func (f *localSlashFilter) PutBlock(ctx context.Context, bh *vtypes.BlockHeader, parentEpoch abi.ChainEpoch, t time.Time, state StateMining) error {
func (f *localSlashFilter) PutBlock(ctx context.Context, bh *vtypes.BlockHeader, parentEpoch abi.ChainEpoch, t time.Time, state types.StateMining) error {
// Only successful block generation is recorded locally
if state != Success {
if state != types.Success {
return nil
}

Expand Down Expand Up @@ -102,6 +102,10 @@ func (f *localSlashFilter) MinedBlock(ctx context.Context, bh *vtypes.BlockHeade
return nil
}

func (f *localSlashFilter) ListBlock(ctx context.Context, params *types.BlocksQueryParams) ([]MinedBlock, error) {
return nil, fmt.Errorf("you are using levelDB, List Block is not supported")
}

func checkFault(ctx context.Context, t datastore.Datastore, key datastore.Key, bh *vtypes.BlockHeader, faultType string) error {
fault, err := t.Has(ctx, key)
if err != nil {
Expand Down
64 changes: 38 additions & 26 deletions node/modules/slashfilter/slashfilter.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ import (
"github.com/filecoin-project/go-state-types/abi"

"github.com/ipfs-force-community/sophon-miner/node/config"
"github.com/ipfs-force-community/sophon-miner/types"

"github.com/filecoin-project/venus/venus-shared/types"
venusTypes "github.com/filecoin-project/venus/venus-shared/types"
)

var log = logging.Logger("mysql_slashFilter")
Expand All @@ -23,22 +24,7 @@ type mysqlSlashFilter struct {
_db *gorm.DB
}

type MinedBlock struct {
ParentEpoch int64 `gorm:"column:parent_epoch;type:bigint(20);default:0;NOT NULL"`
ParentKey string `gorm:"column:parent_key;type:varchar(2048);default:'';NOT NULL"`

Epoch int64 `gorm:"column:epoch;type:bigint(20);NOT NULL;primary_key"`
Miner string `gorm:"column:miner;type:varchar(256);NOT NULL;primary_key"`
Cid string `gorm:"column:cid;type:varchar(256);default:''"`

WinningAt time.Time `gorm:"column:winning_at;type:datetime"`
MineState StateMining `gorm:"column:mine_state;type:tinyint(4);default:0;comment:0-mining,1-success,2-timeout,3-chain forked,4-error;NOT NULL"`
Consuming int64 `gorm:"column:consuming;type:bigint(10);default:0;NOT NULL"` // reserved
}

func (m *MinedBlock) TableName() string {
return "miner_blocks"
}
type MinedBlock = types.MinedBlock

var _ SlashFilterAPI = (*mysqlSlashFilter)(nil)

Expand Down Expand Up @@ -76,7 +62,7 @@ func NewMysql(cfg *config.MySQLConfig) (SlashFilterAPI, error) {
}

// double-fork mining (2 blocks at one epoch)
func (f *mysqlSlashFilter) checkSameHeightFault(bh *types.BlockHeader) error { // nolint: unused
func (f *mysqlSlashFilter) checkSameHeightFault(bh *venusTypes.BlockHeader) error { // nolint: unused
var blk MinedBlock
err := f._db.Model(&MinedBlock{}).Take(&blk, "miner=? and epoch=?", bh.Miner.String(), bh.Height).Error
if err == gorm.ErrRecordNotFound {
Expand All @@ -103,9 +89,9 @@ func (f *mysqlSlashFilter) checkSameHeightFault(bh *types.BlockHeader) error { /
}

// time-offset mining faults (2 blocks with the same parents)
func (f *mysqlSlashFilter) checkSameParentFault(bh *types.BlockHeader) error {
func (f *mysqlSlashFilter) checkSameParentFault(bh *venusTypes.BlockHeader) error {
var blk MinedBlock
err := f._db.Model(&MinedBlock{}).Take(&blk, "miner=? and parent_key=?", bh.Miner.String(), types.NewTipSetKey(bh.Parents...).String()).Error
err := f._db.Model(&MinedBlock{}).Take(&blk, "miner=? and parent_key=?", bh.Miner.String(), venusTypes.NewTipSetKey(bh.Parents...).String()).Error
if err == gorm.ErrRecordNotFound {
return nil
}
Expand All @@ -129,7 +115,7 @@ func (f *mysqlSlashFilter) checkSameParentFault(bh *types.BlockHeader) error {
return fmt.Errorf("produced block would trigger time-offset mining faults consensus fault; miner: %s; bh: %s, other: %s", bh.Miner, bh.Cid(), other)
}

func (f *mysqlSlashFilter) HasBlock(ctx context.Context, bh *types.BlockHeader) (bool, error) {
func (f *mysqlSlashFilter) HasBlock(ctx context.Context, bh *venusTypes.BlockHeader) (bool, error) {
var blk MinedBlock
err := f._db.Model(&MinedBlock{}).Take(&blk, "miner=? and epoch=?", bh.Miner.String(), bh.Height).Error
if err == gorm.ErrRecordNotFound {
Expand All @@ -142,15 +128,15 @@ func (f *mysqlSlashFilter) HasBlock(ctx context.Context, bh *types.BlockHeader)
return len(blk.Cid) > 0, nil
}

func (f *mysqlSlashFilter) PutBlock(ctx context.Context, bh *types.BlockHeader, parentEpoch abi.ChainEpoch, t time.Time, state StateMining) error {
func (f *mysqlSlashFilter) PutBlock(ctx context.Context, bh *venusTypes.BlockHeader, parentEpoch abi.ChainEpoch, t time.Time, state types.StateMining) error {
var blk MinedBlock
err := f._db.Model(&MinedBlock{}).Take(&blk, "miner=? and epoch=?", bh.Miner.String(), bh.Height).Error
if err != nil {
// Timeout may not be the winner when it happens, once the winner database must be recorded.
if err == gorm.ErrRecordNotFound && state != Timeout {
if err == gorm.ErrRecordNotFound && state != types.Timeout {
mblk := &MinedBlock{
ParentEpoch: int64(parentEpoch),
ParentKey: types.NewTipSetKey(bh.Parents...).String(),
ParentKey: venusTypes.NewTipSetKey(bh.Parents...).String(),
Epoch: int64(bh.Height),
Miner: bh.Miner.String(),

Expand All @@ -174,7 +160,7 @@ func (f *mysqlSlashFilter) PutBlock(ctx context.Context, bh *types.BlockHeader,
updateColumns := make(map[string]interface{})
updateColumns["parent_epoch"] = parentEpoch
if len(bh.Parents) > 0 {
updateColumns["parent_key"] = types.NewTipSetKey(bh.Parents...).String()
updateColumns["parent_key"] = venusTypes.NewTipSetKey(bh.Parents...).String()
}
updateColumns["mine_state"] = state
if bh.Ticket != nil {
Expand All @@ -184,7 +170,7 @@ func (f *mysqlSlashFilter) PutBlock(ctx context.Context, bh *types.BlockHeader,
return f._db.Model(&MinedBlock{}).Where("miner=? and epoch=?", bh.Miner.String(), bh.Height).UpdateColumns(updateColumns).Error
}

func (f *mysqlSlashFilter) MinedBlock(ctx context.Context, bh *types.BlockHeader, parentEpoch abi.ChainEpoch) error {
func (f *mysqlSlashFilter) MinedBlock(ctx context.Context, bh *venusTypes.BlockHeader, parentEpoch abi.ChainEpoch) error {
// double-fork mining (2 blocks at one epoch) --> HasBlock
//if err := f.checkSameHeightFault(bh); err != nil {
// return err
Expand Down Expand Up @@ -228,3 +214,29 @@ func (f *mysqlSlashFilter) MinedBlock(ctx context.Context, bh *types.BlockHeader

return nil
}

func (f *mysqlSlashFilter) ListBlock(ctx context.Context, params *types.BlocksQueryParams) ([]MinedBlock, error) {
var blks []MinedBlock
query := f._db.Order("epoch desc")

if len(params.Miners) > 0 {
temp := make([]string, 0, len(params.Miners))
for _, miner := range params.Miners {
temp = append(temp, miner.String())
}
query = query.Where("miner in (?)", temp)
}
if params.Limit > 0 {
query = query.Limit(params.Limit)
}
if params.Offset > 0 {
query = query.Offset(params.Offset)
}

err := query.Find(&blks).Error
if err != nil {
return nil, err
}

return blks, nil
}
Loading

0 comments on commit 6755e1e

Please sign in to comment.