Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(bmr): send only one receipt per transaction #545

Draft
wants to merge 15 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 7 additions & 30 deletions cmd/iconbridge/chain/bsc/sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/icon-project/icon-bridge/cmd/iconbridge/chain"
"github.com/icon-project/icon-bridge/cmd/iconbridge/common/chainutils"

bscTypes "github.com/icon-project/icon-bridge/cmd/iconbridge/chain/bsc/types"
"github.com/icon-project/icon-bridge/common/codec"
"github.com/icon-project/icon-bridge/common/intconv"
Expand Down Expand Up @@ -163,41 +165,16 @@ func (s *sender) Segment(
return nil, msg, nil
}

rm := &chain.RelayMessage{
Receipts: make([][]byte, 0),
relayMsg, newMsg, err := chainutils.SegmentByTxDataSize(msg, s.opts.TxDataSizeLimit)
if err != nil {
return nil, nil, err
}

var msgSize uint64

newMsg = &chain.Message{
From: msg.From,
Receipts: msg.Receipts,
}
for i, receipt := range msg.Receipts {
rlpEvents, err := codec.RLP.MarshalToBytes(receipt.Events)
if err != nil {
return nil, nil, err
}
rlpReceipt, err := codec.RLP.MarshalToBytes(&chain.RelayReceipt{
Index: receipt.Index,
Height: receipt.Height,
Events: rlpEvents,
})
if err != nil {
return nil, nil, err
}
newMsgSize := msgSize + uint64(len(rlpReceipt))
if newMsgSize > s.opts.TxDataSizeLimit {
newMsg.Receipts = msg.Receipts[i:]
break
}
msgSize = newMsgSize
rm.Receipts = append(rm.Receipts, rlpReceipt)
}
message, err := codec.RLP.MarshalToBytes(rm)
message, err := codec.RLP.MarshalToBytes(relayMsg)
if err != nil {
return nil, nil, err
}

cl, _ := s.jointClient()
gasPrice, gasHeight, err := cl.GetMedianGasPriceForBlock(ctx)
if err != nil || gasPrice.Int64() == 0 {
Expand Down
37 changes: 5 additions & 32 deletions cmd/iconbridge/chain/hmny/sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/icon-project/icon-bridge/cmd/iconbridge/chain"
"github.com/icon-project/icon-bridge/cmd/iconbridge/common/chainutils"
"github.com/icon-project/icon-bridge/common/codec"
"github.com/icon-project/icon-bridge/common/intconv"
"github.com/icon-project/icon-bridge/common/log"
Expand Down Expand Up @@ -135,40 +136,12 @@ func (s *sender) Segment(
return nil, msg, nil
}

rm := &chain.RelayMessage{
Receipts: make([][]byte, 0),
}

var msgSize uint64

newMsg = &chain.Message{
From: msg.From,
Receipts: msg.Receipts,
}

for i, receipt := range msg.Receipts {
rlpEvents, err := codec.RLP.MarshalToBytes(receipt.Events)
if err != nil {
return nil, nil, err
}
rlpReceipt, err := codec.RLP.MarshalToBytes(&chain.RelayReceipt{
Index: receipt.Index,
Height: receipt.Height,
Events: rlpEvents,
})
if err != nil {
return nil, nil, err
}
newMsgSize := msgSize + uint64(len(rlpReceipt))
if newMsgSize > s.opts.TxDataSizeLimit {
newMsg.Receipts = msg.Receipts[i:]
break
}
msgSize = newMsgSize
rm.Receipts = append(rm.Receipts, rlpReceipt)
relayMsg, newMsg, err := chainutils.SegmentByTxDataSize(msg, s.opts.TxDataSizeLimit)
if err != nil {
return nil, nil, err
}

message, err := codec.RLP.MarshalToBytes(rm)
message, err := codec.RLP.MarshalToBytes(relayMsg)
if err != nil {
return nil, nil, err
}
Expand Down
40 changes: 7 additions & 33 deletions cmd/iconbridge/chain/icon/sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
"github.com/icon-project/icon-bridge/cmd/iconbridge/chain/icon/types"
"math/big"
"net/url"
"strconv"
"time"

"github.com/icon-project/icon-bridge/cmd/iconbridge/chain/icon/types"
"github.com/icon-project/icon-bridge/cmd/iconbridge/common/chainutils"

"github.com/icon-project/icon-bridge/cmd/iconbridge/chain"
"github.com/icon-project/icon-bridge/common"
"github.com/icon-project/icon-bridge/common/codec"
Expand Down Expand Up @@ -147,40 +149,12 @@ func (s *sender) Segment(
return nil, msg, nil
}

rm := &chain.RelayMessage{
Receipts: make([][]byte, 0),
}

var msgSize uint64

newMsg = &chain.Message{
From: msg.From,
Receipts: msg.Receipts,
}

for i, receipt := range msg.Receipts {
rlpEvents, err := codec.RLP.MarshalToBytes(receipt.Events)
if err != nil {
return nil, nil, err
}
rlpReceipt, err := codec.RLP.MarshalToBytes(&chain.RelayReceipt{
Index: receipt.Index,
Height: receipt.Height,
Events: rlpEvents,
})
if err != nil {
return nil, nil, err
}
newMsgSize := msgSize + uint64(len(rlpReceipt))
if newMsgSize > s.opts.TxDataSizeLimit {
newMsg.Receipts = msg.Receipts[i:]
break
}
msgSize = newMsgSize
rm.Receipts = append(rm.Receipts, rlpReceipt)
relayMsg, newMsg, err := chainutils.SegmentByTxDataSize(msg, s.opts.TxDataSizeLimit)
if err != nil {
return nil, nil, err
}

message, err := codec.RLP.MarshalToBytes(rm)
message, err := codec.RLP.MarshalToBytes(relayMsg)
if err != nil {
return nil, nil, err
}
Expand Down
51 changes: 17 additions & 34 deletions cmd/iconbridge/chain/near/sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@ import (
"github.com/icon-project/icon-bridge/cmd/iconbridge/chain"
"github.com/icon-project/icon-bridge/cmd/iconbridge/chain/near/errors"
"github.com/icon-project/icon-bridge/cmd/iconbridge/chain/near/types"
"github.com/icon-project/icon-bridge/cmd/iconbridge/common/chainutils"
"github.com/icon-project/icon-bridge/common/codec"
"github.com/icon-project/icon-bridge/common/log"
"github.com/icon-project/icon-bridge/common/wallet"
)

const (
txMaxDataSize = 64 * 1024
txMaxDataSize = 4 * 1024
txOverheadScale = 0.01 // base64 encoding overhead 0.36, rlp and other fields 0.01
defaultTxSizeLimit = txMaxDataSize / (1 + txOverheadScale)
functionCallMethod = "handle_relay_message"
gas = uint64(300000000000000)
defaultSendTxTimeout = 15 * time.Second
Expand All @@ -32,6 +35,7 @@ type Sender struct {
wallet Wallet
logger log.Logger
options struct {
TxDataSizeLimit uint64 `json:"tx_data_size_limit"`
BalanceThreshold types.BigInt `json:"balance_threshold"`
}
}
Expand Down Expand Up @@ -75,48 +79,28 @@ func (s *Sender) client() IClient {
return s.clients[rand.Intn(len(s.clients))]
}

func (s *Sender) Segment(ctx context.Context, msg *chain.Message) (tx chain.RelayTx, newMsg *chain.Message, err error) {
func (s *Sender) Segment(
ctx context.Context, msg *chain.Message,
) (tx chain.RelayTx, newMsg *chain.Message, err error) {
if ctx.Err() != nil {
return nil, nil, ctx.Err()
}

if len(msg.Receipts) == 0 {
return nil, msg, nil
if s.options.TxDataSizeLimit == 0 {
limit := defaultTxSizeLimit
s.options.TxDataSizeLimit = uint64(limit)
}

rm := &chain.RelayMessage{
Receipts: make([][]byte, 0),
if len(msg.Receipts) == 0 {
return nil, msg, nil
}

var msgSize uint64

newMsg = &chain.Message{
From: msg.From,
Receipts: msg.Receipts,
}
for i, receipt := range msg.Receipts {
rlpEvents, err := codec.RLP.MarshalToBytes(receipt.Events)
bbist marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, nil, err
}
rlpReceipt, err := codec.RLP.MarshalToBytes(&chain.RelayReceipt{
Index: receipt.Index,
Height: receipt.Height,
Events: rlpEvents,
})
if err != nil {
return nil, nil, err
}
newMsgSize := msgSize + uint64(len(rlpReceipt))
if newMsgSize > txMaxDataSize {
newMsg.Receipts = msg.Receipts[i:]
break
}
msgSize = newMsgSize
rm.Receipts = append(rm.Receipts, rlpReceipt)
relayMsg, newMsg, err := chainutils.SegmentByTxDataSize(msg, s.options.TxDataSizeLimit)
if err != nil {
return nil, nil, err
}

message, err := codec.RLP.MarshalToBytes(rm)
message, err := codec.RLP.MarshalToBytes(relayMsg)
if err != nil {
return nil, nil, err
}
Expand All @@ -128,7 +112,6 @@ func (s *Sender) Segment(ctx context.Context, msg *chain.Message) (tx chain.Rela

return tx, newMsg, nil
}

func (s *Sender) newRelayTransaction(ctx context.Context, prev string, message []byte) (*RelayTransaction, error) {
if nearWallet, Ok := (s.wallet).(*wallet.NearWallet); Ok {
accountId := nearWallet.Address()
Expand Down
67 changes: 67 additions & 0 deletions cmd/iconbridge/common/chainutils/segment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package chainutils

import (
"github.com/icon-project/icon-bridge/cmd/iconbridge/chain"
"github.com/icon-project/icon-bridge/common/codec"
)

func SegmentByTxDataSize(msg *chain.Message, txDataSizeLimit uint64) (relayMsg *chain.RelayMessage, newMsg *chain.Message, err error) {

relayMsg = &chain.RelayMessage{
Receipts: make([][]byte, 0),
}

newMsg = &chain.Message{
From: msg.From,
Receipts: msg.Receipts,
}

var msgSize uint64

rloop:
for i, receipt := range msg.Receipts {

eloop:
for j := range receipt.Events {
// try all events first
// if it exceeds limit, try again by removing last event
events := receipt.Events[:len(receipt.Events)-j]

rlpEvents, err := codec.RLP.MarshalToBytes(events)
if err != nil {
return nil, nil, err
}
rlpReceipt, err := codec.RLP.MarshalToBytes(&chain.RelayReceipt{
Index: receipt.Index,
Height: receipt.Height,
Events: rlpEvents,
})
if err != nil {
return nil, nil, err
}

newMsgSize := msgSize + uint64(len(rlpReceipt))
if newMsgSize <= txDataSizeLimit {

msgSize = newMsgSize
if len(events) == len(receipt.Events) { // all events added
newMsg.Receipts = msg.Receipts[i+1:]
} else { // save remaining events in this receipt
receipt.Events = receipt.Events[len(events):]
newMsg.Receipts = msg.Receipts[i:]
}
relayMsg.Receipts = append(relayMsg.Receipts, rlpReceipt)
break eloop

} else if len(events) == 1 {
// stop iterating over receipts when adding even a single event
// exceeds tx size limit
break rloop
bbist marked this conversation as resolved.
Show resolved Hide resolved
}

}
}

return relayMsg, newMsg, nil

}
Loading