Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
24 changes: 20 additions & 4 deletions relayer/chainreader/chainreader_util/hasher.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ func (h *MessageHasherV1) Hash(ctx context.Context, report *codec.ExecutionRepor
return [32]byte{}, fmt.Errorf("compute metadata hash: %w", err)
}

if len(report.Message.Header.MessageID) != 32 {
h.lggr.Warnw("Invalid message ID length, messageID will be padded or truncated", "messageID", report.Message.Header.MessageID)
}

var messageID [32]byte
copy(messageID[:], report.Message.Header.MessageID)

Expand Down Expand Up @@ -169,13 +173,21 @@ func computeMessageDataHash(

// Manually encode tokens to match the Move implementation
var tokenHashData []byte
tokenHashData = append(tokenHashData, encodeUint256(big.NewInt(int64(len(tokenAmounts))))...)
encodedLen, err := encodeUint256(big.NewInt(int64(len(tokenAmounts))))
if err != nil {
return [32]byte{}, fmt.Errorf("failed to encode token length: %w", err)
}
tokenHashData = append(tokenHashData, encodedLen...)
for _, token := range tokenAmounts {
tokenHashData = append(tokenHashData, encodeBytes(token.SourcePoolAddress)...)
tokenHashData = append(tokenHashData, token.DestTokenAddress[:]...)
tokenHashData = append(tokenHashData, encodeUint32(token.DestGasAmount)...)
tokenHashData = append(tokenHashData, encodeBytes(token.ExtraData)...)
tokenHashData = append(tokenHashData, encodeUint256(token.Amount)...)
encodedAmount, err := encodeUint256(token.Amount)
if err != nil {
return [32]byte{}, fmt.Errorf("failed to encode token amount: %w", err)
}
tokenHashData = append(tokenHashData, encodedAmount...)
}
tokenAmountsHash := crypto.Keccak256Hash(tokenHashData)

Expand Down Expand Up @@ -242,8 +254,12 @@ func computeMetadataHash(
return metadataHash, nil
}

func encodeUint256(n *big.Int) []byte {
return common.LeftPadBytes(n.Bytes(), 32)
func encodeUint256(n *big.Int) ([]byte, error) {
if n == nil {
return []byte{}, fmt.Errorf("nil big.Int cannot be encoded")
}

return common.LeftPadBytes(n.Bytes(), 32), nil
}

func encodeUint32(n uint32) []byte {
Expand Down
6 changes: 6 additions & 0 deletions relayer/chainreader/chainreader_util/package_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,12 @@ func (pr *PackageResolver) InvalidateCache(moduleName string) {
packageAddress := pr.packageAddresses[moduleName]
pr.mutex.RUnlock()

// If the package address is not found, do not invalidate the cache
if packageAddress == "" {
pr.log.Debugw("Package address not found for module, skipping cache invalidation", "module", moduleName)
return
}

keys := []string{
packageAddressCachePrefix + moduleName,
packageIDsCachePrefix + packageAddress + ":" + moduleName,
Expand Down
11 changes: 10 additions & 1 deletion relayer/chainreader/indexer/transactions_indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,16 @@ func (tIndexer *TransactionsIndexer) syncTransmitterTransactions(ctx context.Con
tIndexer.logger.Debugw("Report arg", "reportArg", reportArg)

// Handle the conversion from []interface{} to []byte
reportValue := reportArg["value"].([]any)
reportValue, ok := reportArg["value"].([]any)
if !ok {
tIndexer.logger.Errorw("Expected report value to be a []any",
"transmitter", transmitter,
"txDigest", transactionRecord.Digest,
"reportArg", reportArg,
"valueType", fmt.Sprintf("%T", reportArg["value"]))
continue
}

reportBytes := make([]byte, len(reportValue))
for i, val := range reportValue {
num, ok := val.(float64)
Expand Down
10 changes: 8 additions & 2 deletions relayer/chainreader/reader/chainreader.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,12 @@ func (s *suiChainReader) Unbind(ctx context.Context, bindings []pkgtypes.BoundCo
return fmt.Errorf("failed to unbind package %s: %w", binding.Name, err)
}

modulePrefix := fmt.Sprintf("%s::%s::", binding.Address, binding.Name)

// Clear cached parent object IDs for this unbound contract
s.parentObjectIDsMutex.Lock()
for key := range s.parentObjectIDs {
if strings.HasPrefix(key, binding.Address+"::") {
if strings.HasPrefix(key, modulePrefix) {
delete(s.parentObjectIDs, key)
}
}
Expand Down Expand Up @@ -1047,7 +1049,11 @@ func (s *suiChainReader) transformEventsToSequences(eventRecords []database.Even
}

for _, record := range eventRecords {
eventData := reflect.New(reflect.TypeOf(expectedEventType).Elem()).Interface()
t := reflect.TypeOf(expectedEventType)
if t == nil || t.Kind() != reflect.Ptr {
return nil, fmt.Errorf("sequenceDataType must be a non-nil pointer type")
}
eventData := reflect.New(t.Elem()).Interface()

s.logger.Debugw("Processing database event record", "data", record.Data, "offset", record.EventOffset, "eventDataType", reflect.TypeOf(eventData).Elem())

Expand Down
17 changes: 13 additions & 4 deletions relayer/client/ptb_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"net/http"
"strconv"
"strings"
"testing"
"time"

"github.com/aptos-labs/aptos-go-sdk/bcs"
Expand Down Expand Up @@ -139,6 +140,11 @@ func NewPTBClient(
) (*PTBClient, error) {
log.Infof("Creating new SUI client with blockvision SDK")

if maxConcurrentRequests <= 0 {
log.Warnw("maxConcurrentRequests is less than 0, setting to default value", "maxConcurrentRequests", maxConcurrentRequests)
maxConcurrentRequests = 500 // Default value
}

httpClient := &http.Client{
Timeout: DefaultHTTPTimeout,
Transport: &http.Transport{
Expand All @@ -149,10 +155,6 @@ func NewPTBClient(
}
client := sui.NewSuiClientWithCustomClient(rpcUrl, httpClient)

if maxConcurrentRequests <= 0 {
maxConcurrentRequests = 500 // Default value
}

log.Infof(
"PTBClient config configs transactionTimeout: %s, maxConcurrentRequests: %d",
transactionTimeout,
Expand Down Expand Up @@ -825,7 +827,14 @@ func (c *PTBClient) QueryCoinsByAddress(ctx context.Context, address string, coi
return result, err
}

// FinishPTBAndSend finishes the PTB transaction and sends it to the network.
// IMPORTANT: This method is only used for testing purposes.
func (c *PTBClient) FinishPTBAndSend(ctx context.Context, txnSigner *signer.Signer, tx *transaction.Transaction, requestType TransactionRequestType) (SuiTransactionBlockResponse, error) {
// This method should only be used in test environments
if !testing.Testing() {
return SuiTransactionBlockResponse{}, fmt.Errorf("FinishPTBAndSend is only available in test environments")
}

gasPrice, err := c.GetReferenceGasPrice(ctx)
if err != nil {
return SuiTransactionBlockResponse{}, fmt.Errorf("failed to get reference gas price: %w", err)
Expand Down
4 changes: 2 additions & 2 deletions relayer/codec/decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -475,8 +475,8 @@ func TestHexStringHook(t *testing.T) {
{
name: "hex to byte array",
data: "0x123456",
target: new([4]uint8),
expected: []uint8{0x12, 0x34, 0x56, 0x00},
target: new([3]uint8),
expected: []uint8{0x12, 0x34, 0x56},
},
}

Expand Down
26 changes: 23 additions & 3 deletions relayer/codec/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,21 @@ func encodeAddress(value any) (string, error) {
v = "0x" + v
}

return v, nil
normalizedAddress, err := bind.ToSuiAddress(v)
if err != nil {
return "", fmt.Errorf("failed to convert address to Sui address: %w", err)
}

return normalizedAddress, nil
case []byte:
return "0x" + hex.EncodeToString(v), nil
stringAddr := "0x" + hex.EncodeToString(v)

normalizedAddress, err := bind.ToSuiAddress(stringAddr)
if err != nil {
return "", fmt.Errorf("failed to convert address to Sui address: %w", err)
}

return normalizedAddress, nil
default:
return "", fmt.Errorf("cannot convert %T to address", value)
}
Expand Down Expand Up @@ -298,9 +310,17 @@ func encodeVector(typeName string, value any) ([]any, error) {
}
innerType := typeName[len("vector<") : len(typeName)-1]

// Use reflection to ensure 'value' is a slice or array
if value == nil {
return nil, fmt.Errorf("nil value cannot be encoded in encodeVector")
}
rv := reflect.ValueOf(value)

if !rv.IsValid() {
return nil, fmt.Errorf("invalid reflect value for vector type %s in encodeVector", typeName)
}
kind := rv.Kind()

// Use reflection to ensure 'value' is a slice or array
if kind != reflect.Slice && kind != reflect.Array {
return nil, fmt.Errorf("expected a slice/array for vector type %s, got %T", typeName, value)
}
Expand Down
5 changes: 5 additions & 0 deletions relayer/codec/type_converters.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,11 @@ func (tc *TypeConverter) hexToArray(from, to reflect.Type, data any) (any, error

byteSlice := bytes.([]byte)
out := make([]uint8, to.Len())

if len(byteSlice) != to.Len() {
return nil, fmt.Errorf("hex to array: byte slice length %d is not equal to output array length %d", len(byteSlice), to.Len())
}

copy(out, byteSlice)

return out, nil
Expand Down
10 changes: 10 additions & 0 deletions relayer/config/toml_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ func (cs TOMLConfigs) validateKeys() error {
}

func (cs *TOMLConfigs) SetFrom(fs *TOMLConfigs) error {
// Avoids panics if the source TOMLConfigs is nil
if fs == nil {
return nil
}

if err1 := fs.validateKeys(); err1 != nil {
return err1
}
Expand All @@ -118,6 +123,11 @@ func (cs *TOMLConfigs) SetFrom(fs *TOMLConfigs) error {
type NodeConfigs []*NodeConfig

func (ns *NodeConfigs) SetFrom(fs *NodeConfigs) {
// Avoids panics if the source NodeConfigs is nil
if fs == nil {
return
}

for _, f := range *fs {
if f.Name == nil {
*ns = append(*ns, f)
Expand Down
3 changes: 1 addition & 2 deletions relayer/signer/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"encoding/base64"
"encoding/hex"
"fmt"
"log"

"golang.org/x/crypto/blake2b"
)
Expand Down Expand Up @@ -104,7 +103,7 @@ func (s *PrivateKeySigner) Sign(message []byte) ([]string, error) {
var noHash crypto.Hash
sigBytes, err := s.privateKey.Sign(nil, digest[:], noHash)
if err != nil {
log.Fatal(err)
return nil, fmt.Errorf("failed to sign message with ed25519: %w", err)
}
pubKey := s.privateKey.Public().(ed25519.PublicKey)
serializedSignature := SerializeSuiSignature(sigBytes, pubKey)
Expand Down
10 changes: 4 additions & 6 deletions relayer/txm/confirmer.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ func checkConfirmations(loopCtx context.Context, txm *SuiTxm) {
txm.lggr.Errorw("Error getting in-flight transactions", "error", err)
return
}

for _, tx := range inFlightTransactions {
txm.lggr.Debugw("Checking transaction confirmations", "transactionID", tx.TransactionID)
switch tx.State {
Expand All @@ -115,10 +116,7 @@ func checkConfirmations(loopCtx context.Context, txm *SuiTxm) {
default:
txm.lggr.Infow("Unknown transaction status", "transactionID", tx.TransactionID, "status", resp.Status)
}
case StateRetriable:
// TODO check if the transaction is still retriable
txm.lggr.Debugw("Transaction is still retriable")
case StatePending, StateFinalized, StateFailed:
case StateRetriable, StatePending, StateFinalized, StateFailed:
// Do nothing for pending, finalized and failed transactions
}
}
Expand Down Expand Up @@ -149,8 +147,8 @@ func handleTransactionError(ctx context.Context, txm *SuiTxm, tx SuiTx, result *
txm.lggr.Infow("Transaction is retriable", "transactionID", tx.TransactionID, "strategy", strategy)
switch strategy {
case ExponentialBackoff:
// TODO: for another PR implement exponential backoff
txm.lggr.Infow("Exponential backoff strategy not implemented")
txm.lggr.Errorw("Exponential backoff strategy not implemented", "transactionID", tx.TransactionID)
return errors.New("exponential backoff strategy not implemented")
case GasBump:
txm.lggr.Infow("Gas bump strategy", "transactionID", tx.TransactionID)
updatedGas, err := txm.gasManager.GasBump(ctx, &tx)
Expand Down
8 changes: 7 additions & 1 deletion relayer/txm/gas_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"context"
"errors"
"fmt"
"math"
"math/big"

"github.com/smartcontractkit/chainlink-common/pkg/logger"
Expand Down Expand Up @@ -194,6 +195,11 @@ func (s *SuiGasManager) GasBump(ctx context.Context, tx *SuiTx) (big.Int, error)
// The max amount of the gas that the Gas manager will allow
gasManagerMaxGasBudget := big.NewInt(int64(s.maxGasBudget.Uint64()))

// Check if tx.GasBudget exceeds int64 max value to prevent overflow
if tx.GasBudget > math.MaxInt64 {
return *big.NewInt(0), fmt.Errorf("tx.GasBudget %d exceeds maximum int64 value", tx.GasBudget)
}

// the max amount of the gas that the transaction will allow
txGasBudget := big.NewInt(int64(tx.GasBudget))

Expand All @@ -212,7 +218,7 @@ func (s *SuiGasManager) GasBump(ctx context.Context, tx *SuiTx) (big.Int, error)

s.lggr.Debugw("GasBump", "txGasLimit", txGasLimit, "maxGasLimit", maxGasLimit)

// Check if the current gas limit is at or above the maximum allowed budget.
// Check if the current gas limit is greater than the maximum allowed budget.
if txGasLimit.Cmp(maxGasLimit) > 0 {
return *big.NewInt(0), errors.New("gas budget is already at max gas limit")
}
Expand Down
6 changes: 6 additions & 0 deletions relayer/txm/reaper.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ func (txm *SuiTxm) reaperLoop() {

basePeriod := txm.configuration.ReaperPollSecs
ticker, jitteredDuration := GetTicker(uint(basePeriod))
defer ticker.Stop()

txm.lggr.Infow("Created reaper ticker",
"basePeriod", basePeriod,
Expand Down Expand Up @@ -47,6 +48,11 @@ func cleanupTransactions(txm *SuiTxm) {

currentTimestamp := GetCurrentUnixTimestamp()

if currentTimestamp == 0 {
txm.lggr.Errorw("Found a 0 timestamp, skipping cleanup")
return
}

for _, tx := range finalizedTransactions {
txm.lggr.Debugw("Cleaning up finalized transaction", "transactionID", tx.TransactionID)
timeDiff := currentTimestamp - tx.LastUpdatedAt
Expand Down
Loading