mirror of
https://github.com/scroll-tech/scroll.git
synced 2026-04-23 03:00:50 -04:00
record tx
This commit is contained in:
@@ -149,7 +149,7 @@ func (r *Layer1Relayer) ProcessSavedEvents() {
|
||||
func (r *Layer1Relayer) processSavedEvent(msg *types.L1Message) error {
|
||||
calldata := common.Hex2Bytes(msg.Calldata)
|
||||
|
||||
hash, err := r.messageSender.SendTransaction(msg.MsgHash, &r.cfg.MessengerContractAddress, big.NewInt(0), calldata, r.minGasLimitForMessageRelay)
|
||||
from, tx, err := r.messageSender.SendTransaction(msg.MsgHash, &r.cfg.MessengerContractAddress, big.NewInt(0), calldata, r.minGasLimitForMessageRelay)
|
||||
if err != nil && err.Error() == "execution reverted: Message expired" {
|
||||
return r.db.UpdateLayer1Status(r.ctx, msg.MsgHash, types.MsgExpired)
|
||||
}
|
||||
@@ -160,12 +160,17 @@ func (r *Layer1Relayer) processSavedEvent(msg *types.L1Message) error {
|
||||
return err
|
||||
}
|
||||
bridgeL1MsgsRelayedTotalCounter.Inc(1)
|
||||
log.Info("relayMessage to layer2", "msg hash", msg.MsgHash, "tx hash", hash)
|
||||
log.Info("relayMessage to layer2", "msg hash", msg.MsgHash, "tx hash", tx.Hash().String())
|
||||
|
||||
err = r.db.UpdateLayer1StatusAndLayer2Hash(r.ctx, msg.MsgHash, types.MsgSubmitted, hash.String())
|
||||
err = r.db.UpdateLayer1StatusAndLayer2Hash(r.ctx, msg.MsgHash, types.MsgSubmitted, tx.Hash().String())
|
||||
if err != nil {
|
||||
log.Error("UpdateLayer1StatusAndLayer2Hash failed", "msg.msgHash", msg.MsgHash, "msg.height", msg.Height, "err", err)
|
||||
}
|
||||
err = r.db.SaveTx(msg.MsgHash, from.String(), tx)
|
||||
if err != nil {
|
||||
log.Error("failed to save l1 relay tx message", "msg hash", msg.MsgHash, "tx hash", tx.Hash().String(), "err", err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -201,7 +206,7 @@ func (r *Layer1Relayer) ProcessGasPriceOracle() {
|
||||
return
|
||||
}
|
||||
|
||||
hash, err := r.gasOracleSender.SendTransaction(block.Hash, &r.cfg.GasPriceOracleContractAddress, big.NewInt(0), data, 0)
|
||||
from, tx, err := r.gasOracleSender.SendTransaction(block.Hash, &r.cfg.GasPriceOracleContractAddress, big.NewInt(0), data, 0)
|
||||
if err != nil {
|
||||
if !errors.Is(err, sender.ErrNoAvailableAccount) {
|
||||
log.Error("Failed to send setL1BaseFee tx to layer2 ", "block.Hash", block.Hash, "block.Height", block.Number, "err", err)
|
||||
@@ -209,13 +214,18 @@ func (r *Layer1Relayer) ProcessGasPriceOracle() {
|
||||
return
|
||||
}
|
||||
|
||||
err = r.db.UpdateL1GasOracleStatusAndOracleTxHash(r.ctx, block.Hash, types.GasOracleImporting, hash.String())
|
||||
err = r.db.UpdateL1GasOracleStatusAndOracleTxHash(r.ctx, block.Hash, types.GasOracleImporting, tx.Hash().String())
|
||||
if err != nil {
|
||||
log.Error("UpdateGasOracleStatusAndOracleTxHash failed", "block.Hash", block.Hash, "block.Height", block.Number, "err", err)
|
||||
return
|
||||
}
|
||||
err = r.db.SaveTx(block.Hash, from.String(), tx)
|
||||
if err != nil {
|
||||
log.Error("failed to store l1 gas oracle tx message", "block hash", block.Hash, "tx hash", tx.Hash().String(), "err", err)
|
||||
}
|
||||
|
||||
r.lastGasPrice = block.BaseFee
|
||||
log.Info("Update l1 base fee", "txHash", hash.String(), "baseFee", baseFee)
|
||||
log.Info("Update l1 base fee", "txHash", tx.Hash().String(), "baseFee", baseFee)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ func (r *Layer2Relayer) processSavedEvent(msg *types.L2Message) error {
|
||||
return err
|
||||
}
|
||||
|
||||
hash, err := r.messageSender.SendTransaction(msg.MsgHash, &r.cfg.MessengerContractAddress, big.NewInt(0), data, r.minGasLimitForMessageRelay)
|
||||
senderAddr, tx, err := r.messageSender.SendTransaction(msg.MsgHash, &r.cfg.MessengerContractAddress, big.NewInt(0), data, r.minGasLimitForMessageRelay)
|
||||
if err != nil && err.Error() == "execution reverted: Message expired" {
|
||||
return r.db.UpdateLayer2Status(r.ctx, msg.MsgHash, types.MsgExpired)
|
||||
}
|
||||
@@ -257,15 +257,20 @@ func (r *Layer2Relayer) processSavedEvent(msg *types.L2Message) error {
|
||||
return err
|
||||
}
|
||||
bridgeL2MsgsRelayedTotalCounter.Inc(1)
|
||||
log.Info("relayMessageWithProof to layer1", "msgHash", msg.MsgHash, "txhash", hash.String())
|
||||
log.Info("relayMessageWithProof to layer1", "msgHash", msg.MsgHash, "txhash", tx.Hash().String())
|
||||
|
||||
// save status in db
|
||||
// @todo handle db error
|
||||
err = r.db.UpdateLayer2StatusAndLayer1Hash(r.ctx, msg.MsgHash, types.MsgSubmitted, hash.String())
|
||||
err = r.db.UpdateLayer2StatusAndLayer1Hash(r.ctx, msg.MsgHash, types.MsgSubmitted, tx.Hash().String())
|
||||
if err != nil {
|
||||
log.Error("UpdateLayer2StatusAndLayer1Hash failed", "msgHash", msg.MsgHash, "err", err)
|
||||
return err
|
||||
}
|
||||
err = r.db.SaveTx(msg.MsgHash, senderAddr.String(), tx)
|
||||
if err != nil {
|
||||
log.Error("failed to save l2 relay tx message", "msg hash", msg.MsgHash, "tx hash", tx.Hash().String(), "err", err)
|
||||
}
|
||||
|
||||
r.processingMessage.Store(msg.MsgHash, msg.MsgHash)
|
||||
return nil
|
||||
}
|
||||
@@ -295,7 +300,7 @@ func (r *Layer2Relayer) ProcessGasPriceOracle() {
|
||||
return
|
||||
}
|
||||
|
||||
hash, err := r.gasOracleSender.SendTransaction(batch.Hash, &r.cfg.GasPriceOracleContractAddress, big.NewInt(0), data, 0)
|
||||
from, tx, err := r.gasOracleSender.SendTransaction(batch.Hash, &r.cfg.GasPriceOracleContractAddress, big.NewInt(0), data, 0)
|
||||
if err != nil {
|
||||
if !errors.Is(err, sender.ErrNoAvailableAccount) {
|
||||
log.Error("Failed to send setL2BaseFee tx to layer2 ", "batch.Hash", batch.Hash, "err", err)
|
||||
@@ -303,13 +308,18 @@ func (r *Layer2Relayer) ProcessGasPriceOracle() {
|
||||
return
|
||||
}
|
||||
|
||||
err = r.db.UpdateL2GasOracleStatusAndOracleTxHash(r.ctx, batch.Hash, types.GasOracleImporting, hash.String())
|
||||
err = r.db.UpdateL2GasOracleStatusAndOracleTxHash(r.ctx, batch.Hash, types.GasOracleImporting, tx.Hash().String())
|
||||
if err != nil {
|
||||
log.Error("UpdateGasOracleStatusAndOracleTxHash failed", "batch.Hash", batch.Hash, "err", err)
|
||||
return
|
||||
}
|
||||
// Record gas oracle tx message.
|
||||
err = r.db.SaveTx(batch.Hash, from.String(), tx)
|
||||
if err != nil {
|
||||
log.Error("failed to save l2 gas oracle tx message", "batch hash", batch.Hash, "tx hash", tx.Hash().String(), "err", err)
|
||||
}
|
||||
r.lastGasPrice = suggestGasPriceUint64
|
||||
log.Info("Update l2 gas price", "txHash", hash.String(), "GasPrice", suggestGasPrice)
|
||||
log.Info("Update l2 gas price", "txHash", tx.Hash().String(), "GasPrice", suggestGasPrice)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -341,7 +351,7 @@ func (r *Layer2Relayer) SendCommitTx(batchData []*types.BatchData) error {
|
||||
bytes = append(bytes, batch.Hash().Bytes()...)
|
||||
}
|
||||
txID := crypto.Keccak256Hash(bytes).String()
|
||||
txHash, err := r.rollupSender.SendTransaction(txID, &r.cfg.RollupContractAddress, big.NewInt(0), calldata, 0)
|
||||
from, tx, err := r.rollupSender.SendTransaction(txID, &r.cfg.RollupContractAddress, big.NewInt(0), calldata, 0)
|
||||
if err != nil {
|
||||
if !errors.Is(err, sender.ErrNoAvailableAccount) {
|
||||
log.Error("Failed to send commitBatches tx to layer1 ", "err", err)
|
||||
@@ -350,7 +360,7 @@ func (r *Layer2Relayer) SendCommitTx(batchData []*types.BatchData) error {
|
||||
}
|
||||
bridgeL2BatchesCommittedTotalCounter.Inc(int64(len(commitBatches)))
|
||||
log.Info("Sent the commitBatches tx to layer1",
|
||||
"tx_hash", txHash.Hex(),
|
||||
"tx_hash", tx.Hash().Hex(),
|
||||
"start_batch_index", commitBatches[0].BatchIndex,
|
||||
"end_batch_index", commitBatches[len(commitBatches)-1].BatchIndex)
|
||||
|
||||
@@ -358,11 +368,16 @@ func (r *Layer2Relayer) SendCommitTx(batchData []*types.BatchData) error {
|
||||
batchHashes := make([]string, len(batchData))
|
||||
for i, batch := range batchData {
|
||||
batchHashes[i] = batch.Hash().Hex()
|
||||
err = r.db.UpdateCommitTxHashAndRollupStatus(r.ctx, batchHashes[i], txHash.String(), types.RollupCommitting)
|
||||
err = r.db.UpdateCommitTxHashAndRollupStatus(r.ctx, batchHashes[i], tx.Hash().String(), types.RollupCommitting)
|
||||
if err != nil {
|
||||
log.Error("UpdateCommitTxHashAndRollupStatus failed", "hash", batchHashes[i], "index", batch.Batch.BatchIndex, "err", err)
|
||||
}
|
||||
}
|
||||
// Record gas oracle tx message.
|
||||
err = r.db.SaveTx(txID, from.String(), tx)
|
||||
if err != nil {
|
||||
log.Error("failed to save l2 gas oracle tx message", "tx id", txID, "tx hash", tx.Hash().String(), "err", err)
|
||||
}
|
||||
r.processingBatchesCommitment.Store(txID, batchHashes)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -158,18 +158,19 @@ func (s *Sender) getFeeData(auth *bind.TransactOpts, target *common.Address, val
|
||||
}
|
||||
|
||||
// SendTransaction send a signed L2tL1 transaction.
|
||||
func (s *Sender) SendTransaction(ID string, target *common.Address, value *big.Int, data []byte, minGasLimit uint64) (hash common.Hash, err error) {
|
||||
func (s *Sender) SendTransaction(ID string, target *common.Address, value *big.Int, data []byte, minGasLimit uint64) (common.Address, *types.Transaction, error) {
|
||||
// We occupy the ID, in case some other threads call with the same ID in the same time
|
||||
if _, loaded := s.pendingTxs.LoadOrStore(ID, nil); loaded {
|
||||
return common.Hash{}, fmt.Errorf("has the repeat tx ID, ID: %s", ID)
|
||||
return common.Address{}, nil, fmt.Errorf("has the repeat tx ID, ID: %s", ID)
|
||||
}
|
||||
// get
|
||||
auth := s.auths.getAccount()
|
||||
if auth == nil {
|
||||
s.pendingTxs.Delete(ID) // release the ID on failure
|
||||
return common.Hash{}, ErrNoAvailableAccount
|
||||
return common.Address{}, nil, ErrNoAvailableAccount
|
||||
}
|
||||
|
||||
var err error
|
||||
defer s.auths.releaseAccount(auth)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@@ -183,22 +184,23 @@ func (s *Sender) SendTransaction(ID string, target *common.Address, value *big.I
|
||||
)
|
||||
// estimate gas fee
|
||||
if feeData, err = s.getFeeData(auth, target, value, data, minGasLimit); err != nil {
|
||||
return
|
||||
return common.Address{}, nil, err
|
||||
}
|
||||
if tx, err = s.createAndSendTx(auth, feeData, target, value, data, nil); err == nil {
|
||||
// add pending transaction to queue
|
||||
pending := &PendingTransaction{
|
||||
tx: tx,
|
||||
id: ID,
|
||||
signer: auth,
|
||||
submitAt: atomic.LoadUint64(&s.blockNumber),
|
||||
feeData: feeData,
|
||||
}
|
||||
s.pendingTxs.Store(ID, pending)
|
||||
return tx.Hash(), nil
|
||||
tx, err = s.createAndSendTx(auth, feeData, target, value, data, nil)
|
||||
if err != nil {
|
||||
return common.Address{}, nil, err
|
||||
}
|
||||
// add pending transaction to queue
|
||||
pending := &PendingTransaction{
|
||||
tx: tx,
|
||||
id: ID,
|
||||
signer: auth,
|
||||
submitAt: atomic.LoadUint64(&s.blockNumber),
|
||||
feeData: feeData,
|
||||
}
|
||||
s.pendingTxs.Store(ID, pending)
|
||||
|
||||
return
|
||||
return auth.From, tx, nil
|
||||
}
|
||||
|
||||
func (s *Sender) createAndSendTx(auth *bind.TransactOpts, feeData *FeeData, target *common.Address, value *big.Int, data []byte, overrideNonce *uint64) (tx *types.Transaction, err error) {
|
||||
|
||||
18
common/types/transaction.go
Normal file
18
common/types/transaction.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"github.com/scroll-tech/go-ethereum/common"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type TxMessage struct {
|
||||
Hash common.Hash `json:"hash" db:"hash"`
|
||||
TxHash common.Hash `json:"tx_hash" db:"tx_hash"`
|
||||
Sender common.Address `json:"sender" db:"sender"`
|
||||
Nonce uint64 `json:"nonce" db:"nonce"`
|
||||
Target *common.Address `json:"target" db:"target"`
|
||||
Gas *big.Int `json:"gas" db:"gas"`
|
||||
GasLimit uint64 `json:"gas_limit" db:"gas_limit"`
|
||||
Value *big.Int `json:"value" db:"value"`
|
||||
Data string `json:"data" db:"data"`
|
||||
}
|
||||
29
database/migrate/migrations/00007_transaction.sql
Normal file
29
database/migrate/migrations/00007_transaction.sql
Normal file
@@ -0,0 +1,29 @@
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
|
||||
create table transaction
|
||||
(
|
||||
hash VARCHAR NOT NULL,
|
||||
tx_hash VARCHAR NOT NULL,
|
||||
sender VARCHAR NOT NULL,
|
||||
nonce BIGINT NOT NULL,
|
||||
target VARCHAR NOT NULL,
|
||||
gas BIGINT NOT NULL,
|
||||
gas_limit BIGINT NOT NULL,
|
||||
value VARCHAR NOT NULL,
|
||||
data TEXT DEFAULT NULL,
|
||||
created_time TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
create unique index transaction_hash_uindex
|
||||
on transaction (hash);
|
||||
|
||||
create unique index transaction_tx_hash_uindex
|
||||
on transaction (tx_hash);
|
||||
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
drop table if exists transaction;
|
||||
-- +goose StatementEnd
|
||||
@@ -4,10 +4,11 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"scroll-tech/common/types"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/scroll-tech/go-ethereum/common"
|
||||
etypes "github.com/scroll-tech/go-ethereum/core/types"
|
||||
|
||||
"scroll-tech/common/types"
|
||||
)
|
||||
|
||||
// L1BlockOrm l1_block operation interface
|
||||
@@ -110,3 +111,9 @@ type L2MessageOrm interface {
|
||||
|
||||
GetRelayL2MessageTxHash(nonce uint64) (sql.NullString, error) // for unit tests only
|
||||
}
|
||||
|
||||
// TxOrm transaction operation interfaces.
|
||||
type TxOrm interface {
|
||||
SaveTx(hash, sender string, tx *etypes.Transaction) error
|
||||
GetTxByHash(hash string) (*types.TxMessage, error)
|
||||
}
|
||||
|
||||
51
database/orm/transaction.go
Normal file
51
database/orm/transaction.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package orm
|
||||
|
||||
import (
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/scroll-tech/go-ethereum/common/hexutil"
|
||||
"github.com/scroll-tech/go-ethereum/core/types"
|
||||
|
||||
stypes "scroll-tech/common/types"
|
||||
)
|
||||
|
||||
type txOrm struct {
|
||||
db *sqlx.DB
|
||||
}
|
||||
|
||||
var _ TxOrm = (*txOrm)(nil)
|
||||
|
||||
// NewTxOrm create an TxOrm instance.
|
||||
func NewTxOrm(db *sqlx.DB) TxOrm {
|
||||
return &txOrm{db: db}
|
||||
}
|
||||
|
||||
// SaveTx stores tx message into db.
|
||||
func (t *txOrm) SaveTx(hash, sender string, tx *types.Transaction) error {
|
||||
if tx == nil {
|
||||
return nil
|
||||
}
|
||||
var target string
|
||||
if tx.To() != nil {
|
||||
target = tx.To().String()
|
||||
}
|
||||
_, err := t.db.Exec(
|
||||
t.db.Rebind(t.db.Rebind("INSERT INTO transaction (hash, tx_hash, sender, nonce, target, gas, gas_limit, value, data) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);")),
|
||||
hash,
|
||||
tx.Hash().String(),
|
||||
sender,
|
||||
tx.Nonce(),
|
||||
target,
|
||||
tx.GasPrice().Uint64(),
|
||||
tx.Gas(),
|
||||
hexutil.Encode(tx.Data()),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetTxByHash returns tx message by message hash.
|
||||
func (t *txOrm) GetTxByHash(hash string) (*stypes.TxMessage, error) {
|
||||
db := t.db
|
||||
row := db.QueryRowx(db.Rebind("SELECT * FROM transaction WHERE hash = ?"), hash)
|
||||
txMsg := &stypes.TxMessage{}
|
||||
return txMsg, row.Scan(&txMsg)
|
||||
}
|
||||
@@ -15,6 +15,7 @@ type OrmFactory interface {
|
||||
orm.L1MessageOrm
|
||||
orm.L2MessageOrm
|
||||
orm.SessionInfoOrm
|
||||
orm.TxOrm
|
||||
GetDB() *sqlx.DB
|
||||
Beginx() (*sqlx.Tx, error)
|
||||
Close() error
|
||||
@@ -27,6 +28,7 @@ type ormFactory struct {
|
||||
orm.L1MessageOrm
|
||||
orm.L2MessageOrm
|
||||
orm.SessionInfoOrm
|
||||
orm.TxOrm
|
||||
*sqlx.DB
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user