fixed v4 gateway resolution #616

Closed
tech wants to merge 2 commits from tron-615 into main
4 changed files with 51 additions and 6 deletions

View File

@@ -53,14 +53,19 @@ type config struct {
type chainConfig struct {
Name string `yaml:"name"`
RPCURLEnv string `yaml:"rpc_url_env"`
GRPCURLEnv string `yaml:"grpc_url_env"` // Native TRON gRPC endpoint
GRPCTokenEnv string `yaml:"grpc_token_env"`
GRPC chainGRPCConfig `yaml:"grpc"`
ChainID uint64 `yaml:"chain_id"`
NativeToken string `yaml:"native_token"`
Tokens []tokenConfig `yaml:"tokens"`
GasTopUpPolicy *gasTopUpPolicyConfig `yaml:"gas_topup_policy"`
}
type chainGRPCConfig struct {
URLEnv string `yaml:"url_env"` // Native TRON gRPC endpoint env var
TokenEnv string `yaml:"token_env"` // Optional auth token env var for x-token header
ForceIPv4 bool `yaml:"force_ipv4"` // Force IPv4 sockets when dialing TRON gRPC.
}
type serviceWalletConfig struct {
Chain string `yaml:"chain"`
Address string `yaml:"address"`
@@ -282,14 +287,14 @@ func resolveNetworkConfigs(logger mlogger.Logger, chains []chainConfig) ([]gatew
// Resolve optional TRON gRPC URL
grpcURL := ""
if grpcEnv := strings.TrimSpace(chain.GRPCURLEnv); grpcEnv != "" {
if grpcEnv := strings.TrimSpace(chain.GRPC.URLEnv); grpcEnv != "" {
grpcURL = strings.TrimSpace(os.Getenv(grpcEnv))
if grpcURL != "" {
logger.Info("TRON gRPC URL configured", zap.String("chain", network.String()), zap.String("env", grpcEnv))
}
}
grpcToken := ""
if grpcTokenEnv := strings.TrimSpace(chain.GRPCTokenEnv); grpcTokenEnv != "" {
if grpcTokenEnv := strings.TrimSpace(chain.GRPC.TokenEnv); grpcTokenEnv != "" {
grpcToken = strings.TrimSpace(os.Getenv(grpcTokenEnv))
if grpcToken != "" {
logger.Info("TRON gRPC token configured", zap.String("chain", network.String()), zap.String("env", grpcTokenEnv))
@@ -301,6 +306,7 @@ func resolveNetworkConfigs(logger mlogger.Logger, chains []chainConfig) ([]gatew
RPCURL: rpcURL,
GRPCUrl: grpcURL,
GRPCToken: grpcToken,
GRPCForceIPv4: chain.GRPC.ForceIPv4,
ChainID: chain.ChainID,
NativeToken: chain.NativeToken,
TokenConfigs: contracts,

View File

@@ -6,6 +6,7 @@ import (
"encoding/hex"
"fmt"
"math/big"
"net"
"net/url"
"strings"
"time"
@@ -27,7 +28,7 @@ type Client struct {
}
// NewClient creates a new TRON gRPC client connected to the given endpoint.
func NewClient(grpcURL string, timeout time.Duration, authToken string) (*Client, error) {
func NewClient(grpcURL string, timeout time.Duration, authToken string, forceIPv4 bool) (*Client, error) {
if grpcURL == "" {
return nil, merrors.InvalidArgument("tronclient: grpc url is required")
}
@@ -50,6 +51,9 @@ func NewClient(grpcURL string, timeout time.Duration, authToken string) (*Client
}
opts := []grpc.DialOption{transportCreds}
if forceIPv4 {
opts = append(opts, grpc.WithContextDialer(grpcForceIPv4Dialer))
}
if token := strings.TrimSpace(authToken); token != "" {
opts = append(opts,
grpc.WithUnaryInterceptor(grpcTokenUnaryInterceptor(token)),
@@ -67,6 +71,40 @@ func NewClient(grpcURL string, timeout time.Duration, authToken string) (*Client
}, nil
}
func grpcForceIPv4Dialer(ctx context.Context, address string) (net.Conn, error) {
host, port, err := net.SplitHostPort(address)
if err != nil {
return nil, err
}
// Resolve IPv4 only
ips, err := net.DefaultResolver.LookupIP(ctx, "ip4", host)
if err != nil {
return nil, err
}
if len(ips) == 0 {
return nil, merrors.Internal(fmt.Sprintf("no IPv4 address found for %s", host))
}
var dialer net.Dialer
var lastErr error
for _, ip := range ips {
target := net.JoinHostPort(ip.String(), port)
conn, err := dialer.DialContext(ctx, "tcp4", target)
if err == nil {
return conn, nil
}
lastErr = err
if ctx.Err() != nil {
break
}
}
if lastErr != nil {
return nil, merrors.Internal(fmt.Sprintf("failed to dial any IPv4 address for %s: %v", host, lastErr))
}
return nil, merrors.Internal(fmt.Sprintf("failed to dial IPv4 address for %s", host))
}
func normalizeGRPCAddress(grpcURL string) (string, bool, error) {
target := strings.TrimSpace(grpcURL)
useTLS := false

View File

@@ -58,7 +58,7 @@ func Prepare(ctx context.Context, logger mlogger.Logger, networks []shared.Netwo
zap.String("grpc_url", grpcURL),
)
client, err := NewClient(grpcURL, timeout, grpcToken)
client, err := NewClient(grpcURL, timeout, grpcToken, network.GRPCForceIPv4)
if err != nil {
registry.Close()
registry.logger.Error("Failed to initialize TRON gRPC client",

View File

@@ -170,6 +170,7 @@ type Network struct {
RPCURL string
GRPCUrl string // Native TRON gRPC endpoint (for transactions)
GRPCToken string // Optional auth token for TRON gRPC (x-token header)
GRPCForceIPv4 bool
ChainID uint64
NativeToken string
TokenConfigs []TokenContract