reddio-com / itachi

A high performance decentralized modular sequencer for Starknet
GNU General Public License v3.0
18 stars 8 forks source link

add some starknet rpc #66

Open idmsy opened 3 months ago

idmsy commented 3 months ago

目前还没写:GetStateUpdateSyncingTraceTransactiontraceBlockTransactions

假如改动type StarknetRPC struct

type StarknetRPC struct {
    chain    *kernel.Kernel
    log      utils.SimpleLogger
    srv      *http.Server
    network  utils.Network
    bcReader blockchain.Reader
}

然后相应的在NewStarknetRPC方法中初始化:

var database db.DB
database, err = pebble.New(cfg.DbPath, cfg.DbCache, cfg.DbMaxOpenFiles, log)
if err != nil {
    return nil, err
}
reader := blockchain.New(database, s.network)
s.bcReader = reader

就会让

func (s *StarknetRPC) BlockHashAndNumber() (*rpc.BlockHashAndNumber, *jsonrpc.Error) {
    block, err := s.bcReader.Head()
    if err != nil {
        return nil, rpc.ErrBlockNotFound
    }
    return &rpc.BlockHashAndNumber{Number: block.Number, Hash: block.Hash}, nil
}

之类的方法写起来很简单,但我不太知道哪些时候能直接调用juno的函数。我有点迷糊yu和juno的关系,itachi是以yu为链然后来跟cairoVM交互的吗,所以查询链上数据的时候用yu的函数?比如yu的GetEndBlock

那么这样的话是否是这样的一个流程:

在methods.go文件下写rpc的实现

func (s *StarknetRPC) BlockNumber() (uint64, *jsonrpc.Error) {
    // 这里也是直接用juno的bcReader会很简单
    // num, _ := s.bcReader.Height()
    // return num, nil
    resp, err := s.adaptChainRead(nil, "BlockNumber")
    if err != nil {
        return 0, rpc.ErrNoBlock
    }
    res := resp.DataInterface.(*cairo.BlockNumberResponse)
    return res.Height, res.Err
}

然后在api.go下

type BlockNumberResponse struct {
    Height uint64         `json:"block_number"`
    Err    *jsonrpc.Error `json:"err"`
}

// 不是很确定这里是不是可以不写request,直接response
func (c *Cairo) BlockNumber(ctx *context.ReadContext) {
    Block, err := c.Chain.GetEndBlock()
    if err != nil {
        ctx.Json(http.StatusInternalServerError, &BlockNumberResponse{Err: jsonrpc.Err(jsonrpc.InternalError, err.Error())})
        return
    }
    Height := uint64(Block.Height)
    ctx.JsonOk(&BlockNumberResponse{Height: Height})
}

然后再在cairo.go里面注册一个reading方法.

traceBlockTransactions: juno用来追踪transaction的方法,其中要求starknet version小于0.12.3,我看starknet已经更新到0.13.1.1了,这个version是定义在core.Block的Header里面的,我没在yu的header里找到这个字段,这个限制是必要的吗

if blockVer, err := core.ParseBlockVersion(block.ProtocolVersion); err != nil {
            return nil, ErrUnexpectedError.CloneWithData(err.Error())
        } else if blockVer.Compare(traceFallbackVersion) != 1 || h.forceFeederTracesForBlocks.Contains(block.Number) {
            // version <= 0.12.3 or forcing fetch some blocks from feeder gateway
            return h.fetchTraces(ctx, block.Hash)
        }

然后这个forceFeederTracesForBlocks我看到mainnet有预定义一长串的blocknumber,其他网络都没有,不太清楚为什么这些预定义的区块要强制trace

feeder.Client还没细看,如果要用到的话是否要用network里的feeder url自己实现一个feeder client?

我看juno代码理解的是找feeder client获取trace。fetchTraces-->feederClient.BlockTrace-->buildQueryString

对我来说难点主要在于找到yu框架中对应的方法来复刻juno这个流程。

然后juno维护了一个traceCache,这个要做吗?(倒是做起来很简单,StarknetRPC结构体里面加一个*lru.Cache[traceCacheKey, []TracedBlockTransaction]就行)

juno的Block里的ParentHash是否就是yu的PrevHash?

    state, closer, err := h.bcReader.StateAtBlockHash(block.ParentHash)
    if err != nil {
        return nil, ErrBlockNotFound
    }
    defer h.callAndLogErr(closer, "Failed to close state in traceBlockTransactions")

state是一个stateReader,这个其实也是能直接用bcreader就很方便。

Syncing()其实也是一样的问题,不知道能不能用juno的syncreader,能用最简单。

GetStateUpdate()也是用bcreader最方便。