mirror of
https://github.com/scroll-tech/scroll.git
synced 2026-01-15 00:48:01 -05:00
Co-authored-by: vincent <419436363@qq.com> Co-authored-by: colinlyguo <colinlyguo@scroll.io> Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com> Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
135 lines
4.3 KiB
Go
135 lines
4.3 KiB
Go
package orm
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
|
|
"github.com/scroll-tech/go-ethereum/log"
|
|
"gorm.io/gorm"
|
|
|
|
"scroll-tech/common/types"
|
|
)
|
|
|
|
// L1Message is structure of stored layer1 bridge message
|
|
type L1Message struct {
|
|
db *gorm.DB `gorm:"column:-"`
|
|
|
|
QueueIndex uint64 `json:"queue_index" gorm:"column:queue_index"`
|
|
MsgHash string `json:"msg_hash" gorm:"column:msg_hash"`
|
|
Height uint64 `json:"height" gorm:"column:height"`
|
|
GasLimit uint64 `json:"gas_limit" gorm:"column:gas_limit"`
|
|
Sender string `json:"sender" gorm:"column:sender"`
|
|
Target string `json:"target" gorm:"column:target"`
|
|
Value string `json:"value" gorm:"column:value"`
|
|
Calldata string `json:"calldata" gorm:"column:calldata"`
|
|
Layer1Hash string `json:"layer1_hash" gorm:"column:layer1_hash"`
|
|
Layer2Hash string `json:"layer2_hash" gorm:"column:layer2_hash;default:NULL"`
|
|
Status int `json:"status" gorm:"column:status;default:1"`
|
|
}
|
|
|
|
// NewL1Message create an L1MessageOrm instance
|
|
func NewL1Message(db *gorm.DB) *L1Message {
|
|
return &L1Message{db: db}
|
|
}
|
|
|
|
// TableName define the L1Message table name
|
|
func (*L1Message) TableName() string {
|
|
return "l1_message"
|
|
}
|
|
|
|
// GetLayer1LatestWatchedHeight returns latest height stored in the table
|
|
func (m *L1Message) GetLayer1LatestWatchedHeight() (int64, error) {
|
|
// @note It's not correct, since we may don't have message in some blocks.
|
|
// But it will only be called at start, some redundancy is acceptable.
|
|
var maxHeight sql.NullInt64
|
|
result := m.db.Model(&L1Message{}).Select("MAX(height)").Scan(&maxHeight)
|
|
if result.Error != nil {
|
|
return -1, result.Error
|
|
}
|
|
if maxHeight.Valid {
|
|
return maxHeight.Int64, nil
|
|
}
|
|
return -1, nil
|
|
}
|
|
|
|
// GetLayer1LatestMessageWithLayer2Hash returns latest l1 message with layer2 hash
|
|
func (m *L1Message) GetLayer1LatestMessageWithLayer2Hash() (*L1Message, error) {
|
|
var msg *L1Message
|
|
err := m.db.Where("layer2_hash IS NOT NULL").Order("queue_index DESC").First(&msg).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return msg, nil
|
|
}
|
|
|
|
// GetL1MessagesByStatus fetch list of unprocessed messages given msg status
|
|
func (m *L1Message) GetL1MessagesByStatus(status types.MsgStatus, limit uint64) ([]L1Message, error) {
|
|
var msgs []L1Message
|
|
err := m.db.Where("status", int(status)).Order("queue_index ASC").Limit(int(limit)).Find(&msgs).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return msgs, nil
|
|
}
|
|
|
|
// GetL1MessageByQueueIndex fetch message by queue_index
|
|
// for unit test
|
|
func (m *L1Message) GetL1MessageByQueueIndex(queueIndex uint64) (*L1Message, error) {
|
|
var msg L1Message
|
|
err := m.db.Where("queue_index", queueIndex).First(&msg).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &msg, nil
|
|
}
|
|
|
|
// GetL1MessageByMsgHash fetch message by queue_index
|
|
// for unit test
|
|
func (m *L1Message) GetL1MessageByMsgHash(msgHash string) (*L1Message, error) {
|
|
var msg L1Message
|
|
err := m.db.Where("msg_hash", msgHash).First(&msg).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &msg, nil
|
|
}
|
|
|
|
// SaveL1Messages batch save a list of layer1 messages
|
|
func (m *L1Message) SaveL1Messages(ctx context.Context, messages []*L1Message) error {
|
|
if len(messages) == 0 {
|
|
return nil
|
|
}
|
|
|
|
err := m.db.WithContext(ctx).Create(&messages).Error
|
|
if err != nil {
|
|
queueIndices := make([]uint64, 0, len(messages))
|
|
heights := make([]uint64, 0, len(messages))
|
|
for _, msg := range messages {
|
|
queueIndices = append(queueIndices, msg.QueueIndex)
|
|
heights = append(heights, msg.Height)
|
|
}
|
|
log.Error("failed to insert l1Messages", "queueIndices", queueIndices, "heights", heights, "err", err)
|
|
}
|
|
return err
|
|
}
|
|
|
|
// UpdateLayer1Status updates message stauts, given message hash
|
|
func (m *L1Message) UpdateLayer1Status(ctx context.Context, msgHash string, status types.MsgStatus) error {
|
|
if err := m.db.Model(&L1Message{}).WithContext(ctx).Where("msg_hash", msgHash).Update("status", int(status)).Error; err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// UpdateLayer1StatusAndLayer2Hash updates message status and layer2 transaction hash, given message hash
|
|
func (m *L1Message) UpdateLayer1StatusAndLayer2Hash(ctx context.Context, msgHash string, status types.MsgStatus, layer2Hash string) error {
|
|
updateFields := map[string]interface{}{
|
|
"status": int(status),
|
|
"layer2_hash": layer2Hash,
|
|
}
|
|
if err := m.db.Model(&L1Message{}).WithContext(ctx).Where("msg_hash", msgHash).Updates(updateFields).Error; err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|