Skip to content

Commit

Permalink
divide process of sending signed tx into building and sending
Browse files Browse the repository at this point in the history
Signed-off-by: Daisuke Kanda <[email protected]>
  • Loading branch information
dai1975 committed Jul 26, 2024
1 parent 0f900c1 commit e6e7108
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 94 deletions.
2 changes: 1 addition & 1 deletion pkg/relay/ethereum/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package ethereum

const (
logAttrMsgIndexFrom = "msg_index_from"
logAttrMsgIndexTo = "msg_index_to"
logAttrMsgCount = "msg_count"
logAttrMsgType = "msg_type"
logAttrRevertReason = "revert_reason"
logAttrRawErrorData = "raw_error_data"
Expand Down
158 changes: 65 additions & 93 deletions pkg/relay/ethereum/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ func (c *Chain) SendMsgs(msgs []sdk.Msg) ([]core.MsgID, error) {
logger := &log.RelayLogger{Logger: logger.With(logAttrMsgIndexFrom, from)}
c.ethereumSigner.SetLogger(logger);

tx, err := iter.SendTx(ctx, c)
logger.Logger = logger.With(logAttrMsgIndexTo, iter.Cursor() -1)
tx, count, err := iter.BuildTx(ctx, c)
iter.updateLoggerMessageInfo(logger, iter.Cursor(), count)

if err != nil {
logger.Error("failed to send msg", err)
logger.Error("failed to build msg tx", err)
return nil, err
} else if tx == nil {
break
Expand All @@ -66,6 +66,12 @@ func (c *Chain) SendMsgs(msgs []sdk.Msg) ([]core.MsgID, error) {
logger.Logger = logger.With(logAttrRawTxData, hex.EncodeToString(rawTxData))
}

err = c.client.SendTransaction(ctx, tx)
if err != nil {
logger.Error("failed to send tx", err)
return nil, err
}

receipt, err := c.client.WaitForReceiptAndGet(ctx, tx.Hash())
if err != nil {
logger.Error("failed to get receipt", err)
Expand Down Expand Up @@ -102,9 +108,10 @@ func (c *Chain) SendMsgs(msgs []sdk.Msg) ([]core.MsgID, error) {
}
}
}
for i := from; i < iter.Cursor(); i++ {
for i := 0; i < count; i++ {
msgIDs = append(msgIDs, NewMsgID(tx.Hash()))
}
iter.Next(count);
}
return msgIDs, nil
}
Expand Down Expand Up @@ -341,7 +348,7 @@ func (c *Chain) TxAcknowledgement(opts *bind.TransactOpts, msg *chantypes.MsgAck
})
}

func (c *Chain) SendTx(opts *bind.TransactOpts, msg sdk.Msg, skipUpdateClientCommitment bool) (*gethtypes.Transaction, error) {
func (c *Chain) BuildMessageTx(opts *bind.TransactOpts, msg sdk.Msg, skipUpdateClientCommitment bool) (*gethtypes.Transaction, error) {
logger := c.GetChainLogger()
var (
tx *gethtypes.Transaction
Expand Down Expand Up @@ -406,7 +413,8 @@ func (c *Chain) getRevertReasonFromReceipt(ctx context.Context, receipt *client.

func (c *Chain) getRevertReasonFromRpcError(err error) (string, []byte, error) {
if de, ok := err.(rpc.DataError); !ok {
return "", nil, fmt.Errorf("failed with unexpected error type: errorType=%T", err)
//return "", nil, fmt.Errorf("failed with unexpected error type: errorType=%T", err)
return fmt.Sprintf("not an rpc error: errorType=%T: msg=%s", err, err.Error()), nil, nil
} else if de.ErrorData() == nil {
return "", nil, fmt.Errorf("failed without error data")
} else if errorData, ok := de.ErrorData().(string); !ok {
Expand Down Expand Up @@ -489,10 +497,17 @@ type CallIter struct {
msgTypeNames []string
}
func NewCallIter(msgs []sdk.Msg, skipUpdateClientCommitment bool) CallIter {
msgTypeNames := make([]string, 0, len(msgs))
for i := 0; i < len(msgs); i++ {
msgTypeName := fmt.Sprintf("%T", msgs[i])
msgTypeNames = append(msgTypeNames, msgTypeName)
}

return CallIter {
msgs: msgs,
cursor: 0,
skipUpdateClientCommitment: skipUpdateClientCommitment,
msgTypeNames: msgTypeNames,
}
}
func (iter *CallIter) Cursor() int {
Expand All @@ -504,123 +519,105 @@ func (iter *CallIter) Current() sdk.Msg {
func (iter *CallIter) End() bool {
return len(iter.msgs) <= iter.cursor
}
func (iter *CallIter) Next() {
if !iter.End() {
iter.cursor += 1
func (iter *CallIter) Next(n int) {
iter.cursor = min(len(iter.msgs), iter.cursor + n)
}

func (iter *CallIter) updateLoggerMessageInfo(logger *log.RelayLogger, from int, count int) {
if from < 0 || count < 0 || len(iter.msgs) <= from || len(iter.msgs) < from + count {
logger.Error("invalid parameter", fmt.Errorf("out of index: len(msgs)=%d, from=%d, count=%d", len(iter.msgs), from, count))
return
}

logger.Logger = logger.With(
logAttrMsgIndexFrom, from,
logAttrMsgCount, count,
logAttrMsgType, strings.Join(iter.msgTypeNames[0 : from + count], ","),
)
}

func (iter *CallIter) SendTx(ctx context.Context, c *Chain) (*gethtypes.Transaction, error) {
func (iter *CallIter) BuildTx(ctx context.Context, c *Chain) (*gethtypes.Transaction, int, error) {
if c.multicall3 == nil {
return iter.sendSingleTx(ctx, c)
return iter.buildSingleTx(ctx, c)
} else {
return iter.sendMultiTx(ctx, c)
return iter.buildMultiTx(ctx, c)
}
}

func (iter *CallIter) sendSingleTx(ctx context.Context, c *Chain) (*gethtypes.Transaction, error) {
func (iter *CallIter) buildSingleTx(ctx context.Context, c *Chain) (*gethtypes.Transaction, int, error) {
if iter.End() {
return nil, nil
return nil, 0, nil
}

logger := c.GetChainLogger()
logger = &log.RelayLogger{Logger: logger.With(
logAttrMsgIndexFrom, iter.Cursor(),
logAttrMsgType, fmt.Sprintf("%T", iter.Current()),
)}
iter.updateLoggerMessageInfo(logger, iter.Cursor(), 1)

opts, err := c.TxOpts(ctx, true);
if err != nil {
return nil, err
return nil, 0, err
}

// gas estimation
{
opts.GasLimit = math.MaxUint64
opts.NoSend = true
tx, err := c.SendTx(opts, iter.Current(), iter.skipUpdateClientCommitment)
tx, err := c.BuildMessageTx(opts, iter.Current(), iter.skipUpdateClientCommitment)
if err != nil {
logger.Error("failed to build tx for gas estimation", err)
return nil, err
return nil, 1, err
}

txGasLimit, err := estimateGas(ctx, c, tx, true, logger)
if err != nil {
return nil, err
return nil, 1, err
}
opts.GasLimit = txGasLimit
}

// add raw tx to log attribute
var hexTx string
{
tx, err := c.SendTx(opts, iter.Current(), iter.skipUpdateClientCommitment)
if err != nil {
logger.Error("failed to build tx with real send parameters", err)
return nil, err
}
if rawTxData, err := tx.MarshalBinary(); err != nil {
logger.Error("failed to encode tx", err)
} else {
hexTx = hex.EncodeToString(rawTxData)
}
}

opts.NoSend = false
tx, err := c.SendTx(opts, iter.Current(), iter.skipUpdateClientCommitment)
tx, err := c.BuildMessageTx(opts, iter.Current(), iter.skipUpdateClientCommitment)
if err != nil {
logger.Logger = logger.With(logAttrRawTxData, hexTx)
logger.Error("failed to send msg", err)
return nil, err
logger.Error("failed to build tx", err)
return nil, 0, err
}
iter.Next()
return tx, nil

return tx, 1, nil
}

func (iter *CallIter) sendMultiTx(ctx context.Context, c *Chain) (*gethtypes.Transaction, error) {
func (iter *CallIter) buildMultiTx(ctx context.Context, c *Chain) (*gethtypes.Transaction, int, error) {
if (iter.End()) {
return nil, nil
return nil, 0, nil
}
// now iter.cursor < len(iter.msgs)

logger := c.GetChainLogger()

opts, err := c.TxOpts(ctx, true);
if err != nil {
if err != nil {
return nil, err
}
return nil, 1, err
}

if iter.txs == nil { // create txs at first multicall call
opts.GasLimit = math.MaxUint64
opts.NoSend = true
txs := make([]gethtypes.Transaction, 0, len(iter.msgs))
msgTypeNames := make([]string, 0, len(iter.msgs))

for i := 0; i < len(iter.msgs); i++ {
msgTypeName := fmt.Sprintf("%T", iter.msgs[i])
msgTypeNames = append(msgTypeNames, msgTypeName)
logger := &log.RelayLogger{Logger: logger.Logger}
iter.updateLoggerMessageInfo(logger, iter.Cursor(), i+1)

tx, err := c.SendTx(opts, iter.msgs[i], iter.skipUpdateClientCommitment)
tx, err := c.BuildMessageTx(opts, iter.msgs[i], iter.skipUpdateClientCommitment)
if err != nil {
logger := &log.RelayLogger{Logger: logger.With(
logAttrMsgIndexFrom, i,
logAttrMsgIndexTo, i,
logAttrMsgType, msgTypeName,
)}
logger.Error("failed to build tx for gas estimation", err)
return nil, err
return nil, i+1, err
}
if tx.To() == nil {
err2 := fmt.Errorf("no target address")
logger.Error("failed to construct Multicall3Call", err2)
return nil, err2
return nil, i+1, err2
}
txs = append(txs, *tx)
}
iter.txs = txs
iter.msgTypeNames = msgTypeNames
}

var (
Expand All @@ -633,11 +630,8 @@ func (iter *CallIter) sendMultiTx(ctx context.Context, c *Chain) (*gethtypes.Tra
from := iter.Cursor()
to := from + count

logger := &log.RelayLogger{Logger: logger.With(
logAttrMsgIndexFrom, from,
logAttrMsgIndexTo, from + count - 1,
logAttrMsgType, strings.Join(iter.msgTypeNames[0 : from + count], ","),
)}
logger := &log.RelayLogger{Logger: logger.Logger}
iter.updateLoggerMessageInfo(logger, from, count)

calls := make([]multicall3.Multicall3Call, 0, count)
for i := from; i < to; i++ {
Expand All @@ -664,44 +658,22 @@ func (iter *CallIter) sendMultiTx(ctx context.Context, c *Chain) (*gethtypes.Tra
return nil
})

logger = &log.RelayLogger{Logger: logger.With(
logAttrMsgIndexFrom, iter.Cursor(),
logAttrMsgIndexTo, iter.Cursor() + count - 1,
logAttrMsgType, strings.Join(iter.msgTypeNames[0 : iter.Cursor() + count], ","),
)}
iter.updateLoggerMessageInfo(logger, iter.Cursor(), count)

if err != nil {
logger.Error("failed to prepare multicall tx", err)
return nil, err
return nil, count, err
}

opts.GasLimit = lastOkGasLimit

// add raw tx to log attribute
var hexTx string
{
tx, err := c.multicall3.Aggregate(opts, lastOkCalls)
if err != nil {
logger.Error("failed to build multicall tx with real send parameters", err)
return nil, err
}
if rawTxData, err := tx.MarshalBinary(); err != nil {
logger.Error("failed to encode multicall tx", err)
} else {
hexTx = hex.EncodeToString(rawTxData)
}
}

opts.NoSend = false
tx, err := c.multicall3.Aggregate(opts, lastOkCalls)
if err != nil {
logger.Logger = logger.With(logAttrRawTxData, hexTx)
logger.Error("failed to send multicall tx", err)
return nil, err
logger.Error("failed to build multicall tx with real send parameters", err)
return nil, count, err
}
logger.Info("succeeded in sending multicall")
iter.cursor += count
return tx, nil
return tx, count, nil
}

func findItems(
Expand Down

0 comments on commit e6e7108

Please sign in to comment.