record tx

This commit is contained in:
maskpp
2023-03-29 15:06:21 +08:00
parent 179c6ee978
commit 793804cb2e
8 changed files with 167 additions and 33 deletions

View File

@@ -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)
}
}
}

View File

@@ -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
}

View File

@@ -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) {

View 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"`
}

View 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

View File

@@ -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)
}

View 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)
}

View File

@@ -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
}